summaryrefslogtreecommitdiff
path: root/app/serializers/diffs_entity.rb
blob: 5b30c0bb58ccc7f43b64f84ce22280cd32e20c72 (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
# frozen_string_literal: true

class DiffsEntity < Grape::Entity
  include DiffHelper
  include RequestAwareEntity

  expose :real_size
  expose :size

  expose :branch_name do |diffs|
    merge_request&.source_branch
  end

  expose :source_branch_exists do |diffs|
    merge_request&.source_branch_exists?
  end

  expose :target_branch_name do |diffs|
    merge_request&.target_branch
  end

  expose :commit do |diffs, options|
    CommitEntity.represent(options[:commit], commit_options(options))
  end

  expose :context_commits, using: API::Entities::Commit do |diffs|
    options[:context_commits]
  end

  expose :merge_request_diff, using: MergeRequestDiffEntity do |diffs|
    options[:merge_request_diff]
  end

  expose :start_version, using: MergeRequestDiffEntity do |diffs|
    options[:start_version]
  end

  expose :latest_diff do |diffs|
    options[:latest_diff]
  end

  expose :latest_version_path, if: -> (*) { merge_request } do |diffs|
    diffs_project_merge_request_path(merge_request&.project, merge_request)
  end

  # rubocop: disable CodeReuse/ActiveRecord
  expose :added_lines do |diffs|
    diffs.raw_diff_files.sum(&:added_lines)
  end
  # rubocop: enable CodeReuse/ActiveRecord

  # rubocop: disable CodeReuse/ActiveRecord
  expose :removed_lines do |diffs|
    diffs.raw_diff_files.sum(&:removed_lines)
  end
  # rubocop: enable CodeReuse/ActiveRecord

  expose :render_overflow_warning do |diffs|
    render_overflow_warning?(diffs)
  end

  expose :email_patch_path, if: -> (*) { merge_request } do |diffs|
    merge_request_path(merge_request, format: :patch)
  end

  expose :plain_diff_path, if: -> (*) { merge_request } do |diffs|
    merge_request_path(merge_request, format: :diff)
  end

  expose :diff_files do |diffs, options|
    submodule_links = Gitlab::SubmoduleLinks.new(merge_request.project.repository)

    DiffFileEntity.represent(diffs.diff_files,
      options.merge(
        submodule_links: submodule_links,
        code_navigation_path: code_navigation_path(diffs),
        conflicts: conflicts(allow_tree_conflicts: true)
      )
    )
  end

  expose :merge_request_diffs, using: MergeRequestDiffEntity, if: -> (_, options) { options[:merge_request_diffs]&.any? } do |diffs|
    options[:merge_request_diffs]
  end

  expose :definition_path_prefix do |diffs|
    next unless merge_request.diff_head_sha

    project_blob_path(merge_request.project, merge_request.diff_head_sha)
  end

  expose :context_commits_diff do |diffs, options|
    next unless merge_request.context_commits_diff.commits_count > 0

    ContextCommitsDiffEntity.represent(
      merge_request.context_commits_diff,
      options
    )
  end

  def merge_request
    options[:merge_request]
  end

  private

  def commit_ids
    @commit_ids ||= merge_request.recent_commits.map(&:id)
  end

  def commit_neighbors(commit_id)
    index = commit_ids.index(commit_id)

    return [] unless index

    [(index > 0 ? commit_ids[index - 1] : nil), commit_ids[index + 1]]
  end

  def commit_options(options)
    next_commit_id, prev_commit_id = *commit_neighbors(options[:commit]&.id)

    options.merge(
      type: :full,
      commit_url_params: { merge_request_iid: merge_request&.iid },
      pipeline_ref: merge_request&.source_branch,
      pipeline_project: merge_request&.source_project,
      prev_commit_id: prev_commit_id,
      next_commit_id: next_commit_id
    )
  end
end