50 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			50 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
module Gitlab
 | 
						|
  module Diff
 | 
						|
    class FileCollectionSorter
 | 
						|
      B_FOLLOWS_A = 1
 | 
						|
      A_FOLLOWS_B = -1
 | 
						|
      EQUIVALENT = 0
 | 
						|
 | 
						|
      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 B_FOLLOWS_A if a_parts.size < b_parts.size && a_parts.empty?
 | 
						|
        return A_FOLLOWS_B if a_parts.size > b_parts.size && b_parts.empty?
 | 
						|
 | 
						|
        comparison = a_part <=> b_part
 | 
						|
 | 
						|
        return comparison unless comparison == EQUIVALENT
 | 
						|
        return compare_path_parts(a_parts, b_parts) if a_parts.any? && b_parts.any?
 | 
						|
 | 
						|
        # If A and B have the same name (e.g. symlink change), they are identical so return 0
 | 
						|
        EQUIVALENT
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |