commits_helper.rb 8.29 KB
Newer Older
1
# encoding: utf-8
gitlabhq's avatar
gitlabhq committed
2
module CommitsHelper
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  # Returns a link to the commit author. If the author has a matching user and
  # is a member of the current @project it will link to the team member page.
  # Otherwise it will link to the author email as specified in the commit.
  #
  # options:
  #  avatar: true will prepend the avatar image
  #  size:   size of the avatar image in px
  def commit_author_link(commit, options = {})
    commit_person_link(commit, options.merge(source: :author))
  end

  # Just like #author_link but for the committer.
  def commit_committer_link(commit, options = {})
    commit_person_link(commit, options.merge(source: :committer))
  end

Phil Hughes's avatar
Phil Hughes committed
19 20 21 22 23 24 25
  def commit_author_avatar(commit, options = {})
    options = options.merge(source: :author)
    user = commit.send(options[:source])

    source_email = clean(commit.send "#{options[:source]}_email".to_sym)
    person_email = user.try(:email) || source_email

Phil Hughes's avatar
Phil Hughes committed
26
    image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]} hidden-xs", width: options[:size], alt: "")
Phil Hughes's avatar
Phil Hughes committed
27 28
  end

29 30
  def image_diff_class(diff)
    if diff.deleted_file
31
      "deleted"
32
    elsif diff.new_file
33
      "added"
34 35 36 37
    else
      nil
    end
  end
38

39 40
  def commit_to_html(commit, project, inline = true)
    template = inline ? "inline_commit" : "commit"
41
    render "projects/commits/#{template}", commit: commit, project: project unless commit.nil?
42
  end
43

44 45 46 47 48 49
  # Breadcrumb links for a Project and, if applicable, a tree path
  def commits_breadcrumbs
    return unless @project && @ref

    # Add the root project link and the arrow icon
    crumbs = content_tag(:li) do
Vinnie Okada's avatar
Vinnie Okada committed
50 51 52 53
      link_to(
        @project.path,
        namespace_project_commits_path(@project.namespace, @project, @ref)
      )
54 55 56 57 58 59
    end

    if @path
      parts = @path.split('/')

      parts.each_with_index do |part, i|
60
        crumbs << content_tag(:li) do
61
          # The text is just the individual part, but the link needs all the parts before it
Vinnie Okada's avatar
Vinnie Okada committed
62 63 64 65 66 67 68 69
          link_to(
            part,
            namespace_project_commits_path(
              @project.namespace,
              @project,
              tree_join(@ref, parts[0..i].join('/'))
            )
          )
70 71 72 73 74 75 76
        end
      end
    end

    crumbs.html_safe
  end

77 78 79 80 81 82 83 84
  # Return Project default branch, if it present in array
  # Else - first branch in array (mb last actual branch)
  def commit_default_branch(project, branches)
    branches.include?(project.default_branch) ? branches.delete(project.default_branch) : branches.pop
  end

  # Returns the sorted alphabetically links to branches, separated by a comma
  def commit_branches_links(project, branches)
85
    branches.sort.map do |branch|
Vinnie Okada's avatar
Vinnie Okada committed
86 87 88
      link_to(
        namespace_project_tree_path(project.namespace, project, branch)
      ) do
89
        content_tag :span, class: 'label label-gray' do
90
          icon('code-fork') + ' ' + branch
91 92 93
        end
      end
    end.join(" ").html_safe
94 95
  end

96 97 98
  # Returns the sorted links to tags, separated by a comma
  def commit_tags_links(project, tags)
    sorted = VersionSorter.rsort(tags)
99
    sorted.map do |tag|
Vinnie Okada's avatar
Vinnie Okada committed
100 101 102 103
      link_to(
        namespace_project_commits_path(project.namespace, project,
                                       project.repository.find_tag(tag).name)
      ) do
104
        content_tag :span, class: 'label label-gray' do
105
          icon('tag') + ' ' + tag
106 107 108
        end
      end
    end.join(" ").html_safe
109 110
  end

111 112 113
  def link_to_browse_code(project, commit)
    if current_controller?(:projects, :commits)
      if @repo.blob_at(commit.id, @path)
Vinnie Okada's avatar
Vinnie Okada committed
114
        return link_to(
Phil Hughes's avatar
Phil Hughes committed
115
          "Browse File",
Vinnie Okada's avatar
Vinnie Okada committed
116 117
          namespace_project_blob_path(project.namespace, project,
                                      tree_join(commit.id, @path)),
Phil Hughes's avatar
Phil Hughes committed
118
          class: "btn btn-default"
Vinnie Okada's avatar
Vinnie Okada committed
119
        )
120
      elsif @path.present?
Vinnie Okada's avatar
Vinnie Okada committed
121
        return link_to(
Phil Hughes's avatar
Phil Hughes committed
122
          "Browse Directory",
Vinnie Okada's avatar
Vinnie Okada committed
123 124
          namespace_project_tree_path(project.namespace, project,
                                      tree_join(commit.id, @path)),
Phil Hughes's avatar
Phil Hughes committed
125
          class: "btn btn-default"
Vinnie Okada's avatar
Vinnie Okada committed
126
        )
127 128
      end
    end
Vinnie Okada's avatar
Vinnie Okada committed
129
    link_to(
130
      "Browse Files",
Vinnie Okada's avatar
Vinnie Okada committed
131
      namespace_project_tree_path(project.namespace, project, commit),
Phil Hughes's avatar
Phil Hughes committed
132
      class: "btn btn-default"
Vinnie Okada's avatar
Vinnie Okada committed
133
    )
134 135
  end

136
  def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
137 138
    return unless current_user

139
    tooltip = "Revert this #{commit.change_type_title} in a new merge request" if has_tooltip
140

141
    if can_collaborate_with_project?
142
      btn_class = "btn btn-warning btn-#{btn_class}" unless btn_class.nil?
143
      link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
144
    elsif can?(current_user, :fork_project, @project)
145 146 147 148 149 150
      continue_params = {
        to: continue_to_path,
        notice: edit_in_new_fork_notice + ' Try to revert this commit again.',
        notice_now: edit_in_new_fork_notice_now
      }
      fork_path = namespace_project_forks_path(@project.namespace, @project,
Rubén Dávila's avatar
Rubén Dávila committed
151 152
        namespace_key: current_user.namespace.id,
        continue: continue_params)
153

154
      btn_class = "btn btn-grouped btn-warning" unless btn_class.nil?
155 156

      link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
157 158 159
    end
  end

160
  def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
161 162 163 164 165
    return unless current_user

    tooltip = "Cherry-pick this #{commit.change_type_title} in a new merge request"

    if can_collaborate_with_project?
166
      btn_class = "btn btn-default btn-#{btn_class}" unless btn_class.nil?
167
      link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
168 169 170 171 172 173 174 175 176 177
    elsif can?(current_user, :fork_project, @project)
      continue_params = {
        to: continue_to_path,
        notice: edit_in_new_fork_notice + ' Try to cherry-pick this commit again.',
        notice_now: edit_in_new_fork_notice_now
      }
      fork_path = namespace_project_forks_path(@project.namespace, @project,
        namespace_key: current_user.namespace.id,
        continue: continue_params)

178 179
      btn_class = "btn btn-grouped btn-close" unless btn_class.nil?
      link_to 'Cherry-pick', fork_path, class: "#{btn_class}", method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
180
    end
181 182
  end

183 184 185 186 187 188 189 190 191 192 193
  protected

  # Private: Returns a link to a person. If the person has a matching user and
  # is a member of the current @project it will link to the team member page.
  # Otherwise it will link to the person email as specified in the commit.
  #
  # options:
  #  source: one of :author or :committer
  #  avatar: true will prepend the avatar image
  #  size:   size of the avatar image in px
  def commit_person_link(commit, options = {})
194
    user = commit.send(options[:source])
195

196 197
    source_name = clean(commit.send "#{options[:source]}_name".to_sym)
    source_email = clean(commit.send "#{options[:source]}_email".to_sym)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
198

199
    person_name = user.try(:name) || source_name
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
200

201 202
    text =
      if options[:avatar]
Phil Hughes's avatar
Phil Hughes committed
203
        %Q{<span class="commit-#{options[:source]}-name">#{person_name}</span>}
204 205 206
      else
        person_name
      end
207

208
    options = {
209
      class: "commit-#{options[:source]}-link has-tooltip",
210
      title: source_email
211 212
    }

213
    if user.nil?
214
      mail_to(source_email, text.html_safe, options)
215
    else
216
      link_to(text.html_safe, user_path(user), options)
217 218
    end
  end
219

skv's avatar
skv committed
220
  def view_file_btn(commit_sha, diff, project)
Vinnie Okada's avatar
Vinnie Okada committed
221 222 223
    link_to(
      namespace_project_blob_path(project.namespace, project,
                                  tree_join(commit_sha, diff.new_path)),
Annabel Dunstone's avatar
Annabel Dunstone committed
224
      class: 'btn view-file js-view-file btn-file-option'
Vinnie Okada's avatar
Vinnie Okada committed
225
    ) do
skv's avatar
skv committed
226 227 228 229
      raw('View file @') + content_tag(:span, commit_sha[0..6],
                                       class: 'commit-short-id')
    end
  end
230 231 232 233

  def truncate_sha(sha)
    Commit.truncate_sha(sha)
  end
234 235 236 237

  def clean(string)
    Sanitize.clean(string, remove_contents: true)
  end
238 239 240 241 242 243 244 245 246 247 248

  def limited_commits(commits)
    if commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
      [
        commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE),
        commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE
      ]
    else
      [commits, 0]
    end
  end
gitlabhq's avatar
gitlabhq committed
249
end