summaryrefslogtreecommitdiff
path: root/lib/gitlab/diff/file_collection_sorter.rb
blob: 9462687558001a0fc5f54a5472e2922d46ddc435 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# frozen_string_literal: true

module Gitlab
  module Diff
    class FileCollectionSorter
      attr_reader :diffs

      def initialize(diffs)
        @diffs = diffs
      end

      def sort
        diffs.sort do |a, b|
          compare_path_parts(path_parts(a), path_parts(b))
        end
      end

      private

      def path_parts(diff)
        (diff.new_path.presence || diff.old_path).split(::File::SEPARATOR)
      end

      # Used for sorting the file paths by:
      # 1. Directory name
      # 2. Depth
      # 3. File name
      def compare_path_parts(a_parts, b_parts)
        a_part = a_parts.shift
        b_part = b_parts.shift

        return 1 if a_parts.size < b_parts.size && a_parts.empty?
        return -1 if a_parts.size > b_parts.size && b_parts.empty?

        comparison = a_part <=> b_part

        return comparison unless comparison == 0

        compare_path_parts(a_parts, b_parts)
      end
    end
  end
end