git-commit-notifier 0.11.11 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Not yet released
4
4
 
5
+ ## Version 0.12.0
6
+
7
+ * Detects renamed files.
8
+ * Fudge email send date to ensure ordering of commit messages.
9
+
5
10
  ## Version 0.11.11
6
11
 
7
12
  * Allow per branch mailing lists.
data/Gemfile CHANGED
@@ -8,3 +8,5 @@ gem "ripper", :group => :development, :platforms => :mri_18
8
8
 
9
9
  gem "coveralls", :require => false, :platforms => [:mri_19, :mri_20], :group => :development
10
10
 
11
+ gem "nokogiri", "~> 1.5.0", :platforms => :mri_18
12
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.11.11
1
+ 0.12.0
@@ -217,6 +217,14 @@ ignore_whitespace: all
217
217
  # webooks:
218
218
  # url: http://example.com:8081/commits
219
219
 
220
+ # Adding the similarity detection threshold parameter used by the -M flag when detecting renames
221
+ #
222
+ # The value is a number between 0 and 1
223
+ # with 0 signifying 0% and 1 signifying 100%.
224
+ # The Default value is 0.5, meaning, git will consider a delete/add pair as a rename if
225
+ # more than 50% of it has not changed
226
+ similarity_detection_threshold: "0.5"
227
+
220
228
  # This is developer debugging options. Do not uncomment it if You aren't Jedi
221
229
  # debug:
222
230
  # enabled: true
@@ -95,6 +95,11 @@ module GitCommitNotifier
95
95
  # @return [NilClass] nil
96
96
  # @see config
97
97
  def run(config_name, rev1, rev2, ref_name)
98
+
99
+ if @start_time.nil?
100
+ @start_time = Time.new
101
+ @start_time_offset = 0
102
+ end
98
103
 
99
104
  # Load the configuration
100
105
  if File.exists?(config_name)
@@ -214,7 +219,9 @@ module GitCommitNotifier
214
219
  :from_alias => result[:commit_info][:author],
215
220
  :reply_to_address => config["reply_to_author"] ? result[:commit_info][:email] : config["from"] || result[:commit_info][:email],
216
221
  :subject => subject,
217
- :date => result[:commit_info][:date],
222
+ :commit_date => result[:commit_info][:date],
223
+ :current_date => Time.new.rfc2822,
224
+ :offset_date => (@start_time + @start_time_offset).rfc2822,
218
225
  :text_message => text.join("------------------------------------------\n\n"),
219
226
  :html_message => html.join("<hr /><br />"),
220
227
  :old_rev => rev1,
@@ -238,6 +245,8 @@ module GitCommitNotifier
238
245
  :repo_name => repo_name
239
246
  )
240
247
  webhook.send
248
+
249
+ @start_time_offset += 1
241
250
  end
242
251
  else
243
252
  commit_number = 1
@@ -261,7 +270,9 @@ module GitCommitNotifier
261
270
  :from_alias => result[:commit_info][:author],
262
271
  :reply_to_address => config["reply_to_author"] ? result[:commit_info][:email] : config["from"] || result[:commit_info][:email],
263
272
  :subject => subject,
264
- :date => result[:commit_info][:date],
273
+ :commit_date => result[:commit_info][:date],
274
+ :current_date => Time.new.rfc2822,
275
+ :offset_date => (@start_time + @start_time_offset).rfc2822,
265
276
  :text_message => result[:text_content],
266
277
  :html_message => result[:html_content],
267
278
  :old_rev => rev1,
@@ -288,6 +299,8 @@ module GitCommitNotifier
288
299
  end
289
300
 
290
301
  commit_number += 1
302
+
303
+ @start_time_offset += 1
291
304
  end
292
305
  end
293
306
  nil
@@ -28,7 +28,7 @@ module GitCommitNotifier
28
28
  return m unless match
29
29
  r = { :phrase => match[1] }
30
30
  captures = match[2].split(/[\s\&\,]+/).map { |m| (m =~ /(\d+)/) ? $1 : m }.reject { |c| c.empty? }
31
- r[:links] = captures.map { |mn| { :title => "##{mn}", :url => "#{url}/issues/show/#{mn}" } }
31
+ r[:links] = captures.map { |mn| { :title => "##{mn}", :url => "#{url}/issues/#{mn}" } }
32
32
  r
33
33
  end },
34
34
  :bugzilla => { :search_for => /\bBUG\s*(\d+)/i, :replace_with => '#{url}/show_bug.cgi?id=\1' },
@@ -47,6 +47,9 @@ module GitCommitNotifier
47
47
  @lines_added = 0
48
48
  @file_added = false
49
49
  @file_removed = false
50
+ @file_renamed = false
51
+ @file_renamed_old_name = false
52
+ @file_renamed_new_name = false
50
53
  @file_changes = []
51
54
  @binary = false
52
55
  unless String.method_defined?(:encode!)
@@ -184,6 +187,8 @@ module GitCommitNotifier
184
187
  "Deleted"
185
188
  elsif @file_added
186
189
  "Added"
190
+ elsif @file_renamed
191
+ "Renamed"
187
192
  else
188
193
  "Changed"
189
194
  end
@@ -247,8 +252,15 @@ module GitCommitNotifier
247
252
 
248
253
  @lines_added = 0
249
254
  @diff_result << operation_description
250
- if !@diff_lines.empty? && !@too_many_files
255
+
256
+ if (@file_renamed || !@diff_lines.empty?) && (!@too_many_files)
251
257
  @diff_result << '<table>'
258
+
259
+ ##Adds a ROW in the table for the File Rename Details (if at all present)
260
+ if @file_renamed
261
+ @diff_result << "<tr class='renamed'>\n<td class='ln'>&nbsp;</td><td class='ln'></td><td>&nbsp;<u>#{@file_renamed_old_name}</u> was renamed to <u>#{@file_renamed_new_name}</u></td></tr>"
262
+ end
263
+
252
264
  removals = []
253
265
  additions = []
254
266
 
@@ -290,6 +302,9 @@ module GitCommitNotifier
290
302
  @left_ln = nil
291
303
  @file_added = false
292
304
  @file_removed = false
305
+ @file_renamed = false
306
+ @file_renamed_old_name = false
307
+ @file_renamed_new_name = false
293
308
  @binary = false
294
309
  end
295
310
 
@@ -366,6 +381,11 @@ module GitCommitNotifier
366
381
  elsif line =~ /\/dev\/null differ/ # Binary files ... and /dev/null differ (removal)
367
382
  @binary = true
368
383
  @file_removed = true
384
+ elsif line =~ /^rename from (.*)/
385
+ @file_renamed = true
386
+ @file_renamed_old_name = line.scan(/^rename from (.*)/)[0][0].to_s
387
+ elsif line =~ /^rename to (.*)/
388
+ @file_renamed_new_name = line.scan(/^rename to (.*)/)[0][0].to_s
369
389
  elsif op == '@'
370
390
  @left_ln, @right_ln = range_info(line)
371
391
  end
@@ -9,7 +9,7 @@ class GitCommitNotifier::Emailer
9
9
  # Default ERB template file path
10
10
  TEMPLATE = File.join(File.dirname(__FILE__), *'../../template/email.html.erb'.split('/')).freeze
11
11
  # Instance variable names
12
- PARAMETERS = %w[project_path recipient from_address from_alias reply_to_address date subject text_message html_message repo_name ref_name old_rev new_rev].freeze
12
+ PARAMETERS = %w[project_path recipient from_address from_alias reply_to_address commit_date current_date offset_date subject text_message html_message repo_name ref_name old_rev new_rev].freeze
13
13
 
14
14
  # Gets config.
15
15
  # @return [Hash] Configuration
@@ -194,11 +194,19 @@ class GitCommitNotifier::Emailer
194
194
  content << "Reply-To: #{reply_to}" unless reply_to.nil?
195
195
 
196
196
  # Setting the email date from the commit date is undesired by those
197
- # who sort their email by send date instead of receive date
198
- #content << "Date: #{@date}" if !@date.nil?
197
+ # who sort their email by send date instead of receive date.
198
+ # We currently use @offset_date, which starts with the time the notifier was started,
199
+ # and adds a second of time per commit. This should result in the commits arriving
200
+ # in order by their processing sequence, even when they are all processed within the
201
+ # same second
202
+ #date = @commit_date # Date of the commit
203
+ #date = @current_date # Date we processed this commit
204
+ date = @offset_date # Date notifier started, plus 1 second per commit processed
205
+ date = Time.new.rfc2822 if date.nil? # Fallback to current date if date is nil
199
206
 
200
207
  content.concat [
201
208
  "#{to_tag}: #{quote_if_necessary(@recipient, 'utf-8')}",
209
+ "Date: #{date}",
202
210
  "Subject: #{quote_if_necessary(@subject, 'utf-8')}",
203
211
  "X-Mailer: git-commit-notifier",
204
212
  "X-Git-Repository: #{@repo_name}",
@@ -25,7 +25,7 @@ class GitCommitNotifier::Git
25
25
  end
26
26
 
27
27
  # Runs `git show`
28
- # @note uses "--pretty=fuller" option.
28
+ # @note uses "--pretty=fuller" and "-M" option.
29
29
  # @return [String] Its output
30
30
  # @see from_shell
31
31
  # @param [String] rev Revision
@@ -34,6 +34,7 @@ class GitCommitNotifier::Git
34
34
  def show(rev, opts = {})
35
35
  gitopt = " --date=rfc2822"
36
36
  gitopt += " --pretty=fuller"
37
+ gitopt += " -M#{GitCommitNotifier::CommitHook.config['similarity_detection_threshold'] || "0.5"}"
37
38
  gitopt += " -w" if opts[:ignore_whitespace] == 'all'
38
39
  gitopt += " -b" if opts[:ignore_whitespace] == 'change'
39
40
  from_shell("git show #{rev.strip}#{gitopt}")
@@ -58,13 +59,13 @@ class GitCommitNotifier::Git
58
59
  end
59
60
 
60
61
  # Runs `git log` and extract filenames only
61
- # @note uses "--pretty=oneline" and "--name-status" options.
62
+ # @note uses "--pretty=oneline" and "--name-status" and "-M" options.
62
63
  # @return [Array(String)] File names
63
64
  # @see lines_from_shell
64
65
  # @param [String] rev1 First revision
65
66
  # @param [String] rev2 Second revision
66
67
  def changed_files(rev1, rev2)
67
- lines = lines_from_shell("git log #{rev1}..#{rev2} --name-status --pretty=oneline")
68
+ lines = lines_from_shell("git log #{rev1}..#{rev2} --name-status --pretty=oneline -M#{GitCommitNotifier::CommitHook.config['similarity_detection_threshold'] || "0.5"}")
68
69
  lines = lines.select {|line| line =~ /^\w{1}\s+\w+/} # grep out only filenames
69
70
  lines.uniq
70
71
  end
@@ -79,7 +80,8 @@ class GitCommitNotifier::Git
79
80
  modified = lines.map { |l| l.gsub(/M\s/,'').strip if l[0,1] == 'M' }.select { |l| !l.nil? }
80
81
  added = lines.map { |l| l.gsub(/A\s/,'').strip if l[0,1] == 'A' }.select { |l| !l.nil? }
81
82
  deleted = lines.map { |l| l.gsub(/D\s/,'').strip if l[0,1] == 'D' }.select { |l| !l.nil? }
82
- { :m => modified, :a => added, :d => deleted }
83
+ renamed = lines.map { |l| l.gsub(/R\d+\s/,'').strip if l[0,1] == 'R' }.select { |l| !l.nil? }
84
+ { :m => modified, :a => added, :d => deleted , :r => renamed}
83
85
  end
84
86
 
85
87
  def branch_commits(treeish)
@@ -30,6 +30,7 @@ class GitCommitNotifier::Webhook
30
30
  'added' => @changed[:a],
31
31
  'modified' => @changed[:m],
32
32
  'removed' => @changed[:d],
33
+ 'renamed' => @changed[:r],
33
34
  'committer' => {
34
35
  'name' => @committer,
35
36
  'email' => @email
@@ -206,7 +206,7 @@ describe GitCommitNotifier::DiffToHtml do
206
206
  'mediawiki' => 'http://example.com/wiki', # will rework [[text]] to MediaWiki pages
207
207
  'redmine' => 'http://redmine.example.com' # will rework refs #123, #125 to Redmine issues
208
208
  }
209
- @diff.do_message_integration("[[text]] refs #123, #125").should == "<a href=\"http://example.com/wiki/text\">[[text]]</a> refs <a href=\"http://redmine.example.com/issues/show/123\">#123</a>, <a href=\"http://redmine.example.com/issues/show/125\">#125</a>"
209
+ @diff.do_message_integration("[[text]] refs #123, #125").should == "<a href=\"http://example.com/wiki/text\">[[text]]</a> refs <a href=\"http://redmine.example.com/issues/123\">#123</a>, <a href=\"http://redmine.example.com/issues/125\">#125</a>"
210
210
  end
211
211
  end
212
212
 
@@ -16,18 +16,18 @@ describe GitCommitNotifier::Git do
16
16
  describe :show do
17
17
  it "should get data from shell: git show without whitespaces" do
18
18
  expected = 'some data from git show'
19
- mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --date=rfc2822 --pretty=fuller -w") { expected }
19
+ mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --date=rfc2822 --pretty=fuller -M0.5 -w") { expected }
20
20
  GitCommitNotifier::Git.show(SAMPLE_REV, :ignore_whitespace => 'all').should == expected
21
21
  end
22
22
 
23
23
  it "should get data from shell: git show with whitespaces" do
24
24
  expected = 'some data from git show'
25
- mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --date=rfc2822 --pretty=fuller") { expected }
25
+ mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --date=rfc2822 --pretty=fuller -M0.5") { expected }
26
26
  GitCommitNotifier::Git.show(SAMPLE_REV, :ignore_whitespace => 'none').should == expected
27
27
  end
28
28
 
29
29
  it "should strip given revision" do
30
- mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --date=rfc2822 --pretty=fuller -w")
30
+ mock(GitCommitNotifier::Git).from_shell("git show #{SAMPLE_REV} --date=rfc2822 --pretty=fuller -M0.5 -w")
31
31
  GitCommitNotifier::Git.show("#{SAMPLE_REV}\n", :ignore_whitespace => 'all')
32
32
  end
33
33
  end
@@ -126,7 +126,7 @@ describe GitCommitNotifier::Git do
126
126
  files = ["M README.rdoc\n",
127
127
  "D git_commit_notifier/Rakefile\n",
128
128
  "M post-receive\n"]
129
- mock(GitCommitNotifier::Git).from_shell("git log #{SAMPLE_REV}..#{SAMPLE_REV_2} --name-status --pretty=oneline" ) { IO.read(FIXTURES_PATH + 'git_log_name_status') }
129
+ mock(GitCommitNotifier::Git).from_shell("git log #{SAMPLE_REV}..#{SAMPLE_REV_2} --name-status --pretty=oneline -M0.5" ) { IO.read(FIXTURES_PATH + 'git_log_name_status') }
130
130
  GitCommitNotifier::Git.changed_files(SAMPLE_REV, SAMPLE_REV_2).should == files
131
131
  end
132
132
  end
@@ -136,7 +136,7 @@ describe GitCommitNotifier::Git do
136
136
  files = ["M README.rdoc\n",
137
137
  "D git_commit_notifier/Rakefile\n",
138
138
  "M post-receive\n"]
139
- mock(GitCommitNotifier::Git).from_shell("git log #{SAMPLE_REV}..#{SAMPLE_REV_2} --name-status --pretty=oneline" ) { IO.read(FIXTURES_PATH + 'git_log_name_status') }
139
+ mock(GitCommitNotifier::Git).from_shell("git log #{SAMPLE_REV}..#{SAMPLE_REV_2} --name-status --pretty=oneline -M0.5" ) { IO.read(FIXTURES_PATH + 'git_log_name_status') }
140
140
  output = GitCommitNotifier::Git.split_status(SAMPLE_REV, SAMPLE_REV_2)
141
141
  output[:m].should == [ 'README.rdoc', 'post-receive' ]
142
142
  output[:d].should == [ 'git_commit_notifier/Rakefile' ]
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.11
4
+ version: 0.12.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-05-29 00:00:00.000000000 Z
13
+ date: 2013-06-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: diff-lcs
@@ -339,7 +339,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
339
339
  version: '0'
340
340
  segments:
341
341
  - 0
342
- hash: 778864539407809625
342
+ hash: -459626784997908862
343
343
  required_rubygems_version: !ruby/object:Gem::Requirement
344
344
  none: false
345
345
  requirements: