CVS Web Frontends
--- cvsspam-0.2.12/cvsspam.conf 2005-07-11 18:53:30.000000000 +0300
+++ cvsspam/cvsspam.conf 2006-12-21 11:44:26.827358000 +0200
@@ -34,11 +34,19 @@
#
# When $jiraURL is given, text of the form 'project-1234' will be linked
# to this issue in JIRA.
+#
+# When $xplannerStoryURL, $xplannerIterationURL and $xplannerProjectURL are
+# given, text of the form XS1234 will be linked to XPlanner stories; text of
+# the form XI1234 will be linked to XPlanner iterations; and text of the form
+# XP1234 will be linked to XPlanner projects.
#$bugzillaURL = "http://bugzilla.mozilla.org/show_bug.cgi?id=%s"
#$jiraURL = "http://jira.atlassian.com/secure/ViewIssue.jspa?key=%s"
+#$xplannerStoryURL = "http://www.example.com/xplanner/do/view/userstory?oid=%s"
+#$xplannerIterationURL = "http://www.example.com/xplanner/do/view/iteration?oid=%s"
+#$xplannerProjectURL = "http://www.example.com/xplanner/do/view/project?oid=%s"
# Link to Wiki systems
#
@@ -119,12 +127,21 @@
# cvsdiff keyword ignoring (Default: show changes in keywords)
#
# Changes in CVS keywords can be distracting. For instance, the
-# $Revision$ keyword will change on each commit. Set this value to true
+# $Revision$ keyword will change on each commit. Set this value to true
# to exclude changes in keyword fields (adds the -kk option to cvs diff).
#$diff_ignore_keywords = true
+# cvsdiff whitespace ignoring (Default: show whitespace-only changes)
+#
+# Whitespace-only changes can distract from the rest of a diff. Set this
+# value to true to exclude changes in the amount of whitespace (adds the -b
+# option to cvs diff).
+
+$diff_ignore_whitespace = true
+
+
# $no_removed_file_diff and $no_added_file_diff
#
# Set both these options, and emails will only include diffs for files
@@ -177,3 +194,13 @@
# them happy, you can say $files_in_subject = true here.
#$files_in_subject = false
+
+
+
+# Email size limit (Default: around 2MB)
+#
+# When large changes are committed, large CVSspam emails can result. Here
+# you can set the size of email that CVSspam is not allowed to append any
+# more diffs onto. Specify the number of bytes.
+
+#$mail_size_limit = 2097152
--- cvsspam-0.2.12/cvsspam.rb 2005-07-11 18:53:29.000000000 +0300
+++ cvsspam/cvsspam.rb 2006-12-21 17:36:44.342608880 +0200
@@ -20,6 +20,7 @@
$version = "0.2.12"
+require 'time'
$maxSubjectLength = 200
$maxLinesPerDiff = 1000
@@ -35,10 +36,6 @@
a126 || b==UNDERSCORE || b==TAB
+ if b>126 || b==UNDERSCORE || b==TAB || b==HOOK || b==EQUALS
sprintf("=%02x", b)
elsif b == SPACE
"_"
@@ -388,6 +387,7 @@
class FileEntry
def initialize(path)
@path = path
+ @fromVer = @toVer = nil
@lineAdditions = @lineRemovals = 0
@repository = Repository.get(path)
@repository.merge_common_prefix(basedir())
@@ -533,6 +533,14 @@
# TODO: consolidate these into a nicer framework,
mailSub = proc { |match| "#{match}" }
urlSub = proc { |match| "#{match}" }
+gforgeTaskSub = proc { |match|
+ match =~ /([0-9]+)/
+ "#{match}"
+}
+gforgeBugSub = proc { |match|
+ match =~ /([0-9]+)/
+ "#{match}"
+}
bugzillaSub = proc { |match|
match =~ /([0-9]+)/
"#{match}"
@@ -544,11 +552,27 @@
match =~ /([0-9]+)/
"#{match}"
}
+issueSub = proc { |match|
+ match =~ /([0-9]+)/
+ "#{match}"
+}
wikiSub = proc { |match|
- match =~ /\[\[(.*)\]\]/
+ match =~ /\[\[(.*?)\]\]/
raw = $1
"[[#{raw}]]"
}
+xplannerIterationSub = proc { |match|
+ match =~ /([0-9]+)/
+ "#{match}"
+}
+xplannerProjectSub = proc { |match|
+ match =~ /([0-9]+)/
+ "#{match}"
+}
+xplannerStorySub = proc { |match|
+ match =~ /([0-9]+)/
+ "#{match}"
+}
commentSubstitutions = {
'(?:mailto:)?[\w\.\-\+\=]+\@[\w\-]+(?:\.[\w\-]+)+\b' => mailSub,
'\b(?:http|https|ftp):[^ \t\n<>"]+[\w/]' => urlSub
@@ -670,6 +694,12 @@
def diff(file)
'->'
end
+
+ # may be overridden by subclasses that are able to make a hyperlink to a
+ # history log for a file
+ def log(file)
+ ''
+ end
end
# Superclass for objects that can link to CVS frontends on the web (ViewCVS,
@@ -710,6 +740,14 @@
"#{super(file)}"
end
+ def log(file)
+ link = log_url(file)
+ if link
+ return "(log)"
+ end
+ return nil
+ end
+
protected
def add_repo(url)
if @repository_name
@@ -722,6 +760,10 @@
url
end
end
+
+ def log_url(file)
+ nil
+ end
end
# Link to ViewCVS
@@ -745,6 +787,15 @@
def diff_url(file)
add_repo("#{@base_url}#{urlEncode(file.path)}.diff?r1=#{file.fromVer}&r2=#{file.toVer}")
end
+
+ def log_url(file)
+ if file.toVer
+ log_anchor = "#rev#{file.toVer}"
+ else
+ log_anchor = ""
+ end
+ add_repo("#{@base_url}#{urlEncode(file.path)}#{log_anchor}")
+ end
end
# Link to Chora, from the Horde framework
@@ -767,9 +818,9 @@
class CVSwebFrontend < WebFrontend
def path_url(path, tag)
if tag == nil
- add_repo(@base_url + urlEncode(path))
+ add_repo(@base_url + urlEncode(path) + "/")
else
- add_repo("#{@base_url}#{urlEncode(path)}?only_with_tag=#{urlEncode(tag)}")
+ add_repo("#{@base_url}#{urlEncode(path)}/?only_with_tag=#{urlEncode(tag)}")
end
end
@@ -780,6 +831,17 @@
def diff_url(file)
add_repo("#{@base_url}#{urlEncode(file.path)}.diff?r1=text&tr1=#{file.fromVer}&r2=text&tr2=#{file.toVer}&f=h")
end
+
+ protected
+
+ def log_url(file)
+ if file.toVer
+ log_anchor = "#rev#{file.toVer}"
+ else
+ log_anchor = ""
+ end
+ add_repo("#{@base_url}#{urlEncode(file.path)}#{log_anchor}")
+ end
end
@@ -958,7 +1020,7 @@
end
shift(nil)
if @truncatedLineCount>0
- println("[Note: Some over-long lines of diff output only partialy shown]")
+ println("[Note: Some over-long lines of diff output only partially shown]")
end
end
@@ -1247,10 +1309,16 @@
$no_diff = false
$task_keywords = ['TODO', 'FIXME']
$bugzillaURL = nil
+$gforgeBugURL = nil
+$gforgeTaskURL = nil
$wikiURL = nil
$jiraURL = nil
$ticketURL = nil
+$issueURL = nil
$viewcvsURL = nil
+$xplannerIterationURL = nil
+$xplannerProjectURL = nil
+$xplannerStoryURL = nil
$choraURL = nil
$cvswebURL = nil
$from_address = nil
@@ -1261,6 +1329,7 @@
# 2MiB limit on attached diffs,
$mail_size_limit = 1024 * 1024 * 2
$arg_charset = nil
+$cvsroot_email_header = false
require 'getoptlong'
@@ -1353,7 +1422,13 @@
if $bugzillaURL != nil
- commentSubstitutions['\b[Bb][Uu][Gg]\s*#?[0-9]+'] = bugzillaSub
+ commentSubstitutions['\b[Bb]([Uu][Gg])?\s*[#:]?\s*\[?[0-9]+\]?'] = bugzillaSub
+end
+if $gforgeBugURL != nil
+ commentSubstitutions['\B\[#[0-9]+\]'] = gforgeBugSub
+end
+if $gforgeTaskURL != nil
+ commentSubstitutions['\B\[[Tt][0-9]+\]'] = gforgeTaskSub
end
if $jiraURL != nil
commentSubstitutions['\b[a-zA-Z]+-[0-9]+\b'] = jiraSub
@@ -1361,9 +1436,21 @@
if $ticketURL != nil
commentSubstitutions['\b[Tt][Ii][Cc][Kk][Ee][Tt]\s*#?[0-9]+\b'] = ticketSub
end
+if $issueURL != nil
+ commentSubstitutions['\b[Ii][Ss][Ss][Uu][Ee]\s*#?[0-9]+\b'] = issueSub
+end
if $wikiURL != nil
commentSubstitutions['\[\[.+\]\]'] = wikiSub
end
+if $xplannerIterationURL != nil
+ commentSubstitutions['\bXI\[?[0-9]+\]?'] = xplannerIterationSub
+end
+if $xplannerProjectURL != nil
+ commentSubstitutions['\bXP\[?[0-9]+\]?'] = xplannerProjectSub
+end
+if $xplannerStoryURL != nil
+ commentSubstitutions['\bXS\[?[0-9]+\]?'] = xplannerStorySub
+end
$commentEncoder = MultiSub.new(commentSubstitutions)
@@ -1546,11 +1633,14 @@
elsif file.removal?
name = "#{name}"
end
+ mail.print("")
if file.has_diff?
- mail.print(" | #{prefix}#{name} | ")
+ mail.print("#{prefix}#{name}")
else
- mail.print("#{prefix}#{name} | ")
+ mail.print("#{prefix}#{name}")
end
+ mail.print(" #{$frontend.log(file)}")
+ mail.print("")
if file.isEmpty
mail.print("[empty] | ")
elsif file.isBinary
@@ -1686,6 +1776,8 @@
# sensible header formatting, and for ensuring that the body is seperated
# from the message headers by a blank line (as it is required to be).
class MailContext
+ ENCODE_HEADERS = ["Subject", "X-CVSspam-Module-Path"]
+
def initialize(io)
@done_headers = false
@io = io
@@ -1695,8 +1787,8 @@
# called
def header(name, value)
raise "headers already commited" if @done_headers
- if name == "Subject"
- $encoder.encode_header(@io, "Subject", value)
+ if ENCODE_HEADERS.include?(name)
+ $encoder.encode_header(@io, name, value)
else
@io.puts("#{name}: #{value}")
end
@@ -1769,7 +1861,7 @@
ctx.header("To", recipients.map{|addr| addr.encoded}.join(','))
blah("Mail From: <#{from}>")
ctx.header("From", from.encoded) if from
- ctx.header("Date", Time.now.utc.strftime(DATE_HEADER_FORMAT))
+ ctx.header("Date", Time.now.rfc2822)
yield ctx
end
end
@@ -1800,10 +1892,10 @@
return unless $fileEntries.length == 1
file = $fileEntries[0]
name = zap_header_special_chars(file.path)
- unless file.fromVer == "NONE"
+ if file.fromVer
mail.header("References", make_msg_id("#{name}.#{file.fromVer}", $hostname))
end
- unless file.toVer == "NONE"
+ if file.toVer
mail.header("Message-ID", make_msg_id("#{name}.#{file.toVer}", $hostname))
end
end
@@ -1834,6 +1926,14 @@
end
end
mail.header("X-Mailer", "CVSspam #{$version} ")
+ if $cvsroot_email_header
+ mod = '/'
+ if Repository.count == 1
+ rep = Repository.array.first
+ mod << rep.common_prefix
+ end
+ mail.header("X-CVSspam-Module-Path", mod)
+ end
mail.body do |body|
make_html_email(body)
--- cvsspam-0.2.12/record_lastdir.rb 2005-07-11 18:53:29.000000000 +0300
+++ cvsspam/record_lastdir.rb 2006-12-21 11:44:26.827358000 +0200
@@ -4,7 +4,6 @@
# http://www.badgers-in-foil.co.uk/projects/cvsspam/
# Copyright (c) David Holroyd
-$repositorydir = ARGV.shift
$tmpdir = ENV["TMPDIR"] || "/tmp"
@@ -19,6 +18,36 @@
nil
end
+
+# transform any special / unexpected characters appearing in the argument to
+# --from so that they will not cause problems if the value is inserted into
+# a file or directory name
+def make_fromaddr_safe_for_filename(addr)
+ addr.gsub(/[^a-zA-Z0-1.,_-]/, "_")
+end
+
+# Option processing doesn't use GetoptLong (for the moment) bacause arguments
+# given to this script by CVS include the names of committed files. It
+# seems quite possible that one of those file names could begin with a '-'
+# and therefore be treated by GetoptLong as a value which requires processing.
+# This would probably result in an error.
+#
+# [That could be worked around by placing a '--' option (which tells GetoptLong
+# to stop processing option arguments) at the very end of the arguments to
+# record_lastdir.rb in commitinfo, but that's very easily forgotten, and isn't
+# really backwards compatable with the behaviour of older CVSspam releases.]
+if ARGV.first == "--from"
+ # we could, of course, be tricked, if the first committed file in the list
+ # happened to be named '--from' :S
+
+ # drop the "--from"
+ ARGV.shift
+ # and use the value which was given following the option,
+ $dirtemplate << "." << make_fromaddr_safe_for_filename(ARGV.shift)
+end
+
+$repositorydir = ARGV.shift
+
$datadir = find_data_dir()
if $datadir==nil