git-commit-notifier 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.textile +20 -5
- data/Rakefile +40 -20
- data/VERSION +1 -1
- data/bin/git-commit-notifier +8 -1
- data/config/git-notifier-config.yml.sample +41 -15
- data/git-commit-notifier.gemspec +50 -24
- data/lib/commit_hook.rb +104 -74
- data/lib/diff_to_html.rb +120 -52
- data/lib/emailer.rb +43 -22
- data/lib/git.rb +36 -26
- data/lib/logger.rb +48 -0
- data/lib/result_processor.rb +9 -5
- data/{test → spec}/fixtures/existing_file_one_line.txt +0 -0
- data/{test → spec}/fixtures/git-notifier-group-email-by-push.yml +2 -0
- data/{test → spec}/fixtures/git-notifier-ignore-merge.yml +0 -0
- data/{test → spec}/fixtures/git-notifier-with-merge.yml +0 -0
- data/{test → spec}/fixtures/git_log +0 -0
- data/{test → spec}/fixtures/git_show_055850e7d925110322b8db4e17c3b840d76e144c +0 -0
- data/{test → spec}/fixtures/git_show_51b986619d88f7ba98be7d271188785cbbb541a0 +0 -0
- data/{test → spec}/fixtures/git_show_a4629e707d80a5769f7a71ca6ed9471015e14dc9 +0 -0
- data/{test → spec}/fixtures/git_show_dce6ade4cdc2833b53bd600ef10f9bce83c7102d +0 -0
- data/{test → spec}/fixtures/git_show_e28ad77bba0574241e6eb64dfd0c1291b221effe +0 -0
- data/spec/fixtures/git_show_ff037a73fc1094455e7bbf506171a3f3cf873ae6 +18 -0
- data/{test → spec}/fixtures/new_file_one_line.txt +0 -0
- data/spec/lib/commit_hook_spec.rb +88 -0
- data/spec/lib/diff_to_html_spec.rb +168 -0
- data/spec/lib/emailer_spec.rb +102 -0
- data/spec/lib/git_spec.rb +93 -0
- data/spec/lib/logger_spec.rb +63 -0
- data/spec/lib/result_processor_spec.rb +102 -0
- data/{test/test_helper.rb → spec/spec_helper.rb} +14 -12
- data/template/email.html.erb +2 -2
- data/template/styles.css +2 -1
- metadata +110 -31
- data/test/unit/test_commit_hook.rb +0 -43
- data/test/unit/test_diff_to_html.rb +0 -160
- data/test/unit/test_result_processor.rb +0 -95
data/lib/diff_to_html.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'diff/lcs'
|
3
|
+
require 'digest/sha1'
|
4
|
+
|
3
5
|
require File.dirname(__FILE__) + '/result_processor'
|
4
6
|
|
5
7
|
def escape_content(s)
|
@@ -10,16 +12,23 @@ class DiffToHtml
|
|
10
12
|
INTEGRATION_MAP = {
|
11
13
|
:mediawiki => { :search_for => /\[\[([^\[\]]+)\]\]/, :replace_with => '#{url}/\1' },
|
12
14
|
:redmine => { :search_for => /\b(?:refs|fixes)\s*\#(\d+)/i, :replace_with => '#{url}/issues/show/\1' },
|
13
|
-
:bugzilla => { :search_for => /\bBUG\s*(\d+)/i, :replace_with => '#{url}/show_bug.cgi?id=\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' }
|
14
17
|
}.freeze
|
15
|
-
|
18
|
+
MAX_COMMITS_PER_ACTION = 10000
|
19
|
+
HANDLED_COMMITS_FILE = 'previously.txt'.freeze
|
20
|
+
NEW_HANDLED_COMMITS_FILE = 'previously_new.txt'.freeze
|
21
|
+
|
16
22
|
attr_accessor :file_prefix, :current_file_name
|
17
|
-
attr_reader :result
|
23
|
+
attr_reader :result, :branch
|
18
24
|
|
19
25
|
def initialize(previous_dir = nil, config = nil)
|
20
26
|
@previous_dir = previous_dir
|
21
27
|
@config = config || {}
|
22
28
|
@lines_added = 0
|
29
|
+
@file_added = false
|
30
|
+
@file_removed = false
|
31
|
+
@binary = false
|
23
32
|
end
|
24
33
|
|
25
34
|
def range_info(range)
|
@@ -44,9 +53,17 @@ class DiffToHtml
|
|
44
53
|
end
|
45
54
|
end
|
46
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
|
+
|
47
65
|
def add_line_to_result(line, escape)
|
48
66
|
@lines_added += 1
|
49
|
-
lines_per_diff = @config['lines_per_diff']
|
50
67
|
if lines_per_diff
|
51
68
|
if @lines_added == lines_per_diff
|
52
69
|
@diff_result << '<tr><td colspan="3">Diff too large and stripped…</td></tr>'
|
@@ -62,7 +79,7 @@ class DiffToHtml
|
|
62
79
|
end
|
63
80
|
|
64
81
|
def extract_block_content(block)
|
65
|
-
block.collect { |b| b[:content]}.join("\n")
|
82
|
+
block.collect { |b| b[:content] }.join("\n")
|
66
83
|
end
|
67
84
|
|
68
85
|
def lcs_diff(removals, additions)
|
@@ -96,22 +113,22 @@ class DiffToHtml
|
|
96
113
|
end
|
97
114
|
|
98
115
|
def tokenize_string(str)
|
99
|
-
# tokenize by non-
|
116
|
+
# tokenize by non-word characters
|
100
117
|
tokens = []
|
101
118
|
token = ''
|
102
|
-
str
|
103
|
-
|
104
|
-
|
105
|
-
if !alphanumeric || str.size == i+1
|
106
|
-
token += char if alphanumeric
|
107
|
-
tokens << token unless token.empty?
|
108
|
-
tokens << char unless alphanumeric
|
109
|
-
token = ''
|
119
|
+
str.scan(/./mu) do |ch|
|
120
|
+
if ch =~ /[^\W_]/u
|
121
|
+
token += ch
|
110
122
|
else
|
111
|
-
token
|
123
|
+
unless token.empty?
|
124
|
+
tokens << token
|
125
|
+
token = ''
|
126
|
+
end
|
127
|
+
tokens << ch
|
112
128
|
end
|
113
129
|
end
|
114
|
-
|
130
|
+
tokens << token unless token.empty?
|
131
|
+
tokens
|
115
132
|
end
|
116
133
|
|
117
134
|
def operation_description
|
@@ -123,19 +140,31 @@ class DiffToHtml
|
|
123
140
|
else
|
124
141
|
op = "Changed"
|
125
142
|
end
|
126
|
-
|
143
|
+
|
127
144
|
file_name = @current_file_name
|
128
|
-
|
145
|
+
|
129
146
|
if (@config["link_files"] && @config["link_files"] == "gitweb" && @config["gitweb"])
|
130
147
|
file_name = "<a href='#{@config['gitweb']['path']}?p=#{@config['gitweb']['project']};f=#{file_name};hb=HEAD'>#{file_name}</a>"
|
131
148
|
elsif (@config["link_files"] && @config["link_files"] == "gitorious" && @config["gitorious"])
|
132
|
-
file_name = "<a href='#{@config['gitorious']['path']}/#{@config['gitorious']['project']}/#{@config['gitorious']['repository']}/blobs
|
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>"
|
133
152
|
end
|
134
|
-
|
153
|
+
|
135
154
|
header = "#{op} #{binary}file #{file_name}"
|
136
155
|
"<h2>#{header}</h2>\n"
|
137
156
|
end
|
138
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
|
+
|
139
168
|
def add_changes_to_result
|
140
169
|
return if @current_file_name.nil?
|
141
170
|
@diff_result << operation_description
|
@@ -143,12 +172,10 @@ class DiffToHtml
|
|
143
172
|
unless @diff_lines.empty?
|
144
173
|
removals = []
|
145
174
|
additions = []
|
146
|
-
@diff_lines.
|
147
|
-
if [:
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
if line[:op] == :unchanged || line == @diff_lines.last # unchanged line or end of block, add prev lines to result
|
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
|
152
179
|
if removals.size > 0 && additions.size > 0 # block of removed and added lines - perform intelligent diff
|
153
180
|
add_block_to_results(lcs_diff(removals, additions), escape = false)
|
154
181
|
else # some lines removed or added - no need to perform intelligent diff
|
@@ -156,6 +183,10 @@ class DiffToHtml
|
|
156
183
|
end
|
157
184
|
removals = []
|
158
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
|
159
190
|
add_line_to_result(line, escape = true) if line[:op] == :unchanged
|
160
191
|
end
|
161
192
|
end
|
@@ -179,8 +210,7 @@ class DiffToHtml
|
|
179
210
|
@current_file_name = nil
|
180
211
|
|
181
212
|
content.split("\n").each do |line|
|
182
|
-
if line =~ /^diff\s\-\-git
|
183
|
-
line.match(/diff --git a\/(.*)\sb\//)
|
213
|
+
if line =~ /^diff\s\-\-git\sa\/(.*)\sb\//
|
184
214
|
file_name = $1
|
185
215
|
add_changes_to_result
|
186
216
|
@current_file_name = file_name
|
@@ -200,7 +230,7 @@ class DiffToHtml
|
|
200
230
|
elsif op == '+'
|
201
231
|
@diff_lines << { :added => @right_ln, :removed => nil, :op => :addition, :content => line[1..-1] }
|
202
232
|
@right_ln += 1
|
203
|
-
else
|
233
|
+
else
|
204
234
|
@diff_lines << { :added => @right_ln, :removed => @left_ln, :op => :unchanged, :content => line }
|
205
235
|
@right_ln += 1
|
206
236
|
@left_ln += 1
|
@@ -229,7 +259,7 @@ class DiffToHtml
|
|
229
259
|
diff = []
|
230
260
|
diff_found = false
|
231
261
|
content.split("\n").each do |line|
|
232
|
-
diff_found = true if line =~ /^diff
|
262
|
+
diff_found = true if line =~ /^diff\s\-\-git/
|
233
263
|
next unless diff_found
|
234
264
|
diff << line
|
235
265
|
end
|
@@ -258,15 +288,14 @@ class DiffToHtml
|
|
258
288
|
end
|
259
289
|
|
260
290
|
def message_array_as_html(message)
|
261
|
-
message_map(message.collect { |m| CGI.escapeHTML(m)}.join(
|
291
|
+
message_map(message.collect { |m| CGI.escapeHTML(m) }.join('<br />'))
|
262
292
|
end
|
263
293
|
|
264
294
|
def author_name_and_email(info)
|
265
295
|
# input string format: "autor name <author@email.net>"
|
266
|
-
|
267
|
-
return result if result.is_a?(Array) && result.size == 2 # normal operation
|
296
|
+
return [$1, $2] if info =~ /^([^\<]+)\s+\<\s*(.*)\s*\>\s*$/ # normal operation
|
268
297
|
# incomplete author info - return it as author name
|
269
|
-
|
298
|
+
[info, '']
|
270
299
|
end
|
271
300
|
|
272
301
|
def first_sentence(message_array)
|
@@ -275,7 +304,48 @@ class DiffToHtml
|
|
275
304
|
msg
|
276
305
|
end
|
277
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
|
+
|
278
347
|
def diff_between_revisions(rev1, rev2, repo, branch)
|
348
|
+
@branch = branch
|
279
349
|
@result = []
|
280
350
|
if rev1 == rev2
|
281
351
|
commits = [rev1]
|
@@ -287,42 +357,36 @@ class DiffToHtml
|
|
287
357
|
commits = []
|
288
358
|
else
|
289
359
|
log = Git.log(rev1, rev2)
|
290
|
-
commits = log.scan(/^commit\s([a-f0-9]+)/).map{|
|
360
|
+
commits = log.scan(/^commit\s([a-f0-9]+)/).map { |a| a.first }
|
291
361
|
end
|
292
362
|
|
293
|
-
|
294
|
-
previous_list = []
|
295
|
-
else
|
296
|
-
previous_file = (!@previous_dir.nil? && File.exists?(@previous_dir)) ? File.join(@previous_dir, "previously.txt") : "/tmp/previously.txt"
|
297
|
-
previous_list = (File.read(previous_file).to_a.map {|sha| sha.chomp!} if File.exist?(previous_file)) || []
|
298
|
-
end
|
299
|
-
|
300
|
-
commits.reject!{|c| c.find{|sha| previous_list.include?(sha)} }
|
301
|
-
current_list = (previous_list + commits.flatten).last(1000)
|
302
|
-
File.open(previous_file, "w"){|f| f << current_list.join("\n") } unless current_list.empty? || defined?(Test::Unit)
|
363
|
+
commits = check_handled_commits(commits, branch)
|
303
364
|
|
304
365
|
commits.each_with_index do |commit, i|
|
305
|
-
|
366
|
+
|
306
367
|
raw_diff = Git.show(commit)
|
307
368
|
raise "git show output is empty" if raw_diff.empty?
|
308
|
-
@last_raw = raw_diff
|
309
369
|
|
310
370
|
commit_info = extract_commit_info_from_git_show_output(raw_diff)
|
311
371
|
|
312
372
|
title = "<div class=\"title\">"
|
313
373
|
title += "<strong>Message:</strong> #{message_array_as_html commit_info[:message]}<br />\n"
|
314
374
|
title += "<strong>Commit:</strong> "
|
315
|
-
|
375
|
+
|
316
376
|
if (@config["link_files"] && @config["link_files"] == "gitweb" && @config["gitweb"])
|
317
377
|
title += "<a href='#{@config['gitweb']['path']}?p=#{@config['gitweb']['project']};a=commitdiff;h=#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
318
378
|
elsif (@config["link_files"] && @config["link_files"] == "gitorious" && @config["gitorious"])
|
319
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>"
|
320
384
|
else
|
321
385
|
title += " #{commit_info[:commit]}"
|
322
386
|
end
|
323
|
-
|
387
|
+
|
324
388
|
title += "<br />\n"
|
325
|
-
|
389
|
+
|
326
390
|
title += "<strong>Branch:</strong> #{branch}\n<br />" unless branch =~ /\/head/
|
327
391
|
title += "<strong>Date:</strong> #{CGI.escapeHTML commit_info[:date]}\n<br />"
|
328
392
|
title += "<strong>Author:</strong> #{CGI.escapeHTML(commit_info[:author])} <#{commit_info[:email]}>\n</div>"
|
@@ -343,14 +407,14 @@ class DiffToHtml
|
|
343
407
|
end
|
344
408
|
|
345
409
|
def message_map(message)
|
346
|
-
if @config.
|
410
|
+
if @config['message_integration'].respond_to?(:each_pair)
|
347
411
|
@config['message_integration'].each_pair do |pm, url|
|
348
412
|
pm_def = DiffToHtml::INTEGRATION_MAP[pm.to_sym] or next
|
349
413
|
replace_with = pm_def[:replace_with].gsub('#{url}', url)
|
350
414
|
message_replace!(message, pm_def[:search_for], replace_with)
|
351
415
|
end
|
352
416
|
end
|
353
|
-
if @config.
|
417
|
+
if @config['message_map'].respond_to?(:each_pair)
|
354
418
|
@config['message_map'].each_pair do |search_for, replace_with|
|
355
419
|
message_replace!(message, Regexp.new(search_for), replace_with)
|
356
420
|
end
|
@@ -379,3 +443,7 @@ class DiffCallback
|
|
379
443
|
end
|
380
444
|
|
381
445
|
end
|
446
|
+
|
447
|
+
__END__
|
448
|
+
|
449
|
+
vim: tabstop=2:expandtab:shiftwidth=2
|
data/lib/emailer.rb
CHANGED
@@ -1,23 +1,42 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'erb'
|
3
1
|
require 'tamtam'
|
4
2
|
|
5
3
|
class Emailer
|
4
|
+
DEFAULT_STYLESHEET_PATH = File.join(File.dirname(__FILE__), '/../template/styles.css').freeze
|
5
|
+
TEMPLATE = File.join(File.dirname(__FILE__), '/../template/email.html.erb').freeze
|
6
|
+
PARAMETERS = %w[project_path recipient from_address from_alias subject text_message html_message ref_name old_rev new_rev].freeze
|
6
7
|
|
7
|
-
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
def initialize(config, options = {})
|
8
11
|
@config = config || {}
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
PARAMETERS.each do |name|
|
13
|
+
instance_variable_set("@#{name}".to_sym, options[name.to_sym])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def reset_template
|
19
|
+
@template = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def template
|
23
|
+
unless @template
|
24
|
+
source = IO.read(TEMPLATE)
|
25
|
+
begin
|
26
|
+
require 'erubis'
|
27
|
+
@template = Erubis::Eruby.new(source)
|
28
|
+
rescue LoadError
|
29
|
+
require 'erb'
|
30
|
+
@template = ERB.new(source)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
@template
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def generate_message
|
38
|
+
# TODO: do not use @html, simply return value
|
39
|
+
@html = TamTam.inline(:document => Emailer.template.result(binding))
|
21
40
|
end
|
22
41
|
|
23
42
|
def boundary
|
@@ -28,8 +47,8 @@ class Emailer
|
|
28
47
|
end
|
29
48
|
|
30
49
|
def stylesheet_string
|
31
|
-
stylesheet =
|
32
|
-
|
50
|
+
stylesheet = config['stylesheet'] || DEFAULT_STYLESHEET_PATH
|
51
|
+
IO.read(stylesheet)
|
33
52
|
end
|
34
53
|
|
35
54
|
def perform_delivery_smtp(content, smtp_settings)
|
@@ -38,12 +57,12 @@ class Emailer
|
|
38
57
|
val = smtp_settings[key].to_s.empty? ? nil : smtp_settings[key]
|
39
58
|
settings.merge!({ key => val})
|
40
59
|
end
|
41
|
-
|
60
|
+
|
42
61
|
Net::SMTP.start(settings['address'], settings['port'], settings['domain'],
|
43
62
|
settings['user_name'], settings['password'], settings['authentication']) do |smtp|
|
44
63
|
|
45
64
|
smtp.enable_tls if settings['enable_tls']
|
46
|
-
|
65
|
+
|
47
66
|
smtp.open_message_stream(@from_address, [@recipient]) do |f|
|
48
67
|
content.each do |line|
|
49
68
|
f.puts line
|
@@ -63,13 +82,15 @@ class Emailer
|
|
63
82
|
f.flush
|
64
83
|
end
|
65
84
|
end
|
66
|
-
|
85
|
+
|
67
86
|
def send
|
87
|
+
generate_message
|
68
88
|
from = quote_if_necessary(@from_alias.empty? ? @from_address : "#{@from_alias} <#{@from_address}>", 'utf-8')
|
69
89
|
content = ["From: #{from}",
|
70
90
|
"Reply-To: #{from}",
|
71
91
|
"To: #{quote_if_necessary(@recipient, 'utf-8')}",
|
72
92
|
"Subject: #{quote_if_necessary(@subject, 'utf-8')}",
|
93
|
+
"X-Mailer: git-commit-notifier",
|
73
94
|
"X-Git-Refname: #{@ref_name}",
|
74
95
|
"X-Git-Oldrev: #{@old_rev}",
|
75
96
|
"X-Git-Newrev: #{@new_rev}",
|
@@ -84,7 +105,7 @@ class Emailer
|
|
84
105
|
"Content-Type: text/html; charset=utf-8",
|
85
106
|
"Content-Transfer-Encoding: 8bit",
|
86
107
|
"Content-Disposition: inline\n\n\n",
|
87
|
-
@
|
108
|
+
@html,
|
88
109
|
"--#{boundary}--"]
|
89
110
|
|
90
111
|
if @recipient.empty?
|
@@ -92,7 +113,7 @@ class Emailer
|
|
92
113
|
return
|
93
114
|
end
|
94
115
|
|
95
|
-
if
|
116
|
+
if config['delivery_method'] == 'smtp'
|
96
117
|
perform_delivery_smtp(content, @config['smtp_server'])
|
97
118
|
else
|
98
119
|
perform_delivery_sendmail(content, @config['sendmail_options'])
|
data/lib/git.rb
CHANGED
@@ -1,35 +1,45 @@
|
|
1
1
|
class Git
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
class << self
|
3
|
+
def from_shell(cmd)
|
4
|
+
`#{cmd}`
|
5
|
+
end
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def show(rev)
|
8
|
+
from_shell("git show #{rev.strip} -w")
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
args << treeish
|
14
|
-
`git rev-list #{args.join(' ')}`.to_a.map{|commit| commit.chomp}
|
15
|
-
end
|
11
|
+
def log(rev1, rev2)
|
12
|
+
from_shell("git log #{rev1}..#{rev2}").strip
|
13
|
+
end
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def branch_commits(treeish)
|
16
|
+
args = Git.branch_heads - [ Git.branch_head(treeish) ]
|
17
|
+
args.map! { |tree| "^#{tree}" }
|
18
|
+
args << treeish
|
19
|
+
lines = from_shell("git rev-list #{args.join(' ')}")
|
20
|
+
lines = lines.lines if lines.respond_to?(:lines)
|
21
|
+
lines.to_a.map { |commit| commit.chomp }
|
22
|
+
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
def branch_heads
|
25
|
+
lines = from_shell("git rev-parse --branches")
|
26
|
+
lines = lines.lines if lines.respond_to?(:lines)
|
27
|
+
lines.to_a.map { |head| head.chomp }
|
28
|
+
end
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
dir_name = `pwd`.chomp.split("/").last.gsub(/\.git$/, '')
|
29
|
-
return "#{dir_name}"
|
30
|
-
end
|
30
|
+
def branch_head(treeish)
|
31
|
+
from_shell("git rev-parse #{treeish}").strip
|
32
|
+
end
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
+
def repo_name
|
35
|
+
git_prefix = from_shell("git config hooks.emailprefix").strip
|
36
|
+
return git_prefix unless git_prefix.empty?
|
37
|
+
Dir.pwd.split("/").last.sub(/\.git$/, '')
|
38
|
+
end
|
39
|
+
|
40
|
+
def mailing_list_address
|
41
|
+
from_shell("git config hooks.mailinglist").strip
|
42
|
+
end
|
34
43
|
end
|
35
44
|
end
|
45
|
+
|