git-commit-notifier 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|