git-commit-notifier 0.11.0 → 0.11.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -14
- data/VERSION +1 -1
- data/config/git-notifier-config.example.yml +15 -3
- data/git-commit-notifier.gemspec +1 -1
- data/lib/git_commit_notifier.rb +2 -0
- data/lib/git_commit_notifier/commit_hook.rb +37 -24
- data/lib/git_commit_notifier/diff_callback.rb +2 -0
- data/lib/git_commit_notifier/diff_to_html.rb +212 -114
- data/lib/git_commit_notifier/emailer.rb +9 -5
- data/lib/git_commit_notifier/escape_helper.rb +13 -1
- data/lib/git_commit_notifier/executor.rb +11 -4
- data/lib/git_commit_notifier/git.rb +65 -1
- data/lib/git_commit_notifier/logger.rb +2 -0
- data/lib/git_commit_notifier/result_processor.rb +2 -0
- data/local-run.rb +1 -0
- data/spec/lib/git_commit_notifier/commit_hook_spec.rb +5 -1
- data/spec/lib/git_commit_notifier/diff_to_html_spec.rb +18 -40
- data/spec/lib/git_commit_notifier/emailer_spec.rb +2 -0
- data/spec/lib/git_commit_notifier/git_spec.rb +4 -2
- data/spec/lib/git_commit_notifier/logger_spec.rb +2 -0
- data/spec/lib/git_commit_notifier/result_processor_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- data/template/styles.css +4 -1
- metadata +30 -30
data/README.md
CHANGED
@@ -88,10 +88,7 @@ More examples can be found in the config file.
|
|
88
88
|
|
89
89
|
## Logic of commits handling
|
90
90
|
|
91
|
-
|
92
|
-
handled commits to not send repeated messages about commits.
|
93
|
-
|
94
|
-
By default all commits are tracked through the whole repository so after a merge
|
91
|
+
By default all commits are tracked through the whole repository so after a merge
|
95
92
|
you should not receive messages about those commits already posted in other branches.
|
96
93
|
|
97
94
|
This behaviour can be changed using unique\_commits\_per\_branch option. When it's true,
|
@@ -110,16 +107,6 @@ old commits in processes of forking, branching etc.
|
|
110
107
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
111
108
|
* Send me a pull request. Bonus points for topic branches.
|
112
109
|
|
113
|
-
## Troubleshooting
|
114
|
-
|
115
|
-
### Permission denied - /var/git/repo/previously.txt (Errno::EACCES)
|
116
|
-
|
117
|
-
The file _previously.txt_ is created at the first commit. If you moved the file to the server, you have to check the rights to that file and fix them if needed. The git repo owner needs the right to write into that file.
|
118
|
-
|
119
|
-
### Empty html on ruby 1.8.7
|
120
|
-
|
121
|
-
Check <code>gem list premailer</code>. Please remove premailer 1.7.2 if exists (<code>gem uninstall premailer -v 1.7.2; gem install premailer</code>), because 1.7.2 was broken.
|
122
|
-
|
123
110
|
## Credits
|
124
111
|
|
125
112
|
Thanks for [putpat.tv](http://www.putpat.tv), [Primalgrasp](http://www.primalgrasp.com) and [Undev](http://undev.ru/) for sponsoring this work.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.11.
|
1
|
+
0.11.1
|
@@ -26,18 +26,20 @@ too_many_files: 50
|
|
26
26
|
#
|
27
27
|
# prefix - The emailprefix set, defaulting to repo_name
|
28
28
|
# repo_name - Name of the git repo
|
29
|
-
# branch_name - Name of the git branch
|
29
|
+
# branch_name - Name of the git branch
|
30
|
+
# slash_branch_name - /branch_name (master is "" unless show_master_branch_name)
|
30
31
|
# commit_id - The git commit id (hash)
|
31
32
|
# message - The commit message
|
32
33
|
# commit_number - The commit number within the push; 1-based
|
33
34
|
# commit_count - The number of commits within the push
|
34
35
|
# commit_count_phrase - The number of commits, as "1 commit", "2 commits", etc.
|
36
|
+
# commit_count_phrase2 - "2 commits: ", "3 commits: ", etc, or "" if just one
|
35
37
|
#
|
36
38
|
# The default subject template varies a little depending on whether
|
37
39
|
# or not group_email_by_push is set.
|
38
40
|
#
|
39
|
-
#subject: "[${prefix}${
|
40
|
-
#subject: "[${prefix}${
|
41
|
+
#subject: "[${prefix}${slash_branch_name}] ${commit_count_phrase2}${message}"
|
42
|
+
#subject: "[${prefix}${slash_branch_name}][${commit_number}] ${message}"
|
41
43
|
|
42
44
|
# defines what branches to email for (defaults to all)
|
43
45
|
# include_branches: ['master', 'some_other_branch']
|
@@ -151,6 +153,16 @@ message_integration:
|
|
151
153
|
# fogbugz: http://yourondemand.fogbugz.com/? # will rework BugzId: 123 to FogBugz cases
|
152
154
|
|
153
155
|
# Track unique commits per branch?
|
156
|
+
# The name of this option is confusing.
|
157
|
+
#
|
158
|
+
# If set to false, notifications are issued only for commits that are unique to the current branch.
|
159
|
+
# If set to true, notifications are issued for any commit on the current branch, whether or not
|
160
|
+
# it also occurs on other branches.
|
161
|
+
#
|
162
|
+
# In other words, setting this to false will filter out commits that have already been displayed
|
163
|
+
# at some time in the past, for another branch. The confusing "unique" in the option name can
|
164
|
+
# be thought of as implying that commits for each branch are considered in isolation, without
|
165
|
+
# considering other branches.
|
154
166
|
unique_commits_per_branch: false
|
155
167
|
|
156
168
|
# Skip commits older than N days
|
data/git-commit-notifier.gemspec
CHANGED
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
|
|
36
36
|
s.add_development_dependency(%q<rspec-expectations>, [">= 0"])
|
37
37
|
s.add_development_dependency(%q<rr>, ["~> 1.0"])
|
38
38
|
s.add_development_dependency(%q<faker>, ["~> 0.9.5"])
|
39
|
-
s.add_development_dependency(%q<yard>, ["~> 0.7.
|
39
|
+
s.add_development_dependency(%q<yard>, ["~> 0.7.4"])
|
40
40
|
s.add_development_dependency(%q<redcarpet>, ["~> 1.17.2"])
|
41
41
|
end
|
42
42
|
|
data/lib/git_commit_notifier.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
require 'git_commit_notifier/commit_hook'
|
2
4
|
require 'git_commit_notifier/diff_to_html'
|
3
5
|
require 'git_commit_notifier/diff_callback'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
require 'cgi'
|
3
5
|
require 'net/smtp'
|
@@ -7,7 +9,7 @@ module GitCommitNotifier
|
|
7
9
|
class CommitHook
|
8
10
|
|
9
11
|
class << self
|
10
|
-
attr_reader :config
|
12
|
+
attr_reader :config
|
11
13
|
|
12
14
|
def show_error(message)
|
13
15
|
$stderr.puts "************** GIT NOTIFIER PROBLEM *******************"
|
@@ -42,9 +44,23 @@ module GitCommitNotifier
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def run(config_name, rev1, rev2, ref_name)
|
47
|
+
|
48
|
+
# Load the configuration
|
45
49
|
@config = File.exists?(config_name) ? YAML::load_file(config_name) : {}
|
46
50
|
|
47
|
-
project_path =
|
51
|
+
project_path = Git.git_dir
|
52
|
+
repo_name = Git.repo_name
|
53
|
+
prefix = config["emailprefix"] || repo_name
|
54
|
+
|
55
|
+
branch_name = if ref_name =~ /^refs\/heads\/(.+)$/
|
56
|
+
$1
|
57
|
+
else
|
58
|
+
ref_name.split("/").last
|
59
|
+
end
|
60
|
+
slash_branch_name = "/#{branch_name}"
|
61
|
+
slash_branch_name = "" if !config["show_master_branch_name"] && slash_branch_name == '/master'
|
62
|
+
|
63
|
+
# Identify email recipients
|
48
64
|
recipient = config["mailinglist"] || Git.mailing_list_address
|
49
65
|
|
50
66
|
# If no recipients specified, bail out gracefully. This is not an error, and might be intentional
|
@@ -53,56 +69,51 @@ module GitCommitNotifier
|
|
53
69
|
return
|
54
70
|
end
|
55
71
|
|
72
|
+
# Debug information
|
56
73
|
logger.debug('----')
|
57
|
-
logger.debug("
|
74
|
+
logger.debug("cwd: #{Dir.pwd}")
|
75
|
+
logger.debug("Git Directory: #{project_path}")
|
76
|
+
logger.debug("prefix: #{prefix}")
|
77
|
+
logger.debug("repo_name: #{repo_name}")
|
78
|
+
logger.debug("branch: #{branch_name}")
|
79
|
+
logger.debug("slash_branch: #{slash_branch_name}")
|
58
80
|
logger.debug("ref_name: #{ref_name}")
|
59
81
|
logger.debug("rev1: #{rev1}")
|
60
82
|
logger.debug("rev2: #{rev2}")
|
61
83
|
logger.debug("included branches: #{include_branches.join(', ')}") unless include_branches.nil?
|
62
84
|
|
63
|
-
repo_name = Git.repo_name
|
64
|
-
prefix = config["emailprefix"] || repo_name
|
65
|
-
|
66
|
-
branch_name = if ref_name =~ /^refs\/heads\/(.+)$/
|
67
|
-
$1
|
68
|
-
else
|
69
|
-
ref_name.split("/").last
|
70
|
-
end
|
71
|
-
|
72
|
-
logger.debug("prefix: #{prefix}")
|
73
|
-
logger.debug("branch: #{branch_name}")
|
74
|
-
|
75
85
|
unless include_branches.nil? || include_branches.include?(branch_name)
|
76
86
|
info("Supressing mail for branch #{branch_name}...")
|
77
87
|
return
|
78
88
|
end
|
79
89
|
|
80
|
-
branch_name = "/#{branch_name}"
|
81
|
-
branch_name = "" if !config["show_master_branch_name"] && branch_name == '/master'
|
82
|
-
|
83
90
|
# Replacements for subject template
|
84
91
|
# prefix
|
85
92
|
# repo_name
|
86
93
|
# branch_name
|
94
|
+
# slash_branch_name
|
87
95
|
# commit_id (hash)
|
88
96
|
# short_message
|
89
97
|
# commit_number
|
90
98
|
# commit_count
|
91
99
|
# commit_count_phrase (1 commit, 2 commits, etc)
|
100
|
+
# commit_count_phrase2 (2 commits:, 3 commits:, etc, or "" if just one)
|
92
101
|
subject_words = {
|
93
102
|
:prefix => prefix,
|
94
103
|
:repo_name => repo_name,
|
95
104
|
:branch_name => branch_name,
|
105
|
+
:slash_branch_name => slash_branch_name,
|
96
106
|
:commit_id => nil,
|
97
107
|
:message => nil,
|
98
108
|
:commit_number => nil,
|
99
109
|
:commit_count => nil,
|
100
|
-
:commit_count_phrase => nil
|
110
|
+
:commit_count_phrase => nil,
|
111
|
+
:commit_count_phrase2 => nil
|
101
112
|
}
|
102
113
|
|
103
114
|
info("Sending mail...")
|
104
115
|
|
105
|
-
diff2html = DiffToHtml.new(
|
116
|
+
diff2html = DiffToHtml.new(config)
|
106
117
|
if config["group_email_by_push"]
|
107
118
|
diff2html.diff_between_revisions(rev1, rev2, prefix, ref_name)
|
108
119
|
diffresult = diff2html.result
|
@@ -129,9 +140,10 @@ module GitCommitNotifier
|
|
129
140
|
:message => result[:commit_info][:message],
|
130
141
|
:commit_number => 1,
|
131
142
|
:commit_count => diffresult.size,
|
132
|
-
:commit_count_phrase => diffresult.size == 1 ? "
|
143
|
+
:commit_count_phrase => diffresult.size == 1 ? "1 commit" : "#{diffresult.size} commits",
|
144
|
+
:commit_count_phrase2 => diffresult.size == 1 ? "" : "#{diffresult.size} commits: "
|
133
145
|
})
|
134
|
-
subject_template = config['subject'] || "[${prefix}${
|
146
|
+
subject_template = config['subject'] || "[${prefix}${slash_branch_name}] ${commit_count_phrase2}${message}"
|
135
147
|
subject = subject_template.gsub(/\$\{(\w+)\}/) { |m| revised_subject_words[$1.intern] }
|
136
148
|
|
137
149
|
emailer = Emailer.new(config,
|
@@ -159,9 +171,10 @@ module GitCommitNotifier
|
|
159
171
|
:message => result[:commit_info][:message],
|
160
172
|
:commit_number => commit_number,
|
161
173
|
:commit_count => 1,
|
162
|
-
:commit_count_phrase => "1 commit"
|
174
|
+
:commit_count_phrase => "1 commit",
|
175
|
+
:commit_count_phrase2 => ""
|
163
176
|
})
|
164
|
-
subject_template = config['subject'] || "[${prefix}${
|
177
|
+
subject_template = config['subject'] || "[${prefix}${slash_branch_name}][${commit_number}] ${message}"
|
165
178
|
subject = subject_template.gsub(/\$\{(\w+)\}/) { |m| revised_subject_words[$1.intern] }
|
166
179
|
|
167
180
|
emailer = Emailer.new(config,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
require 'diff/lcs'
|
2
4
|
require 'digest/sha1'
|
3
5
|
require 'time'
|
@@ -35,14 +37,12 @@ module GitCommitNotifier
|
|
35
37
|
HANDLED_COMMITS_FILE = 'previously.txt'.freeze
|
36
38
|
NEW_HANDLED_COMMITS_FILE = 'previously_new.txt'.freeze
|
37
39
|
GIT_CONFIG_FILE = File.join('.git', 'config').freeze
|
38
|
-
DEFAULT_NEW_FILE_RIGHTS = 0664
|
39
40
|
SECS_PER_DAY = 24 * 60 * 60
|
40
41
|
|
41
42
|
attr_accessor :file_prefix, :current_file_name
|
42
|
-
attr_reader :result, :
|
43
|
+
attr_reader :result, :oldrev, :newrev, :rev, :ref_name, :config
|
43
44
|
|
44
|
-
def initialize(
|
45
|
-
@previous_dir = previous_dir
|
45
|
+
def initialize(config = nil)
|
46
46
|
@config = config || {}
|
47
47
|
@lines_added = 0
|
48
48
|
@file_added = false
|
@@ -336,9 +336,11 @@ module GitCommitNotifier
|
|
336
336
|
def extract_commit_info_from_git_show_output(content)
|
337
337
|
result = { :message => [], :commit => '', :author => '', :date => '', :email => '',
|
338
338
|
:committer => '', :commit_date => '', :committer_email => ''}
|
339
|
+
|
340
|
+
message = []
|
339
341
|
content.split("\n").each do |line|
|
340
|
-
if line =~ /^diff/ # end of commit info
|
341
|
-
|
342
|
+
if line =~ /^diff/ # end of commit info
|
343
|
+
break
|
342
344
|
elsif line =~ /^commit /
|
343
345
|
result[:commit] = line[7..-1]
|
344
346
|
elsif line =~ /^Author:/
|
@@ -352,10 +354,19 @@ module GitCommitNotifier
|
|
352
354
|
elsif line =~ /^Merge:/
|
353
355
|
result[:merge] = line[7..-1]
|
354
356
|
else
|
355
|
-
|
356
|
-
result[:message] << clean_line unless clean_line.empty?
|
357
|
+
message << line.strip
|
357
358
|
end
|
358
359
|
end
|
360
|
+
|
361
|
+
# Strip blank lines off top and bottom of message
|
362
|
+
while !message.empty? && message.first.empty?
|
363
|
+
message.shift
|
364
|
+
end
|
365
|
+
while !message.empty? && message.last.empty?
|
366
|
+
message.pop
|
367
|
+
end
|
368
|
+
result[:message] = message
|
369
|
+
|
359
370
|
result
|
360
371
|
end
|
361
372
|
|
@@ -380,60 +391,8 @@ module GitCommitNotifier
|
|
380
391
|
! ! config['unique_commits_per_branch']
|
381
392
|
end
|
382
393
|
|
383
|
-
def get_previous_commits(previous_file)
|
384
|
-
return [] unless File.exists?(previous_file)
|
385
|
-
lines = IO.read(previous_file)
|
386
|
-
lines = lines.lines if lines.respond_to?(:lines) # Ruby 1.9 tweak
|
387
|
-
lines.to_a.map { |s| s.chomp }.compact.uniq
|
388
|
-
end
|
389
|
-
|
390
|
-
def previous_dir
|
391
|
-
(!@previous_dir.nil? && File.exists?(@previous_dir)) ? @previous_dir : '/tmp'
|
392
|
-
end
|
393
|
-
|
394
|
-
def previous_prefix
|
395
|
-
unique_commits_per_branch? ? "#{Digest::SHA1.hexdigest(branch)}." : ''
|
396
|
-
end
|
397
|
-
|
398
|
-
def previous_file_path
|
399
|
-
previous_name = "#{previous_prefix}#{HANDLED_COMMITS_FILE}"
|
400
|
-
File.join(previous_dir, previous_name)
|
401
|
-
end
|
402
|
-
|
403
|
-
def new_file_path
|
404
|
-
new_name = "#{previous_prefix}#{NEW_HANDLED_COMMITS_FILE}"
|
405
|
-
File.join(previous_dir, new_name)
|
406
|
-
end
|
407
|
-
|
408
|
-
def new_file_rights
|
409
|
-
git_config_path = File.expand_path(GIT_CONFIG_FILE, '.')
|
410
|
-
# we should copy rights from git config if possible
|
411
|
-
File.stat(git_config_path).mode
|
412
|
-
rescue
|
413
|
-
DEFAULT_NEW_FILE_RIGHTS
|
414
|
-
end
|
415
|
-
|
416
|
-
def save_handled_commits(previous_list, flatten_commits)
|
417
|
-
return if flatten_commits.empty?
|
418
|
-
current_list = (previous_list + flatten_commits).last(MAX_COMMITS_PER_ACTION)
|
419
|
-
|
420
|
-
# use new file, unlink and rename to make it more atomic
|
421
|
-
File.open(new_file_path, 'w') { |f| f << current_list.join("\n") }
|
422
|
-
File.chmod(new_file_rights, new_file_path) rescue nil
|
423
|
-
File.unlink(previous_file_path) if File.exists?(previous_file_path)
|
424
|
-
File.rename(new_file_path, previous_file_path)
|
425
|
-
end
|
426
|
-
|
427
|
-
def check_handled_commits(commits)
|
428
|
-
previous_list = get_previous_commits(previous_file_path)
|
429
|
-
commits.reject! {|c| (c.respond_to?(:lines) ? c.lines : c).find { |sha| previous_list.include?(sha) } }
|
430
|
-
save_handled_commits(previous_list, commits.flatten)
|
431
|
-
|
432
|
-
commits
|
433
|
-
end
|
434
|
-
|
435
394
|
def branch_name
|
436
|
-
|
395
|
+
ref_name.split('/').last
|
437
396
|
end
|
438
397
|
|
439
398
|
def old_commit?(commit_info)
|
@@ -485,7 +444,29 @@ module GitCommitNotifier
|
|
485
444
|
output.string
|
486
445
|
end
|
487
446
|
end
|
488
|
-
|
447
|
+
|
448
|
+
def markup_commit_for_html(commit)
|
449
|
+
commit = if config["link_files"]
|
450
|
+
if config["link_files"] == "gitweb" && config["gitweb"]
|
451
|
+
"<a href='#{config['gitweb']['path']}?p=#{Git.repo_name}.git;a=commitdiff;h=#{commit}'>#{commit}</a>"
|
452
|
+
elsif config["link_files"] == "gitorious" && config["gitorious"]
|
453
|
+
"<a href='#{config['gitorious']['path']}/#{config['gitorious']['project']}/#{config['gitorious']['repository']}/commit/#{commit}'>#{commit}</a>"
|
454
|
+
elsif config["link_files"] == "trac" && config["trac"]
|
455
|
+
"<a href='#{config['trac']['path']}/#{commit}'>#{commit}</a>"
|
456
|
+
elsif config["link_files"] == "cgit" && config["cgit"]
|
457
|
+
"<a href='#{config['cgit']['path']}/#{config['cgit']['project']}/commit/?id=#{commit}'>#{commit}</a>"
|
458
|
+
elsif config["link_files"] == "gitlabhq" && config["gitlabhq"]
|
459
|
+
"<a href='#{config['gitlabhq']['path']}/#{Git.repo_name.gsub(".", "_")}/commits/#{commit}'>#{commit}</a>"
|
460
|
+
elsif config["link_files"] == "redmine" && config["redmine"]
|
461
|
+
"<a href='#{config['redmine']['path']}/projects/#{config['redmine']['project'] || Git.repo_name}/repository/revisions/#{commit}'>#{commit}</a>"
|
462
|
+
else
|
463
|
+
"#{commit}"
|
464
|
+
end
|
465
|
+
else
|
466
|
+
"#{commit}"
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
489
470
|
def diff_for_commit(commit)
|
490
471
|
@current_commit = commit
|
491
472
|
raw_diff = truncate_long_lines(Git.show(commit, :ignore_whitespaces => ignore_whitespaces?))
|
@@ -505,36 +486,23 @@ module GitCommitNotifier
|
|
505
486
|
changed_files = "Changed files:\n\n#{changed_file_list.uniq.join()}\n"
|
506
487
|
end
|
507
488
|
|
508
|
-
title = "<
|
509
|
-
title += "<
|
510
|
-
title += "<
|
511
|
-
|
512
|
-
title +=
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
elsif config["link_files"] == "trac" && config["trac"]
|
518
|
-
"<a href='#{config['trac']['path']}/#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
519
|
-
elsif config["link_files"] == "cgit" && config["cgit"]
|
520
|
-
"<a href='#{config['cgit']['path']}/#{config['cgit']['project']}/commit/?id=#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
521
|
-
elsif config["link_files"] == "gitlabhq" && config["gitlabhq"]
|
522
|
-
"<a href='#{config['gitlabhq']['path']}/#{Git.repo_name.gsub(".", "_")}/commits/#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
523
|
-
elsif config["link_files"] == "redmine" && config["redmine"]
|
524
|
-
"<a href='#{config['redmine']['path']}/projects/#{config['redmine']['project'] || Git.repo_name}/repository/revisions/#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
525
|
-
else
|
526
|
-
" #{commit_info[:commit]}"
|
527
|
-
end
|
528
|
-
else
|
529
|
-
" #{commit_info[:commit]}"
|
489
|
+
title = "<dl class=\"title\">"
|
490
|
+
title += "<dt>Commit</dt><dd>#{markup_commit_for_html(commit_info[:commit])}</dd>\n"
|
491
|
+
title += "<dt>Branch</dt><dd>#{CGI.escapeHTML(branch_name)}</dd>\n" if branch_name
|
492
|
+
|
493
|
+
title += "<dt>Author</dt><dd>#{CGI.escapeHTML(commit_info[:author])} <#{commit_info[:email]}></dd>\n"
|
494
|
+
|
495
|
+
# Show separate committer name/email only if it differs from author
|
496
|
+
if commit_info[:author] != commit_info[:committer] || commit_info[:email] != commit_info[:commit_email]
|
497
|
+
title += "<dt>Committer</dt><dd>#{CGI.escapeHTML(commit_info[:committer])} <#{commit_info[:commit_email]}></dd>\n"
|
530
498
|
end
|
531
499
|
|
532
|
-
title += "<
|
533
|
-
|
534
|
-
|
535
|
-
title += "<
|
536
|
-
|
537
|
-
title += "
|
500
|
+
title += "<dt>Date</dt><dd>#{CGI.escapeHTML commit_info[:date]}</dd>\n"
|
501
|
+
|
502
|
+
multi_line_message = commit_info[:message].count > 1
|
503
|
+
title += "<dt>Message</dt><dd class='#{multi_line_message ? "multi-line" : ""}'>#{message_array_as_html(commit_info[:message])}</dd>\n"
|
504
|
+
|
505
|
+
title += "</dl>"
|
538
506
|
|
539
507
|
text = "#{raw_diff}"
|
540
508
|
text += "#{changed_files}\n\n\n"
|
@@ -552,39 +520,169 @@ module GitCommitNotifier
|
|
552
520
|
}
|
553
521
|
end
|
554
522
|
|
555
|
-
def
|
556
|
-
|
523
|
+
def diff_for_lightweight_tag(tag, rev, change_type)
|
524
|
+
|
525
|
+
if change_type == :delete
|
526
|
+
message = "Remove Lightweight Tag #{tag}"
|
527
|
+
|
528
|
+
html = "<dl class='title'>"
|
529
|
+
html += "<dt>Tag</dt><dd>#{CGI.escapeHTML(tag)} (removed)</dd>\n"
|
530
|
+
html += "<dt>Type</dt><dd>lightweight</dd>\n"
|
531
|
+
html += "<dt>Commit</dt><dd>#{markup_commit_for_html(rev)}</dd>\n"
|
532
|
+
html += "</dl>"
|
533
|
+
|
534
|
+
text = "Remove Tag: #{tag}\n"
|
535
|
+
text += "Type: lightweight\n"
|
536
|
+
text += "Commit: #{rev}\n"
|
537
|
+
else
|
538
|
+
message = "#{change_type == :create ? "Add" : "Update"} Lightweight Tag #{tag}"
|
539
|
+
|
540
|
+
html = "<dl class='title'>"
|
541
|
+
html += "<dt>Tag</dt><dd>#{CGI.escapeHTML(tag)} (#{change_type == :create ? "added" : "updated"})</dd>\n"
|
542
|
+
html += "<dt>Type</dt><dd>lightweight</dd>\n"
|
543
|
+
html += "<dt>Commit</dt><dd>#{markup_commit_for_html(rev)}</dd>\n"
|
544
|
+
html += "</dl>"
|
545
|
+
|
546
|
+
text = "Tag: #{tag} (#{change_type == :create ? "added" : "updated"})\n"
|
547
|
+
text += "Type: lightweight\n"
|
548
|
+
text += "Commit: #{rev}\n"
|
549
|
+
end
|
550
|
+
|
551
|
+
commit_info = {
|
552
|
+
:commit => rev,
|
553
|
+
:message => message
|
554
|
+
}
|
555
|
+
|
556
|
+
@result << {
|
557
|
+
:commit_info => commit_info,
|
558
|
+
:html_content => html,
|
559
|
+
:text_content => text
|
560
|
+
}
|
557
561
|
end
|
558
562
|
|
559
|
-
def
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
563
|
+
def diff_for_annotated_tag(tag, rev, change_type)
|
564
|
+
|
565
|
+
commit_info = {
|
566
|
+
:commit => rev
|
567
|
+
}
|
568
|
+
|
569
|
+
if change_type == :delete
|
570
|
+
message = "Remove Annotated Tag #{tag}"
|
571
|
+
|
572
|
+
html = "<dl class='title'>"
|
573
|
+
html += "<dt>Tag</dt><dd>#{CGI.escapeHTML(tag)} (removed)</dd>\n"
|
574
|
+
html += "<dt>Type</dt><dd>annotated</dd>\n"
|
575
|
+
html += "</dl>"
|
576
|
+
|
577
|
+
text = message
|
578
|
+
commit_info[:message] = message
|
570
579
|
else
|
571
|
-
|
572
|
-
log.scan(/^commit\s([a-f0-9]+)/).map { |a| a.first }.reverse
|
573
|
-
end
|
580
|
+
tag_info = Git.tag_info(ref_name)
|
574
581
|
|
575
|
-
|
582
|
+
message = tag_info[:subject] || "#{change_type == :create ? "Add" : "Update"} Annotated Tag #{tag}"
|
583
|
+
|
584
|
+
html = "<dl class='title'>"
|
585
|
+
html += "<dt>Tag</dt><dd>#{CGI.escapeHTML(tag)} (#{change_type == :create ? "added" : "updated"})</dd>\n"
|
586
|
+
html += "<dt>Type</dt><dd>annotated</dd>\n"
|
587
|
+
html += "<dt>Commit</dt><dd>#{markup_commit_for_html(tag_info[:tagobject])}</dd>\n"
|
588
|
+
html += "<dt>Tagger</dt><dd>#{CGI.escapeHTML(tag_info[:taggername])} #{CGI.escapeHTML(tag_info[:taggeremail])}</dd>\n"
|
589
|
+
|
590
|
+
message_array = tag_info[:contents].split("\n")
|
591
|
+
multi_line_message = message_array.count > 1
|
592
|
+
html += "<dt>Message</dt><dd class='#{multi_line_message ? "multi-line" : ""}'>#{message_array_as_html(message_array)}</dd>\n"
|
593
|
+
html += "</dl>"
|
594
|
+
|
595
|
+
text = "Tag:</strong> #{tag} (#{change_type == :create ? "added" : "updated"})\n"
|
596
|
+
text += "Type: annotated\n"
|
597
|
+
text += "Commit: #{tag_info[:tagobject]}\n"
|
598
|
+
text += "Tagger: tag_info[:taggername] tag_info[:taggeremail]\n"
|
599
|
+
text += "Message: #{tag_info[:contents]}\n"
|
600
|
+
|
601
|
+
commit_info[:message] = message
|
602
|
+
commit_info[:author], commit_info[:email] = author_name_and_email("#{tag_info[:taggername]} #{tag_info[:taggeremail]}")
|
603
|
+
end
|
604
|
+
|
605
|
+
@result << {
|
606
|
+
:commit_info => commit_info,
|
607
|
+
:html_content => html,
|
608
|
+
:text_content => text
|
609
|
+
}
|
610
|
+
end
|
576
611
|
|
612
|
+
def diff_for_branch(branch, rev, change_type)
|
613
|
+
commits = case change_type
|
614
|
+
when :delete
|
615
|
+
puts "ignoring branch delete"
|
616
|
+
[]
|
617
|
+
when :create, :update
|
618
|
+
# Note that "unique_commits_per_branch" really means "consider commits
|
619
|
+
# on this branch without regard to whether they occur on other branches"
|
620
|
+
# The flag unique_to_current_branch passed to new_commits means the
|
621
|
+
# opposite: "consider only commits that are unique to this branch"
|
622
|
+
Git.new_commits(oldrev, newrev, ref_name, !unique_commits_per_branch?)
|
623
|
+
end
|
624
|
+
|
625
|
+
# Add each diff to @result
|
577
626
|
commits.each do |commit|
|
578
|
-
begin
|
579
627
|
commit_result = diff_for_commit(commit)
|
580
628
|
next if commit_result.nil?
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
629
|
+
@result << commit_result
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
633
|
+
def clear_result
|
634
|
+
@result = []
|
635
|
+
end
|
636
|
+
|
637
|
+
def diff_between_revisions(rev1, rev2, repo, ref_name)
|
638
|
+
clear_result
|
639
|
+
|
640
|
+
# Cleanup revs
|
641
|
+
@oldrev = Git.rev_parse(rev1)
|
642
|
+
@newrev = Git.rev_parse(rev2)
|
643
|
+
@ref_name = ref_name
|
644
|
+
|
645
|
+
# Establish the type of change
|
646
|
+
change_type = if @oldrev =~ /^0+$/
|
647
|
+
:create
|
648
|
+
elsif @newrev =~ /^0+$/
|
649
|
+
:delete
|
650
|
+
else
|
651
|
+
:update
|
587
652
|
end
|
653
|
+
|
654
|
+
# Establish type of the revs
|
655
|
+
@oldrev_type = Git.rev_type(@oldrev)
|
656
|
+
@newrev_type = Git.rev_type(@newrev)
|
657
|
+
if newrev =~ /^0+$/
|
658
|
+
@rev_type = @oldrev_type
|
659
|
+
@rev = @oldrev
|
660
|
+
else
|
661
|
+
@rev_type = @newrev_type
|
662
|
+
@rev = @newrev
|
663
|
+
end
|
664
|
+
|
665
|
+
# Determine what to do based on the ref_name and the rev_type
|
666
|
+
case "#{@ref_name},#{@rev_type}"
|
667
|
+
when %r!^refs/tags/(.+),commit$!
|
668
|
+
# Change to an unannotated tag
|
669
|
+
diff_for_lightweight_tag($1, @rev, change_type)
|
670
|
+
when %r!^refs/tags/(.+),tag$!
|
671
|
+
# Change to a annotated tag
|
672
|
+
diff_for_annotated_tag($1, @rev, change_type)
|
673
|
+
when %r!^refs/heads/(.+),commit$!
|
674
|
+
# Change on a branch
|
675
|
+
diff_for_branch($1, @rev, change_type)
|
676
|
+
when %r!^refs/remotes/(.+),commit$!
|
677
|
+
# Remote branch
|
678
|
+
puts "Ignoring #{change_type} on remote branch #{$1}"
|
679
|
+
else
|
680
|
+
# Something we don't understand
|
681
|
+
puts "Unknown change type #{ref_name},#{@rev_type}"
|
682
|
+
end
|
683
|
+
|
684
|
+
# If a block was given, pass it the results, in turn
|
685
|
+
@result.each { |result| yield result } if block_given?
|
588
686
|
end
|
589
687
|
|
590
688
|
def message_replace!(message, search_for, replace_with)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
require 'premailer'
|
2
4
|
|
3
5
|
class GitCommitNotifier::Emailer
|
@@ -116,17 +118,19 @@ class GitCommitNotifier::Emailer
|
|
116
118
|
|
117
119
|
def send
|
118
120
|
to_tag = config['delivery_method'] == 'nntp' ? 'Newsgroups' : 'To'
|
119
|
-
quoted_from_alias = quote_if_necessary("#{@from_alias}",'utf-8')
|
120
|
-
from = @from_alias.empty? ? @from_address : "#{quoted_from_alias} <#{@from_address}>"
|
121
|
+
quoted_from_alias = !@from_alias.nil? ? quote_if_necessary("#{@from_alias}",'utf-8') : nil
|
122
|
+
from = (@from_alias.nil? || @from_alias.empty?) ? @from_address : "#{quoted_from_alias} <#{@from_address}>"
|
121
123
|
|
122
124
|
plaintext = if config['add_plaintext'].nil? || config['add_plaintext']
|
123
125
|
@text_message
|
124
126
|
else
|
125
127
|
"Plain text part omitted. Consider setting add_plaintext in configuration."
|
126
128
|
end
|
129
|
+
|
130
|
+
content = []
|
131
|
+
content << "From: #{from}" if !from.nil?
|
127
132
|
|
128
|
-
content
|
129
|
-
"From: #{from}",
|
133
|
+
content.concat [
|
130
134
|
"#{to_tag}: #{quote_if_necessary(@recipient, 'utf-8')}",
|
131
135
|
"Subject: #{quote_if_necessary(@subject, 'utf-8')}",
|
132
136
|
"X-Mailer: git-commit-notifier",
|
@@ -222,7 +226,7 @@ class GitCommitNotifier::Emailer
|
|
222
226
|
|
223
227
|
# A quick-and-dirty regexp for determining whether a string contains any
|
224
228
|
# characters that need escaping.
|
225
|
-
CHARS_NEEDING_QUOTING = /[\
|
229
|
+
CHARS_NEEDING_QUOTING = /[^\x0a\x0d\x20-\x7e]/
|
226
230
|
|
227
231
|
# Quote the given text if it contains any "illegal" characters
|
228
232
|
def quote_if_necessary(text, charset)
|
@@ -1,5 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
module GitCommitNotifier::EscapeHelper
|
4
|
+
|
5
|
+
def expand_tabs(s, tabWidth)
|
6
|
+
delta = 0
|
7
|
+
s.gsub(/\t/) do |m|
|
8
|
+
add = tabWidth - (delta + $~.offset(0)[0]) % tabWidth
|
9
|
+
delta += add - 1
|
10
|
+
" " * add
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
2
14
|
def escape_content(s)
|
3
|
-
CGI.escapeHTML(s).gsub(" ", " ")
|
15
|
+
CGI.escapeHTML(expand_tabs(s, 4)).gsub(" ", " ")
|
4
16
|
end
|
5
17
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
# parameters: revision1, revision 2, branch
|
2
4
|
|
3
5
|
require 'git_commit_notifier'
|
@@ -15,13 +17,18 @@ module GitCommitNotifier
|
|
15
17
|
GitCommitNotifier::CommitHook.show_error("You have to add a path to the config file for git-commit-notifier")
|
16
18
|
puts "Usage: git-commit-notifier config-script [oldrev newrev [ref]]"
|
17
19
|
when 1
|
18
|
-
|
19
|
-
if stdin.nil?
|
20
|
+
if $stdin.eof?
|
20
21
|
GitCommitNotifier::CommitHook.show_error("No data given on standard input")
|
21
22
|
return
|
22
23
|
end
|
23
|
-
|
24
|
-
|
24
|
+
|
25
|
+
# Note that there may be multiple lines on stdin, such
|
26
|
+
# as in the case of multiple tags being pushed
|
27
|
+
$stdin.each_line do |line|
|
28
|
+
oldrev, newrev, ref = line.strip.split
|
29
|
+
GitCommitNotifier::CommitHook.run args.first, oldrev, newrev, ref
|
30
|
+
end
|
31
|
+
|
25
32
|
when 2
|
26
33
|
GitCommitNotifier::CommitHook.run args.first, args.last, args.last, ""
|
27
34
|
when 3
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
1
5
|
# Git methods
|
2
6
|
class GitCommitNotifier::Git
|
3
7
|
class << self
|
@@ -66,9 +70,69 @@ class GitCommitNotifier::Git
|
|
66
70
|
lines.to_a.map { |head| head.chomp }
|
67
71
|
end
|
68
72
|
|
73
|
+
def git_dir()
|
74
|
+
from_shell("git rev-parse --git-dir").strip
|
75
|
+
end
|
76
|
+
|
77
|
+
def rev_parse(param)
|
78
|
+
from_shell("git rev-parse '#{param}'").strip
|
79
|
+
end
|
80
|
+
|
69
81
|
def branch_head(treeish)
|
70
82
|
from_shell("git rev-parse #{treeish}").strip
|
71
83
|
end
|
84
|
+
|
85
|
+
def new_commits(oldrev, newrev, refname, unique_to_current_branch)
|
86
|
+
# We want to get the set of commits (^B1 ^B2 ... ^oldrev newrev)
|
87
|
+
# Where B1, B2, ..., are any other branch
|
88
|
+
|
89
|
+
s = Set.new
|
90
|
+
|
91
|
+
# If we want to include only those commits that are
|
92
|
+
# unique to this branch, then exclude commits that occur on
|
93
|
+
# other branches
|
94
|
+
if unique_to_current_branch
|
95
|
+
# Make a set of all branches, not'd (^BCURRENT ^B1 ^B2...)
|
96
|
+
not_branches = from_shell("git rev-parse --not --branches")
|
97
|
+
s.merge(not_branches.lines.map {|l| l.chomp}.to_set)
|
98
|
+
|
99
|
+
# Remove the current branch (^BCURRENT) from the set
|
100
|
+
current_branch = rev_parse(refname)
|
101
|
+
s.delete("^#{current_branch}")
|
102
|
+
end
|
103
|
+
|
104
|
+
# Add not'd oldrev (^oldrev)
|
105
|
+
s.add("^#{oldrev}") unless oldrev =~ /^0+$/
|
106
|
+
|
107
|
+
# Add newrev
|
108
|
+
s.add(newrev)
|
109
|
+
|
110
|
+
# We should now have ^B1... ^oldrev newrev
|
111
|
+
|
112
|
+
# Get all the commits that match that specification
|
113
|
+
lines = from_shell("git rev-list #{s.to_a.join(' ')}")
|
114
|
+
commits = lines.lines.map {|l| l.chomp}
|
115
|
+
end
|
116
|
+
|
117
|
+
def rev_type(rev)
|
118
|
+
from_shell("git cat-file -t '#{rev}' 2> /dev/null").strip
|
119
|
+
rescue ArgumentError
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
def tag_info(refname)
|
124
|
+
fields = [
|
125
|
+
':tagobject => %(*objectname)',
|
126
|
+
':tagtype => %(*objecttype)',
|
127
|
+
':taggername => %(taggername)',
|
128
|
+
':taggeremail => %(taggeremail)',
|
129
|
+
':subject => %(subject)',
|
130
|
+
':contents => %(contents)'
|
131
|
+
]
|
132
|
+
joined_fields = fields.join(",")
|
133
|
+
hash_script = from_shell("git for-each-ref --shell --format='{ #{joined_fields} }' #{refname}")
|
134
|
+
eval(hash_script)
|
135
|
+
end
|
72
136
|
|
73
137
|
def repo_name
|
74
138
|
git_prefix = begin
|
@@ -77,7 +141,7 @@ class GitCommitNotifier::Git
|
|
77
141
|
''
|
78
142
|
end
|
79
143
|
return git_prefix unless git_prefix.empty?
|
80
|
-
|
144
|
+
File.expand_path(git_dir).split("/").last.sub(/\.git$/, '')
|
81
145
|
end
|
82
146
|
|
83
147
|
def mailing_list_address
|
data/local-run.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
require File.expand_path('../../../spec_helper', __FILE__)
|
2
4
|
require 'git_commit_notifier'
|
3
5
|
|
@@ -70,7 +72,9 @@ describe GitCommitNotifier::CommitHook do
|
|
70
72
|
end
|
71
73
|
|
72
74
|
def expect_repository_access
|
73
|
-
mock(GitCommitNotifier::Git).
|
75
|
+
mock(GitCommitNotifier::Git).rev_type(REVISIONS.first) { "commit" }
|
76
|
+
mock(GitCommitNotifier::Git).rev_type(REVISIONS.last) { "commit" }
|
77
|
+
mock(GitCommitNotifier::Git).new_commits(anything, anything, anything, anything) { REVISIONS }
|
74
78
|
mock(GitCommitNotifier::Git).mailing_list_address { 'recipient@test.com' }
|
75
79
|
mock(GitCommitNotifier::Git).repo_name { 'testproject' }
|
76
80
|
mock(GitCommitNotifier::Git).changed_files('7e4f6b4', '4f13525') { [] }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
require File.expand_path('../../../spec_helper', __FILE__)
|
2
4
|
require 'tempfile'
|
3
5
|
require 'nokogiri'
|
@@ -5,23 +7,6 @@ require 'git_commit_notifier'
|
|
5
7
|
|
6
8
|
describe GitCommitNotifier::DiffToHtml do
|
7
9
|
|
8
|
-
describe :new_file_rights do
|
9
|
-
before(:all) do
|
10
|
-
@diff_to_html = GitCommitNotifier::DiffToHtml.new
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should be DEFAULT_NEW_FILE_RIGHTS unless get stats of git config file" do
|
14
|
-
mock(File).stat(File.expand_path(GitCommitNotifier::DiffToHtml::GIT_CONFIG_FILE, '.')) { raise Errno::ENOENT.new('') }
|
15
|
-
@diff_to_html.new_file_rights.should == GitCommitNotifier::DiffToHtml::DEFAULT_NEW_FILE_RIGHTS
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should be rights of git config file if exists" do
|
19
|
-
stats = mock!.mode { 0444 }.subject
|
20
|
-
mock(File).stat(File.expand_path(GitCommitNotifier::DiffToHtml::GIT_CONFIG_FILE, '.')) { stats }
|
21
|
-
@diff_to_html.new_file_rights.should == 0444
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
10
|
describe :chmod do
|
26
11
|
it "should not raise anything and set mode from stats mode" do
|
27
12
|
file = Tempfile.new('stattest')
|
@@ -100,48 +85,40 @@ describe GitCommitNotifier::DiffToHtml do
|
|
100
85
|
|
101
86
|
describe :unique_commits_per_branch? do
|
102
87
|
it "should be false unless specified in config" do
|
103
|
-
diff = GitCommitNotifier::DiffToHtml.new
|
88
|
+
diff = GitCommitNotifier::DiffToHtml.new
|
104
89
|
diff.should_not be_unique_commits_per_branch
|
105
90
|
end
|
106
91
|
|
107
92
|
it "should be false if specified as false in config" do
|
108
|
-
diff = GitCommitNotifier::DiffToHtml.new(
|
93
|
+
diff = GitCommitNotifier::DiffToHtml.new({ 'unique_commits_per_branch' => false })
|
109
94
|
diff.should_not be_unique_commits_per_branch
|
110
95
|
end
|
111
96
|
|
112
97
|
it "should be true if specified as true in config" do
|
113
|
-
diff = GitCommitNotifier::DiffToHtml.new(
|
98
|
+
diff = GitCommitNotifier::DiffToHtml.new({ 'unique_commits_per_branch' => true })
|
114
99
|
diff.should be_unique_commits_per_branch
|
115
100
|
end
|
116
101
|
end
|
117
102
|
|
118
|
-
describe :get_previous_commits do
|
119
|
-
it "should read and parse previous file if it exists" do
|
120
|
-
fn = GitCommitNotifier::DiffToHtml::HANDLED_COMMITS_FILE
|
121
|
-
diff = GitCommitNotifier::DiffToHtml.new
|
122
|
-
mock(File).exists?(fn) { true }
|
123
|
-
mock(IO).read(fn) { "a\nb" }
|
124
|
-
diff.get_previous_commits(fn).should == %w[a b]
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
103
|
it "multiple commits" do
|
104
|
+
|
129
105
|
mock(GitCommitNotifier::Git).changed_files('7e4f6b4', '4f13525') { [] }
|
130
|
-
mock(GitCommitNotifier::Git).
|
106
|
+
mock(GitCommitNotifier::Git).rev_type(REVISIONS.first) { "commit" }
|
107
|
+
mock(GitCommitNotifier::Git).rev_type(REVISIONS.last) { "commit" }
|
108
|
+
mock(GitCommitNotifier::Git).new_commits(anything, anything, anything, anything) { REVISIONS.reverse }
|
131
109
|
REVISIONS.each do |rev|
|
132
110
|
mock(GitCommitNotifier::Git).show(rev, :ignore_whitespaces => true) { IO.read(FIXTURES_PATH + 'git_show_' + rev) }
|
133
111
|
end
|
134
112
|
|
135
113
|
diff = GitCommitNotifier::DiffToHtml.new
|
136
|
-
|
137
|
-
diff.diff_between_revisions REVISIONS.first, REVISIONS.last, 'testproject', 'master'
|
114
|
+
diff.diff_between_revisions REVISIONS.first, REVISIONS.last, 'testproject', 'refs/heads/master'
|
138
115
|
|
139
116
|
diff.result.should have(5).commits # one result for each of the commits
|
140
117
|
|
141
118
|
diff.result.each do |html|
|
142
119
|
html.should_not be_include('@@') # diff correctly processed
|
143
120
|
end
|
144
|
-
|
121
|
+
|
145
122
|
# second commit - 51b986619d88f7ba98be7d271188785cbbb541a0
|
146
123
|
hp = Nokogiri::HTML diff.result[1][:html_content]
|
147
124
|
(hp/"table").should have(3).tables # 3 files updated
|
@@ -179,14 +156,15 @@ describe GitCommitNotifier::DiffToHtml do
|
|
179
156
|
end
|
180
157
|
|
181
158
|
it "should get good diff when new branch created" do
|
182
|
-
first_rev, last_rev = %w[ 0000000000000000000000000000000000000000
|
183
|
-
mock(GitCommitNotifier::Git).
|
159
|
+
first_rev, last_rev = %w[ 0000000000000000000000000000000000000000 ff037a73fc1094455e7bbf506171a3f3cf873ae6 ]
|
160
|
+
mock(GitCommitNotifier::Git).rev_type(first_rev) { "commit" }
|
161
|
+
mock(GitCommitNotifier::Git).rev_type(last_rev) { "commit" }
|
162
|
+
mock(GitCommitNotifier::Git).new_commits(anything, anything, anything, anything) { [ 'ff037a73fc1094455e7bbf506171a3f3cf873ae6' ] }
|
184
163
|
%w[ ff037a73fc1094455e7bbf506171a3f3cf873ae6 ].each do |rev|
|
185
164
|
mock(GitCommitNotifier::Git).show(rev, :ignore_whitespaces => true) { IO.read(FIXTURES_PATH + 'git_show_' + rev) }
|
186
165
|
end
|
187
166
|
diff = GitCommitNotifier::DiffToHtml.new
|
188
|
-
|
189
|
-
diff.diff_between_revisions(first_rev, last_rev, 'tm-admin', 'rvm')
|
167
|
+
diff.diff_between_revisions(first_rev, last_rev, 'tm-admin', 'refs/heads/rvm')
|
190
168
|
diff.result.should have(1).commit
|
191
169
|
hp = Nokogiri::HTML diff.result.first[:html_content]
|
192
170
|
(hp/"table").should have(1).table
|
@@ -214,7 +192,7 @@ describe GitCommitNotifier::DiffToHtml do
|
|
214
192
|
describe :do_message_integration do
|
215
193
|
before(:each) do
|
216
194
|
@config = Hash.new
|
217
|
-
@diff = GitCommitNotifier::DiffToHtml.new(
|
195
|
+
@diff = GitCommitNotifier::DiffToHtml.new(@config)
|
218
196
|
end
|
219
197
|
|
220
198
|
it "should do nothing unless message_integration config section exists" do
|
@@ -234,7 +212,7 @@ describe GitCommitNotifier::DiffToHtml do
|
|
234
212
|
describe :old_commit? do
|
235
213
|
before(:each) do
|
236
214
|
@config = Hash.new
|
237
|
-
@diff_to_html = GitCommitNotifier::DiffToHtml.new(
|
215
|
+
@diff_to_html = GitCommitNotifier::DiffToHtml.new(@config)
|
238
216
|
end
|
239
217
|
|
240
218
|
it "should be false unless skip_commits_older_than set" do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8; mode: ruby; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- vim:fenc=utf-8:filetype=ruby:et:sw=2:ts=2:sts=2
|
2
|
+
|
1
3
|
require File.expand_path('../../../spec_helper', __FILE__)
|
2
4
|
require 'git_commit_notifier'
|
3
5
|
|
@@ -60,13 +62,13 @@ describe GitCommitNotifier::Git do
|
|
60
62
|
|
61
63
|
it "should return folder name if no emailprefix and directory not ended with .git" do
|
62
64
|
mock(GitCommitNotifier::Git).from_shell("git config hooks.emailprefix") { " " }
|
63
|
-
mock(
|
65
|
+
mock(GitCommitNotifier::Git).git_dir { "/home/someuser/repositories/myrepo" }
|
64
66
|
GitCommitNotifier::Git.repo_name.should == "myrepo"
|
65
67
|
end
|
66
68
|
|
67
69
|
it "should return folder name without extension if no emailprefix and directory ended with .git" do
|
68
70
|
mock(GitCommitNotifier::Git).from_shell("git config hooks.emailprefix") { " " }
|
69
|
-
mock(
|
71
|
+
mock(GitCommitNotifier::Git).git_dir { "/home/someuser/repositories/myrepo.git" }
|
70
72
|
GitCommitNotifier::Git.repo_name.should == "myrepo"
|
71
73
|
end
|
72
74
|
end
|
data/spec/spec_helper.rb
CHANGED
data/template/styles.css
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
* {font-size:
|
1
|
+
* {font-size:12px;}
|
2
2
|
h2 {font-family:Verdana;font-size:12px;background-color: #bbb; font-weight: bold; line-height:25px; margin-bottom:2px; padding-left:5px}
|
3
3
|
table {width:100%;border-collapse:collapse}
|
4
4
|
.r {background-color: #fdd;}
|
@@ -6,6 +6,9 @@ table {width:100%;border-collapse:collapse}
|
|
6
6
|
.a {background-color: #dfd;}
|
7
7
|
.aa {background-color: #afa;}
|
8
8
|
.title {background-color: #ddd; padding: 10px;font-family:Verdana;font-size:12px;}
|
9
|
+
dt { float: left; font-weight: bold; min-width: 6em; }
|
10
|
+
dt:after { content: ':'; }
|
11
|
+
dd.multi-line { clear: both; margin-left: 0; padding-top: 1em; }
|
9
12
|
td {color:#000;font-family: "Bitstream Vera Sans Mono","Monaco","Courier",monospace}
|
10
13
|
.ln {background-color: #ccc; width:23px; text-align:right}
|
11
14
|
td.sep {text-align:center;border-top:1px solid DimGray;border-bottom:1px solid DimGray;}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-commit-notifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-12-
|
13
|
+
date: 2011-12-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: diff-lcs
|
17
|
-
requirement: &
|
17
|
+
requirement: &70278308411520 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 1.1.2
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70278308411520
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: nntp
|
28
|
-
requirement: &
|
28
|
+
requirement: &70278308410260 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '1.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70278308410260
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: premailer
|
39
|
-
requirement: &
|
39
|
+
requirement: &70278308409140 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -50,10 +50,10 @@ dependencies:
|
|
50
50
|
version: 1.7.2
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
|
-
version_requirements: *
|
53
|
+
version_requirements: *70278308409140
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: nokogiri
|
56
|
-
requirement: &
|
56
|
+
requirement: &70278308423600 !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
@@ -61,10 +61,10 @@ dependencies:
|
|
61
61
|
version: '1.4'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
|
-
version_requirements: *
|
64
|
+
version_requirements: *70278308423600
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
66
|
name: rake
|
67
|
-
requirement: &
|
67
|
+
requirement: &70278308422800 !ruby/object:Gem::Requirement
|
68
68
|
none: false
|
69
69
|
requirements:
|
70
70
|
- - ~>
|
@@ -75,10 +75,10 @@ dependencies:
|
|
75
75
|
version: 0.9.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
|
-
version_requirements: *
|
78
|
+
version_requirements: *70278308422800
|
79
79
|
- !ruby/object:Gem::Dependency
|
80
80
|
name: bundler
|
81
|
-
requirement: &
|
81
|
+
requirement: &70278308420960 !ruby/object:Gem::Requirement
|
82
82
|
none: false
|
83
83
|
requirements:
|
84
84
|
- - ~>
|
@@ -89,10 +89,10 @@ dependencies:
|
|
89
89
|
version: 1.0.10
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
|
-
version_requirements: *
|
92
|
+
version_requirements: *70278308420960
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
94
|
name: code-cleaner
|
95
|
-
requirement: &
|
95
|
+
requirement: &70278308419040 !ruby/object:Gem::Requirement
|
96
96
|
none: false
|
97
97
|
requirements:
|
98
98
|
- - ! '>='
|
@@ -100,10 +100,10 @@ dependencies:
|
|
100
100
|
version: '0'
|
101
101
|
type: :development
|
102
102
|
prerelease: false
|
103
|
-
version_requirements: *
|
103
|
+
version_requirements: *70278308419040
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
105
|
name: rspec-core
|
106
|
-
requirement: &
|
106
|
+
requirement: &70278308418280 !ruby/object:Gem::Requirement
|
107
107
|
none: false
|
108
108
|
requirements:
|
109
109
|
- - ! '>='
|
@@ -111,10 +111,10 @@ dependencies:
|
|
111
111
|
version: '0'
|
112
112
|
type: :development
|
113
113
|
prerelease: false
|
114
|
-
version_requirements: *
|
114
|
+
version_requirements: *70278308418280
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
116
|
name: rspec-expectations
|
117
|
-
requirement: &
|
117
|
+
requirement: &70278308417680 !ruby/object:Gem::Requirement
|
118
118
|
none: false
|
119
119
|
requirements:
|
120
120
|
- - ! '>='
|
@@ -122,10 +122,10 @@ dependencies:
|
|
122
122
|
version: '0'
|
123
123
|
type: :development
|
124
124
|
prerelease: false
|
125
|
-
version_requirements: *
|
125
|
+
version_requirements: *70278308417680
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: rr
|
128
|
-
requirement: &
|
128
|
+
requirement: &70278308417200 !ruby/object:Gem::Requirement
|
129
129
|
none: false
|
130
130
|
requirements:
|
131
131
|
- - ~>
|
@@ -133,10 +133,10 @@ dependencies:
|
|
133
133
|
version: '1.0'
|
134
134
|
type: :development
|
135
135
|
prerelease: false
|
136
|
-
version_requirements: *
|
136
|
+
version_requirements: *70278308417200
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
138
|
name: faker
|
139
|
-
requirement: &
|
139
|
+
requirement: &70278308416500 !ruby/object:Gem::Requirement
|
140
140
|
none: false
|
141
141
|
requirements:
|
142
142
|
- - ~>
|
@@ -144,21 +144,21 @@ dependencies:
|
|
144
144
|
version: 0.9.5
|
145
145
|
type: :development
|
146
146
|
prerelease: false
|
147
|
-
version_requirements: *
|
147
|
+
version_requirements: *70278308416500
|
148
148
|
- !ruby/object:Gem::Dependency
|
149
149
|
name: yard
|
150
|
-
requirement: &
|
150
|
+
requirement: &70278308471460 !ruby/object:Gem::Requirement
|
151
151
|
none: false
|
152
152
|
requirements:
|
153
153
|
- - ~>
|
154
154
|
- !ruby/object:Gem::Version
|
155
|
-
version: 0.7.
|
155
|
+
version: 0.7.4
|
156
156
|
type: :development
|
157
157
|
prerelease: false
|
158
|
-
version_requirements: *
|
158
|
+
version_requirements: *70278308471460
|
159
159
|
- !ruby/object:Gem::Dependency
|
160
160
|
name: redcarpet
|
161
|
-
requirement: &
|
161
|
+
requirement: &70278308470480 !ruby/object:Gem::Requirement
|
162
162
|
none: false
|
163
163
|
requirements:
|
164
164
|
- - ~>
|
@@ -166,7 +166,7 @@ dependencies:
|
|
166
166
|
version: 1.17.2
|
167
167
|
type: :development
|
168
168
|
prerelease: false
|
169
|
-
version_requirements: *
|
169
|
+
version_requirements: *70278308470480
|
170
170
|
description: This git commit notifier sends html mails with nice diffs for every changed
|
171
171
|
file.
|
172
172
|
email: bodo@bitboxer.de
|
@@ -237,7 +237,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
237
237
|
version: '0'
|
238
238
|
segments:
|
239
239
|
- 0
|
240
|
-
hash: -
|
240
|
+
hash: -2647894486101160074
|
241
241
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
242
242
|
none: false
|
243
243
|
requirements:
|