commit_controller.rb 4.47 KB
Newer Older
Robert Speicher's avatar
Robert Speicher committed
1 2 3
# Controller for a specific Commit
#
# Not to be confused with CommitsController, plural.
4
class Projects::CommitController < Projects::ApplicationController
5
  include CreatesCommit
6
  include DiffHelper
7

Robert Speicher's avatar
Robert Speicher committed
8
  # Authorize
9
  before_action :require_non_empty_project
10 11 12
  before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds]
  before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
  before_action :authorize_read_commit_status!, only: [:builds]
13
  before_action :commit
Kamil Trzcinski's avatar
Kamil Trzcinski committed
14
  before_action :define_show_vars, only: [:show, :builds]
15
  before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
Robert Speicher's avatar
Robert Speicher committed
16 17

  def show
18 19
    apply_diff_view_cookie!

20
    @grouped_diff_notes = commit.notes.grouped_diff_notes
Douwe Maan's avatar
Douwe Maan committed
21
    @notes = commit.notes.non_diff_notes.fresh
22

Douwe Maan's avatar
Douwe Maan committed
23 24 25 26 27
    Banzai::NoteRenderer.render(
      @grouped_diff_notes.values.flatten + @notes,
      @project,
      current_user,
    )
28

29
    @note = @project.build_commit_note(commit)
Douwe Maan's avatar
Douwe Maan committed
30

31
    @noteable = @commit
Douwe Maan's avatar
Douwe Maan committed
32
    @comments_target = {
33 34 35
      noteable_type: 'Commit',
      commit_id: @commit.id
    }
36 37

    respond_to do |format|
38
      format.html
39
      format.diff  { render text: @commit.to_diff }
40
      format.patch { render text: @commit.to_patch }
Robert Speicher's avatar
Robert Speicher committed
41 42
    end
  end
43

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
  def diff_for_path
    return git_not_found! unless commit

    opts = diff_options
    opts[:ignore_whitespace_change] = true if params[:format] == 'diff'

    diffs = commit.diffs(opts.merge(paths: [params[:path]]))
    diff_refs = [commit.parent || commit, commit]

    @comments_target = {
      noteable_type: 'Commit',
      commit_id: @commit.id
    }
    @grouped_diff_notes = {}

    render_diff_for_path(diffs, diff_refs, @project)
  end

Kamil Trzcinski's avatar
Kamil Trzcinski committed
62
  def builds
63 64
  end

65
  def cancel_builds
Kamil Trzcinski's avatar
Kamil Trzcinski committed
66
    ci_builds.running_or_pending.each(&:cancel)
67

Douwe Maan's avatar
Douwe Maan committed
68
    redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
69 70
  end

Kamil Trzcinski's avatar
Kamil Trzcinski committed
71
  def retry_builds
Kamil Trzcinski's avatar
Kamil Trzcinski committed
72
    ci_builds.latest.failed.each do |build|
Kamil Trzcinski's avatar
Kamil Trzcinski committed
73
      if build.retryable?
74
        Ci::Build.retry(build, current_user)
Kamil Trzcinski's avatar
Kamil Trzcinski committed
75 76 77
      end
    end

Douwe Maan's avatar
Douwe Maan committed
78
    redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
Kamil Trzcinski's avatar
Kamil Trzcinski committed
79
  end
80

81 82 83 84 85 86
  def branches
    @branches = @project.repository.branch_names_contains(commit.id)
    @tags = @project.repository.tag_names_contains(commit.id)
    render layout: false
  end

87
  def revert
88
    assign_change_commit_vars(@commit.revert_branch_name)
89

90
    return render_404 if @target_branch.blank?
91

92 93
    create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title} has been successfully reverted.",
                                          success_path: successful_change_path, failure_path: failed_change_path)
94
  end
95

96 97
  def cherry_pick
    assign_change_commit_vars(@commit.cherry_pick_branch_name)
98

99
    return render_404 if @target_branch.blank?
100

101 102
    create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.",
                                              success_path: successful_change_path, failure_path: failed_change_path)
103 104
  end

105 106 107
  private

  def successful_change_path
108 109 110 111 112
    return referenced_merge_request_url if @commit.merged_merge_request

    namespace_project_commits_url(@project.namespace, @project, @target_branch)
  end

113
  def failed_change_path
114 115 116 117 118 119 120 121 122
    return referenced_merge_request_url if @commit.merged_merge_request

    namespace_project_commit_url(@project.namespace, @project, params[:id])
  end

  def referenced_merge_request_url
    namespace_project_merge_request_url(@project.namespace, @project, @commit.merged_merge_request)
  end

123
  def commit
124
    @commit ||= @project.commit(params[:id])
125
  end
126

127 128
  def pipelines
    @pipelines ||= project.pipelines.where(sha: commit.sha)
Kamil Trzcinski's avatar
Kamil Trzcinski committed
129 130
  end

Kamil Trzcinski's avatar
Kamil Trzcinski committed
131
  def ci_builds
132
    @ci_builds ||= Ci::Build.where(pipeline: pipelines)
Kamil Trzcinski's avatar
Kamil Trzcinski committed
133 134 135
  end

  def define_show_vars
136 137
    return git_not_found! unless commit

138 139
    opts = diff_options
    opts[:ignore_whitespace_change] = true if params[:format] == 'diff'
140

141
    @diffs = commit.diffs(opts)
Kamil Trzcinski's avatar
Kamil Trzcinski committed
142
    @notes_count = commit.notes.count
Douwe Maan's avatar
Douwe Maan committed
143

144 145
    @statuses = CommitStatus.where(pipeline: pipelines)
    @builds = Ci::Build.where(pipeline: pipelines)
Kamil Trzcinski's avatar
Kamil Trzcinski committed
146
  end
147

148
  def assign_change_commit_vars(mr_source_branch)
149
    @commit = project.commit(params[:id])
150
    @target_branch = params[:target_branch]
151
    @mr_source_branch = mr_source_branch
152
    @mr_target_branch = @target_branch
153
    @commit_params = {
154 155
      commit: @commit,
      create_merge_request: params[:create_merge_request].present? || different_project?
156 157
    }
  end
Robert Speicher's avatar
Robert Speicher committed
158
end