git-commit-notifier 0.10.5 → 0.11.0
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/.yardopts +3 -1
- data/README.md +2 -2
- data/VERSION +1 -1
- data/config/git-notifier-config.example.yml +49 -4
- data/git-commit-notifier.gemspec +1 -1
- data/lib/git_commit_notifier/commit_hook.rb +59 -15
- data/lib/git_commit_notifier/diff_to_html.rb +100 -34
- data/lib/git_commit_notifier/emailer.rb +72 -15
- data/lib/git_commit_notifier/executor.rb +6 -0
- data/lib/git_commit_notifier/git.rb +27 -2
- data/spec/lib/git_commit_notifier/commit_hook_spec.rb +3 -3
- data/spec/lib/git_commit_notifier/diff_to_html_spec.rb +20 -20
- data/spec/lib/git_commit_notifier/git_spec.rb +3 -3
- metadata +31 -31
data/.yardopts
CHANGED
data/README.md
CHANGED
@@ -102,7 +102,7 @@ old commits in processes of forking, branching etc.
|
|
102
102
|
|
103
103
|
## Note on Patches/Pull Requests
|
104
104
|
|
105
|
-
* Fork the project.
|
105
|
+
* Fork [the project](https://github.com/bitboxer/git-commit-notifier).
|
106
106
|
* Make your feature addition or bug fix.
|
107
107
|
* Add tests for it. This is important so I don't break it in a
|
108
108
|
future version unintentionally.
|
@@ -126,5 +126,5 @@ Thanks for [putpat.tv](http://www.putpat.tv), [Primalgrasp](http://www.primalgra
|
|
126
126
|
|
127
127
|
## License
|
128
128
|
|
129
|
-
MIT License, see the file
|
129
|
+
MIT License, see the {file:LICENSE}.
|
130
130
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0
|
@@ -4,11 +4,40 @@ ignore_merge: false
|
|
4
4
|
# Optional parameter for the subject-line of the mail
|
5
5
|
# emailprefix: GIT
|
6
6
|
|
7
|
-
#
|
8
|
-
|
7
|
+
# Set limit on maximum number of lines per file diff
|
8
|
+
lines_per_diff: 300
|
9
9
|
|
10
10
|
# Show file list only when too many files
|
11
|
-
|
11
|
+
too_many_files: 50
|
12
|
+
|
13
|
+
# Whether to expand css inline. May be compatible with more mail readers
|
14
|
+
# but consumes much more space and more cpu. Defaults to true
|
15
|
+
# expand_css: true
|
16
|
+
|
17
|
+
# Determine whether to add plaintext alternative section to generated email.
|
18
|
+
# This allows text-only readers an option, but greatly increases the size
|
19
|
+
# of generated emails. Defaults to true
|
20
|
+
# add_plaintext: true
|
21
|
+
|
22
|
+
# Subject: the subject may be set by specifying a template.
|
23
|
+
#
|
24
|
+
# Substitution into the template is available for the following
|
25
|
+
# words, via the form ${word}
|
26
|
+
#
|
27
|
+
# prefix - The emailprefix set, defaulting to repo_name
|
28
|
+
# repo_name - Name of the git repo
|
29
|
+
# branch_name - Name of the git branch (master is "" unless show_master_branch_name)
|
30
|
+
# commit_id - The git commit id (hash)
|
31
|
+
# message - The commit message
|
32
|
+
# commit_number - The commit number within the push; 1-based
|
33
|
+
# commit_count - The number of commits within the push
|
34
|
+
# commit_count_phrase - The number of commits, as "1 commit", "2 commits", etc.
|
35
|
+
#
|
36
|
+
# The default subject template varies a little depending on whether
|
37
|
+
# or not group_email_by_push is set.
|
38
|
+
#
|
39
|
+
#subject: "[${prefix}${branch_name}] ${commit_count_phrase}: ${message}"
|
40
|
+
#subject: "[${prefix}${branch_name}][${commit_number}] ${message}"
|
12
41
|
|
13
42
|
# defines what branches to email for (defaults to all)
|
14
43
|
# include_branches: ['master', 'some_other_branch']
|
@@ -68,7 +97,8 @@ nntp_settings:
|
|
68
97
|
address: your.nntp.host.here
|
69
98
|
port: 119
|
70
99
|
|
71
|
-
# Decorate files and commit ids with link to a webview. Possible values: none, gitweb,
|
100
|
+
# Decorate files and commit ids with link to a webview. Possible values: none, gitweb,
|
101
|
+
# gitorious, cgit, trac, gitlabhq, or redmine
|
72
102
|
link_files: none
|
73
103
|
|
74
104
|
# If link_files is set to "gitweb", you need to configure the path to your gitweb
|
@@ -94,6 +124,21 @@ cgit:
|
|
94
124
|
trac:
|
95
125
|
path: http://example.com/changeset
|
96
126
|
|
127
|
+
# If link_files is set to "gitlabhq", you need to configure the path to your gitlabhq
|
128
|
+
# instance
|
129
|
+
gitlabhq:
|
130
|
+
path: http://gitlabhq.example.com
|
131
|
+
version: 1.2
|
132
|
+
|
133
|
+
# If link_files is set to "redmine", you need to configure the path to your redmine
|
134
|
+
# instance
|
135
|
+
redmine:
|
136
|
+
path: http://redmine.example.com
|
137
|
+
# project: project-name
|
138
|
+
# keywords: [refs, fixes]
|
139
|
+
# project defaults to git repository name, keywords defaults to refs, fixes (for use with message_integration)
|
140
|
+
|
141
|
+
|
97
142
|
# commit message URL map
|
98
143
|
message_map:
|
99
144
|
# '\brefs\s*\#(\d+)': 'http://example.com/redmine/issues/show/\1'
|
data/git-commit-notifier.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
20
20
|
|
21
|
-
s.homepage = %q{http://github.com/
|
21
|
+
s.homepage = %q{http://bitboxer.github.com/git-commit-notifier/}
|
22
22
|
s.require_paths = ["lib"]
|
23
23
|
s.rubygems_version = %q{1.3.7}
|
24
24
|
s.summary = %q{Sends git commit messages with diffs}
|
@@ -47,11 +47,9 @@ module GitCommitNotifier
|
|
47
47
|
project_path = Dir.getwd
|
48
48
|
recipient = config["mailinglist"] || Git.mailing_list_address
|
49
49
|
|
50
|
+
# If no recipients specified, bail out gracefully. This is not an error, and might be intentional
|
50
51
|
if recipient.nil? || recipient.length == 0
|
51
|
-
|
52
|
-
"Please add a recipient for the emails. Eg : \n" +
|
53
|
-
" git config hooks.mailinglist developer@example.com"
|
54
|
-
)
|
52
|
+
info("bypassing commit notification; no recipients specified (consider setting git config hooks.mailinglist)")
|
55
53
|
return
|
56
54
|
end
|
57
55
|
|
@@ -62,7 +60,9 @@ module GitCommitNotifier
|
|
62
60
|
logger.debug("rev2: #{rev2}")
|
63
61
|
logger.debug("included branches: #{include_branches.join(', ')}") unless include_branches.nil?
|
64
62
|
|
65
|
-
|
63
|
+
repo_name = Git.repo_name
|
64
|
+
prefix = config["emailprefix"] || repo_name
|
65
|
+
|
66
66
|
branch_name = if ref_name =~ /^refs\/heads\/(.+)$/
|
67
67
|
$1
|
68
68
|
else
|
@@ -76,10 +76,30 @@ module GitCommitNotifier
|
|
76
76
|
info("Supressing mail for branch #{branch_name}...")
|
77
77
|
return
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
branch_name = "/#{branch_name}"
|
81
81
|
branch_name = "" if !config["show_master_branch_name"] && branch_name == '/master'
|
82
|
-
|
82
|
+
|
83
|
+
# Replacements for subject template
|
84
|
+
# prefix
|
85
|
+
# repo_name
|
86
|
+
# branch_name
|
87
|
+
# commit_id (hash)
|
88
|
+
# short_message
|
89
|
+
# commit_number
|
90
|
+
# commit_count
|
91
|
+
# commit_count_phrase (1 commit, 2 commits, etc)
|
92
|
+
subject_words = {
|
93
|
+
:prefix => prefix,
|
94
|
+
:repo_name => repo_name,
|
95
|
+
:branch_name => branch_name,
|
96
|
+
:commit_id => nil,
|
97
|
+
:message => nil,
|
98
|
+
:commit_number => nil,
|
99
|
+
:commit_count => nil,
|
100
|
+
:commit_count_phrase => nil
|
101
|
+
}
|
102
|
+
|
83
103
|
info("Sending mail...")
|
84
104
|
|
85
105
|
diff2html = DiffToHtml.new(Dir.pwd, config)
|
@@ -102,39 +122,63 @@ module GitCommitNotifier
|
|
102
122
|
text << result[:text_content]
|
103
123
|
html << result[:html_content]
|
104
124
|
end
|
125
|
+
|
126
|
+
# Form the subject from template
|
127
|
+
revised_subject_words = subject_words.merge({
|
128
|
+
:commit_id => result[:commit_info][:commit],
|
129
|
+
:message => result[:commit_info][:message],
|
130
|
+
:commit_number => 1,
|
131
|
+
:commit_count => diffresult.size,
|
132
|
+
:commit_count_phrase => diffresult.size == 1 ? "#{diffresult.size} commit" : "#{diffresult.size} commits"
|
133
|
+
})
|
134
|
+
subject_template = config['subject'] || "[${prefix}${branch_name}] ${commit_count_phrase}: ${message}"
|
135
|
+
subject = subject_template.gsub(/\$\{(\w+)\}/) { |m| revised_subject_words[$1.intern] }
|
105
136
|
|
106
137
|
emailer = Emailer.new(config,
|
107
138
|
:project_path => project_path,
|
108
139
|
:recipient => recipient,
|
109
140
|
:from_address => config["from"] || result[:commit_info][:email],
|
110
141
|
:from_alias => result[:commit_info][:author],
|
111
|
-
:subject =>
|
142
|
+
:subject => subject,
|
112
143
|
:text_message => text.join("------------------------------------------\n\n"),
|
113
144
|
:html_message => html.join("<hr /><br />"),
|
114
145
|
:old_rev => rev1,
|
115
146
|
:new_rev => rev2,
|
116
|
-
:ref_name => ref_name
|
147
|
+
:ref_name => ref_name,
|
148
|
+
:repo_name => repo_name
|
117
149
|
)
|
118
150
|
emailer.send
|
119
151
|
else
|
120
|
-
|
152
|
+
commit_number = 1
|
121
153
|
diff2html.diff_between_revisions(rev1, rev2, prefix, ref_name) do |result|
|
122
|
-
next
|
123
|
-
|
154
|
+
next if config["ignore_merge"] && merge_commit?(result)
|
155
|
+
|
156
|
+
# Form the subject from template
|
157
|
+
revised_subject_words = subject_words.merge({
|
158
|
+
:commit_id => result[:commit_info][:commit],
|
159
|
+
:message => result[:commit_info][:message],
|
160
|
+
:commit_number => commit_number,
|
161
|
+
:commit_count => 1,
|
162
|
+
:commit_count_phrase => "1 commit"
|
163
|
+
})
|
164
|
+
subject_template = config['subject'] || "[${prefix}${branch_name}][${commit_number}] ${message}"
|
165
|
+
subject = subject_template.gsub(/\$\{(\w+)\}/) { |m| revised_subject_words[$1.intern] }
|
166
|
+
|
124
167
|
emailer = Emailer.new(config,
|
125
168
|
:project_path => project_path,
|
126
169
|
:recipient => recipient,
|
127
170
|
:from_address => config["from"] || result[:commit_info][:email],
|
128
171
|
:from_alias => result[:commit_info][:author],
|
129
|
-
:subject =>
|
172
|
+
:subject => subject,
|
130
173
|
:text_message => result[:text_content],
|
131
174
|
:html_message => result[:html_content],
|
132
175
|
:old_rev => rev1,
|
133
176
|
:new_rev => rev2,
|
134
|
-
:ref_name => ref_name
|
177
|
+
:ref_name => ref_name,
|
178
|
+
:repo_name => repo_name
|
135
179
|
)
|
136
180
|
emailer.send
|
137
|
-
|
181
|
+
commit_number += 1
|
138
182
|
end
|
139
183
|
end
|
140
184
|
end
|
@@ -10,20 +10,27 @@ module GitCommitNotifier
|
|
10
10
|
|
11
11
|
INTEGRATION_MAP = {
|
12
12
|
:mediawiki => { :search_for => /\[\[([^\[\]]+)\]\]/, :replace_with => '#{url}/\1' },
|
13
|
-
:redmine => {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
:redmine => {
|
14
|
+
:search_for => lambda do |config|
|
15
|
+
keywords = (config['redmine'] && config['redmine']['keywords']) || ["refs", "fixes"]
|
16
|
+
/\b(?:#{keywords.join('\b|')})([\s&,]+\#\d+)+/i
|
17
|
+
end,
|
18
|
+
:replace_with => lambda do |m, url, config|
|
19
|
+
# we can provide Proc that gets matched string and configuration url.
|
20
|
+
# result should be in form of:
|
21
|
+
# { :phrase => 'phrase started with', :links => [ { :title => 'title of url', :url => 'target url' }, ... ] }
|
22
|
+
keywords = (config['redmine'] && config['redmine']['keywords']) || ["refs", "fixes"]
|
23
|
+
match = m.match(/^(#{keywords.join('\b|')})(.*)$/i)
|
24
|
+
return m unless match
|
25
|
+
r = { :phrase => match[1] }
|
26
|
+
captures = match[2].split(/[\s\&\,]+/).map { |m| (m =~ /(\d+)/) ? $1 : m }.reject { |c| c.empty? }
|
27
|
+
r[:links] = captures.map { |mn| { :title => "##{mn}", :url => "#{url}/issues/show/#{mn}" } }
|
28
|
+
r
|
29
|
+
end },
|
24
30
|
:bugzilla => { :search_for => /\bBUG\s*(\d+)/i, :replace_with => '#{url}/show_bug.cgi?id=\1' },
|
25
31
|
:fogbugz => { :search_for => /\bbugzid:\s*(\d+)/i, :replace_with => '#{url}\1' }
|
26
32
|
}.freeze
|
33
|
+
MAX_LINE_LENGTH = 512
|
27
34
|
MAX_COMMITS_PER_ACTION = 10000
|
28
35
|
HANDLED_COMMITS_FILE = 'previously.txt'.freeze
|
29
36
|
NEW_HANDLED_COMMITS_FILE = 'previously_new.txt'.freeze
|
@@ -64,17 +71,13 @@ module GitCommitNotifier
|
|
64
71
|
end
|
65
72
|
|
66
73
|
def lines_per_diff
|
67
|
-
config['lines_per_diff']
|
74
|
+
@config['lines_per_diff']
|
68
75
|
end
|
69
76
|
|
70
|
-
def
|
77
|
+
def ignore_whitespaces?
|
71
78
|
@config['ignore_whitespace'].nil? || @config['ignore_whitespace']
|
72
79
|
end
|
73
80
|
|
74
|
-
def skip_lines?
|
75
|
-
lines_per_diff && (@lines_added >= lines_per_diff)
|
76
|
-
end
|
77
|
-
|
78
81
|
def add_separator
|
79
82
|
@diff_result << '<tr class="sep"><td class="sep" colspan="3" title="Unchanged content skipped between diff. blocks">…</td></tr>'
|
80
83
|
end
|
@@ -84,7 +87,6 @@ module GitCommitNotifier
|
|
84
87
|
end
|
85
88
|
|
86
89
|
def add_line_to_result(line, escape)
|
87
|
-
@lines_added += 1
|
88
90
|
klass = line_class(line)
|
89
91
|
content = (escape == :escape) ? escape_content(line[:content]) : line[:content]
|
90
92
|
padding = ' ' if klass != ''
|
@@ -155,7 +157,8 @@ module GitCommitNotifier
|
|
155
157
|
end
|
156
158
|
|
157
159
|
file_name = @current_file_name
|
158
|
-
|
160
|
+
|
161
|
+
# TODO: these filenames, etc, should likely be properly html escaped
|
159
162
|
if config['link_files']
|
160
163
|
file_name = if config["link_files"] == "gitweb" && config["gitweb"]
|
161
164
|
"<a href='#{config['gitweb']['path']}?p=#{Git.repo_name}.git;f=#{file_name};h=#{@current_sha};hb=#{@current_commit}'>#{file_name}</a>"
|
@@ -163,10 +166,18 @@ module GitCommitNotifier
|
|
163
166
|
"<a href='#{config['gitorious']['path']}/#{config['gitorious']['project']}/#{config['gitorious']['repository']}/blobs/#{branch_name}/#{file_name}'>#{file_name}</a>"
|
164
167
|
elsif config["link_files"] == "cgit" && config["cgit"]
|
165
168
|
"<a href='#{config['cgit']['path']}/#{config['cgit']['project']}/tree/#{file_name}'>#{file_name}</a>"
|
169
|
+
elsif config["link_files"] == "gitlabhq" && config["gitlabhq"]
|
170
|
+
if config["gitlabhq"]["version"] && config["gitlabhq"]["version"] < 1.2
|
171
|
+
"<a href='#{config['gitlabhq']['path']}/#{Git.repo_name.gsub(".", "_")}/tree/#{@current_commit}/#{file_name}'>#{file_name}</a>"
|
172
|
+
else
|
173
|
+
"<a href='#{config['gitlabhq']['path']}/#{Git.repo_name.gsub(".", "_")}/#{@current_commit}/tree/#{file_name}'>#{file_name}</a>"
|
174
|
+
end
|
175
|
+
elsif config["link_files"] == "redmine" && config["redmine"]
|
176
|
+
"<a href='#{config['redmine']['path']}/projects/#{config['redmine']['project'] || Git.repo_name}/repository/revisions/#{@current_commit}/entry/#{file_name}'>#{file_name}</a>"
|
166
177
|
else
|
167
178
|
file_name
|
168
179
|
end
|
169
|
-
|
180
|
+
end
|
170
181
|
|
171
182
|
header = "#{op} #{binary}file #{file_name}"
|
172
183
|
"<h2>#{header}</h2>\n"
|
@@ -184,19 +195,26 @@ module GitCommitNotifier
|
|
184
195
|
|
185
196
|
def add_changes_to_result
|
186
197
|
return if @current_file_name.nil?
|
198
|
+
|
199
|
+
@lines_added = 0
|
187
200
|
@diff_result << operation_description
|
188
201
|
if !@diff_lines.empty? && !@too_many_files
|
189
202
|
@diff_result << '<table>'
|
190
203
|
removals = []
|
191
204
|
additions = []
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
205
|
+
|
206
|
+
lines = if lines_per_diff.nil?
|
207
|
+
line_budget = nil
|
208
|
+
@diff_lines
|
209
|
+
else
|
210
|
+
line_budget = lines_per_diff - @lines_added
|
211
|
+
@diff_lines.slice(0, line_budget)
|
212
|
+
end
|
213
|
+
|
214
|
+
lines.each_with_index do |line, index|
|
197
215
|
removals << line if line[:op] == :removal
|
198
216
|
additions << line if line[:op] == :addition
|
199
|
-
if line[:op] == :unchanged || index ==
|
217
|
+
if line[:op] == :unchanged || index == lines.size - 1 # unchanged line or end of block, add prev lines to result
|
200
218
|
if removals.size > 0 && additions.size > 0 # block of removed and added lines - perform intelligent diff
|
201
219
|
add_block_to_results(lcs_diff(removals, additions), :dont_escape)
|
202
220
|
else # some lines removed or added - no need to perform intelligent diff
|
@@ -204,14 +222,17 @@ module GitCommitNotifier
|
|
204
222
|
end
|
205
223
|
removals = []
|
206
224
|
additions = []
|
207
|
-
if index > 0 && index !=
|
208
|
-
prev_line =
|
225
|
+
if index > 0 && index != lines.size - 1
|
226
|
+
prev_line = lines[index - 1]
|
209
227
|
add_separator unless lines_are_sequential?(prev_line, line)
|
210
228
|
end
|
211
229
|
add_line_to_result(line, :escape) if line[:op] == :unchanged
|
212
230
|
end
|
213
|
-
|
231
|
+
@lines_added += 1
|
214
232
|
end
|
233
|
+
|
234
|
+
add_skip_notification if !line_budget.nil? && line_budget < @diff_lines.size
|
235
|
+
|
215
236
|
@diff_result << '</table>'
|
216
237
|
@diff_lines = []
|
217
238
|
end
|
@@ -424,10 +445,50 @@ module GitCommitNotifier
|
|
424
445
|
def merge_commit?(commit_info)
|
425
446
|
! commit_info[:merge].nil?
|
426
447
|
end
|
448
|
+
|
449
|
+
def truncate_long_lines(text)
|
450
|
+
StringIO.open("", "w") do |output|
|
451
|
+
# Match encoding of output string to that of input string
|
452
|
+
output.string.force_encoding(text.encoding) if output.string.respond_to?(:force_encoding)
|
453
|
+
|
454
|
+
input = StringIO.new(text, "r")
|
455
|
+
input.each_line "\n" do |line|
|
456
|
+
if line.length > MAX_LINE_LENGTH && MAX_LINE_LENGTH >= 9
|
457
|
+
# Truncate the line
|
458
|
+
line.slice!(MAX_LINE_LENGTH-3..-1)
|
459
|
+
|
460
|
+
# Ruby < 1.9 doesn't know how to slice between
|
461
|
+
# characters, so deal specially with that case
|
462
|
+
# so that we don't truncate in the middle of a UTF8 sequence,
|
463
|
+
# which would be invalid.
|
464
|
+
if !line.respond_to?(:force_encoding)
|
465
|
+
# If the last remaining character is part of a UTF8 multibyte character,
|
466
|
+
# keep truncating until we go past the start of a UTF8 character.
|
467
|
+
# This assumes that this is a UTF8 string, which may be a false assumption
|
468
|
+
# unless somebody has taken care to check the encoding of the source file.
|
469
|
+
# We truncate at most 6 additional bytes, which is the length of the longest
|
470
|
+
# UTF8 sequence
|
471
|
+
6.times do
|
472
|
+
c = line[-1, 1].to_i
|
473
|
+
break if (c & 0x80) == 0 # Last character is plain ASCII: don't truncate
|
474
|
+
line.slice!(-1, 1) # Truncate character
|
475
|
+
break if (c & 0xc0) == 0xc0 # Last character was the start of a UTF8 sequence, so we can stop now
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
# Append three dots to the end of line to indicate it's been truncated
|
480
|
+
# (avoiding ellipsis character so as not to introduce more encoding issues)
|
481
|
+
line << "...\n"
|
482
|
+
end
|
483
|
+
output << line
|
484
|
+
end
|
485
|
+
output.string
|
486
|
+
end
|
487
|
+
end
|
427
488
|
|
428
489
|
def diff_for_commit(commit)
|
429
490
|
@current_commit = commit
|
430
|
-
raw_diff = Git.show(commit,
|
491
|
+
raw_diff = truncate_long_lines(Git.show(commit, :ignore_whitespaces => ignore_whitespaces?))
|
431
492
|
raise "git show output is empty" if raw_diff.empty?
|
432
493
|
|
433
494
|
commit_info = extract_commit_info_from_git_show_output(raw_diff)
|
@@ -457,6 +518,10 @@ module GitCommitNotifier
|
|
457
518
|
"<a href='#{config['trac']['path']}/#{commit_info[:commit]}'>#{commit_info[:commit]}</a>"
|
458
519
|
elsif config["link_files"] == "cgit" && config["cgit"]
|
459
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>"
|
460
525
|
else
|
461
526
|
" #{commit_info[:commit]}"
|
462
527
|
end
|
@@ -504,13 +569,12 @@ module GitCommitNotifier
|
|
504
569
|
[]
|
505
570
|
else
|
506
571
|
log = Git.log(rev1, rev2)
|
507
|
-
log.scan(/^commit\s([a-f0-9]+)/).map { |a| a.first }
|
572
|
+
log.scan(/^commit\s([a-f0-9]+)/).map { |a| a.first }.reverse
|
508
573
|
end
|
509
574
|
|
510
575
|
commits = check_handled_commits(commits)
|
511
576
|
|
512
577
|
commits.each do |commit|
|
513
|
-
@lines_added = 0 unless config["group_email_by_push"]
|
514
578
|
begin
|
515
579
|
commit_result = diff_for_commit(commit)
|
516
580
|
next if commit_result.nil?
|
@@ -539,9 +603,11 @@ module GitCommitNotifier
|
|
539
603
|
return message unless config['message_integration'].respond_to?(:each_pair)
|
540
604
|
config['message_integration'].each_pair do |pm, url|
|
541
605
|
pm_def = DiffToHtml::INTEGRATION_MAP[pm.to_sym] or next
|
606
|
+
search_for = pm_def[:search_for]
|
607
|
+
search_for = search_for.kind_of?(Proc) ? search_for.call(@config) : search_for
|
542
608
|
replace_with = pm_def[:replace_with]
|
543
|
-
replace_with = replace_with.kind_of?(Proc) ? lambda { |m| pm_def[:replace_with].call(m, url) } : replace_with.gsub('#{url}', url)
|
544
|
-
message_replace!(message,
|
609
|
+
replace_with = replace_with.kind_of?(Proc) ? lambda { |m| pm_def[:replace_with].call(m, url, @config) } : replace_with.gsub('#{url}', url)
|
610
|
+
message_replace!(message, search_for, replace_with)
|
545
611
|
end
|
546
612
|
message
|
547
613
|
end
|
@@ -3,7 +3,7 @@ require 'premailer'
|
|
3
3
|
class GitCommitNotifier::Emailer
|
4
4
|
DEFAULT_STYLESHEET_PATH = File.join(File.dirname(__FILE__), '/../../template/styles.css').freeze
|
5
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
|
+
PARAMETERS = %w[project_path recipient from_address from_alias subject text_message html_message repo_name ref_name old_rev new_rev].freeze
|
7
7
|
|
8
8
|
def config
|
9
9
|
@@config
|
@@ -43,8 +43,11 @@ class GitCommitNotifier::Emailer
|
|
43
43
|
|
44
44
|
def mail_html_message
|
45
45
|
html = GitCommitNotifier::Emailer.template.result(binding)
|
46
|
-
|
47
|
-
|
46
|
+
if config['expand_css'].nil? || config['expand_css']
|
47
|
+
premailer = Premailer.new(html, :with_html_string => true, :adapter => :nokogiri)
|
48
|
+
html = premailer.to_inline_css
|
49
|
+
end
|
50
|
+
html
|
48
51
|
end
|
49
52
|
|
50
53
|
def boundary
|
@@ -78,10 +81,13 @@ class GitCommitNotifier::Emailer
|
|
78
81
|
main_smtp.start( settings['domain'],
|
79
82
|
settings['user_name'], settings['password'], settings['authentication']) do |smtp|
|
80
83
|
|
81
|
-
|
82
|
-
|
84
|
+
recipients = @recipient.dup
|
85
|
+
recipients.force_encoding('ASCII-8BIT') if recipients.respond_to?(:force_encoding)
|
86
|
+
recipients = recipients.split(",")
|
87
|
+
smtp.open_message_stream(@from_address, recipients) do |f|
|
83
88
|
content.each do |line|
|
84
|
-
|
89
|
+
line.force_encoding('ASCII-8BIT') if line.respond_to?(:force_encoding)
|
90
|
+
f.print(line, "\r\n")
|
85
91
|
end
|
86
92
|
end
|
87
93
|
end
|
@@ -94,7 +100,9 @@ class GitCommitNotifier::Emailer
|
|
94
100
|
}.merge(options || {})
|
95
101
|
command = "#{sendmail_settings['location']} #{sendmail_settings['arguments']}"
|
96
102
|
IO.popen(command, "w+") do |f|
|
97
|
-
|
103
|
+
content.each do |line|
|
104
|
+
f.print(line, "\r\n")
|
105
|
+
end
|
98
106
|
f.flush
|
99
107
|
end
|
100
108
|
end
|
@@ -110,27 +118,37 @@ class GitCommitNotifier::Emailer
|
|
110
118
|
to_tag = config['delivery_method'] == 'nntp' ? 'Newsgroups' : 'To'
|
111
119
|
quoted_from_alias = quote_if_necessary("#{@from_alias}",'utf-8')
|
112
120
|
from = @from_alias.empty? ? @from_address : "#{quoted_from_alias} <#{@from_address}>"
|
121
|
+
|
122
|
+
plaintext = if config['add_plaintext'].nil? || config['add_plaintext']
|
123
|
+
@text_message
|
124
|
+
else
|
125
|
+
"Plain text part omitted. Consider setting add_plaintext in configuration."
|
126
|
+
end
|
113
127
|
|
114
128
|
content = [
|
115
129
|
"From: #{from}",
|
116
130
|
"#{to_tag}: #{quote_if_necessary(@recipient, 'utf-8')}",
|
117
131
|
"Subject: #{quote_if_necessary(@subject, 'utf-8')}",
|
118
132
|
"X-Mailer: git-commit-notifier",
|
133
|
+
"X-Git-Repository: #{@repo_name}",
|
119
134
|
"X-Git-Refname: #{@ref_name}",
|
120
135
|
"X-Git-Oldrev: #{@old_rev}",
|
121
136
|
"X-Git-Newrev: #{@new_rev}",
|
122
137
|
"Mime-Version: 1.0",
|
123
|
-
"Content-Type: multipart/alternative; boundary=#{boundary}
|
138
|
+
"Content-Type: multipart/alternative; boundary=#{boundary}",
|
139
|
+
"",
|
124
140
|
"--#{boundary}",
|
125
141
|
"Content-Type: text/plain; charset=utf-8",
|
126
|
-
"Content-Transfer-Encoding:
|
127
|
-
"Content-Disposition: inline
|
128
|
-
|
129
|
-
|
142
|
+
"Content-Transfer-Encoding: quoted-printable",
|
143
|
+
"Content-Disposition: inline",
|
144
|
+
"",
|
145
|
+
encode_quoted_printable_message(plaintext),
|
146
|
+
"--#{boundary}",
|
130
147
|
"Content-Type: text/html; charset=utf-8",
|
131
|
-
"Content-Transfer-Encoding:
|
132
|
-
"Content-Disposition: inline
|
133
|
-
|
148
|
+
"Content-Transfer-Encoding: quoted-printable",
|
149
|
+
"Content-Disposition: inline",
|
150
|
+
"",
|
151
|
+
encode_quoted_printable_message(mail_html_message),
|
134
152
|
"--#{boundary}--"]
|
135
153
|
|
136
154
|
if @recipient.empty?
|
@@ -147,6 +165,45 @@ class GitCommitNotifier::Emailer
|
|
147
165
|
end
|
148
166
|
end
|
149
167
|
|
168
|
+
# Convert a message into quoted printable encoding,
|
169
|
+
# limiting line length to 76 characters per spec
|
170
|
+
# Encoding messages in this way ensures that they
|
171
|
+
# won't violate rules for maximum line length, which
|
172
|
+
# can result in the MTA breaking lines at inconvenient points,
|
173
|
+
# such as in the middle of UTF8 characters.
|
174
|
+
def encode_quoted_printable_message(text)
|
175
|
+
StringIO.open("", "w") do |output|
|
176
|
+
# Character encoding of output string can be plain US-ASCII since quoted-printable is plain ASCII
|
177
|
+
output.string.force_encoding("US-ASCII") if output.string.respond_to?(:force_encoding)
|
178
|
+
|
179
|
+
line_max = 76
|
180
|
+
line_len = 0
|
181
|
+
|
182
|
+
input = StringIO.new(text, "r")
|
183
|
+
input.each_byte do |b|
|
184
|
+
case (b)
|
185
|
+
when 9, 32..60, 62..126
|
186
|
+
if line_len >= line_max - 1
|
187
|
+
output << "=\r\n"
|
188
|
+
line_len = 0
|
189
|
+
end
|
190
|
+
output << b.chr
|
191
|
+
line_len += 1
|
192
|
+
else
|
193
|
+
if line_len >= line_max - 3
|
194
|
+
output << "=\r\n"
|
195
|
+
line_len = 0
|
196
|
+
end
|
197
|
+
output << "=%02X" % b
|
198
|
+
line_len += 3
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
output << "=\r\n" if line_len > 0
|
203
|
+
output.string
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
150
207
|
# Convert the given text into quoted printable format, with an instruction
|
151
208
|
# that the text be eventually interpreted in the given charset.
|
152
209
|
def quoted_printable(text, charset)
|
@@ -2,8 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'git_commit_notifier'
|
4
4
|
|
5
|
+
# Git commit notifier namespace
|
5
6
|
module GitCommitNotifier
|
7
|
+
# binaries code
|
6
8
|
class Executor
|
9
|
+
# runs git commit notifier life
|
10
|
+
# @param [Array(String)] args Command line arguments
|
11
|
+
# @return [nil] Nothing
|
7
12
|
def self.run!(args)
|
8
13
|
case args.length
|
9
14
|
when 0
|
@@ -24,6 +29,7 @@ module GitCommitNotifier
|
|
24
29
|
else
|
25
30
|
GitCommitNotifier::CommitHook.run args.first, args[1], args[2], args[3]
|
26
31
|
end
|
32
|
+
nil
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -1,5 +1,9 @@
|
|
1
|
+
# Git methods
|
1
2
|
class GitCommitNotifier::Git
|
2
3
|
class << self
|
4
|
+
# Runs specified command.
|
5
|
+
# @return (String) Shell command STDOUT (forced to UTF-8)
|
6
|
+
# @raise [ArgumentError] when command exits with nonzero status.
|
3
7
|
def from_shell(cmd)
|
4
8
|
r = `#{cmd}`
|
5
9
|
raise ArgumentError.new("#{cmd} failed") unless $?.exitstatus.zero?
|
@@ -7,19 +11,38 @@ class GitCommitNotifier::Git
|
|
7
11
|
r
|
8
12
|
end
|
9
13
|
|
10
|
-
|
14
|
+
# runs `git show`
|
15
|
+
# @note uses "--pretty=fuller" option.
|
16
|
+
# @return [String] Its output
|
17
|
+
# @see from_shell
|
18
|
+
# @param [String] rev Revision
|
19
|
+
# @param [Hash] opts Options
|
20
|
+
# @option opts [Boolean] :ignore_whitespaces Ignore whitespaces or not
|
21
|
+
def show(rev, opts = {})
|
11
22
|
gitopt = ""
|
12
23
|
gitopt += " --pretty=fuller"
|
13
|
-
gitopt += " -w" if
|
24
|
+
gitopt += " -w" if opts[:ignore_whitespaces]
|
14
25
|
data = from_shell("git show #{rev.strip}#{gitopt}")
|
15
26
|
data
|
16
27
|
end
|
17
28
|
|
29
|
+
# runs `git log`
|
30
|
+
# @note uses "--pretty=fuller" option.
|
31
|
+
# @return [String] Its output
|
32
|
+
# @see from_shell
|
33
|
+
# @param [String] rev1 First revision
|
34
|
+
# @param [String] rev2 Second revision
|
18
35
|
def log(rev1, rev2)
|
19
36
|
data = from_shell("git log --pretty=fuller #{rev1}..#{rev2}").strip
|
20
37
|
data
|
21
38
|
end
|
22
39
|
|
40
|
+
# runs `git log` and extract filenames only
|
41
|
+
# @note uses "--pretty=fuller" and "--name-status" options.
|
42
|
+
# @return [Array(String)] File names
|
43
|
+
# @see from_shell
|
44
|
+
# @param [String] rev1 First revision
|
45
|
+
# @param [String] rev2 Second revision
|
23
46
|
def changed_files(rev1, rev2)
|
24
47
|
output = ""
|
25
48
|
lines = from_shell("git log #{rev1}..#{rev2} --name-status --pretty=oneline")
|
@@ -59,6 +82,8 @@ class GitCommitNotifier::Git
|
|
59
82
|
|
60
83
|
def mailing_list_address
|
61
84
|
from_shell("git config hooks.mailinglist").strip
|
85
|
+
rescue ArgumentError
|
86
|
+
nil
|
62
87
|
end
|
63
88
|
end
|
64
89
|
end
|
@@ -75,7 +75,7 @@ describe GitCommitNotifier::CommitHook do
|
|
75
75
|
mock(GitCommitNotifier::Git).repo_name { 'testproject' }
|
76
76
|
mock(GitCommitNotifier::Git).changed_files('7e4f6b4', '4f13525') { [] }
|
77
77
|
REVISIONS.each do |rev|
|
78
|
-
mock(GitCommitNotifier::Git).show(rev, true) { IO.read(FIXTURES_PATH + "git_show_#{rev}") }
|
78
|
+
mock(GitCommitNotifier::Git).show(rev, :ignore_whitespaces => true) { IO.read(FIXTURES_PATH + "git_show_#{rev}") }
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -104,10 +104,10 @@ describe GitCommitNotifier::CommitHook do
|
|
104
104
|
end
|
105
105
|
|
106
106
|
describe :run do
|
107
|
-
it "should report
|
107
|
+
it "should report informational message when no recipients specified" do
|
108
108
|
mock(File).exists?(:noconfig) { false }
|
109
109
|
mock(GitCommitNotifier::Git).mailing_list_address { nil }
|
110
|
-
mock(GitCommitNotifier::CommitHook).
|
110
|
+
mock(GitCommitNotifier::CommitHook).info(/recipient/)
|
111
111
|
GitCommitNotifier::CommitHook.run(:noconfig, :rev1, :rev2, 'master')
|
112
112
|
end
|
113
113
|
end
|
@@ -129,9 +129,9 @@ describe GitCommitNotifier::DiffToHtml do
|
|
129
129
|
mock(GitCommitNotifier::Git).changed_files('7e4f6b4', '4f13525') { [] }
|
130
130
|
mock(GitCommitNotifier::Git).log(REVISIONS.first, REVISIONS.last) { IO.read(FIXTURES_PATH + 'git_log') }
|
131
131
|
REVISIONS.each do |rev|
|
132
|
-
mock(GitCommitNotifier::Git).show(rev, true) { IO.read(FIXTURES_PATH + 'git_show_' + rev) }
|
132
|
+
mock(GitCommitNotifier::Git).show(rev, :ignore_whitespaces => true) { IO.read(FIXTURES_PATH + 'git_show_' + rev) }
|
133
133
|
end
|
134
|
-
|
134
|
+
|
135
135
|
diff = GitCommitNotifier::DiffToHtml.new
|
136
136
|
mock(diff).check_handled_commits(anything) { |commits| commits }
|
137
137
|
diff.diff_between_revisions REVISIONS.first, REVISIONS.last, 'testproject', 'master'
|
@@ -142,22 +142,16 @@ describe GitCommitNotifier::DiffToHtml do
|
|
142
142
|
html.should_not be_include('@@') # diff correctly processed
|
143
143
|
end
|
144
144
|
|
145
|
-
#
|
146
|
-
hp = Nokogiri::HTML diff.result
|
147
|
-
(hp/"table").should have(
|
145
|
+
# second commit - 51b986619d88f7ba98be7d271188785cbbb541a0
|
146
|
+
hp = Nokogiri::HTML diff.result[1][:html_content]
|
147
|
+
(hp/"table").should have(3).tables # 3 files updated
|
148
148
|
(hp/"table"/"tr"/"td").each do |td|
|
149
|
-
if td.inner_html
|
150
|
-
|
151
|
-
|
152
|
-
td.parent.search('td')[1].inner_text.should == '2' # right
|
153
|
-
td.parent.search('td')[2].inner_html.should == "require 'iconv'" # change
|
149
|
+
if td.inner_html =~ /create_btn/
|
150
|
+
cols = td.parent.search('td')
|
151
|
+
['405', '408', ''].should be_include(cols[0].inner_text) # line 405 changed
|
154
152
|
end
|
155
153
|
end
|
156
154
|
|
157
|
-
# second commit
|
158
|
-
hp = Nokogiri::HTML diff.result[1][:html_content]
|
159
|
-
(hp/"table").should have(1).table # 1 file updated
|
160
|
-
|
161
155
|
# third commit - dce6ade4cdc2833b53bd600ef10f9bce83c7102d
|
162
156
|
hp = Nokogiri::HTML diff.result[2][:html_content]
|
163
157
|
(hp/"h2").should have(6).headers # 6 files in commit
|
@@ -167,13 +161,19 @@ describe GitCommitNotifier::DiffToHtml do
|
|
167
161
|
(hp/"h2")[3].inner_text.should == 'Deleted file railties/doc/guides/source/icons/README'
|
168
162
|
(hp/"h2")[4].inner_text.should == 'Added file railties/doc/guides/source/images/icons/README'
|
169
163
|
|
170
|
-
# fourth commit
|
164
|
+
# fourth commit
|
171
165
|
hp = Nokogiri::HTML diff.result[3][:html_content]
|
172
|
-
(hp/"table").should have(
|
166
|
+
(hp/"table").should have(1).table # 1 file updated
|
167
|
+
|
168
|
+
# fifth commit
|
169
|
+
hp = Nokogiri::HTML diff.result[4][:html_content]
|
170
|
+
(hp/"table").should have(2).tables # 2 files updated - one table for each of the files
|
173
171
|
(hp/"table"/"tr"/"td").each do |td|
|
174
|
-
if td.inner_html
|
175
|
-
|
176
|
-
|
172
|
+
if td.inner_html == "require 'iconv'"
|
173
|
+
# first added line in changeset a4629e707d80a5769f7a71ca6ed9471015e14dc9
|
174
|
+
td.parent.search('td')[0].inner_text.should == '' # left
|
175
|
+
td.parent.search('td')[1].inner_text.should == '2' # right
|
176
|
+
td.parent.search('td')[2].inner_html.should == "require 'iconv'" # change
|
177
177
|
end
|
178
178
|
end
|
179
179
|
end
|
@@ -182,7 +182,7 @@ describe GitCommitNotifier::DiffToHtml do
|
|
182
182
|
first_rev, last_rev = %w[ 0000000000000000000000000000000000000000 9b15cebcc5434e27c00a4a2acea43509f9faea21 ]
|
183
183
|
mock(GitCommitNotifier::Git).branch_commits('rvm') { %w[ ff037a73fc1094455e7bbf506171a3f3cf873ae6 ] }
|
184
184
|
%w[ ff037a73fc1094455e7bbf506171a3f3cf873ae6 ].each do |rev|
|
185
|
-
mock(GitCommitNotifier::Git).show(rev, true) { IO.read(FIXTURES_PATH + 'git_show_' + rev) }
|
185
|
+
mock(GitCommitNotifier::Git).show(rev, :ignore_whitespaces => true) { IO.read(FIXTURES_PATH + 'git_show_' + rev) }
|
186
186
|
end
|
187
187
|
diff = GitCommitNotifier::DiffToHtml.new
|
188
188
|
mock(diff).check_handled_commits(anything) { |commits| commits }
|
@@ -15,18 +15,18 @@ describe GitCommitNotifier::Git do
|
|
15
15
|
it "should get data from shell: git show without whitespaces" do
|
16
16
|
expected = 'some data from git show'
|
17
17
|
mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --pretty=fuller -w") { expected }
|
18
|
-
GitCommitNotifier::Git.show(SAMPLE_REV, true).should == expected
|
18
|
+
GitCommitNotifier::Git.show(SAMPLE_REV, :ignore_whitespaces => true).should == expected
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should get data from shell: git show with whitespaces" do
|
22
22
|
expected = 'some data from git show'
|
23
23
|
mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --pretty=fuller") { expected }
|
24
|
-
GitCommitNotifier::Git.show(SAMPLE_REV, false).should == expected
|
24
|
+
GitCommitNotifier::Git.show(SAMPLE_REV, :ignore_whitespaces => false).should == expected
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should strip given revision" do
|
28
28
|
mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --pretty=fuller -w")
|
29
|
-
GitCommitNotifier::Git.show("#{SAMPLE_REV}\n", true)
|
29
|
+
GitCommitNotifier::Git.show("#{SAMPLE_REV}\n", :ignore_whitespaces => true)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
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.
|
4
|
+
version: 0.11.0
|
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-
|
13
|
+
date: 2011-12-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: diff-lcs
|
17
|
-
requirement: &
|
17
|
+
requirement: &70202081729720 !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: *70202081729720
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: nntp
|
28
|
-
requirement: &
|
28
|
+
requirement: &70202081729240 !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: *70202081729240
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: premailer
|
39
|
-
requirement: &
|
39
|
+
requirement: &70202081728720 !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: *70202081728720
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: nokogiri
|
56
|
-
requirement: &
|
56
|
+
requirement: &70202081727760 !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: *70202081727760
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
66
|
name: rake
|
67
|
-
requirement: &
|
67
|
+
requirement: &70202081727220 !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: *70202081727220
|
79
79
|
- !ruby/object:Gem::Dependency
|
80
80
|
name: bundler
|
81
|
-
requirement: &
|
81
|
+
requirement: &70202081726400 !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: *70202081726400
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
94
|
name: code-cleaner
|
95
|
-
requirement: &
|
95
|
+
requirement: &70202081725280 !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: *70202081725280
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
105
|
name: rspec-core
|
106
|
-
requirement: &
|
106
|
+
requirement: &70202081724720 !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: *70202081724720
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
116
|
name: rspec-expectations
|
117
|
-
requirement: &
|
117
|
+
requirement: &70202081724240 !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: *70202081724240
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: rr
|
128
|
-
requirement: &
|
128
|
+
requirement: &70202081723720 !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: *70202081723720
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
138
|
name: faker
|
139
|
-
requirement: &
|
139
|
+
requirement: &70202081723240 !ruby/object:Gem::Requirement
|
140
140
|
none: false
|
141
141
|
requirements:
|
142
142
|
- - ~>
|
@@ -144,10 +144,10 @@ dependencies:
|
|
144
144
|
version: 0.9.5
|
145
145
|
type: :development
|
146
146
|
prerelease: false
|
147
|
-
version_requirements: *
|
147
|
+
version_requirements: *70202081723240
|
148
148
|
- !ruby/object:Gem::Dependency
|
149
149
|
name: yard
|
150
|
-
requirement: &
|
150
|
+
requirement: &70202081722760 !ruby/object:Gem::Requirement
|
151
151
|
none: false
|
152
152
|
requirements:
|
153
153
|
- - ~>
|
@@ -155,10 +155,10 @@ dependencies:
|
|
155
155
|
version: 0.7.3
|
156
156
|
type: :development
|
157
157
|
prerelease: false
|
158
|
-
version_requirements: *
|
158
|
+
version_requirements: *70202081722760
|
159
159
|
- !ruby/object:Gem::Dependency
|
160
160
|
name: redcarpet
|
161
|
-
requirement: &
|
161
|
+
requirement: &70202081858160 !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: *70202081858160
|
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
|
@@ -223,7 +223,7 @@ files:
|
|
223
223
|
- spec/spec_helper.rb
|
224
224
|
- template/email.html.erb
|
225
225
|
- template/styles.css
|
226
|
-
homepage: http://github.com/
|
226
|
+
homepage: http://bitboxer.github.com/git-commit-notifier/
|
227
227
|
licenses: []
|
228
228
|
post_install_message:
|
229
229
|
rdoc_options: []
|
@@ -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: -3538399353583787974
|
241
241
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
242
242
|
none: false
|
243
243
|
requirements:
|
@@ -246,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
246
246
|
version: '0'
|
247
247
|
requirements: []
|
248
248
|
rubyforge_project:
|
249
|
-
rubygems_version: 1.8.
|
249
|
+
rubygems_version: 1.8.10
|
250
250
|
signing_key:
|
251
251
|
specification_version: 3
|
252
252
|
summary: Sends git commit messages with diffs
|