]> git.pld-linux.org Git - packages/cvsspam.git/blame - cvsspam-branch.diff
drop ruby_mod_ver_requires_eq
[packages/cvsspam.git] / cvsspam-branch.diff
CommitLineData
efaa2289
ER
1Index: cvsspam.conf
2===================================================================
83963645
ER
3--- cvsspam.conf (.../tags/RELEASE-0_2_12) (revision 277)
4+++ cvsspam.conf (.../trunk) (revision 277)
efaa2289
ER
5@@ -34,11 +34,19 @@
6 #
7 # When $jiraURL is given, text of the form 'project-1234' will be linked
8 # to this issue in JIRA.
9+#
10+# When $xplannerStoryURL, $xplannerIterationURL and $xplannerProjectURL are
11+# given, text of the form XS1234 will be linked to XPlanner stories; text of
12+# the form XI1234 will be linked to XPlanner iterations; and text of the form
13+# XP1234 will be linked to XPlanner projects.
14
15 #$bugzillaURL = "http://bugzilla.mozilla.org/show_bug.cgi?id=%s"
16
17 #$jiraURL = "http://jira.atlassian.com/secure/ViewIssue.jspa?key=%s"
18
19+#$xplannerStoryURL = "http://www.example.com/xplanner/do/view/userstory?oid=%s"
20+#$xplannerIterationURL = "http://www.example.com/xplanner/do/view/iteration?oid=%s"
21+#$xplannerProjectURL = "http://www.example.com/xplanner/do/view/project?oid=%s"
22
23 # Link to Wiki systems
24 #
ca77e894
ER
25@@ -71,6 +79,7 @@
26
27 #$cvswebURL = "http://localhost/cgi-bin/cvsweb.cgi"
28
29+#$tracURL = "http://localhost/trac/project"
30
31
32 # Additional SMTP Headers (Optional)
83963645
ER
33@@ -116,15 +125,32 @@
34
35
36
37-# cvsdiff keyword ignoring (Default: show changes in keywords)
38+# cvsdiff keyword ignoring (Default: show changes in keywords)
d895f970
ER
39 #
40 # Changes in CVS keywords can be distracting. For instance, the
40f465db 41-# $Revision: 1.12 $ keyword will change on each commit. Set this value to true
d895f970
ER
42+# $Revision$ keyword will change on each commit. Set this value to true
43 # to exclude changes in keyword fields (adds the -kk option to cvs diff).
44
efaa2289
ER
45 #$diff_ignore_keywords = true
46
47
83963645 48+# cvsdiff whitespace ignoring (Default: show whitespace-only changes)
efaa2289
ER
49+#
50+# Whitespace-only changes can distract from the rest of a diff. Set this
51+# value to true to exclude changes in the amount of whitespace (adds the -b
52+# option to cvs diff).
53+
54+$diff_ignore_whitespace = true
55+
83963645
ER
56+
57+# cvs diff files ignoring (Default: empty)
58+#
59+# Make CVSspam ignore certain files.
60+#
61+# Can contain file masks, separated by whitespace.
62+
63+#$ignore_files = "*.al *.gif"
efaa2289
ER
64+
65 # $no_removed_file_diff and $no_added_file_diff
66 #
67 # Set both these options, and emails will only include diffs for files
83963645
ER
68@@ -132,7 +158,7 @@
69 # deleted...
70
71
72-# Don't show diff for removed files (Default: show file's contents)
73+# Don't show diff for removed files (Default: show file's contents)
74 #
75 # If you aren't interested in seeing the contents of a file that was
76 # removed, set this option to true. The files will still appear in the index
77@@ -166,14 +192,46 @@
ca77e894
ER
78 # Allows the specification of a character set for all generated emails.
79 # The files CVS is dealing with should already be in the character set you
80 # specify -- no transcoding is done.
81+#
82+# Note that you can override this with --charset argument per module, etc.
83
84 #$charset="ISO-8859-1"
85
86
87
88+# Users file (Default: $CVSROOT/CVSROOT/users)
89+#
90+# Specify users file to lookup From addresses for commites
91+
92+#$users_file = "/srv/svn/users"
93+
94+# Users file charset (Default: $charset)
95+#
96+# If the users file is encoded differently than $charset, You can override
97+# it here. Especially useful if you use --charset argument. See above.
98+
99+#$users_file_charset = "ISO-8859-1"
100+
101+
102 # File names in Subject (Default: no filenames in Subject)
103 #
104 # Some people like file names to appear in the email subject. To make
efaa2289
ER
105 # them happy, you can say $files_in_subject = true here.
106
107 #$files_in_subject = false
108+
109+
ca77e894
ER
110+# Module Path email header (Default: no X-CVSspam-Module-Path header)
111+#
112+# Sets 'X-CVSspam-Module-Path' header to contain common path of files commited.
113+# Useful for server side mail filtering.
114+
115+#$cvsroot_email_header = true
efaa2289
ER
116+
117+# Email size limit (Default: around 2MB)
118+#
119+# When large changes are committed, large CVSspam emails can result. Here
120+# you can set the size of email that CVSspam is not allowed to append any
121+# more diffs onto. Specify the number of bytes.
122+
123+#$mail_size_limit = 2097152
ca77e894
ER
124
125Property changes on: cvsspam.conf
126___________________________________________________________________
127Deleted: svn:executable
128 - *
d895f970
ER
129Modified: svn:keywords
130 - Author Date Id Revision
131 + Author Date Id
ca77e894 132
efaa2289
ER
133Index: collect_diffs.rb
134===================================================================
83963645
ER
135--- collect_diffs.rb (.../tags/RELEASE-0_2_12) (revision 277)
136+++ collect_diffs.rb (.../trunk) (revision 277)
137@@ -26,7 +26,18 @@
138 $tmpdir = ENV["TMPDIR"] || "/tmp"
f34e4066
ER
139 $dirtemplate = "#cvsspam.#{Process.getpgrp}.#{Process.uid}"
140
83963645
ER
141+def shell_mask2regex(mask)
142+ '^' + mask.gsub('.', '\.').gsub('?', '.').gsub('*', '.*') + '$'
143+end
144+
f34e4066
ER
145 def find_data_dir
146+ if $from_address
147+ safe_from = make_fromaddr_safe_for_filename($from_address)
148+ Dir["#{$tmpdir}/#{$dirtemplate}.#{safe_from}-*"].each do |dir|
149+ stat = File.stat(dir)
150+ return dir if stat.owned?
151+ end
152+ end
153 Dir["#{$tmpdir}/#{$dirtemplate}-*"].each do |dir|
154 stat = File.stat(dir)
155 return dir if stat.owned?
83963645 156@@ -35,6 +46,14 @@
f34e4066
ER
157 end
158
159
160+# transform any special / unexpected characters appearing in the argument to
161+# --from so that they will not cause problems if the value is inserted into
162+# a file or directory name
163+def make_fromaddr_safe_for_filename(addr)
164+ addr.gsub(/[^a-zA-Z0-1.,_-]/, "_")
165+end
166+
167+
168 def blah(msg)
169 if $debug
170 $stderr.puts "collect_diffs.rb: #{msg}"
83963645
ER
171@@ -81,11 +100,11 @@
172 File.open("#{$datadir}/commitinfo-tags") do |file|
173 $commitinfo_tags = Hash.new
174 file.each_line do |line|
175- line =~ /([^\t]+)\t(.+)/
176- key = $2
177- val = $1
178- key.sub!(/^#{ENV['CVSROOT']}\//, '')
179- $commitinfo_tags[key] = val
180+ line =~ /([^\t]+)\t(.+)/
181+ key = $2
182+ val = $1
183+ key.sub!(/^#{ENV['CVSROOT']}\//, '')
184+ $commitinfo_tags[key] = val
185 end
186 end
187 end
188@@ -129,7 +148,14 @@
f34e4066
ER
189 changes = Array.new
190 i = 0
191 while i < cvs_info.length
192- changes << ChangeInfo.new(cvs_info[i], cvs_info[i+=1], cvs_info[i+=1])
193+ change_file = cvs_info[i]
194+ # It's been reported,
195+ # http://lists.badgers-in-foil.co.uk/pipermail/cvsspam-devel/2005-September/000380.html
196+ # that sometimes the second revision number that CVS gives us contains a
197+ # trailing newline character, so we strip ws from these values before use,
198+ change_from = cvs_info[i+=1].strip
199+ change_to = cvs_info[i+=1].strip
200+ changes << ChangeInfo.new(change_file, change_from, change_to)
201 i+=1
202 end
203 return changes
83963645
ER
204@@ -194,6 +220,8 @@
205
206 changes.each do |change|
207
208+ next if $ignore_file_regexes and $ignore_file_regexes.any?{|r| change.file =~ /#{r}/}
209+
210 # record version information
211 file.puts "#V #{change.fromVer},#{change.toVer}"
212
213@@ -202,7 +230,7 @@
214 # note if the file is on a branch
215 tag = nil
216 if change.isRemoval
217- tag = get_commitinfo_tag("#{$repository_path}/#{change.file}")
218+ tag = get_commitinfo_tag("#{$repository_path}/#{change.file}")
219 else
220 status = nil
221 safer_popen($cvs_prog, "-nq", "status", change.file) do |io|
222@@ -210,18 +238,19 @@
223 end
224 fail "couldn't get cvs status: #{$!} (exited with #{$?})" unless ($?>>8)==0
225
226- if status =~ /^\s*Sticky Tag:\s*(.+) \(branch: +/m
227- tag = $1
228- end
229+ if status =~ /^\s*Sticky Tag:\s*(.+) \(branch: +/m
230+ tag = $1
231+ end
232
233- if status =~ /^\s*Sticky Options:\s*-kb/m
234- binary_file = true
235- end
236+ if status =~ /^\s*Sticky Options:\s*-kb/m
237+ binary_file = true
238+ end
239 end
240 file.puts "#T #{tag}" unless tag.nil?
f34e4066
ER
241
242 diff_cmd = Array.new << $cvs_prog << "-nq" << "diff" << "-Nu"
243 diff_cmd << "-kk" if $diff_ignore_keywords
244+ diff_cmd << "-b" if $diff_ignore_whitespace
245
246 if change.isAddition
247 file.write "#A "
83963645
ER
248@@ -240,24 +269,24 @@
249 file.puts "#{$repository_path}/#{change.file}"
250 diff_cmd << change.file
251 if binary_file
252- blah("not diffing #{change.file}; has -kb set")
253- # fake diff lines that will cause cvsspam.rb to consider this a binary
254- # file,
255- file.puts "#U diff x x"
256- file.puts "#U Binary files x and y differ"
257+ blah("not diffing #{change.file}; has -kb set")
258+ # fake diff lines that will cause cvsspam.rb to consider this a binary
259+ # file,
260+ file.puts "#U diff x x"
261+ file.puts "#U Binary files x and y differ"
262 else
263- # do a cvs diff and place the output into our temp file
264- blah("about to run #{diff_cmd.join(' ')}")
265- safer_popen(*diff_cmd) do |pipe|
266- # skip over cvs-diff's preamble
267- pipe.each do |line|
268- break if line =~ /^diff /
269- end
270- file.puts "#U #{line}"
271- pipe.each do |line|
272- file.puts "#U #{line}"
273- end
274- end
275+ # do a cvs diff and place the output into our temp file
276+ blah("about to run #{diff_cmd.join(' ')}")
277+ safer_popen(*diff_cmd) do |pipe|
278+ # skip over cvs-diff's preamble
279+ pipe.each do |line|
280+ break if line =~ /^diff /
281+ end
282+ file.puts "#U #{line}"
283+ pipe.each do |line|
284+ file.puts "#U #{line}"
285+ end
286+ end
287 end
288 # TODO: don't how to do this reliably on different systems...
289 #fail "cvsdiff did not give exit status 1 for invocation: #{diff_cmd.join(' ')}" unless ($?>>8)==1
290@@ -333,10 +362,13 @@
f34e4066
ER
291 end
292
293 $config = nil
294+$from_address = nil
295 $cvs_prog = "cvs"
296 $debug = false
297 $diff_ignore_keywords = false
298+$diff_ignore_whitespace = false
299 $task_keywords = []
83963645 300+$ignore_file_regexes = nil
f34e4066
ER
301
302 unless ENV.has_key?('CVSROOT')
83963645
ER
303 fail "$CVSROOT not defined. It should be when I am invoked from CVSROOT/loginfo"
304@@ -387,6 +419,7 @@
f34e4066
ER
305 end
306 $config = arg if opt=="--config"
307 $debug = true if opt == "--debug"
308+ $from_address = arg if opt == "--from"
309 end
310
311 blah("CVSROOT is #{ENV['CVSROOT']}")
83963645
ER
312@@ -426,6 +459,9 @@
313 class GUESS
314 end
315 load $config
316+ if $ignore_files
317+ $ignore_file_regexes = $ignore_files.split(/\s+/).map{|i| shell_mask2regex(i)}
318+ end
319 else
320 blah("Config file '#{$config}' not found, ignoring")
321 end
322@@ -447,3 +483,5 @@
323 process_log(ARGV[0])
324 end
325 mailtest
326+
327+# vim:et:ts=2:sw=2
efaa2289
ER
328Index: record_lastdir.rb
329===================================================================
83963645
ER
330--- record_lastdir.rb (.../tags/RELEASE-0_2_12) (revision 277)
331+++ record_lastdir.rb (.../trunk) (revision 277)
efaa2289
ER
332@@ -4,7 +4,6 @@
333 # http://www.badgers-in-foil.co.uk/projects/cvsspam/
334 # Copyright (c) David Holroyd
335
336-$repositorydir = ARGV.shift
337
338 $tmpdir = ENV["TMPDIR"] || "/tmp"
339
340@@ -19,6 +18,36 @@
341 nil
342 end
343
344+
345+# transform any special / unexpected characters appearing in the argument to
346+# --from so that they will not cause problems if the value is inserted into
347+# a file or directory name
348+def make_fromaddr_safe_for_filename(addr)
349+ addr.gsub(/[^a-zA-Z0-1.,_-]/, "_")
350+end
351+
352+# Option processing doesn't use GetoptLong (for the moment) bacause arguments
353+# given to this script by CVS include the names of committed files. It
354+# seems quite possible that one of those file names could begin with a '-'
355+# and therefore be treated by GetoptLong as a value which requires processing.
356+# This would probably result in an error.
357+#
358+# [That could be worked around by placing a '--' option (which tells GetoptLong
359+# to stop processing option arguments) at the very end of the arguments to
360+# record_lastdir.rb in commitinfo, but that's very easily forgotten, and isn't
361+# really backwards compatable with the behaviour of older CVSspam releases.]
362+if ARGV.first == "--from"
363+ # we could, of course, be tricked, if the first committed file in the list
364+ # happened to be named '--from' :S
365+
366+ # drop the "--from"
367+ ARGV.shift
368+ # and use the value which was given following the option,
369+ $dirtemplate << "." << make_fromaddr_safe_for_filename(ARGV.shift)
370+end
371+
372+$repositorydir = ARGV.shift
373+
374 $datadir = find_data_dir()
375
376 if $datadir==nil
83963645
ER
377@@ -78,5 +107,7 @@
378 # email yet.
379
380 File.open("#{$datadir}/lastdir", "w") { |file|
381- file.write $repositorydir
382+ file.write $repositorydir
383 }
384+
385+# vim:et:ts=2:sw=2
ca77e894
ER
386
387Property changes on: TODO
388___________________________________________________________________
389Deleted: svn:executable
390 - *
391
efaa2289
ER
392Index: project.xml
393===================================================================
d895f970
ER
394Index: svn_post_commit_hook.rb
395===================================================================
396--- svn_post_commit_hook.rb (.../tags/RELEASE-0_2_12) (revision 0)
83963645
ER
397+++ svn_post_commit_hook.rb (.../trunk) (revision 277)
398@@ -0,0 +1,412 @@
d895f970
ER
399+#!/usr/bin/ruby -w
400+
401+$svnlook_exe = "svnlook" # default assumes the program is in $PATH
402+
403+def usage(msg)
404+ $stderr.puts(msg)
405+ exit(1)
406+end
407+
408+def blah(msg)
409+ if $debug
410+ $stderr.puts "svn_post_commit_hook.rb: #{msg}"
411+ end
412+end
413+
414+$debug = false
415+$tmpdir = ENV["TMPDIR"] || "/tmp"
416+$dirtemplate = "#svnspam.#{Process.getpgrp}.#{Process.uid}"
417+# arguments to pass though to 'cvsspam.rb'
418+$passthrough_args = []
419+
420+def make_data_dir
421+ dir = "#{$tmpdir}/#{$dirtemplate}-#{rand(99999999)}"
422+ Dir.mkdir(dir, 0700)
423+ dir
424+end
425+
426+def init
427+ $datadir = make_data_dir
428+
429+ # set PWD so that svnlook can create its .svnlook directory
430+ Dir.chdir($datadir)
431+end
432+
433+def cleanup
434+ unless $debug
83963645
ER
435+ File.unlink("#{$datadir}/logfile")
436+ Dir.rmdir($datadir)
d895f970
ER
437+ end
438+end
439+
440+def send_email
441+ cmd = File.dirname($0) + "/cvsspam.rb"
442+ unless system(cmd,"--svn","#{$datadir}/logfile", *$passthrough_args)
443+ fail "problem running '#{cmd}'"
444+ end
445+end
446+
447+# Like IO.popen, but accepts multiple arguments like Kernel.exec
448+# (So no need to escape shell metacharacters)
449+def safer_popen(*args)
450+ IO.popen("-") do |pipe|
451+ if pipe==nil
452+ exec(*args)
453+ else
454+ yield pipe
455+ end
456+ end
457+end
458+
459+
460+# Process the command-line arguments in the given list
461+def process_args
462+ require 'getoptlong'
463+
464+ opts = GetoptLong.new(
465+ [ "--to", "-t", GetoptLong::REQUIRED_ARGUMENT ],
466+ [ "--config", "-c", GetoptLong::REQUIRED_ARGUMENT ],
467+ [ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
468+ [ "--from", "-u", GetoptLong::REQUIRED_ARGUMENT ],
469+ [ "--charset", GetoptLong::REQUIRED_ARGUMENT ]
470+ )
471+
472+ opts.each do |opt, arg|
473+ if ["--to", "--config", "--from", "--charset"].include?(opt)
474+ $passthrough_args << opt << arg
475+ end
476+ if ["--debug"].include?(opt)
477+ $passthrough_args << opt
478+ end
479+ $config = arg if opt=="--config"
480+ $debug = true if opt == "--debug"
481+ end
482+
483+ $repository = ARGV[0]
484+ $revision = ARGV[1]
485+
486+ unless $revision =~ /^\d+$/
487+ usage("revision must be an integer: #{revision.inspect}")
488+ end
489+ $revision = $revision.to_i
490+
491+ unless FileTest.directory?($repository)
492+ usage("no such directory: #{$repository.inspect}")
493+ end
494+end
495+
496+# runs the given svnlook subcommand
497+def svnlook(cmd, revision, *args)
498+ rev = revision.to_s
499+ safer_popen($svnlook_exe, cmd, $repository, "-r", rev, *args) do |io|
500+ yield io
501+ end
502+end
503+
504+class Change
505+ def initialize(filechange, propchange, path)
506+ @filechange = filechange
507+ @propchange = propchange
508+ @path = path
509+ end
510+
511+ attr_accessor :filechange, :propchange, :path
512+
513+ def property_change?
514+ @propchange != " "
515+ end
516+
517+ def file_change?
518+ @filechange != "_"
519+ end
520+
521+ def addition?
522+ @filechange == "A"
523+ end
524+
525+ def deletion?
526+ @filechange == "D"
527+ end
528+end
529+
530+
531+
532+# Line-oriented access to an underlying IO object. Remembers 'current' line
533+# for lookahead during parsing.
534+class LineReader
535+ def initialize(io)
536+ @io = io
537+ end
538+
539+ def current
540+ @line
541+ end
542+
543+ def next_line
544+ (@line = @io.gets) != nil
545+ end
546+
547+ def assert_current(re)
548+ raise "unexpected #{current.inspect}" unless @line =~ re
549+ $~
550+ end
551+
552+ def assert_next(re=nil)
553+ raise "unexpected end of text" unless next_line
554+ unless re.nil?
555+ raise "unexpected #{current.inspect}" unless @line =~ re
556+ end
557+ $~
558+ end
559+end
560+
561+
562+def read_modified_diff(out, lines, path)
563+ lines.assert_next(/^=+$/)
564+ lines.assert_next
565+ if lines.current =~ /\(Binary files differ\)/
566+ process_modified_binary_diff(out, lines, path)
567+ else
568+ process_modified_text_diff(out, lines, path)
569+ end
570+end
571+
572+
573+def process_modified_binary_diff(out, lines, path)
574+ prev_rev= $revision-1
575+ next_rev= $revision
576+ out.puts "#V #{prev_rev},#{next_rev}"
577+ out.puts "#M #{path}"
578+ out.puts "#U diff x x"
579+ out.puts "#U Binary files x and y differ"
580+end
581+
582+
583+def process_modified_text_diff(out, lines, path)
584+ m = lines.assert_current(/^---.*\(rev (\d+)\)$/)
585+ prev_rev = m[1].to_i
586+ diff1 = lines.current
587+ m = lines.assert_next(/^\+\+\+.*\(rev (\d+)\)$/)
588+ next_rev = m[1].to_i
589+ diff2 = lines.current
590+ out.puts "#V #{prev_rev},#{next_rev}"
591+ out.puts "#M #{path}"
592+ out.puts "#U #{diff1}"
593+ out.puts "#U #{diff2}"
594+ while lines.next_line && lines.current =~ /^[-\+ @\\]/
595+ out.puts "#U #{lines.current}"
596+ end
597+end
598+
599+def read_added_diff(out, lines, path)
600+ lines.assert_next(/^=+$/)
601+ lines.assert_next
602+ if lines.current =~ /\(Binary files differ\)/
603+ process_added_binary_diff(out, lines, path)
604+ else
605+ process_added_text_diff(out, lines, path)
606+ end
607+end
608+
609+def process_added_binary_diff(out, lines, path)
610+ next_rev= $revision
611+ out.puts "#V NONE,#{next_rev}"
612+ out.puts "#A #{path}"
613+ out.puts "#U diff x x"
614+ out.puts "#U Binary file x added"
615+end
616+
617+def process_added_text_diff(out, lines, path)
618+ m = lines.assert_current(/^---.*\(rev (\d+)\)$/)
619+ prev_rev = m[1].to_i
620+ diff1 = lines.current
621+ m = lines.assert_next(/^\+\+\+.*\(rev (\d+)\)$/)
622+ next_rev = m[1].to_i
623+ diff2 = lines.current
624+ out.puts "#V NONE,#{next_rev}"
625+ out.puts "#A #{path}"
626+ out.puts "#U #{diff1}"
627+ out.puts "#U #{diff2}"
628+ while lines.next_line && lines.current =~ /^[-\+ @\\]/
629+ out.puts "#U #{lines.current}"
630+ end
631+end
632+
633+def read_deleted_diff(out, lines, path)
634+ lines.assert_next(/^=+$/)
635+ m = lines.assert_next(/^---.*\(rev (\d+)\)$/)
636+ prev_rev = m[1].to_i
637+ diff1 = lines.current
638+ m = lines.assert_next(/^\+\+\+.*\(rev (\d+)\)$/)
639+ next_rev = m[1].to_i
640+ diff2 = lines.current
641+ out.puts "#V #{prev_rev},NONE"
642+ out.puts "#R #{path}"
643+ out.puts "#U #{diff1}"
644+ out.puts "#U #{diff2}"
645+ while lines.next_line && lines.current =~ /^[-\+ @\\]/
646+ out.puts "#U #{lines.current}"
647+ end
648+end
649+
650+def read_property_lines(path, prop_name, revision)
651+ lines = []
652+ svnlook("propget", revision, prop_name, path) do |io|
653+ io.each_line do |line|
654+ lines << line.chomp
655+ end
656+ end
657+ lines
658+end
659+
660+def assert_prop_match(a, b)
661+ if !b.nil? && a != b
662+ raise "property mismatch: #{a.inspect}!=#{b.inspect}"
663+ end
664+end
665+
666+# We need to read the property change from the output of svnlook, but have
667+# a difficulty in that there's no unambiguous delimiter marking the end of
668+# a potentially multi-line property value. Therefore, we do a seperate
669+# svn propget on the given file to get the value of the property on its own,
670+# and then use that value as a guide as to how much data to read from the
671+# svnlook output.
672+def munch_prop_text(path, prop_name, revision, lines, line0)
673+ prop = read_property_lines(path, prop_name, revision)
674+ if prop.empty?
675+ assert_prop_match(line0, "")
676+ return
677+ end
678+ assert_prop_match(line0, prop.shift)
679+ prop.each do |prop_line|
680+ lines.assert_next
681+ assert_prop_match(lines.current.chomp, prop_line)
682+ end
683+end
684+
685+def read_properties_changed(out, lines, path)
686+ prev_rev= $revision-1
687+ next_rev= $revision
688+ lines.assert_next(/^_+$/)
689+ return unless lines.next_line
690+ out.puts "#V #{prev_rev},#{next_rev}"
691+ out.puts "#P #{path}"
692+# The first three get consumed and not highlighted
693+ out.puts "#U "
694+ out.puts "#U Property changes:"
695+ out.puts "#U "
696+
697+ while true
698+ break unless lines.current =~ /^(?:Name|Added|Deleted): (.+)$/
699+
700+ prop_name = $1
701+ m = lines.assert_next(/^ ([-+]) (.*)/)
702+ op = m[1]
703+ line0 = m[2]
704+ if op == "-"
705+ munch_prop_text(path, prop_name, $revision-1, lines, line0)
706+ if lines.next_line && lines.current =~ /^ \+ (.*)/
83963645
ER
707+ munch_prop_text(path, prop_name, $revision, lines, $1)
708+ lines.next_line
d895f970
ER
709+ end
710+ else # op == "+"
711+ munch_prop_text(path, prop_name, $revision, lines, line0)
712+ lines.next_line
713+ end
714+ out.puts "#U #{m[1]} #{prop_name}:#{m[2]}"
715+ end
716+ out.puts "#U "
717+end
718+
719+def handle_copy(out, lines, path, from_ref, from_file)
720+ prev_rev= $revision-1
721+ next_rev= $revision
722+ out.puts "#V #{from_file}:#{prev_rev},#{next_rev}"
723+ out.puts "#C #{path}"
724+ if lines.next_line && lines.current =~ /^=+$/
725+ m = lines.assert_next(/^---.*\(rev (\d+)\)$/)
726+ prev_rev = m[1].to_i
727+ diff1 = lines.current
728+ m = lines.assert_next(/^\+\+\+.*\(rev (\d+)\)$/)
729+ next_rev = m[1].to_i
730+ diff2 = lines.current
731+ out.puts "#U #{diff1}"
732+ out.puts "#U #{diff2}"
733+ while lines.next_line && lines.current =~ /^[-\+ @\\]/
734+ out.puts "#U #{lines.current}"
735+ end
736+ else
737+ out.puts "#U "
738+ out.puts "#U Copied from #{from_file}:#{from_ref}"
739+ out.puts "#U "
740+ end
741+end
742+
743+def svnlook_author
744+ svnlook("author", $revision) do |io|
745+ return io.readline.chomp
746+ end
747+ nil
748+end
749+
750+def find_author
751+ return if $passthrough_args.include?("--from")
752+ author = svnlook_author
753+ if author
754+ blah("Author from svnlook: '#{author}'")
755+ $passthrough_args << "--from" << author
756+ end
757+end
758+
759+def process_svnlook_log(file)
760+ svnlook("log", $revision) do |io|
761+ io.each_line do |line|
762+ file.puts("#> #{line}")
763+ end
764+ end
765+end
766+
767+def process_svnlook_diff(file)
768+ svnlook("diff", $revision) do |io|
769+ lines = LineReader.new(io)
770+ while lines.next_line
771+ if lines.current =~ /^Modified:\s+(.*)/
83963645 772+ read_modified_diff(file, lines, $1)
d895f970 773+ elsif lines.current =~ /^Added:\s+(.*)/
83963645 774+ read_added_diff(file, lines, $1)
d895f970 775+ elsif lines.current =~ /^Copied:\s+(.*) \(from rev (\d+), (.*)\)$/
83963645 776+ handle_copy(file, lines, $1, $2, $3)
d895f970 777+ elsif lines.current =~ /^Deleted:\s+(.*)/
83963645 778+ read_deleted_diff(file, lines, $1)
d895f970 779+ elsif lines.current =~ /^Property changes on:\s+(.*)/
83963645 780+ read_properties_changed(file, lines, $1)
d895f970 781+ elsif lines.current == "\n"
83963645 782+ # ignore
d895f970 783+ else
83963645 784+ raise "unable to parse line '#{lines.current.inspect}'"
d895f970
ER
785+ end
786+ end
787+ end
788+end
789+
790+def process_commit()
791+ File.open("#{$datadir}/logfile", File::WRONLY|File::CREAT) do |file|
792+ process_svnlook_log(file)
793+ process_svnlook_diff(file)
794+ end
795+end
796+
797+
798+def main
799+ init()
800+ process_args()
801+ find_author()
802+ process_commit()
803+ send_email()
804+ cleanup()
805+end
806+
807+
808+main
83963645
ER
809+
810+# vim:et:ts=2:sw=2
d895f970
ER
811
812Property changes on: svn_post_commit_hook.rb
813___________________________________________________________________
814Added: svn:mergeinfo
815Added: svn:executable
816 + *
817
ca77e894
ER
818
819Property changes on: COPYING
820___________________________________________________________________
821Deleted: svn:executable
822 - *
823
efaa2289
ER
824Index: CREDITS
825===================================================================
83963645
ER
826--- CREDITS (.../tags/RELEASE-0_2_12) (revision 277)
827+++ CREDITS (.../trunk) (revision 277)
efaa2289
ER
828@@ -29,3 +29,10 @@
829