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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
class Commit
include ActiveModel::Conversion
include StaticModel
extend ActiveModel::Naming
include Mentionable
attr_mentionable :safe_message
# Safe amount of changes (files and lines) in one commit to render
# Used to prevent 500 error on huge commits by suppressing diff
#
# User can force display of diff above this size
DIFF_SAFE_FILES = 100
DIFF_SAFE_LINES = 5000
# Commits above this size will not be rendered in HTML
DIFF_HARD_LIMIT_FILES = 1000
DIFF_HARD_LIMIT_LINES = 50000
class << self
def decorate(commits)
commits.map do |commit|
if commit.kind_of?(Commit)
commit
else
self.new(commit)
end
end
end
# Calculate number of lines to render for diffs
def diff_line_count(diffs)
diffs.reduce(0) { |sum, d| sum + d.diff.lines.count }
end
# Truncate sha to 8 characters
def truncate_sha(sha)
sha[0..7]
end
end
attr_accessor :raw
def initialize(raw_commit)
raise "Nil as raw commit passed" unless raw_commit
@raw = raw_commit
end
def id
@raw.id
end
def diff_line_count
@diff_line_count ||= Commit::diff_line_count(self.diffs)
@diff_line_count
end
# 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.
# In case this first line is longer than 100 characters, it is cut off
# after 80 characters and ellipses (`&hellp;`) are appended.
def title
title = safe_message
return no_commit_message if title.blank?
title_end = title.index(/\n/)
if (!title_end && title.length > 100) || (title_end && title_end > 100)
title[0..79] << "…".html_safe
else
title.split(/\n/, 2).first
end
end
# Returns the commits description
#
# cut off, ellipses (`&hellp;`) are prepended to the commit message.
def description
title_end = safe_message.index(/\n/)
@description ||= if (!title_end && safe_message.length > 100) || (title_end && title_end > 100)
"…".html_safe << safe_message[80..-1]
else
safe_message.split(/\n/, 2)[1].try(:chomp)
end
end
def description?
description.present?
end
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
# Discover issues should be closed when this commit is pushed to a project's
# default branch.
def closes_issues(project)
Gitlab::ClosingIssueExtractor.closed_by_message_in_project(safe_message, project)
end
# Mentionable override.
def gfm_reference
"commit #{id}"
end
def method_missing(m, *args, &block)
@raw.send(m, *args, &block)
end
def respond_to?(method)
return true if @raw.respond_to?(method)
super
end
# Truncate sha to 8 characters
def short_id
@raw.short_id(7)
end
def parents
@parents ||= Commit.decorate(super)
end
end
|