[GME-commit] CVSROOT syncmail,1.16,1.17

gme-commit at list.isis.vanderbilt.edu gme-commit at list.isis.vanderbilt.edu
Thu Mar 17 09:23:33 CST 2005


Update of /project/gme-repository/CVSROOT
In directory escher:/tmp/cvs-serv21261

Modified Files:
	syncmail 
Log Message:
upgrading syncmail

CVS User: volgy

Index: syncmail
===================================================================
RCS file: /project/gme-repository/CVSROOT/syncmail,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -d -r1.16 -r1.17
*** syncmail	17 Mar 2005 15:16:14 -0000	1.16
--- syncmail	17 Mar 2005 15:23:31 -0000	1.17
***************
*** 1,6 ****
  #! /usr/bin/python
  
! # NOTE: Until SourceForge installs a modern version of Python on the cvs
! # servers, this script MUST be compatible with Python 1.5.2.
  
  """Complicated notification for CVS checkins.
--- 1,10 ----
  #! /usr/bin/python
  
! # Copyright (c) 2002, 2003, 2004 Barry Warsaw, Fred Drake, and contributors
! # All rights reserved.
! # See the accompanying LICENSE file for details.
! 
! # NOTE: SourceForge currently runs Python 2.2.3, so we need to remain
! # compatible with the Python 2.2 line.
  
  """Complicated notification for CVS checkins.
***************
*** 35,40 ****
  
      --cvsroot=<path>
!     	Use <path> as the environment variable CVSROOT.  Otherwise this
!     	variable must exist in the environment.
  
      --context=#
--- 39,44 ----
  
      --cvsroot=<path>
!         Use <path> as the environment variable CVSROOT.  Otherwise this
!         variable must exist in the environment.
  
      --context=#
***************
*** 45,60 ****
          Produce a context diff (default).
  
      -u
          Produce a unified diff (smaller).
  
      --quiet / -q
          Don't print as much status to stdout.
  
!     --fromaddr=emailaddr
!     -f emailaddr
!         The address that email messages appear to be coming from. By
!         default, the From: header will of the outgoing message will 
!         look like user at hostname, where hostname is the machine's fully 
!         qualified domain name and user is current user (uid)
  
      --help / -h
--- 49,76 ----
          Produce a context diff (default).
  
+     -m hostname
+     --mailhost hostname
+         The hostname of an available SMTP server.  The default is
+         'localhost'.
+ 
      -u
          Produce a unified diff (smaller).
  
+     -S TEXT
+     --subject-prefix=TEXT
+         Prepend TEXT to the email subject line.
+ 
+     -R ADDR
+     --reply-to=ADDR
+       Add a "Reply-To: ADDR" header to the email message.
+ 
      --quiet / -q
          Don't print as much status to stdout.
  
!     --fromhost=hostname
!     -f hostname
!         The hostname that email messages appear to be coming from.  The From:
!         header of the outgoing message will look like user at hostname.  By
!         default, hostname is the machine's fully qualified domain name.
  
      --help / -h
***************
*** 73,107 ****
          At least one email address.
  """
  import os
- import sys
  import re
  import time
- import string
  import getopt
- import smtplib
- import pwd
  import socket
! 
! try:
!     from socket import getfqdn
! except ImportError:
!     def getfqdn():
!         # Python 1.5.2 :(
!         hostname = socket.gethostname()
!         byaddr = socket.gethostbyaddr(socket.gethostbyname(hostname))
!         aliases = byaddr[1]
!         aliases.insert(0, byaddr[0])
!         aliases.insert(0, hostname)
!         for fqdn in aliases:
!             if '.' in fqdn:
!                 break
!         else:
!             fqdn = 'localhost.localdomain'
!         return fqdn
!     
  
  from cStringIO import StringIO
  
! # Which SMTP server to do we connect to?  Empty string means localhost.
  MAILHOST = 'localhost'
  MAILPORT = 25
--- 89,107 ----
          At least one email address.
  """
+ __version__ = '$Revision$'
+ 
  import os
  import re
+ import pwd
+ import sys
  import time
  import getopt
  import socket
! import smtplib
  
  from cStringIO import StringIO
+ from email.Utils import formataddr
  
! # Which SMTP server to do we connect to?
  MAILHOST = 'localhost'
  MAILPORT = 25
***************
*** 112,118 ****
  DIFF_TRUNCATE_IF_LARGER = 1000
  
- EMPTYSTRING = ''
- SPACE = ' '
- DOT = '.'
  COMMASPACE = ', '
  
--- 112,115 ----
***************
*** 123,128 ****
      ]
  
! REVCRE = re.compile("^(NONE|[0-9.]+)$")
! NOVERSION = "Couldn't generate diff; no version number found in filespec: %s"
  BACKSLASH = "Couldn't generate diff: backslash in filespec's filename: %s"
  
--- 120,124 ----
      ]
  
! NOVERSION = "Couldn't generate diff; no version number found for file: %s"
  BACKSLASH = "Couldn't generate diff: backslash in filespec's filename: %s"
  
***************
*** 137,161 ****
  
  
! def calculate_diff(filespec, contextlines):
!     file, oldrev, newrev = string.split(filespec, ',')
!     # Make sure we can find a CVS version number
!     if not REVCRE.match(oldrev):
!         return NOVERSION % filespec
!     if not REVCRE.match(newrev):
!         return NOVERSION % filespec
  
!     if string.find(file, '\\') <> -1:
!         # I'm sorry, a file name that contains a backslash is just too much.
!         # XXX if someone wants to figure out how to escape the backslashes in
!         # a safe way to allow filenames containing backslashes, this is the
!         # place to do it.  --Zooko 2002-03-17
!         return BACKSLASH % filespec
  
!     if string.find(file, "'") <> -1:
          # Those crazy users put single-quotes in their file names!  Now we
          # have to escape everything that is meaningful inside double-quotes.
!         filestr = string.replace(file, '`', '\`')
!         filestr = string.replace(filestr, '"', '\"')
!         filestr = string.replace(filestr, '$', '\$')
          # and quote it with double-quotes.
          filestr = '"' + filestr + '"'
--- 133,152 ----
  
  
! def calculate_diff(entry, contextlines):
!     file = entry.name
!     oldrev = entry.revision
!     newrev = entry.new_revision
  
!     # Make sure we can find a CVS version number
!     if oldrev is None and newrev is None:
!         return NOVERSION % file
  
!     if file.find("'") <> -1:
          # Those crazy users put single-quotes in their file names!  Now we
          # have to escape everything that is meaningful inside double-quotes.
!         filestr = filestr.replace('\\', '\\\\')
!         filestr = filestr.replace('`', '\`')
!         filestr = filestr.replace('"', '\"')
!         filestr = filestr.replace('$', '\$')
          # and quote it with double-quotes.
          filestr = '"' + filestr + '"'
***************
*** 163,167 ****
          # quote it with single-quotes.
          filestr = "'" + file + "'"
!     if oldrev == 'NONE':
          try:
              if os.path.exists(file):
--- 154,159 ----
          # quote it with single-quotes.
          filestr = "'" + file + "'"
!     if oldrev is None:
!         # File is being added.
          try:
              if os.path.exists(file):
***************
*** 175,180 ****
              # lines to figure it out:
              for line in lines[:5]:
!                 for c in string.rstrip(line):
!                     if c in string.whitespace:
                          continue
                      if c < ' ' or c > chr(127):
--- 167,172 ----
              # lines to figure it out:
              for line in lines[:5]:
!                 for c in line.rstrip():
!                     if c.isspace():
                          continue
                      if c < ' ' or c > chr(127):
***************
*** 185,191 ****
              lines = ['***** Error reading new file: ',
                       str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()]
!     elif newrev == 'NONE':
          lines = ['--- %s DELETED ---\n' % file]
      else:
          # This /has/ to happen in the background, otherwise we'll run into CVS
          # lock contention.  What a crock.
--- 177,184 ----
              lines = ['***** Error reading new file: ',
                       str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()]
!     elif newrev is None:
          lines = ['--- %s DELETED ---\n' % file]
      else:
+         # File has been changed.
          # This /has/ to happen in the background, otherwise we'll run into CVS
          # lock contention.  What a crock.
***************
*** 198,205 ****
          fp = os.popen(diffcmd)
          lines = fp.readlines()
-         sts = fp.close()
          # ignore the error code, it always seems to be 1 :(
! ##        if sts:
! ##            return 'Error code %d occurred during diff\n' % (sts >> 8)
      if len(lines) > DIFF_TRUNCATE_IF_LARGER:
          removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES
--- 191,196 ----
          fp = os.popen(diffcmd)
          lines = fp.readlines()
          # ignore the error code, it always seems to be 1 :(
!         fp.close()
      if len(lines) > DIFF_TRUNCATE_IF_LARGER:
          removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES
***************
*** 207,220 ****
          lines.insert(DIFF_HEAD_LINES,
                       '[...%d lines suppressed...]\n' % removedlines)
!     return string.join(lines, '')
  
  
  
! def blast_mail(subject, people, filestodiff, contextlines, fromaddr):
      # cannot wait for child process or that will cause parent to retain cvs
      # lock for too long.  Urg!
-     print "HAHAHA"
      if not os.fork():
-         print "HIHIHI" 
          # in the child
          # give up the lock you cvs thang!
--- 198,219 ----
          lines.insert(DIFF_HEAD_LINES,
                       '[...%d lines suppressed...]\n' % removedlines)
!     return ''.join(lines)
  
  
  
! rfc822_specials_re = re.compile(r'[\(\)\<\>\@\,\;\:\\\"\.\[\]]')
! 
! def quotename(name):
!     if name and rfc822_specials_re.search(name):
!         return '"%s"' % name.replace('"', '\\"')
!     else:
!         return name
! 
! 
! 
! def blast_mail(subject, people, entries, contextlines, fromhost, replyto):
      # cannot wait for child process or that will cause parent to retain cvs
      # lock for too long.  Urg!
      if not os.fork():
          # in the child
          # give up the lock you cvs thang!
***************
*** 223,250 ****
          conn = smtplib.SMTP()
          conn.connect(MAILHOST, MAILPORT)
!         author = pwd.getpwuid(os.getuid())[0]
!         if not fromaddr:
!         	fromaddr = '%s@%s' % (author, getfqdn())
!         print "Sending mail from %s, to %s" % (fromaddr, people)
          s = StringIO()
!         sys.stdout = s
!         try:
!             print '''\
! From: %(fromaddr)s
! To: %(people)s
  Subject: %(subject)s
! ''' % {'fromaddr' : fromaddr,
!        'people' : string.join(people, COMMASPACE),
!        'subject': subject,
!        }
!             s.write(sys.stdin.read())
!             s.write("\nCVS User: %s\n" % (author))
!             # append the diffs if available
!             print
!             for file in filestodiff:
!                 print calculate_diff(file, contextlines)
!         finally:
!             sys.stdout = sys.__stdout__
!         resp = conn.sendmail(fromaddr, people, s.getvalue())
          conn.close()
          os._exit(0)
--- 222,255 ----
          conn = smtplib.SMTP()
          conn.connect(MAILHOST, MAILPORT)
!         pwinfo = pwd.getpwuid(os.getuid())
!         user = pwinfo[0]
!         name = pwinfo[4]
!         domain = fromhost or socket.getfqdn()
!         address = '%s@%s' % (user, domain)
          s = StringIO()
!         datestamp = time.strftime('%a, %d %b %Y %H:%M:%S +0000',
!                                   time.gmtime(time.time()))
!         vars = {'author'  : formataddr((name, address)),
!                 'people'  : COMMASPACE.join(people),
!                 'subject' : subject,
!                 'version' : __version__,
!                 'date'    : datestamp,
!                 }
!         print >> s, '''\
! From: %(author)s
! To: %(people)s''' % vars
!         if replyto:
!             print >> s, 'Reply-To: %s' % replyto
!         print >>s, '''\
  Subject: %(subject)s
! Date: %(date)s
! X-Mailer: Python syncmail %(version)s <http://sf.net/projects/cvs-syncmail>
! ''' % vars
!         s.write(sys.stdin.read())
!         # append the diffs if available
!         print >> s
!         for entry in entries:
!             print >> s, calculate_diff(entry, contextlines)
!         resp = conn.sendmail(address, people, s.getvalue())
          conn.close()
          os._exit(0)
***************
*** 252,261 ****
  
  
  # scan args for options
  def main():
      try:
          opts, args = getopt.getopt(
!             sys.argv[1:], 'hC:cuqf:',
!             ['fromaddr=', 'context=', 'cvsroot=', 'help', 'quiet'])
      except getopt.error, msg:
          usage(1, msg)
--- 257,366 ----
  
  
+ class CVSEntry:
+     def __init__(self, name, revision, timestamp, conflict, options, tagdate):
+         self.name = name
+         self.revision = revision
+         self.timestamp = timestamp
+         self.conflict = conflict
+         self.options = options
+         self.tagdate = tagdate
+ 
+ def get_entry(prefix, mapping, line, filename):
+     line = line.strip()
+     parts = line.split("/")
+     _, name, revision, timestamp, options, tagdate = parts
+     key = namekey(prefix, name)
+     try:
+         entry = mapping[key]
+     except KeyError:
+         if revision == "0":
+             revision = None
+         if timestamp.find("+") != -1:
+             timestamp, conflict = tuple(timestamp.split("+"))
+         else:
+             conflict = None
+         entry = CVSEntry(key, revision, timestamp, conflict,
+                          options, tagdate)
+         mapping[key] = entry
+     return entry
+ 
+ def namekey(prefix, name):
+     if prefix:
+         return os.path.join(prefix, name)
+     else:
+         return name
+ 
+ def load_change_info(prefix=None):
+     if prefix is not None:
+         entries_fn = os.path.join(prefix, "CVS", "Entries")
+     else:
+         entries_fn = os.path.join("CVS", "Entries")
+     entries_log_fn = entries_fn + ".Log"
+     mapping = {}
+     f = open(entries_fn)
+     while 1:
+         line = f.readline()
+         if not line:
+             break
+ ##        if line.strip() == "D":
+ ##            continue
+         # we could recurse down subdirs, except the Entries.Log files
+         # we need haven't been written to the subdirs yet, so it
+         # doesn't do us any good
+ ##        if line[0] == "D":
+ ##            name = line.split("/")[1]
+ ##            dirname = namekey(prefix, name)
+ ##            if os.path.isdir(dirname):
+ ##                m = load_change_info(dirname)
+ ##                mapping.update(m)
+         if line[0] == "/":
+             # normal file
+             get_entry(prefix, mapping, line, entries_fn)
+         # else: bogus Entries line
+     f.close()
+     if os.path.isfile(entries_log_fn):
+         f = open(entries_log_fn)
+         while 1:
+             line = f.readline()
+             if not line:
+                 break
+             if line[1:2] != ' ':
+                 # really old version of CVS
+                 break
+             entry = get_entry(prefix, mapping, line[2:], entries_log_fn)
+             parts = line.split("/")[1:]
+             if line[0] == "A":
+                 # adding a file
+                 entry.new_revision = parts[1]
+             elif line[0] == "R":
+                 # removing a file
+                 entry.new_revision = None
+         f.close()
+     for entry in mapping.values():
+         if not hasattr(entry, "new_revision"):
+             print 'confused about file', entry.name, '-- ignoring'
+             del mapping[entry.name]
+     return mapping
+ 
+ def load_branch_name():
+     tag_fn = os.path.join("CVS", "Tag")
+     if os.path.isfile(tag_fn):
+         f = open(tag_fn)
+         line = f.readline().strip()
+         f.close()
+         if line[:1] == "T":
+             return line[1:]
+     return None
+ 
  # scan args for options
  def main():
+     # XXX Should really move all the options to an object, just to
+     # avoid threading so many positional args through everything.
      try:
          opts, args = getopt.getopt(
!             sys.argv[1:], 'hC:cuS:R:qf:m:',
!             ['fromhost=', 'context=', 'cvsroot=', 'mailhost=',
!              'subject-prefix=', 'reply-to=',
!              'help', 'quiet'])
      except getopt.error, msg:
          usage(1, msg)
***************
*** 264,268 ****
      contextlines = 2
      verbose = 1
!     fromaddr = None
      for opt, arg in opts:
          if opt in ('-h', '--help'):
--- 369,375 ----
      contextlines = 2
      verbose = 1
!     subject_prefix = ""
!     replyto = None
!     fromhost = None
      for opt, arg in opts:
          if opt in ('-h', '--help'):
***************
*** 277,284 ****
          elif opt == '-u':
              contextlines = 0
          elif opt in ('-q', '--quiet'):
              verbose = 0
!         elif opt in ('-f', '--fromaddr'):
!             fromaddr = arg
  
      # What follows is the specification containing the files that were
--- 384,398 ----
          elif opt == '-u':
              contextlines = 0
+         elif opt in ('-S', '--subject-prefix'):
+             subject_prefix = arg
+         elif opt in ('-R', '--reply-to'):
+             replyto = arg
          elif opt in ('-q', '--quiet'):
              verbose = 0
!         elif opt in ('-f', '--fromhost'):
!             fromhost = arg
!         elif opt in ('-m', '--mailhost'):
!             global MAILHOST
!             MAILHOST = arg
  
      # What follows is the specification containing the files that were
***************
*** 288,293 ****
      if not args:
          usage(1, 'No CVS module specified')
!     subject = args[0]
!     specs = string.split(args[0])
      del args[0]
  
--- 402,407 ----
      if not args:
          usage(1, 'No CVS module specified')
!     subject = subject_prefix + args[0]
!     specs = args[0].split()
      del args[0]
  
***************
*** 299,322 ****
      people = args
  
!     if verbose:
!         print 'Mailing %s...' % string.join(people, COMMASPACE)
! 
!     if specs == ['-', 'Imported', 'sources']:
          return
!     if specs[-3:] == ['-', 'New', 'directory']:
!         del specs[-3:]
!     elif len(specs) > 2:
!         L = specs[:2]
!         for s in specs[2:]:
!             prev = L[-1]
!             if string.count(prev, ',') < 2:
!                 L[-1] = "%s %s" % (prev, s)
!             else:
!                 L.append(s)
!         specs = L
  
      if verbose:
          print 'Generating notification message...'
!     blast_mail(subject, people, specs[1:], contextlines, fromaddr)
      if verbose:
          print 'Generating notification message... done.'
--- 413,428 ----
      people = args
  
!     if specs[-3:] == ['-', 'Imported', 'sources']:
!         print 'Not sending email for imported sources.'
          return
! 
!     branch = load_branch_name()
!     changes = load_change_info()
  
      if verbose:
+         print 'Mailing %s...' % COMMASPACE.join(people)
          print 'Generating notification message...'
!     blast_mail(subject, people, changes.values(),
!                contextlines, fromhost, replyto)
      if verbose:
          print 'Generating notification message... done.'
***************
*** 327,328 ****
--- 433,435 ----
      main()
      sys.exit(0)
+ 



More information about the GME-commit mailing list