[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