Welcome to mirror list, hosted at ThFree Co, Russian Federation.

base.rb « file_collection « diff « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3117b7c8c7fe21edeb55e25739e74a80beb3d138 (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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

module Gitlab
  module Diff
    module FileCollection
      class Base
        include Gitlab::Utils::StrongMemoize

        attr_reader :project, :diff_options, :diff_refs, :fallback_diff_refs, :diffable

        delegate :count, :size, :real_size, to: :raw_diff_files

        def self.default_options
          ::Commit.max_diff_options.merge(ignore_whitespace_change: false, expanded: false, include_stats: true, use_extra_viewer_as_main: false)
        end

        def initialize(diffable, project:, diff_options: nil, diff_refs: nil, fallback_diff_refs: nil)
          diff_options = self.class.default_options.merge(diff_options || {})

          @diffable = diffable
          @include_stats = diff_options.delete(:include_stats)
          @pagination_data = diff_options.delete(:pagination_data)
          @project = project
          @diff_options = diff_options
          @diff_refs = diff_refs
          @fallback_diff_refs = fallback_diff_refs
          @repository = project.repository
          @use_extra_viewer_as_main = diff_options.delete(:use_extra_viewer_as_main)
        end

        def diffs
          @diffs ||= diffable.raw_diffs(diff_options)
        end

        def diff_files(sorted: false)
          raw_diff_files(sorted: sorted)
        end

        def raw_diff_files(sorted: false)
          strong_memoize(:"raw_diff_files_#{sorted}") do
            collection = diffs.decorate! { |diff| decorate_diff!(diff) }
            collection = sort_diffs(collection) if sorted
            collection
          end
        end

        # This is either the new path, otherwise the old path for the diff_file
        def diff_file_paths
          diffs.map do |diff|
            diff.new_path.presence || diff.old_path
          end
        end

        # This is both the new and old paths for the diff_file
        def diff_paths
          diff_files.map(&:paths).flatten.uniq
        end

        def pagination_data
          @pagination_data || empty_pagination_data
        end

        # This mutates `diff_files` lines.
        def unfold_diff_files(positions)
          positions_grouped_by_path = positions.group_by { |position| position.file_path }

          diff_files.each do |diff_file|
            positions = positions_grouped_by_path.fetch(diff_file.file_path, [])
            positions.each { |position| diff_file.unfold_diff_lines(position) }
          end
        end

        def diff_file_with_old_path(old_path)
          diff_files.find { |diff_file| diff_file.old_path == old_path }
        end

        def diff_file_with_new_path(new_path)
          diff_files.find { |diff_file| diff_file.new_path == new_path }
        end

        def clear_cache
          # No-op
        end

        def write_cache
          # No-op
        end

        def overflow?
          raw_diff_files.overflow?
        end

        private

        def empty_pagination_data
          { total_pages: nil }
        end

        def diff_stats_collection
          strong_memoize(:diff_stats) do
            next unless fetch_diff_stats?

            @repository.diff_stats(diff_refs.base_sha, diff_refs.head_sha)
          end
        end

        def fetch_diff_stats?
          # There are scenarios where we don't need to request Diff Stats,
          # when caching for instance.
          @include_stats && diff_refs
        end

        def decorate_diff!(diff)
          return diff if diff.is_a?(File)

          stats = diff_stats_collection&.find_by_path(diff.new_path)

          diff_file = Gitlab::Diff::File.new(diff,
                                 repository: project.repository,
                                 diff_refs: diff_refs,
                                 fallback_diff_refs: fallback_diff_refs,
                                 stats: stats,
                                 max_blob_size: self.class.max_blob_size(project))

          if @use_extra_viewer_as_main && diff_file.has_renderable?
            diff_file.rendered
          else
            diff_file
          end
        end

        def sort_diffs(diffs)
          Gitlab::Diff::FileCollectionSorter.new(diffs).sort
        end

        def self.max_blob_size(_) = nil
      end
    end
  end
end