From rick at javalobby.org Mon Nov 10 20:13:26 2003 From: rick at javalobby.org (Rick Ross) Date: Mon, 10 Nov 2003 15:13:26 -0500 Subject: [cvsspam-devel] Patched version to support multiple cvsroots in cvsweb Message-ID: <3FAFF166.9090203@javalobby.org> This is a multi-part message in MIME format. --------------040206060200050900010907 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit We're really happy to have found CVSspam, it was the solution to a problem that gave us untold headaches for way longer than we are happy to admit! We needed to support multiple cvsroots in cvsweb, so we bit the bullet and did our first-ever Ruby hacking to patch CVSspam to support this feature. Enclosed is the modified cvsspam.rb file. We just add an optional "$cvswebRoot" parameter to the cvsspam.conf file, and if it is there, the required parameter is tacked onto the cvsweb urls that CVSspam produces. We make no claim to having any sense of Ruby elegance, we just wanted to make this work. Please feel free to incorporate these additions if you wish. Warm regards, Rick Ross & Matt Schmidt --------------040206060200050900010907 Content-Type: text/plain; name="cvsspam.rb" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="cvsspam.rb" #!/usr/bin/ruby -w # Part of CVSspam # http://www.badgers-in-foil.co.uk/projects/cvsspam/ # Copyright (c) David Holroyd # collect_diffs.rb expects to find this script in the same directory as it # # TODO: exemplify syntax for 'cvs admin -m' when log message is missing # TODO: make max-line limit on diff output configurable # TODO: put max size limit on whole email # TODO: support non-html mail too (text/plain, multipart/alternative) # If you want another 'todo keyword' (TODO & FIXME are highlighted by default) # you could add # $task_keywords << "KEYWORD" << "MAYBEANOTHERWORD" # to your cvssppam.conf $version = "0.2.8" $maxSubjectLength = 200 $maxLinesPerDiff = 1000 $charset = nil # nil implies 'don't specify a charset' $mailSubject = nil def blah(text) $stderr.puts("cvsspam.rb: #{text}") if $debug end def min(a, b) a0 && start.length+match.length>@right_margin io.puts(start) start = " " match.sub!(/^\s+/, "") # strip existing leading-whitespace end start << match end io.puts(start) end UNDERSCORE = "_"[0] SPACE = " "[0] TAB = "\t"[0] def rfc2047_encode_quoted(io, start, rest) raise "no charset" if @charset.nil? code_begin = "=?#{@charset}?#{@encoding}?" start << code_begin rest.each_byte do |b| code = if b>126 || b==UNDERSCORE || b==TAB sprintf("=%02x", b) elsif b == SPACE "_" else b.chr end if start.length+code.length+2 > @right_margin io.puts(start + "?=") start = " " + code_begin end start << code end io.puts(start + "?=") end private def requires_rfc2047?(word) (word =~ /[\177-\377]/) != nil end end class LogReader def initialize(logIO) @io = logIO advance end def currentLineCode ; @line[1,1] end class ConstrainedIO def initialize(reader) @reader = reader @linecode = reader.currentLineCode end def each return if @reader == nil while true yield @reader.currentLine break unless @reader.advance && currentValid? end @reader = nil end def gets return nil if @reader == nil line = @reader.currentLine return nil if line==nil || !currentValid? @reader.advance return line end def currentValid? @linecode == @reader.currentLineCode end end def getLines ConstrainedIO.new(self) end def eof ; @line==nil end def advance @line = @io.gets return false if @line == nil unless @line[0,1] == "#" raise "#{$logfile}:#{@io.lineno} line did not begin with '#': #{@line}" end return true end def currentLine @line==nil ? nil : @line[3, @line.length-4] end end def htmlEncode(text) text.gsub(/./) do case $& when "&" then "&" when "<" then "<" when ">" then ">" else $& end end end # actually, allows '/' to appear def urlEncode(text) text.sub(/[^a-zA-Z0-9\-,.*_\/]/) do "%#{sprintf('%2X', $&[0])}" end end # a top-level directory under the $CVSROOT class Repository @@repositories = Hash.new def initialize(name) @name = name @common_prefix = nil @all_tags = Hash.new end def add_tag(tag_name) if @all_tags[tag_name] @all_tags[tag_name] += 1 else @all_tags[tag_name] = 1 end end def has_multiple_tags @all_tags.length > 1 end def each_tag @all_tags.each_key do |tag| yield tag end end def trunk_only? @all_tags.length==1 && @all_tags[nil]!=nil end def mixed_tags? @all_tags.length>1 end def tag_count @all_tags.length end # calculate the path prefix shared by all files commited to this # reposotory def merge_common_prefix(path) if @common_prefix == nil @common_prefix = path.dup else path = path.dup until @common_prefix == path if @common_prefix.size>path.size if @common_prefix.sub!(/(.*)\/.*$/, '\1').nil? raise "unable to merge '#{path}' in to '#{@common_prefix}': prefix totally different" end else if path.sub!(/(.*)\/.*$/, '\1').nil? raise "unable to merge '#{path}' in to '#{@common_prefix}': prefix totally different" end end end end end attr_reader :name, :common_prefix def Repository.get(name) name =~ /^[^\/]+/ name = $& rep = @@repositories[name] if rep.nil? rep = Repository.new(name) @@repositories[name] = rep end rep end def Repository.count @@repositories.size end def Repository.each @@repositories.each_value do |rep| yield rep end end def Repository.array @@repositories.values end def to_s if trunk_only? @name elsif mixed_tags? "#{@name}@.." else "#{@name}@#{@all_tags.keys[0]}" end end end class FileEntry def initialize(path) @path = path @lineAdditions = @lineRemovals = 0 @repository = Repository.get(path) @repository.merge_common_prefix(basedir()) @isEmpty = @isBinary = false end attr_accessor :path, :type, :lineAdditions, :lineRemovals, :isBinary, :isEmpty, :fromVer, :toVer def file @path =~ /.*\/(.*)/ $1 end def tag=(name) @tag = name @repository.add_tag(name) end def tag @tag end def basedir @path =~ /(.*)\/.*/ $1 end def repository @repository end def name_after_common_prefix @path.slice(@repository.common_prefix.size+1,@path.size-@repository.common_prefix.size-1) end def removal? @type == "R" end def addition? @type == "A" end def modification? @type == "M" end end class LineConsumer def handleLines(lines, emailIO) @emailIO = emailIO @lineCount = 0 setup lines.each do |line| @lineCount += 1 consume(line) end teardown end def setup end def teardown end def lineno @lineCount end def println(text) @emailIO.puts(text) end def print(text) @emailIO.print(text) end end # TODO: consolidate these into a nicer framework, mailSub = proc { |match| "#{match}" } urlSub = proc { |match| "#{match}" } bugzillaSub = proc { |match| match =~ /([0-9]+)/ "#{match}" } jiraSub = proc { |match| "#{match}" } ticketSub = proc { |match| match =~ /([0-9]+)/ "#{match}" } commentSubstitutions = { '(?:mailto:)?[\w\.\-\+\=]+\@[\w\-]+(?:\.[\w\-]+)+\b' => mailSub, '\b(?:http|https|ftp):[^ \t\n<>"]+[\w/]' => urlSub} class CommentHandler < LineConsumer def initialize @lastComment = nil end def setup @haveBlank = false @comment = "" end def consume(line) if line =~ /^\s*$/ @haveBlank = true else if @haveBlank @comment += "\n" @haveBlank = false end $mailSubject = line if $mailSubject == nil @comment += line += "\n" end end def teardown unless @comment == @lastComment println("

") encoded = htmlEncode(@comment) $commentEncoder.gsub!(encoded) println(encoded) println("

") @lastComment = @comment end end end class TagHandler < LineConsumer def initialize @tag = nil end def consume(line) # TODO: check there is only one line @tag = line end def getLastTag tmp = @tag @tag = nil tmp end end class VersionHandler < LineConsumer def consume(line) # TODO: check there is only one line $fromVer,$toVer = line.split(/,/) end end class FileHandler < LineConsumer def setTagHandler(handler) @tagHandler = handler end def setup $fileHeaderHtml = '' println("
") end def consume(line) $file = FileEntry.new(line) $fileEntries << $file $file.tag = getTag handleFile($file) end protected def getTag @tagHandler.getLastTag end def println(text) $fileHeaderHtml << text << "\n" end def print(text) $fileHeaderHtml << text end end # don't make any links class NoFrontend def path(path, tag) htmlEncode(path) end def version(path, version) version end def diff(file) '->' end end # Superclass for objects that can link to CVS frontends on the web (ViewCVS, # Chora, etc.). class WebFrontend < NoFrontend def initialize(base_url) @base_url = base_url end def path(path, tag) path_for_href = "" result = "" path.split("/").each do |component| unless result == "" result << "/" path_for_href << "/" end path_for_href << component result << "#{htmlEncode(component)}" end result end def version(path, version) "#{version}" end def diff(file) "#{super(file)}" end end # Link to ViewCVS class ViewCVSFrontend < WebFrontend attr_accessor :repository_name def initialize(base_url) super(base_url) @repository_name = nil end def path_url(path, tag) if tag == nil add_repo(@base_url + urlEncode(path)) else add_repo("#{@base_url}#{urlEncode(path)}?only_with_tag=#{urlEncode(tag)}") end end def version_url(path, version) add_repo("#{@base_url}#{urlEncode(path)}?rev=#{version}&content-type=text/vnd.viewcvs-markup") end def diff_url(file) add_repo("#{@base_url}#{urlEncode(file.path)}.diff?r1=#{file.fromVer}&r2=#{file.toVer}") end private def add_repo(url) if @repository_name if url =~ /\?/ "#{url}&cvsroot=#{urlEncode(@repository_name)}" else "#{url}?cvsroot=#{urlEncode(@repository_name)}" end else url end end end # Link to Chora, from the Horde framework class ChoraFrontend < WebFrontend def path_url(path, tag) # TODO: can we pass the tag somehow? "#{@base_url}/cvs.php/#{urlEncode(path)}" end def version_url(path, version) "#{@base_url}/co.php/#{urlEncode(path)}?r=#{version}" end def diff_url(file) "#{@base_url}/diff.php/#{urlEncode(file.path)}?r1=#{file.fromVer}&r2=#{file.toVer}" end end # Link to CVSweb class CVSwebFrontend < WebFrontend def path_url(path, tag) if tag == nil if $cvswebRoot != nil "#{@base_url}#{urlEncode(path)}?cvsroot=#{$cvswebRoot}" else @base_url + urlEncode(path) end else if $cvswebRoot != nil "#{@base_url}#{urlEncode(path)}?only_with_tag=#{urlEncode(tag)}&cvsroot=#{$cvswebRoot}" else "#{@base_url}#{urlEncode(path)}?only_with_tag=#{urlEncode(tag)}" end end end def version_url(path, version) if $cvswebRoot != nil "#{@base_url}#{urlEncode(path)}?rev=#{version}&content-type=text/x-cvsweb-markup&cvsroot=#{$cvswebRoot}" else "#{@base_url}#{urlEncode(path)}?rev=#{version}&content-type=text/x-cvsweb-markup" end end def diff_url(file) if $cvswebRoot != nil "#{@base_url}#{urlEncode(file.path)}.diff?r1=text&tr1=#{file.fromVer}&r2=text&tr2=#{file.toVer}&f=h&cvsroot=#{$cvswebRoot}" else "#{@base_url}#{urlEncode(file.path)}.diff?r1=text&tr1=#{file.fromVer}&r2=text&tr2=#{file.toVer}&f=h" end end end # in need of refactoring... class AddedFileHandler < FileHandler def handleFile(file) file.type="A" file.toVer=$toVer print("") print($frontend.path(file.basedir, file.tag)) println("
") println("
#{htmlEncode(file.file)} added at #{$frontend.version(file.path,file.toVer)}
") end end class RemovedFileHandler < FileHandler def handleFile(file) file.type="R" file.fromVer=$fromVer print("") print($frontend.path(file.basedir, file.tag)) println("
") println("
#{htmlEncode(file.file)} removed after #{$frontend.version(file.path,file.fromVer)}
") end end class ModifiedFileHandler < FileHandler def handleFile(file) file.type="M" file.fromVer=$fromVer file.toVer=$toVer print("") print($frontend.path(file.basedir, file.tag)) println("
") println("
#{htmlEncode(file.file)} #{$frontend.version(file.path,file.fromVer)} #{$frontend.diff(file)} #{$frontend.version(file.path,file.toVer)}
") end end class UnifiedDiffStats def initialize @diffLines=3 # the three initial lines in the unidiff end def diffLines @diffLines end def consume(line) @diffLines += 1 case line[0,1] when "+" then $file.lineAdditions += 1 when "-" then $file.lineRemovals += 1 end end end # TODO: change-within-line colourisation should really be comparing the # set of lines just removed with the set of lines just added, but # it currently considers just a single line class UnifiedDiffColouriser < LineConsumer def initialize @currentState = "@" @currentStyle = "info" @lineJustDeleted = nil end def output=(io) @emailIO = io end def consume(line) initial = line[0,1] if initial != @currentState prefixLen = 1 suffixLen = 0 if initial=="+" && @currentState=="-" && @lineJustDeleted!=nil # may be an edit, try to highlight the changes part of the line a = line[1,line.length-1] b = @lineJustDeleted[1,@lineJustDeleted.length-1] prefixLen = commonPrefixLength(a, b)+1 suffixLen = commonPrefixLength(a.reverse, b.reverse) # prevent prefix/suffux having overlap, suffixLen = min(suffixLen, min(line.length,@lineJustDeleted.length)-prefixLen) deleteInfixSize = @lineJustDeleted.length - (prefixLen+suffixLen) addInfixSize = line.length - (prefixLen+suffixLen) oversize_change = deleteInfixSize*100/@lineJustDeleted.length>33 || addInfixSize*100/line.length>33 if prefixLen==1 && suffixLen==0 || deleteInfixSize<=0 || oversize_change println(htmlEncode(@lineJustDeleted)) else print(htmlEncode(@lineJustDeleted[0,prefixLen])) print("") print(formatChange(@lineJustDeleted[prefixLen,deleteInfixSize])) print("") println(htmlEncode(@lineJustDeleted[@lineJustDeleted.length-suffixLen,suffixLen])) end @lineJustDeleted = nil end if initial=="-" @lineJustDeleted=line shift(initial) # we'll print it next time (fingers crossed) return elsif @lineJustDeleted!=nil println(htmlEncode(@lineJustDeleted)) @lineJustDeleted = nil end shift(initial) if prefixLen==1 && suffixLen==0 || addInfixSize<=0 || oversize_change encoded = htmlEncode(line) else encoded = htmlEncode(line[0,prefixLen]) + "" + formatChange(line[prefixLen,addInfixSize]) + "" + htmlEncode(line[line.length-suffixLen,suffixLen]) end else encoded = htmlEncode(line) end if initial=="-" unless @lineJustDeleted==nil println(htmlEncode(@lineJustDeleted)) @lineJustDeleted=nil end end if initial=="+" $task_keywords.each do |task| if line =~ /\b(#{task}\b.*)/ $task_list << $1 encoded.sub!(/\b#{task}\b/, "#{task}") encoded = "" + encoded break end end end println(encoded) end def teardown unless @lineJustDeleted==nil println(htmlEncode(@lineJustDeleted)) @lineJustDeleted = nil end shift(nil) end private def formatChange(text) return '^M' if text=="\r" htmlEncode(text).gsub(/ /, ' ') end def shift(nextState) unless @currentState == nil if @currentStyle == "info" print("") else print("") end @currentStyle = case nextState when "\\" then "info" # as in '\ No newline at end of file' when "@" then "info" when " " then "context" when "+" then "added" when "-" then "removed" end unless nextState == nil if @currentStyle=='info' print("
")
        else
          print("
")
        end
      end
    end
    @currentState = nextState
  end

  def commonPrefixLength(a, b)
    length = 0
    a.each_byte do |char|
      break unless b[length]==char
      length = length + 1
    end
    return length
  end
end


class UnifiedDiffHandler < LineConsumer
  def setup
    @stats = UnifiedDiffStats.new
    @colour = UnifiedDiffColouriser.new
    @colour.output = @emailIO
    @lookahead = nil
  end

  def consume(line)
    case lineno()
     when 1
      @diffline = line
     when 2
      @lookahead = line
     when 3
      println($fileHeaderHtml)
      # TODO: move to UnifiedDiffColouriser
      print("
")
      println(htmlEncode(@diffline))  # 'diff ...'
      println(htmlEncode(@lookahead)) # '--- ...'
      println(htmlEncode(line))      # '+++ ...'
     else
      unless $file.removal? && $no_removed_file_diff
        @stats.consume(line)
      end
      if @stats.diffLines < $maxLinesPerDiff
        @colour.consume(line)
      elsif @stats.diffLines == $maxLinesPerDiff
        @colour.consume(line)
        @colour.teardown
      end
    end
  end

  def teardown
    if @lookahead == nil
      $file.isEmpty = true
    elsif @lookahead  =~ /Binary files .* and .* differ/
      $file.isBinary = true
    else
      unless $file.removal? && $no_removed_file_diff
        if @stats.diffLines > $maxLinesPerDiff
          println("
") println("[truncated at #{$maxLinesPerDiff} lines; #{@stats.diffLines-$maxLinesPerDiff} more skipped]") else @colour.teardown end println("
") # end of "file" div end end end end $config = "#{ENV['CVSROOT']}/CVSROOT/cvsspam.conf" $debug = false $recipients = Array.new $sendmail_prog = "/usr/sbin/sendmail" $no_removed_file_diff = false $task_keywords = ['TODO', 'FIXME'] $bugzillaURL = nil $jiraURL = nil $ticketURL = nil $viewcvsURL = nil $choraURL = nil $cvswebURL = nil $cvswebRoot = nil $from_address = nil $subjectPrefix = nil $files_in_subject = false; $smtp_host = nil $repository_name = nil require 'getoptlong' opts = GetoptLong.new( [ "--to", "-t", GetoptLong::REQUIRED_ARGUMENT ], [ "--config", "-c", GetoptLong::REQUIRED_ARGUMENT ], [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--from", "-u", GetoptLong::REQUIRED_ARGUMENT ] ) opts.each do |opt, arg| $recipients << arg if opt=="--to" $config = arg if opt=="--config" $debug = true if opt=="--debug" $from_address = arg if opt=="--from" end if ARGV.length != 1 if ARGV.length > 1 $stderr.puts "extra arguments not needed: #{ARGV[1, ARGV.length-1].join(', ')}" else $stderr.puts "missing required file argument" end puts "Usage: cvsspam.rb [ --to ] [ --config ] " exit(-1) end $logfile = ARGV[0] $additionalHeaders = Array.new $problemHeaders = Array.new # helper functions called from the 'config file' def addHeader(name, value) if name =~ /^[!-9;-~]+$/ $additionalHeaders << [name, value] else $problemHeaders << [name, value] end end def addRecipient(email) $recipients << email end class GUESS end if FileTest.exists?($config) blah("Using config '#{$config}'") load $config else blah("Config file '#{$config}' not found, ignoring") end if $recipients.empty? fail "No email recipients defined" end if $viewcvsURL != nil $viewcvsURL << "/" unless $viewcvsURL =~ /\/$/ $frontend = ViewCVSFrontend.new($viewcvsURL) if $repository_name == GUESS ENV['CVSROOT'] =~ /([^\/]+$)/ $frontend.repository_name = $1 elsif $repository_name != nil $frontend.repository_name = $repository_name end elsif $choraURL !=nil $frontend = ChoraFrontend.new($choraURL) elsif $cvswebURL !=nil $cvswebURL << "/" unless $cvswebURL =~ /\/$/ $frontend = CVSwebFrontend.new($cvswebURL) else $frontend = NoFrontend.new end if $bugzillaURL != nil commentSubstitutions['\b[Bb][Uu][Gg]\s*#?[0-9]+'] = bugzillaSub end if $jiraURL != nil commentSubstitutions['\b[a-zA-Z]+-[0-9]+\b'] = jiraSub end if $ticketURL != nil commentSubstitutions['\b[Tt][Ii][Cc][Kk][Ee][Tt]\s*#?[0-9]+\b'] = ticketSub end $commentEncoder = MultiSub.new(commentSubstitutions) tagHandler = TagHandler.new $handlers = Hash[">" => CommentHandler.new, "U" => UnifiedDiffHandler.new, "T" => tagHandler, "A" => AddedFileHandler.new, "R" => RemovedFileHandler.new, "M" => ModifiedFileHandler.new, "V" => VersionHandler.new] $handlers["A"].setTagHandler(tagHandler) $handlers["R"].setTagHandler(tagHandler) $handlers["M"].setTagHandler(tagHandler) $fileEntries = Array.new $task_list = Array.new $allTags = Hash.new File.open("#{$logfile}.emailtmp", File::RDWR|File::CREAT|File::TRUNC) do |mail| File.open($logfile) do |log| reader = LogReader.new(log) until reader.eof handler = $handlers[reader.currentLineCode] if handler == nil raise "No handler file lines marked '##{reader.currentLineCode}'" end handler.handleLines(reader.getLines, mail) end end end if $subjectPrefix == nil $subjectPrefix = "[CVS #{Repository.array.join(',')}]" end if $files_in_subject all_files = "" $fileEntries.each do |file| name = htmlEncode(file.name_after_common_prefix) if all_files != "" all_files = all_files + ";" + name else all_files = name end end $mailSubject = all_files + ":" + $mailSubject end mailSubject = "#{$subjectPrefix} #{$mailSubject}" if mailSubject.length > $maxSubjectLength mailSubject = mailSubject[0, $maxSubjectLength] end $encoder = HeaderEncoder.new $encoder.charset = $charset.nil? ? "ISO-8859-1" : $charset def make_html_email(mail) mail.puts(< HEAD unless ($problemHeaders.empty?) mail.puts("Bad header format in '#{$config}':
    ") $stderr.puts("Bad header format in '#{$config}':") $problemHeaders.each do |header| mail.puts("
  • #{htmlEncode(header[0])}
  • ") $stderr.puts(" - #{header[0]}") end mail.puts("
") end mail.puts("") haveTags = false Repository.each do |repository| haveTags |= repository.has_multiple_tags end filesAdded = 0 filesRemoved = 0 filesModified = 0 totalLinesAdded = 0 totalLinesRemoved = 0 file_count = 0 lastPath = "" last_repository = nil $fileEntries.each do |file| unless file.repository == last_repository last_repository = file.repository mail.print("") end file_count += 1 if (file_count%2==0) mail.print("") else mail.print("") end if file.addition? filesAdded += 1 elsif file.removal? filesRemoved += 1 elsif file.modification? filesModified += 1 end name = htmlEncode(file.name_after_common_prefix) slashPos = name.rindex("/") if slashPos==nil prefix = "" else thisPath = name[0,slashPos] name = name[slashPos+1,name.length] if thisPath == lastPath prefix = " "*(slashPos) + "/" else prefix = thisPath + "/" end lastPath = thisPath end if file.addition? name = "#{name}" elsif file.removal? name = "#{name}" end if file.isEmpty || file.isBinary || (file.removal? && $no_removed_file_diff) mail.print("") else mail.print("") end if file.isEmpty mail.print("") elsif file.isBinary mail.print("") else if file.lineAdditions>0 totalLinesAdded += file.lineAdditions mail.print("") else mail.print("") end if file.lineRemovals>0 totalLinesRemoved += file.lineRemovals mail.print("") else mail.print("") end end if last_repository.has_multiple_tags if file.tag mail.print("") else mail.print("") end elsif haveTags mail.print("") end if file.addition? mail.print("") elsif file.removal? mail.print("") elsif file.modification? mail.print("") end mail.puts("") end if $fileEntries.size>1 && (totalLinesAdded+totalLinesRemoved)>0 # give total number of lines added/removed accross all files mail.print("") if totalLinesAdded>0 mail.print("") else mail.print("") end if totalLinesRemoved>0 mail.print("") else mail.print("") end mail.print("") if haveTags mail.puts("") end mail.puts("
") if last_repository.has_multiple_tags mail.print("Mixed-tag commit") else mail.print("Commit") end mail.print(" in #{htmlEncode(last_repository.common_prefix)}") if last_repository.trunk_only? mail.print(" on MAIN") else mail.print(" on ") tagCount = 0 last_repository.each_tag do |tag| tagCount += 1 if tagCount > 1 mail.print tagCountMAIN" end end mail.puts("
#{prefix}#{name}#{prefix}#{name}[empty][binary]+#{file.lineAdditions}-#{file.lineRemovals}#{htmlEncode(file.tag)}MAINadded #{$frontend.version(file.path,file.toVer)}#{$frontend.version(file.path,file.fromVer)} removed#{$frontend.version(file.path,file.fromVer)} #{$frontend.diff(file)} #{$frontend.version(file.path,file.toVer)}
+#{totalLinesAdded}-#{totalLinesRemoved}
") totalFilesChanged = filesAdded+filesRemoved+filesModified if totalFilesChanged > 1 mail.print("") changeKind = 0 if filesAdded>0 mail.print("#{filesAdded} added") changeKind += 1 end if filesRemoved>0 mail.print(" + ") if changeKind>0 mail.print("#{filesRemoved} removed") changeKind += 1 end if filesModified>0 mail.print(" + ") if changeKind>0 mail.print("#{filesModified} modified") changeKind += 1 end mail.print(", total #{totalFilesChanged}") if changeKind > 1 mail.puts(" files
") end if $task_list.size > 0 task_count = 0 mail.puts("
") end File.open("#{$logfile}.emailtmp") do |input| input.each do |line| mail.puts(line.chomp) end end if $debug blah("leaving file #{$logfile}.emailtmp") else File.unlink("#{$logfile}.emailtmp") end mail.puts("
CVSspam #{$version}
") mail.puts("") end class MailContext def initialize(io) @done_headers = false @io = io end def header(name, value) raise "headers already commited" if @done_headers if name == "Subject" $encoder.encode_header(@io, "Subject", value) else @io.puts("#{name}: #{value}") end end def body @done_headers = true @io.puts yield @io end end class SendmailMailer def send(from, recipients) blah("invoking #{$sendmail_prog} -t") IO.popen("#{$sendmail_prog} -t", "w") do |mail| ctx = MailContext.new(mail) ctx.header("To", recipients.join(',')) ctx.header("From", from) if from yield ctx end end end class SMTPMailer def initialize(smtp_host) @smtp_host = smtp_host end class IOAdapter def initialize(mail) @mail = mail end def puts(text="") @mail.write(text) @mail.write("\r\n") end def print(text) @mail.write(text) end end def send(from, recipients) if from == nil from = ENV['USER'] || ENV['USERNAME'] || 'cvsspam' end unless from =~ /@/ from = "#{from}@#{ENV['HOSTNAME']||'localhost'}" end smtp = Net::SMTP.new(@smtp_host) blah("connecting to '#{@smtp_host}'") smtp.start() smtp.ready(from, recipients) do |mail| ctx = MailContext.new(IOAdapter.new(mail)) ctx.header("To", recipients.join(',')) ctx.header("From", from) if from yield ctx end end end if $smtp_host require 'net/smtp' mailer = SMTPMailer.new($smtp_host) else mailer = SendmailMailer.new end mailer.send($from_address, $recipients) do |mail| mail.header("Subject", mailSubject) mail.header("MIME-Version", "1.0") mail.header("Content-Type", "text/html" + ($charset.nil? ? "" : "; charset=\"#{$charset}\"")) if ENV['REMOTE_HOST'] # TODO: I think this will always be an IP address. If a hostname is # possible, it may need encoding of some kind, mail.header("X-Originating-IP", "[#{ENV['REMOTE_HOST']}]") end unless ($additionalHeaders.empty?) $additionalHeaders.each do |header| mail.header(header[0], header[1]) end end mail.header("X-Mailer", "CVSspam #{$version} ") mail.body do |body| make_html_email(body) end end --------------040206060200050900010907-- From matt at raibledesigns.com Mon Nov 10 22:46:06 2003 From: matt at raibledesigns.com (Matt Raible) Date: Mon, 10 Nov 2003 15:46:06 -0700 Subject: [cvsspam-devel] CVS Spam on Windows (with CVS NT) Message-ID: <001101c3a7dc$704e01b0$5700a8c0@fatbastard> I'm familiar with CVS Spam and think it's a great product. I've set it up twice on a couple of Linux boxes and its working great there. Now I'm trying to set it up on a Windows 2000 Server machine with CVS NT. I tried using the Ruby Installer from SF, but had no luck: http://rubygarden.com/ruby?WindowsInstaller After reading the Archives, I saw that the best way was to install Cygwin and use cygwin/bin/ruby.exe. I tried this and now I'm getting the following error: Checking in README.txt; c:/source/apptracker/README.txt,v <-- README.txt new revision: 1.9; previous revision: 1.8 done C:/Source/CVSROOT/COLLEC~1.RB:100:in `process_log': missing data dir (/tmp/#cvsspam.2632.18-XXXXXX) (RuntimeError) from C:/Source/CVSROOT/COLLEC~1.RB:215:in `choose_operation' from C:/Source/CVSROOT/COLLEC~1.RB:314 In CVSROOT/commitinfo, I have: ^apptracker c:/Source/CVSROOT/record_lastdir.rb In CVSROOT/loginfo, I have: ^apptracker c:/Source/CVSROOT/collect_diffs.rb --to mraible@mac.com %{sVv} And I checked in cvsspam.conf to CVSROOT and uncommented smtp.host to be localhost. Any help is appreciated. Matt From dave at badgers-in-foil.co.uk Tue Nov 11 10:40:12 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Tue, 11 Nov 2003 10:40:12 +0000 Subject: [cvsspam-devel] Patched version to support multiple cvsroots in cvsweb In-Reply-To: <3FAFF166.9090203@javalobby.org> References: <3FAFF166.9090203@javalobby.org> Message-ID: <20031111104011.GA2850@vhost.badgers-in-foil.co.uk> On Mon, Nov 10, 2003 at 03:13:26PM -0500, Rick Ross wrote: > We're really happy to have found CVSspam, it was the solution to a > problem that gave us untold headaches for way longer than we are happy > to admit! Thank you. > We needed to support multiple cvsroots in cvsweb, so we bit the bullet > and did our first-ever Ruby hacking to patch CVSspam to support this > feature. Enclosed is the modified cvsspam.rb file. Great! I'll add this in as soon as possible (noting that I've just moved home, and the CVS server still needs to be unpacked). > We just add an optional "$cvswebRoot" parameter to the cvsspam.conf > file, and if it is there, the required parameter is tacked onto the > cvsweb urls that CVSspam produces. We make no claim to having any sense > of Ruby elegance, we just wanted to make this work. Please feel free to > incorporate these additions if you wish. I make so such claims either -- CVSspam is a port of an earlier Perl script, after all. Many thanks for the code, dave From dave at badgers-in-foil.co.uk Tue Nov 11 11:30:53 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Tue, 11 Nov 2003 11:30:53 +0000 Subject: [cvsspam-devel] CVS Spam on Windows (with CVS NT) In-Reply-To: <001101c3a7dc$704e01b0$5700a8c0@fatbastard> References: <001101c3a7dc$704e01b0$5700a8c0@fatbastard> Message-ID: <20031111113053.GB2850@vhost.badgers-in-foil.co.uk> On Mon, Nov 10, 2003 at 03:46:06PM -0700, Matt Raible wrote: > I'm familiar with CVS Spam and think it's a great product. I've set it > up > twice on a couple of Linux boxes and its working great there. Now I'm > trying > to set it up on a Windows 2000 Server machine with CVS NT. I tried > using the > Ruby Installer from SF, but had no luck: > > http://rubygarden.com/ruby?WindowsInstaller > > After reading the Archives, I saw that the best way was to install > Cygwin and > use cygwin/bin/ruby.exe. I tried this and now I'm getting the following > error: > > Checking in README.txt; > c:/source/apptracker/README.txt,v <-- README.txt > new revision: 1.9; previous revision: 1.8 > done > C:/Source/CVSROOT/COLLEC~1.RB:100:in `process_log': missing data dir > (/tmp/#cvsspam.2632.18-XXXXXX) (RuntimeError) > from C:/Source/CVSROOT/COLLEC~1.RB:215:in `choose_operation' > from C:/Source/CVSROOT/COLLEC~1.RB:314 Angus Mezick did some great work hacking on CVSspam to get it working in this configuration, and I can forward you his modified version of CVSspam-0.2.7 if you want. Unfortunately, (IIRC) the changes to the scripts would stop CVSspam working in 'nix environments, so I've not yet included them in the distributed version. I seem to have lost my replies to his messages (which were off list, sorry), but I think the above problem is due to Process.getpgrp returning different values when CVS NT invokes the scripts, whereas using CVS under unix, Process.getpgrp always gives the same value during a given commit. [FYI, I made a start on altering CVSspam to work on both 'nix and windows (using CVS NT and the non-cygwin port of Ruby), but got fustrated after I realised that simulating missing 'popen' semantics would be fiddly. I may pick this up again at some point in the future.] dave From mraible at mac.com Mon Nov 17 17:14:35 2003 From: mraible at mac.com (Matt Raible) Date: Mon, 17 Nov 2003 10:14:35 -0700 Subject: [cvsspam-devel] CVS Spam with CVS NT Message-ID: <7669529.1069089275286.JavaMail.mraible@mac.com> I'm trying to use Angus's patch to resolve my issues with CVS Spam on CVS NT (http://www.raibledesigns.com/page/rd?anchor=problems_integrating_cvs_spam_and), but I installed them this morning and I'm not having any luck (so far). I changed collect_diffs.rb and record_lastdir.rb to have: $tmpdir = "/cygdrive/c/Temp" but this only squashed the first errors I was getting. Now I'm getting the following: C:/Source/CVSROOT/COLLEC~1.RB:103:in `gets': Bad file descriptor (Errno::EBADF) from C:/Source/CVSROOT/COLLEC~1.RB:103:in `process_log' from C:/Source/CVSROOT/COLLEC~1.RB:218:in `choose_operation' from C:/Source/CVSROOT/COLLEC~1.RB:302 Line 103 is: line = $stdin.gets 218 is: process_log(op) 302 is: choose_operation(ARGV[0]) I have my CVSROOT and application module checked out into c:\Temp - could that be causing a conflict? Thanks, Matt From dave at badgers-in-foil.co.uk Mon Nov 17 17:32:51 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Mon, 17 Nov 2003 17:32:51 +0000 Subject: [cvsspam-devel] CVS Spam with CVS NT In-Reply-To: <7669529.1069089275286.JavaMail.mraible@mac.com> References: <7669529.1069089275286.JavaMail.mraible@mac.com> Message-ID: <20031117173251.GA27843@vhost.badgers-in-foil.co.uk> On Mon, Nov 17, 2003 at 10:14:35AM -0700, Matt Raible wrote: > I'm trying to use Angus's patch to resolve my issues with CVS Spam on CVS NT (http://www.raibledesigns.com/page/rd?anchor=problems_integrating_cvs_spam_and), but I installed them this morning and I'm not having any luck (so far). I changed collect_diffs.rb and record_lastdir.rb to have: > > $tmpdir = "/cygdrive/c/Temp" > > but this only squashed the first errors I was getting. Now I'm getting the following: > > C:/Source/CVSROOT/COLLEC~1.RB:103:in `gets': Bad file descriptor (Errno::EBADF) > from C:/Source/CVSROOT/COLLEC~1.RB:103:in `process_log' > from C:/Source/CVSROOT/COLLEC~1.RB:218:in `choose_operation' > from C:/Source/CVSROOT/COLLEC~1.RB:302 > > Line 103 is: line = $stdin.gets > 218 is: process_log(op) > 302 is: choose_operation(ARGV[0]) I recall Angus fixed this problem by explicitly invoking ruby on the CVSspam scripts from loginfo/commitinfo (cmd.exe doesn't passing file descriptors the same way as 'nix shells do). So, off the top of my head, your config needs... ^somepath ruby $CVSROOT/CVSROOT/collect_diffs.rb dave From matt at raibledesigns.com Mon Nov 17 20:57:47 2003 From: matt at raibledesigns.com (Matt Raible) Date: Mon, 17 Nov 2003 12:57:47 -0800 (PST) Subject: [cvsspam-devel] CVS Spam with CVS NT In-Reply-To: <20031117173251.GA27843@vhost.badgers-in-foil.co.uk> Message-ID: <20031117205747.12555.qmail@web14304.mail.yahoo.com> That seemed to help, but I'm still having issues. It doesn't seem to read my cvsspam.conf file, which specifies a smtp_host - instead it's trying to use the ssmtp program from cygwin. I'm assuming this is because it's hard-coded into the modified scripts. Here's my latest errors: c:/Source/CVSROOT/collect_diffs.rb:51: warning: Insecure world writable dir /cygdrive/c, mode 040777 c:/Source/CVSROOT/collect_diffs.rb:51: warning: Insecure world writable dir /cygdrive/c, mode 040777 c:/Source/CVSROOT/collect_diffs.rb:232: warning: Insecure world writable dir /cygdrive/c, mode 040777 c:/Source/CVSROOT/cvsspam.rb:1011: warning: Insecure world writable dir /cygdrive/c, mode 040777 /cygdrive/c/Tools/cygwin/usr/sbin/ssmtp: can't open the smtp port (0) on mailhost. At this point, it seems easier to find another cvs e-mail program that works with CVS NT. Thanks for all the help, Matt --- David Holroyd wrote: > > I recall Angus fixed this problem by explicitly invoking ruby on the > CVSspam scripts from loginfo/commitinfo (cmd.exe doesn't passing file > descriptors the same way as 'nix shells do). So, off the top of my > head, your config needs... > > > ^somepath ruby $CVSROOT/CVSROOT/collect_diffs.rb > > > dave > > _______________________________________________ > cvsspam-devel mailing list > cvsspam-devel@lists.badgers-in-foil.co.uk > http://lists.badgers-in-foil.co.uk/mailman/listinfo/cvsspam-devel > > __________________________________ Do you Yahoo!? Protect your identity with Yahoo! Mail AddressGuard http://antispam.yahoo.com/whatsnewfree From dave at badgers-in-foil.co.uk Tue Nov 18 15:19:49 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Tue, 18 Nov 2003 15:19:49 +0000 Subject: [cvsspam-devel] CVS Spam on Windows (with CVS NT) In-Reply-To: <002701c3add5$6f516370$5700a8c0@fatbastard> References: <24A8596C44DF4F4DA442CBE269C351BD012DB1BD@wbmail.guidestar.net> <002701c3add5$6f516370$5700a8c0@fatbastard> Message-ID: <20031118151949.GA13297@vhost.badgers-in-foil.co.uk> On Tue, Nov 18, 2003 at 06:11:10AM -0700, Matt Raible wrote: > Do you use Cygwin's CVS (as well as ruby)? Angus is using his modified script with CVSNT. I tried CVSspam with cygwin's CVS a few versions (of CVSspam) ago, and it worked. I never got around to working out how to do the fiddly things like making Cygwin's CVS run as a service at startup, though. It was just an exercise to see if this would work at all; I wasn't putting it to use for a real project, so YMMV. dave From skoehler at upb.de Thu Nov 20 16:46:38 2003 From: skoehler at upb.de (=?ISO-8859-1?Q?Sven_K=F6hler?=) Date: Thu, 20 Nov 2003 17:46:38 +0100 Subject: [cvsspam-devel] [BUG] files in subject doesn't work Message-ID: <3FBCEFEE.9040101@upb.de> hi, setting $files_in_subject to true causes the following exception: /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/cvsspam.rb:1025:in `+': failed to convert nil into String (TypeError) from /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/cvsspam.rb:1025 /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/collect_diffs.rb:230:in `mailtest': problem running '/homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/cvsspam.rb' (RuntimeError) from /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/collect_diffs.rb:216:in `choose_operation' from /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/collect_diffs.rb:314 I'm using cvsspam 0.2.8 BTW: why do you load the cvsspam.conf from $CVSROOT/CVSROOT? I would have liked it, if cvsspam loads it from the directory where cvsspam.rb is. From skoehler at upb.de Thu Nov 20 22:30:18 2003 From: skoehler at upb.de (=?ISO-8859-15?Q?Sven_K=F6hler?=) Date: Thu, 20 Nov 2003 23:30:18 +0100 Subject: [cvsspam-devel] [RFE] From-Adress Message-ID: <3FBD407A.3020101@upb.de> It would be nice to be abled to set the domain or even the whole from-adress for the mails that are sent. The domain would be appended to the user-name that's executing the commit. It might be that one's already abled to set the whole from-address by using the addHader-directive in cvsspam.conf, but setting the domain would be nice too. From dave at badgers-in-foil.co.uk Fri Nov 21 11:03:46 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Fri, 21 Nov 2003 11:03:46 +0000 Subject: [cvsspam-devel] [BUG] files in subject doesn't work In-Reply-To: <3FBCEFEE.9040101@upb.de> References: <3FBCEFEE.9040101@upb.de> Message-ID: <20031121110346.GA2561@vhost.badgers-in-foil.co.uk> --+HP7ph2BbKc20aGI Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, Nov 20, 2003 at 05:46:38PM +0100, Sven K?hler wrote: > hi, > > setting $files_in_subject to true causes the following exception: > /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/cvsspam.rb:1025:in `+': > failed to convert nil into String (TypeError) > from /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/cvsspam.rb:1025 > /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/collect_diffs.rb:230:in > `mailtest': problem running > '/homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/cvsspam.rb' (RuntimeError) > from > /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/collect_diffs.rb:216:in > `choose_operation' > from > /homes3/info-stud/skoehler/CVS/CVSROOT/cvsspam/collect_diffs.rb:314 > > I'm using cvsspam 0.2.8 Looks like this problem would be triggered if no log message is entered for the commit. Do you recall if that was the case? Please try the attached patch to see if it fixes the problem. > BTW: why do you load the cvsspam.conf from $CVSROOT/CVSROOT? I would > have liked it, if cvsspam loads it from the directory where cvsspam.rb is. In hindsight, the default location could be better. If we where to change it, I think it would become something like '/etc/cvsspam/cvsspam.comf', though. (If you missed it, you can specify a different location for the config file using the --config option.) Thanks for the bug report, dave --+HP7ph2BbKc20aGI Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="failed_to_convert_nil_into_String-patch.diff" Index: cvsspam.rb =================================================================== RCS file: /var/lib/cvs/cvsspam/cvsspam.rb,v retrieving revision 1.40 diff -u -r1.40 cvsspam.rb --- cvsspam.rb 22 Sep 2003 21:18:17 -0000 1.40 +++ cvsspam.rb 21 Nov 2003 09:57:23 -0000 @@ -24,7 +24,7 @@ $maxSubjectLength = 200 $maxLinesPerDiff = 1000 $charset = nil # nil implies 'don't specify a charset' -$mailSubject = nil +$mailSubject = '' def blah(text) $stderr.puts("cvsspam.rb: #{text}") if $debug @@ -421,7 +421,7 @@ @comment += "\n" @haveBlank = false end - $mailSubject = line if $mailSubject == nil + $mailSubject = line unless $mailSubject @comment += line += "\n" end end --+HP7ph2BbKc20aGI-- From dave at badgers-in-foil.co.uk Fri Nov 21 11:18:13 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Fri, 21 Nov 2003 11:18:13 +0000 Subject: [cvsspam-devel] [RFE] From-Adress In-Reply-To: <3FBD407A.3020101@upb.de> References: <3FBD407A.3020101@upb.de> Message-ID: <20031121111813.GB2561@vhost.badgers-in-foil.co.uk> On Thu, Nov 20, 2003 at 11:30:18PM +0100, Sven K?hler wrote: > It would be nice to be abled to set the domain or even the whole > from-adress for the mails that are sent. > The domain would be appended to the user-name that's executing the > commit. It might be that one's already abled to set the whole > from-address by using the addHader-directive in cvsspam.conf, but > setting the domain would be nice too. If you currently see messages with just the username in the from-address (no hostname) and you are using the machine's MTA (e.g. /usr/sbin/sendmail), you may be able to fix the MTA's config to append the correct hostname to outbound mail. For exim, if you don't want the machine's primary hostname added to the username, provide your qualify_domain = myhostname.com in exim.conf instead. On the other hand, if your setup means that all commits appear to come from a user like 'cvs' or 'nobody', consider supplying the --from $USER option in loginfo... http://www.badgers-in-foil.co.uk/projects/cvsspam/cvsspam-doc.html#AEN98 (Saying --from $USER@myhostname.com would be valid too, I think.) dave From skoehler at upb.de Fri Nov 21 14:25:20 2003 From: skoehler at upb.de (=?ISO-8859-1?Q?Sven_K=F6hler?=) Date: Fri, 21 Nov 2003 15:25:20 +0100 Subject: [cvsspam-devel] [BUG] files in subject doesn't work In-Reply-To: <20031121110346.GA2561@vhost.badgers-in-foil.co.uk> References: <3FBCEFEE.9040101@upb.de> <20031121110346.GA2561@vhost.badgers-in-foil.co.uk> Message-ID: <3FBE2050.3080907@upb.de> > Looks like this problem would be triggered if no log message is entered > for the commit. Do you recall if that was the case? i think it was the case. > Please try the attached patch to see if it fixes the problem. tried it, and it seems to work. >>BTW: why do you load the cvsspam.conf from $CVSROOT/CVSROOT? I would >>have liked it, if cvsspam loads it from the directory where cvsspam.rb is. > > In hindsight, the default location could be better. If we where to change > it, I think it would become something like '/etc/cvsspam/cvsspam.comf', > though. If the default location for cvsspam.conf every becomes /etc/cvsspam/cvsspam.conf only, that would be bad. everybody should be abled to a cvsspam.conf to their CVSROOT. Perhaps my suggestion doesn't make much sense to you. I've put cvsspam into CVSROOT/cvsspam/ and i first wondered why it wouldn't find my cvsspam.conf until i put in CVSROOT/ itself. Usually when i write Perl script with a config-file i try to determine which directory my Perl script is in (via $0 which is the patch to the script) and than try to access the config-file in that directory. > (If you missed it, you can specify a different location for the config > file using the --config option.) Well, i have many entries in my CVSROOT/loginfo file because it depends on the CVS module which people are getting mail. Perhaps that would be a nice feature to add: addRecipient("module1, module2", "mail1@host, mail2@host") which adds the mail-adresses to the list of recipient if the module-name matches one in the module-list. My loginfo would look like chaos if i'd add the --config option to every line. > Thanks for the bug report, Thanks for fixing it that fast From skoehler at upb.de Fri Nov 21 14:29:55 2003 From: skoehler at upb.de (=?ISO-8859-1?Q?Sven_K=F6hler?=) Date: Fri, 21 Nov 2003 15:29:55 +0100 Subject: [cvsspam-devel] [RFE] From-Adress In-Reply-To: <20031121111813.GB2561@vhost.badgers-in-foil.co.uk> References: <3FBD407A.3020101@upb.de> <20031121111813.GB2561@vhost.badgers-in-foil.co.uk> Message-ID: <3FBE2163.9000909@upb.de> >>It would be nice to be abled to set the domain or even the whole >>from-adress for the mails that are sent. >>The domain would be appended to the user-name that's executing the >>commit. It might be that one's already abled to set the whole >>from-address by using the addHader-directive in cvsspam.conf, but >>setting the domain would be nice too. > > If you currently see messages with just the username in the from-address > (no hostname) and you are using the machine's MTA (e.g. > /usr/sbin/sendmail), you may be able to fix the MTA's config to append > the correct hostname to outbound mail. An domain is added to the from-adress, but it's the wrong one. The case is a bit complicated: it's not my computer and i don't have root-access. So i cannot configure anything. I have a CVS-Repository on the computers at my college which i can access via ssh. I use it together with some other students. So it wouldn't be nice to set the user or even the whole from-adress. Thx Sven From Aaron.Korver at Fiserv.com Sat Nov 22 17:49:03 2003 From: Aaron.Korver at Fiserv.com (Korver, Aaron) Date: Sat, 22 Nov 2003 11:49:03 -0600 Subject: [cvsspam-devel] From-Address Message-ID: <0205C50D41B7D611AEA50002A537CEC20165969B@DES10MS01> This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_001_01C3B120.EADA49F0 Content-Type: text/plain; charset="iso-8859-1" Hey cool! you updated the documentation. Nice. When did you sneak that external MTA transport configuration in? I missed that. Gonna have to upgrade now to get that fix :-) ------_=_NextPart_001_01C3B120.EADA49F0 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable From-Address

Hey cool! you updated the = documentation.   Nice.

When did you sneak that external MTA = transport configuration in?  I missed that.  Gonna have to = upgrade now to get that fix :-) 

------_=_NextPart_001_01C3B120.EADA49F0-- From dave at badgers-in-foil.co.uk Sun Nov 23 14:30:37 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sun, 23 Nov 2003 14:30:37 +0000 Subject: [cvsspam-devel] From-Address In-Reply-To: <0205C50D41B7D611AEA50002A537CEC20165969B@DES10MS01> References: <0205C50D41B7D611AEA50002A537CEC20165969B@DES10MS01> Message-ID: <20031123143037.GA12563@vhost.badgers-in-foil.co.uk> On Sat, Nov 22, 2003 at 11:49:03AM -0600, Korver, Aaron wrote: > Hey cool! you updated the documentation. Nice. > > When did you sneak that external MTA transport configuration in? I missed > that. Gonna have to upgrade now to get that fix :-) Support for using SMTP directly got added in 0.2.8 because it's a small step towards getting CVSspam going on Windows (and because it was easy to implement). There's still lots preventing the same scripts working on both Windows and 'nix, unfortunately (unless you run everything in Cygwin). dave From dave at badgers-in-foil.co.uk Sun Nov 23 17:31:22 2003 From: dave at badgers-in-foil.co.uk (David Holroyd) Date: Sun, 23 Nov 2003 17:31:22 +0000 Subject: [cvsspam-devel] Patched version to support multiple cvsroots in cvsweb In-Reply-To: <3FAFF166.9090203@javalobby.org> References: <3FAFF166.9090203@javalobby.org> Message-ID: <20031123173122.GA15243@vhost.badgers-in-foil.co.uk> --T4sUOijqQbZv57TR Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Nov 10, 2003 at 03:13:26PM -0500, Rick Ross wrote: > We needed to support multiple cvsroots in cvsweb, so we bit the bullet > and did our first-ever Ruby hacking to patch CVSspam to support this > feature. Enclosed is the modified cvsspam.rb file. > > We just add an optional "$cvswebRoot" parameter to the cvsspam.conf > file, and if it is there, the required parameter is tacked onto the > cvsweb urls that CVSspam produces. We make no claim to having any sense > of Ruby elegance, we just wanted to make this work. Please feel free to > incorporate these additions if you wish. Ok, I've had the time to look though your changes, and I've noticed that we're do the same thing as the existing code to support multiple roots with ViewCVS. I've moved that existing code around so that it's now available for both CVSweb and ViewCVS; a patch against the 0.2.8 version of cvsspam.rb is attached. It would be really great if you could verify that this alternative implementation works (I don't have a CVSweb installation). Note that this version uses a config variable called '$repository_name' rather than '$cvswebRoot', and that the patch doesn't include the formatting change also present in your version of the script (hmm, maybe the included CSS should be configurable also). Many thanks for the code, dave --T4sUOijqQbZv57TR Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="cvsweb_repository_name-patch.diff" Index: cvsspam.rb =================================================================== RCS file: /var/lib/cvs/cvsspam/cvsspam.rb,v retrieving revision 1.41 diff -u -r1.41 cvsspam.rb --- cvsspam.rb 23 Nov 2003 13:24:09 -0000 1.41 +++ cvsspam.rb 23 Nov 2003 17:11:55 -0000 @@ -539,6 +539,19 @@ def diff(file) "#{super(file)}" end + + protected + def add_repo(url) + if @repository_name + if url =~ /\?/ + "#{url}&cvsroot=#{urlEncode(@repository_name)}" + else + "#{url}?cvsroot=#{urlEncode(@repository_name)}" + end + else + url + end + end end # Link to ViewCVS @@ -566,19 +579,6 @@ def diff_url(file) add_repo("#{@base_url}#{urlEncode(file.path)}.diff?r1=#{file.fromVer}&r2=#{file.toVer}") end - - private - def add_repo(url) - if @repository_name - if url =~ /\?/ - "#{url}&cvsroot=#{urlEncode(@repository_name)}" - else - "#{url}?cvsroot=#{urlEncode(@repository_name)}" - end - else - url - end - end end # Link to Chora, from the Horde framework @@ -601,18 +601,18 @@ class CVSwebFrontend < WebFrontend def path_url(path, tag) if tag == nil - @base_url + urlEncode(path) + add_repo(@base_url + urlEncode(path)) else - "#{@base_url}#{urlEncode(path)}?only_with_tag=#{urlEncode(tag)}" + add_repo("#{@base_url}#{urlEncode(path)}?only_with_tag=#{urlEncode(tag)}") end end def version_url(path, version) - "#{@base_url}#{urlEncode(path)}?rev=#{version}&content-type=text/x-cvsweb-markup" + add_repo("#{@base_url}#{urlEncode(path)}?rev=#{version}&content-type=text/x-cvsweb-markup") end def diff_url(file) - "#{@base_url}#{urlEncode(file.path)}.diff?r1=text&tr1=#{file.fromVer}&r2=text&tr2=#{file.toVer}&f=h" + add_repo("#{@base_url}#{urlEncode(file.path)}.diff?r1=text&tr1=#{file.fromVer}&r2=text&tr2=#{file.toVer}&f=h") end end @@ -948,12 +948,6 @@ if $viewcvsURL != nil $viewcvsURL << "/" unless $viewcvsURL =~ /\/$/ $frontend = ViewCVSFrontend.new($viewcvsURL) - if $repository_name == GUESS - ENV['CVSROOT'] =~ /([^\/]+$)/ - $frontend.repository_name = $1 - elsif $repository_name != nil - $frontend.repository_name = $repository_name - end elsif $choraURL !=nil $frontend = ChoraFrontend.new($choraURL) elsif $cvswebURL !=nil @@ -962,6 +956,17 @@ else $frontend = NoFrontend.new end + +if $viewcvsURL != nil || $cvswebURL !=nil + if $repository_name == GUESS + # use the last component of the repository path as the name + ENV['CVSROOT'] =~ /([^\/]+$)/ + $frontend.repository_name = $1 + elsif $repository_name != nil + $frontend.repository_name = $repository_name + end +end + if $bugzillaURL != nil commentSubstitutions['\b[Bb][Uu][Gg]\s*#?[0-9]+'] = bugzillaSub --T4sUOijqQbZv57TR--