git-commit-notifier 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +21 -0
- data/Gemfile.lock +105 -0
- data/README.textile +6 -1
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/bin/git-commit-notifier +3 -1
- data/config/git-notifier-config.yml.sample +28 -4
- data/git-commit-notifier.gemspec +81 -56
- data/lib/git_commit_notifier.rb +8 -0
- data/lib/git_commit_notifier/commit_hook.rb +130 -0
- data/lib/git_commit_notifier/diff_callback.rb +22 -0
- data/lib/git_commit_notifier/diff_to_html.rb +471 -0
- data/lib/{emailer.rb → git_commit_notifier/emailer.rb} +47 -31
- data/lib/git_commit_notifier/escape_helper.rb +5 -0
- data/lib/{git.rb → git_commit_notifier/git.rb} +1 -1
- data/lib/{logger.rb → git_commit_notifier/logger.rb} +1 -1
- data/lib/git_commit_notifier/result_processor.rb +131 -0
- data/spec/fixtures/git-notifier-with-branch-restrictions.yml +22 -0
- data/spec/lib/{commit_hook_spec.rb → git_commit_notifier/commit_hook_spec.rb} +37 -11
- data/spec/lib/{diff_to_html_spec.rb → git_commit_notifier/diff_to_html_spec.rb} +94 -16
- data/spec/lib/{emailer_spec.rb → git_commit_notifier/emailer_spec.rb} +9 -20
- data/spec/lib/{git_spec.rb → git_commit_notifier/git_spec.rb} +4 -6
- data/spec/lib/{logger_spec.rb → git_commit_notifier/logger_spec.rb} +4 -7
- data/spec/lib/{result_processor_spec.rb → git_commit_notifier/result_processor_spec.rb} +4 -2
- data/template/email.html.erb +1 -1
- metadata +150 -50
- data/.gitignore +0 -21
- data/lib/commit_hook.rb +0 -129
- data/lib/diff_to_html.rb +0 -449
- data/lib/result_processor.rb +0 -126
data/.gitignore
DELETED
data/lib/commit_hook.rb
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'yaml'
|
3
|
-
require 'cgi'
|
4
|
-
require 'net/smtp'
|
5
|
-
require 'digest/sha1'
|
6
|
-
|
7
|
-
require 'logger'
|
8
|
-
require 'diff_to_html'
|
9
|
-
require 'emailer'
|
10
|
-
require 'git'
|
11
|
-
|
12
|
-
class CommitHook
|
13
|
-
|
14
|
-
class << self
|
15
|
-
attr_reader :config
|
16
|
-
|
17
|
-
def show_error(message)
|
18
|
-
$stderr.puts "************** GIT NOTIFIER PROBLEM *******************"
|
19
|
-
$stderr.puts "\n"
|
20
|
-
$stderr.puts message
|
21
|
-
$stderr.puts "\n"
|
22
|
-
$stderr.puts "************** GIT NOTIFIER PROBLEM *******************"
|
23
|
-
end
|
24
|
-
|
25
|
-
def info(message)
|
26
|
-
$stdout.puts message
|
27
|
-
$stdout.flush
|
28
|
-
end
|
29
|
-
|
30
|
-
def logger
|
31
|
-
@logger ||= Logger.new(config)
|
32
|
-
end
|
33
|
-
|
34
|
-
def run(config_name, rev1, rev2, ref_name)
|
35
|
-
@config = File.exists?(config_name) ? YAML::load_file(config_name) : {}
|
36
|
-
|
37
|
-
project_path = Dir.getwd
|
38
|
-
recipient = config["mailinglist"] || Git.mailing_list_address
|
39
|
-
|
40
|
-
if recipient.nil? || recipient.length == 0
|
41
|
-
CommitHook.show_error(
|
42
|
-
"Please add a recipient for the emails. Eg : \n" +
|
43
|
-
" git config hooks.mailinglist developer@example.com"
|
44
|
-
)
|
45
|
-
return
|
46
|
-
end
|
47
|
-
|
48
|
-
logger.debug('----')
|
49
|
-
logger.debug("pwd: #{Dir.pwd}")
|
50
|
-
logger.debug("ref_name: #{ref_name}")
|
51
|
-
logger.debug("rev1: #{rev1}")
|
52
|
-
logger.debug("rev2: #{rev2}")
|
53
|
-
|
54
|
-
|
55
|
-
info("Sending mail...")
|
56
|
-
|
57
|
-
prefix = @config["emailprefix"] || Git.repo_name
|
58
|
-
branch_name = (ref_name =~ /master$/i) ? "" : "/#{ref_name.split("/").last}"
|
59
|
-
|
60
|
-
logger.debug("prefix: #{prefix}")
|
61
|
-
logger.debug("branch: #{branch_name}")
|
62
|
-
|
63
|
-
diff2html = DiffToHtml.new(Dir.pwd, config)
|
64
|
-
diff2html.diff_between_revisions(rev1, rev2, prefix, ref_name)
|
65
|
-
|
66
|
-
diffresult = diff2html.result
|
67
|
-
|
68
|
-
if config["ignore_merge"]
|
69
|
-
diffresult = diffresult.reject do |result|
|
70
|
-
!result[:commit_info][:merge].nil?
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
if config["group_email_by_push"]
|
75
|
-
text, html = [], []
|
76
|
-
diffresult.each_with_index do |result, i|
|
77
|
-
text << result[:text_content]
|
78
|
-
html << result[:html_content]
|
79
|
-
end
|
80
|
-
result = diffresult.first
|
81
|
-
return if result.nil? || !result[:commit_info]
|
82
|
-
|
83
|
-
emailer = Emailer.new(config,
|
84
|
-
:project_path => project_path,
|
85
|
-
:recipient => recipient,
|
86
|
-
:from_address => config["from"] || result[:commit_info][:email],
|
87
|
-
:from_alias => result[:commit_info][:author],
|
88
|
-
:subject => "[#{prefix}#{branch_name}] #{diffresult.size > 1 ? "#{diffresult.size} commits: " : ''}#{result[:commit_info][:message]}",
|
89
|
-
:text_message => text.join("------------------------------------------\n\n"),
|
90
|
-
:html_message => html.join("<hr /><br />"),
|
91
|
-
:old_rev => rev1,
|
92
|
-
:new_rev => rev2,
|
93
|
-
:ref_name => ref_name
|
94
|
-
)
|
95
|
-
emailer.send
|
96
|
-
else
|
97
|
-
diffresult.reverse.each_with_index do |result, i|
|
98
|
-
next unless result[:commit_info]
|
99
|
-
nr = number(diffresult.size, i)
|
100
|
-
|
101
|
-
emailer = Emailer.new(config,
|
102
|
-
:project_path => project_path,
|
103
|
-
:recipient => recipient,
|
104
|
-
:from_address => config["from"] || result[:commit_info][:email],
|
105
|
-
:from_alias => result[:commit_info][:author],
|
106
|
-
:subject => "[#{prefix}#{branch_name}]#{nr} #{result[:commit_info][:message]}",
|
107
|
-
:text_message => result[:text_content],
|
108
|
-
:html_message => result[:html_content],
|
109
|
-
:old_rev => rev1,
|
110
|
-
:new_rev => rev2,
|
111
|
-
:ref_name => ref_name
|
112
|
-
)
|
113
|
-
emailer.send
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def number(total_entries, i)
|
119
|
-
return '' if total_entries <= 1
|
120
|
-
digits = total_entries < 10 ? 1 : 3
|
121
|
-
'[' + sprintf("%0#{digits}d", i + 1) + ']'
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
__END__
|
127
|
-
|
128
|
-
vim: tabstop=2:expandtab:shiftwidth=2
|
129
|
-
|
data/lib/diff_to_html.rb
DELETED
@@ -1,449 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'diff/lcs'
|
3
|
-
require 'digest/sha1'
|
4
|
-
|
5
|
-
require File.dirname(__FILE__) + '/result_processor'
|
6
|
-
|
7
|
-
def escape_content(s)
|
8
|
-
CGI.escapeHTML(s).gsub(" ", " ")
|
9
|
-
end
|
10
|
-
|
11
|
-
class DiffToHtml
|
12
|
-
INTEGRATION_MAP = {
|
13
|
-
:mediawiki => { :search_for => /\[\[([^\[\]]+)\]\]/, :replace_with => '#{url}/\1' },
|
14
|
-
:redmine => { :search_for => /\b(?:refs|fixes)\s*\#(\d+)/i, :replace_with => '#{url}/issues/show/\1' },
|
15
|
-
:bugzilla => { :search_for => /\bBUG\s*(\d+)/i, :replace_with => '#{url}/show_bug.cgi?id=\1' },
|
16
|
-
:fogbugz => { :search_for => /\bbugzid:\s*(\d+)/i, :replace_with => '#{url}\1' }
|
17
|
-
}.freeze
|
18
|
-
MAX_COMMITS_PER_ACTION = 10000
|
19
|
-
HANDLED_COMMITS_FILE = 'previously.txt'.freeze
|
20
|
-
NEW_HANDLED_COMMITS_FILE = 'previously_new.txt'.freeze
|
21
|
-
|
22
|
-
attr_accessor :file_prefix, :current_file_name
|
23
|
-
attr_reader :result, :branch
|
24
|
-
|
25
|
-
def initialize(previous_dir = nil, config = nil)
|
26
|
-
@previous_dir = previous_dir
|
27
|
-
@config = config || {}
|
28
|
-
@lines_added = 0
|
29
|
-
@file_added = false
|
30
|
-
@file_removed = false
|
31
|
-
@binary = false
|
32
|
-
end
|
33
|
-
|
34
|
-
def range_info(range)
|
35
|
-
matches = range.match(/^@@ \-(\S+) \+(\S+)/)
|
36
|
-
return matches[1..2].map { |m| m.split(',')[0].to_i }
|
37
|
-
end
|
38
|
-
|
39
|
-
def line_class(line)
|
40
|
-
if line[:op] == :removal
|
41
|
-
return " class=\"r\""
|
42
|
-
elsif line[:op] == :addition
|
43
|
-
return " class=\"a\""
|
44
|
-
else
|
45
|
-
return ''
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def add_block_to_results(block, escape)
|
50
|
-
return if block.empty?
|
51
|
-
block.each do |line|
|
52
|
-
add_line_to_result(line, escape)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def lines_per_diff
|
57
|
-
@config['lines_per_diff']
|
58
|
-
end
|
59
|
-
|
60
|
-
def add_separator
|
61
|
-
return if lines_per_diff && @lines_added >= lines_per_diff
|
62
|
-
@diff_result << '<tr class="sep"><td class="sep" colspan="3" title="Unchanged content skipped between diff. blocks">…</td></tr>'
|
63
|
-
end
|
64
|
-
|
65
|
-
def add_line_to_result(line, escape)
|
66
|
-
@lines_added += 1
|
67
|
-
if lines_per_diff
|
68
|
-
if @lines_added == lines_per_diff
|
69
|
-
@diff_result << '<tr><td colspan="3">Diff too large and stripped…</td></tr>'
|
70
|
-
end
|
71
|
-
if @lines_added >= lines_per_diff
|
72
|
-
return
|
73
|
-
end
|
74
|
-
end
|
75
|
-
klass = line_class(line)
|
76
|
-
content = escape ? escape_content(line[:content]) : line[:content]
|
77
|
-
padding = ' ' if klass != ''
|
78
|
-
@diff_result << "<tr#{klass}>\n<td class=\"ln\">#{line[:removed]}</td>\n<td class=\"ln\">#{line[:added]}</td>\n<td>#{padding}#{content}</td></tr>"
|
79
|
-
end
|
80
|
-
|
81
|
-
def extract_block_content(block)
|
82
|
-
block.collect { |b| b[:content] }.join("\n")
|
83
|
-
end
|
84
|
-
|
85
|
-
def lcs_diff(removals, additions)
|
86
|
-
# arrays always have at least 1 element
|
87
|
-
callback = DiffCallback.new
|
88
|
-
|
89
|
-
s1 = extract_block_content(removals)
|
90
|
-
s2 = extract_block_content(additions)
|
91
|
-
|
92
|
-
s1 = tokenize_string(s1)
|
93
|
-
s2 = tokenize_string(s2)
|
94
|
-
|
95
|
-
Diff::LCS.traverse_balanced(s1, s2, callback)
|
96
|
-
|
97
|
-
processor = ResultProcessor.new(callback.tags)
|
98
|
-
|
99
|
-
diff_for_removals, diff_for_additions = processor.results
|
100
|
-
result = []
|
101
|
-
|
102
|
-
ln_start = removals[0][:removed]
|
103
|
-
diff_for_removals.each_with_index do |line, i|
|
104
|
-
result << { :removed => ln_start + i, :added => nil, :op => :removal, :content => line}
|
105
|
-
end
|
106
|
-
|
107
|
-
ln_start = additions[0][:added]
|
108
|
-
diff_for_additions.each_with_index do |line, i|
|
109
|
-
result << { :removed => nil, :added => ln_start + i, :op => :addition, :content => line}
|
110
|
-
end
|
111
|
-
|
112
|
-
result
|
113
|
-
end
|
114
|
-
|
115
|
-
def tokenize_string(str)
|
116
|
-
# tokenize by non-word characters
|
117
|
-
tokens = []
|
118
|
-
token = ''
|
119
|
-
str.scan(/./mu) do |ch|
|
120
|
-
if ch =~ /[^\W_]/u
|
121
|
-
token += ch
|
122
|
-
else
|
123
|
-
unless token.empty?
|
124
|
-
tokens << token
|
125
|
-
token = ''
|
126
|
-
end
|
127
|
-
tokens << ch
|
128
|
-
end
|
129
|
-
end
|
130
|
-
tokens << token unless token.empty?
|
131
|
-
tokens
|
132
|
-
end
|
133
|
-
|
134
|
-
def operation_description
|
135
|
-
binary = @binary ? 'binary ' : ''
|
136
|
-
if @file_removed
|
137
|
-
op = "Deleted"
|
138
|
-
elsif @file_added
|
139
|
-
op = "Added"
|
140
|
-
else
|
141
|
-
op = "Changed"
|
142
|
-
end
|
143
|
-
|
144
|
-
file_name = @current_file_name
|
145
|
-
|
146
|
-
if (@config["link_files"] && @config["link_files"] == "gitweb" && @config["gitweb"])
|
147
|
-
file_name = "<a href='#{@config['gitweb']['path']}?p=#{@config['gitweb']['project']};f=#{file_name};hb=HEAD'>#{file_name}</a>"
|
148
|
-
elsif (@config["link_files"] && @config["link_files"] == "gitorious" && @config["gitorious"])
|
149
|
-
file_name = "<a href='#{@config['gitorious']['path']}/#{@config['gitorious']['project']}/#{@config['gitorious']['repository']}/blobs/#{branch}/#{file_name}'>#{file_name}</a>"
|
150
|
-
elsif (@config["link_files"] && @config["link_files"] == "cgit" && @config["cgit"])
|
151
|
-
file_name = "<a href='#{@config['cgit']['path']}/#{@config['cgit']['project']}/tree/#{file_name}'>#{file_name}</a>"
|
152
|
-
end
|
153
|
-
|
154
|
-
header = "#{op} #{binary}file #{file_name}"
|
155
|
-
"<h2>#{header}</h2>\n"
|
156
|
-
end
|
157
|
-
|
158
|
-
def lines_are_sequential?(first, second)
|
159
|
-
result = false
|
160
|
-
[:added, :removed].each do |side|
|
161
|
-
if !first[side].nil? && !second[side].nil?
|
162
|
-
result = true if first[side] == (second[side] - 1)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
result
|
166
|
-
end
|
167
|
-
|
168
|
-
def add_changes_to_result
|
169
|
-
return if @current_file_name.nil?
|
170
|
-
@diff_result << operation_description
|
171
|
-
@diff_result << '<table>'
|
172
|
-
unless @diff_lines.empty?
|
173
|
-
removals = []
|
174
|
-
additions = []
|
175
|
-
@diff_lines.each_with_index do |line, index|
|
176
|
-
removals << line if line[:op] == :removal
|
177
|
-
additions << line if line[:op] == :addition
|
178
|
-
if line[:op] == :unchanged || index == @diff_lines.size - 1 # unchanged line or end of block, add prev lines to result
|
179
|
-
if removals.size > 0 && additions.size > 0 # block of removed and added lines - perform intelligent diff
|
180
|
-
add_block_to_results(lcs_diff(removals, additions), escape = false)
|
181
|
-
else # some lines removed or added - no need to perform intelligent diff
|
182
|
-
add_block_to_results(removals + additions, escape = true)
|
183
|
-
end
|
184
|
-
removals = []
|
185
|
-
additions = []
|
186
|
-
if index > 0 && index != @diff_lines.size - 1
|
187
|
-
prev_line = @diff_lines[index - 1]
|
188
|
-
add_separator unless lines_are_sequential?(prev_line, line)
|
189
|
-
end
|
190
|
-
add_line_to_result(line, escape = true) if line[:op] == :unchanged
|
191
|
-
end
|
192
|
-
end
|
193
|
-
@diff_lines = []
|
194
|
-
@diff_result << '</table>'
|
195
|
-
end
|
196
|
-
# reset values
|
197
|
-
@right_ln = nil
|
198
|
-
@left_ln = nil
|
199
|
-
@file_added = false
|
200
|
-
@file_removed = false
|
201
|
-
@binary = false
|
202
|
-
end
|
203
|
-
|
204
|
-
def diff_for_revision(content)
|
205
|
-
@left_ln = @right_ln = nil
|
206
|
-
|
207
|
-
@diff_result = []
|
208
|
-
@diff_lines = []
|
209
|
-
@removed_files = []
|
210
|
-
@current_file_name = nil
|
211
|
-
|
212
|
-
content.split("\n").each do |line|
|
213
|
-
if line =~ /^diff\s\-\-git\sa\/(.*)\sb\//
|
214
|
-
file_name = $1
|
215
|
-
add_changes_to_result
|
216
|
-
@current_file_name = file_name
|
217
|
-
end
|
218
|
-
|
219
|
-
op = line[0,1]
|
220
|
-
@left_ln.nil? || op == '@' ? process_info_line(line, op) : process_code_line(line, op)
|
221
|
-
end
|
222
|
-
add_changes_to_result
|
223
|
-
@diff_result.join("\n")
|
224
|
-
end
|
225
|
-
|
226
|
-
def process_code_line(line, op)
|
227
|
-
if op == '-'
|
228
|
-
@diff_lines << { :removed => @left_ln, :added => nil, :op => :removal, :content => line[1..-1] }
|
229
|
-
@left_ln += 1
|
230
|
-
elsif op == '+'
|
231
|
-
@diff_lines << { :added => @right_ln, :removed => nil, :op => :addition, :content => line[1..-1] }
|
232
|
-
@right_ln += 1
|
233
|
-
else
|
234
|
-
@diff_lines << { :added => @right_ln, :removed => @left_ln, :op => :unchanged, :content => line }
|
235
|
-
@right_ln += 1
|
236
|
-
@left_ln += 1
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def process_info_line(line, op)
|
241
|
-
if line =~/^deleted\sfile\s/
|
242
|
-
@file_removed = true
|
243
|
-
elsif line =~ /^\-\-\-\s/ && line =~ /\/dev\/null/
|
244
|
-
@file_added = true
|
245
|
-
elsif line =~ /^\+\+\+\s/ && line =~ /\/dev\/null/
|
246
|
-
@file_removed = true
|
247
|
-
elsif line =~ /^Binary files \/dev\/null/ # Binary files /dev/null and ... differ (addition)
|
248
|
-
@binary = true
|
249
|
-
@file_added = true
|
250
|
-
elsif line =~ /\/dev\/null differ/ # Binary files ... and /dev/null differ (removal)
|
251
|
-
@binary = true
|
252
|
-
@file_removed = true
|
253
|
-
elsif op == '@'
|
254
|
-
@left_ln, @right_ln = range_info(line)
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
def extract_diff_from_git_show_output(content)
|
259
|
-
diff = []
|
260
|
-
diff_found = false
|
261
|
-
content.split("\n").each do |line|
|
262
|
-
diff_found = true if line =~ /^diff\s\-\-git/
|
263
|
-
next unless diff_found
|
264
|
-
diff << line
|
265
|
-
end
|
266
|
-
diff.join("\n")
|
267
|
-
end
|
268
|
-
|
269
|
-
def extract_commit_info_from_git_show_output(content)
|
270
|
-
result = { :message => [], :commit => '', :author => '', :date => '', :email => '' }
|
271
|
-
content.split("\n").each do |line|
|
272
|
-
if line =~ /^diff/ # end of commit info, return results
|
273
|
-
return result
|
274
|
-
elsif line =~ /^commit/
|
275
|
-
result[:commit] = line[7..-1]
|
276
|
-
elsif line =~ /^Author/
|
277
|
-
result[:author], result[:email] = author_name_and_email(line[8..-1])
|
278
|
-
elsif line =~ /^Date/
|
279
|
-
result[:date] = line[8..-1]
|
280
|
-
elsif line =~ /^Merge/
|
281
|
-
result[:merge] = line[8..-1]
|
282
|
-
else
|
283
|
-
clean_line = line.strip
|
284
|
-
result[:message] << clean_line unless clean_line.empty?
|
285
|
-
end
|
286
|
-
end
|
287
|
-
result
|
288
|
-
end
|
289
|
-
|
290
|
-
def message_array_as_html(message)
|
291
|
-
message_map(message.collect { |m| CGI.escapeHTML(m) }.join('<br />'))
|
292
|
-
end
|
293
|
-
|
294
|
-
def author_name_and_email(info)
|
295
|
-
# input string format: "autor name <author@email.net>"
|
296
|
-
return [$1, $2] if info =~ /^([^\<]+)\s+\<\s*(.*)\s*\>\s*$/ # normal operation
|
297
|
-
# incomplete author info - return it as author name
|
298
|
-
[info, '']
|
299
|
-
end
|
300
|
-
|
301
|
-
def first_sentence(message_array)
|
302
|
-
msg = message_array.first.to_s.strip
|
303
|
-
return message_array.first if msg.empty? || msg =~ /^Merge\:/
|
304
|
-
msg
|
305
|
-
end
|
306
|
-
|
307
|
-
def unique_commits_per_branch?
|
308
|
-
!!@config['unique_commits_per_branch']
|
309
|
-
end
|
310
|
-
|
311
|
-
def get_previous_commits(previous_file)
|
312
|
-
previous_list = []
|
313
|
-
if File.exists?(previous_file)
|
314
|
-
lines = IO.read(previous_file)
|
315
|
-
lines = lines.lines if lines.respond_to?(:lines) # Ruby 1.9 tweak
|
316
|
-
previous_list = lines.to_a.map { |s| s.chomp }.compact.uniq
|
317
|
-
lines = nil
|
318
|
-
end
|
319
|
-
previous_list
|
320
|
-
end
|
321
|
-
|
322
|
-
def check_handled_commits(commits, branch)
|
323
|
-
previous_dir = (!@previous_dir.nil? && File.exists?(@previous_dir)) ? @previous_dir : '/tmp'
|
324
|
-
prefix = unique_commits_per_branch? ? "#{Digest::SHA1.hexdigest(branch)}." : ''
|
325
|
-
previous_name = "#{prefix}#{HANDLED_COMMITS_FILE}"
|
326
|
-
new_name = "#{prefix}#{NEW_HANDLED_COMMITS_FILE}"
|
327
|
-
previous_file = File.join(previous_dir, previous_name)
|
328
|
-
new_file = File.join(previous_dir, new_name)
|
329
|
-
|
330
|
-
previous_list = get_previous_commits(previous_file)
|
331
|
-
|
332
|
-
commits.reject! {|c| c.find { |sha| previous_list.include?(sha) } }
|
333
|
-
|
334
|
-
# if commit list empty there is no need to override list of handled commits
|
335
|
-
flatten_commits = commits.flatten
|
336
|
-
unless flatten_commits.empty?
|
337
|
-
current_list = (previous_list + flatten_commits).last(MAX_COMMITS_PER_ACTION)
|
338
|
-
|
339
|
-
# use new file, unlink and rename to make it more atomic
|
340
|
-
File.open(new_file, 'w') { |f| f << current_list.join("\n") }
|
341
|
-
File.unlink(previous_file) if File.exists?(previous_file)
|
342
|
-
File.rename(new_file, previous_file)
|
343
|
-
end
|
344
|
-
commits
|
345
|
-
end
|
346
|
-
|
347
|
-
def diff_between_revisions(rev1, rev2, repo, branch)
|
348
|
-
@branch = branch
|
349
|
-
@result = []
|
350
|
-
if rev1 == rev2
|
351
|
-
commits = [rev1]
|
352
|
-
elsif rev1 =~ /^0+$/
|
353
|
-
# creating a new remote branch
|
354
|
-
commits = Git.branch_commits(branch)
|
355
|
-
elsif rev2 =~ /^0+$/
|
356
|
-
# deleting an existing remote branch
|
357
|
-
commits = []
|
358
|
-
else
|
359
|
-
log = Git.log(rev1, rev2)
|
360
|
-
commits = log.scan(/^commit\s([a-f0-9]+)/).map { |a| a.first }
|
361
|
-
end
|
362
|
-
|
363
|
-
commits = check_handled_commits(commits, branch)
|
364
|
-
|
365
|
-
commits.each_with_index do |commit, i|
|
366
|
-
|
367
|
-
raw_diff = Git.show(commit)
|
368
|
-
raise "git show output is empty" if raw_diff.empty?
|
369
|
-
|
370
|
-
commit_info = extract_commit_info_from_git_show_output(raw_diff)
|
371
|
-
|
372
|
-
title = "<div class=\"title\">"
|
373
|
-
title += "<strong>Message:</strong> #{message_array_as_html commit_info[:message]}<br />\n"
|
374
|
-
title += "<strong>Commit:</strong> "
|
375
|
-
|
376
|
-
if (@config["link_files"] && @config["link_files"] == "gitweb" && @config["gitweb"])
|
377
|
-
title += "<a href='#{@config['gitweb']['path']}?p=#{@config['gitweb']['project']};a=commitdiff;h=#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
378
|
-
elsif (@config["link_files"] && @config["link_files"] == "gitorious" && @config["gitorious"])
|
379
|
-
title += "<a href='#{@config['gitorious']['path']}/#{@config['gitorious']['project']}/#{@config['gitorious']['repository']}/commit/#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
380
|
-
elsif (@config["link_files"] && @config["link_files"] == "trac" && @config["trac"])
|
381
|
-
title += "<a href='#{@config['trac']['path']}/#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
382
|
-
elsif (@config["link_files"] && @config["link_files"] == "cgit" && @config["cgit"])
|
383
|
-
title += "<a href='#{@config['cgit']['path']}/#{@config['cgit']['project']}/commit/?id=#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
384
|
-
else
|
385
|
-
title += " #{commit_info[:commit]}"
|
386
|
-
end
|
387
|
-
|
388
|
-
title += "<br />\n"
|
389
|
-
|
390
|
-
title += "<strong>Branch:</strong> #{branch}\n<br />" unless branch =~ /\/head/
|
391
|
-
title += "<strong>Date:</strong> #{CGI.escapeHTML commit_info[:date]}\n<br />"
|
392
|
-
title += "<strong>Author:</strong> #{CGI.escapeHTML(commit_info[:author])} <#{commit_info[:email]}>\n</div>"
|
393
|
-
|
394
|
-
text = "#{raw_diff}\n\n\n"
|
395
|
-
|
396
|
-
html = title
|
397
|
-
html += diff_for_revision(extract_diff_from_git_show_output(raw_diff))
|
398
|
-
html += "<br /><br />"
|
399
|
-
commit_info[:message] = first_sentence(commit_info[:message])
|
400
|
-
@result << {:commit_info => commit_info, :html_content => html, :text_content => text }
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
def message_replace!(message, search_for, replace_with)
|
405
|
-
full_replace_with = "<a href=\"#{replace_with}\">\\0</a>"
|
406
|
-
message.gsub!(Regexp.new(search_for), full_replace_with)
|
407
|
-
end
|
408
|
-
|
409
|
-
def message_map(message)
|
410
|
-
if @config['message_integration'].respond_to?(:each_pair)
|
411
|
-
@config['message_integration'].each_pair do |pm, url|
|
412
|
-
pm_def = DiffToHtml::INTEGRATION_MAP[pm.to_sym] or next
|
413
|
-
replace_with = pm_def[:replace_with].gsub('#{url}', url)
|
414
|
-
message_replace!(message, pm_def[:search_for], replace_with)
|
415
|
-
end
|
416
|
-
end
|
417
|
-
if @config['message_map'].respond_to?(:each_pair)
|
418
|
-
@config['message_map'].each_pair do |search_for, replace_with|
|
419
|
-
message_replace!(message, Regexp.new(search_for), replace_with)
|
420
|
-
end
|
421
|
-
end
|
422
|
-
message
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
class DiffCallback
|
427
|
-
attr_reader :tags
|
428
|
-
|
429
|
-
def initialize
|
430
|
-
@tags = []
|
431
|
-
end
|
432
|
-
|
433
|
-
def match(event)
|
434
|
-
@tags << { :action => :match, :token => event.old_element }
|
435
|
-
end
|
436
|
-
|
437
|
-
def discard_b(event)
|
438
|
-
@tags << { :action => :discard_b, :token => event.new_element }
|
439
|
-
end
|
440
|
-
|
441
|
-
def discard_a(event)
|
442
|
-
@tags << { :action => :discard_a, :token => event.old_element }
|
443
|
-
end
|
444
|
-
|
445
|
-
end
|
446
|
-
|
447
|
-
__END__
|
448
|
-
|
449
|
-
vim: tabstop=2:expandtab:shiftwidth=2
|