commits_helper.rb 7.1 KB
Newer Older
G
gitlabhq 已提交
1
module CommitsHelper
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  # 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

D
Dmitriy Zaporozhets 已提交
18
  def each_diff_line(diff, index)
S
skv-headless 已提交
19 20 21 22
    Gitlab::DiffParser.new(diff.diff.lines.to_a, diff.new_path)
      .each do |full_line, type, line_code, line_new, line_old|
        yield(full_line, type, line_code, line_new, line_old)
      end
23
  end
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
  def each_diff_line_near(diff, index, expected_line_code)
    max_number_of_lines = 16

    prev_match_line = nil
    prev_lines = []

    each_diff_line(diff, index) do |full_line, type, line_code, line_new, line_old|
      line = [full_line, type, line_code, line_new, line_old]
      if line_code != expected_line_code
        if type == "match"
          prev_lines.clear
          prev_match_line = line
        else
          prev_lines.push(line)
          prev_lines.shift if prev_lines.length >= max_number_of_lines
        end
      else
        yield(prev_match_line) if !prev_match_line.nil?
        prev_lines.each { |ln| yield(ln) }
        yield(line)
        break
      end
    end
  end

50 51
  def image_diff_class(diff)
    if diff.deleted_file
52
      "deleted"
53
    elsif diff.new_file
54
      "added"
55 56 57 58
    else
      nil
    end
  end
V
Valeriy Sizov 已提交
59

D
Dmitriy Zaporozhets 已提交
60 61 62
  def commit_to_html(commit, project, inline = true)
    template = inline ? "inline_commit" : "commit"
    escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil?
63
  end
64 65 66 67 68 69 70 71

  def diff_line_content(line)
    if line.blank?
      "  "
    else
      line
    end
  end
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

  # 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
      content_tag(:span, nil, class: 'arrow') +
      link_to(@project.name, project_commits_path(@project, @ref))
    end

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

      parts.each_with_index do |part, i|
87
        crumbs += content_tag(:span, ' / ', class: 'divider')
88 89 90 91 92 93 94 95 96 97
        crumbs += content_tag(:li) do
          # The text is just the individual part, but the link needs all the parts before it
          link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
        end
      end
    end

    crumbs.html_safe
  end

98 99 100 101 102 103 104 105 106 107 108
  # 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)
    branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe
  end

109 110 111 112 113 114 115 116 117 118 119
  def parallel_diff_lines(project, commit, diff, file)
    old_file = project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id
    deleted_lines = {}
    added_lines = {}
    each_diff_line(diff, 0) do |line, type, line_code, line_new, line_old|
      if type == "old"
        deleted_lines[line_old] = { line_code: line_code, type: type, line: line }
      elsif type == "new"
        added_lines[line_new]   = { line_code: line_code, type: type, line: line }
      end
    end
120
    max_length = old_file ? [old_file.loc, file.loc].max : file.loc
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

    offset1 = 0
    offset2 = 0
    old_lines = []
    new_lines = []

    max_length.times do |line_index|
      line_index1 = line_index - offset1
      line_index2 = line_index - offset2
      deleted_line = deleted_lines[line_index1 + 1]
      added_line = added_lines[line_index2 + 1]
      old_line = old_file.lines[line_index1] if old_file
      new_line = file.lines[line_index2]

      if deleted_line && added_line
      elsif deleted_line
        new_line = nil
        offset2 += 1
      elsif added_line
        old_line = nil
        offset1 += 1
      end

      old_lines[line_index] = DiffLine.new
      new_lines[line_index] = DiffLine.new

      # old
      if line_index == 0 && diff.new_file
        old_lines[line_index].type = :file_created
        old_lines[line_index].content = 'File was created'
      elsif deleted_line
        old_lines[line_index].type = :deleted
        old_lines[line_index].content = old_line
        old_lines[line_index].num = line_index1 + 1
        old_lines[line_index].code = deleted_line[:line_code]
      elsif old_line
        old_lines[line_index].type = :no_change
        old_lines[line_index].content = old_line
        old_lines[line_index].num = line_index1 + 1
      else
        old_lines[line_index].type = :added
      end

      # new
      if line_index == 0 && diff.deleted_file
        new_lines[line_index].type = :file_deleted
        new_lines[line_index].content = "File was deleted"
      elsif added_line
        new_lines[line_index].type = :added
        new_lines[line_index].num = line_index2 + 1
        new_lines[line_index].content = new_line
        new_lines[line_index].code = added_line[:line_code]
      elsif new_line
        new_lines[line_index].type = :no_change
        new_lines[line_index].num = line_index2 + 1
        new_lines[line_index].content = new_line
      else
        new_lines[line_index].type = :deleted
      end
    end

    return old_lines, new_lines
183 184
  end

185 186 187 188 189 190 191 192 193 194 195 196 197
  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 = {})
    source_name = commit.send "#{options[:source]}_name".to_sym
    source_email = commit.send "#{options[:source]}_email".to_sym
198 199 200 201 202
    
    user = User.find_for_commit(source_email, source_name)
    person_name = user.nil? ? source_name : user.name
    person_email = user.nil? ? source_email : user.email
    
203
    text = if options[:avatar]
204 205
            avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
            %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
206
          else
207
            person_name
208 209
          end

210 211 212 213 214
    options = {
      class: "commit-#{options[:source]}-link has_tooltip",
      data: { :'original-title' => sanitize(source_email) }
    }

215
    if user.nil?
216
      mail_to(source_email, text.html_safe, options)
217
    else
218
      link_to(text.html_safe, user_path(user), options)
219 220
    end
  end
G
gitlabhq 已提交
221
end