BigW Consortium Gitlab

commit.rb 3.44 KB
Newer Older
1
class Commit
2
  include ActiveModel::Conversion
3
  include StaticModel
4
  extend ActiveModel::Naming
5 6 7
  include Mentionable

  attr_mentionable :safe_message
Saito committed
8

9
  # Safe amount of changes (files and lines) in one commit to render
10 11
  # Used to prevent 500 error on huge commits by suppressing diff
  #
12
  # User can force display of diff above this size
13 14
  DIFF_SAFE_FILES  = 100 unless defined?(DIFF_SAFE_FILES)
  DIFF_SAFE_LINES  = 5000 unless defined?(DIFF_SAFE_LINES)
15

16
  # Commits above this size will not be rendered in HTML
17 18
  DIFF_HARD_LIMIT_FILES = 1000 unless defined?(DIFF_HARD_LIMIT_FILES)
  DIFF_HARD_LIMIT_LINES = 50000 unless defined?(DIFF_HARD_LIMIT_LINES)
19

20 21
  class << self
    def decorate(commits)
22 23 24 25 26 27 28
      commits.map do |commit|
        if commit.kind_of?(Commit)
          commit
        else
          self.new(commit)
        end
      end
29
    end
30

31 32
    # Calculate number of lines to render for diffs
    def diff_line_count(diffs)
33
      diffs.reduce(0) { |sum, d| sum + d.diff.lines.count }
34
    end
35

36
    # Truncate sha to 8 characters
37
    def truncate_sha(sha)
38
      sha[0..7]
39
    end
40 41
  end

42
  attr_accessor :raw
43

44
  def initialize(raw_commit)
45 46
    raise "Nil as raw commit passed" unless raw_commit

47
    @raw = raw_commit
48
  end
49

50 51 52 53
  def id
    @raw.id
  end

54 55 56 57 58
  def diff_line_count
    @diff_line_count ||= Commit::diff_line_count(self.diffs)
    @diff_line_count
  end

59 60 61 62 63 64 65 66 67 68 69 70
  # Returns a string describing the commit for use in a link title
  #
  # Example
  #
  #   "Commit: Alex Denisov - Project git clone panel"
  def link_title
    "Commit: #{author_name} - #{title}"
  end

  # Returns the commits title.
  #
  # Usually, the commit title is the first line of the commit message.
71 72
  # In case this first line is longer than 100 characters, it is cut off
  # after 80 characters and ellipses (`&hellp;`) are appended.
73 74 75 76 77
  def title
    title = safe_message

    return no_commit_message if title.blank?

78
    title_end = title.index("\n")
79 80
    if (!title_end && title.length > 100) || (title_end && title_end > 100)
      title[0..79] << "&hellip;".html_safe
81
    else
82
      title.split("\n", 2).first
83 84 85 86 87 88 89
    end
  end

  # Returns the commits description
  #
  # cut off, ellipses (`&hellp;`) are prepended to the commit message.
  def description
90
    title_end = safe_message.index("\n")
91 92 93 94 95 96
    @description ||=
      if (!title_end && safe_message.length > 100) || (title_end && title_end > 100)
        "&hellip;".html_safe << safe_message[80..-1]
      else
        safe_message.split("\n", 2)[1].try(:chomp)
      end
97
  end
98

99 100
  def description?
    description.present?
101 102
  end

Kirill Zaitsev committed
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
  def hook_attrs(project)
    path_with_namespace = project.path_with_namespace

    {
      id: id,
      message: safe_message,
      timestamp: committed_date.xmlschema,
      url: "#{Gitlab.config.gitlab.url}/#{path_with_namespace}/commit/#{id}",
      author: {
        name: author_name,
        email: author_email
      }
    }
  end

118 119
  # Discover issues should be closed when this commit is pushed to a project's
  # default branch.
120
  def closes_issues(project)
121
    Gitlab::ClosingIssueExtractor.closed_by_message_in_project(safe_message, project)
122 123 124 125
  end

  # Mentionable override.
  def gfm_reference
126
    "commit #{id}"
127 128
  end

129 130
  def method_missing(m, *args, &block)
    @raw.send(m, *args, &block)
131
  end
132 133 134 135 136 137

  def respond_to?(method)
    return true if @raw.respond_to?(method)

    super
  end
138

139 140 141 142 143
  # Truncate sha to 8 characters
  def short_id
    @raw.short_id(7)
  end

144 145 146
  def parents
    @parents ||= Commit.decorate(super)
  end
147
end