copie du fichier de egon a la place du vieux
celui de egon est sarge complient darcs-hash:20040406191621-9f550-81433bf3087ed581abea2c669a5a823b392d769f.gz
This commit is contained in:
parent
1c86bdf678
commit
2a712f54b4
1 changed files with 210 additions and 86 deletions
296
syncmail
296
syncmail
|
@ -1,5 +1,9 @@
|
||||||
#! /usr/bin/python
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
# Copyright (c) 2002, 2003, Barry Warsaw, Fred Drake, and contributors
|
||||||
|
# All rights reserved.
|
||||||
|
# See the accompanying LICENSE file for details.
|
||||||
|
|
||||||
# NOTE: Until SourceForge installs a modern version of Python on the cvs
|
# NOTE: Until SourceForge installs a modern version of Python on the cvs
|
||||||
# servers, this script MUST be compatible with Python 1.5.2.
|
# servers, this script MUST be compatible with Python 1.5.2.
|
||||||
|
|
||||||
|
@ -34,8 +38,8 @@ Usage:
|
||||||
Where options are:
|
Where options are:
|
||||||
|
|
||||||
--cvsroot=<path>
|
--cvsroot=<path>
|
||||||
Use <path> as the environment variable CVSROOT. Otherwise this
|
Use <path> as the environment variable CVSROOT. Otherwise this
|
||||||
variable must exist in the environment.
|
variable must exist in the environment.
|
||||||
|
|
||||||
--context=#
|
--context=#
|
||||||
-C #
|
-C #
|
||||||
|
@ -44,16 +48,32 @@ Where options are:
|
||||||
-c
|
-c
|
||||||
Produce a context diff (default).
|
Produce a context diff (default).
|
||||||
|
|
||||||
|
-m hostname
|
||||||
|
--mailhost hostname
|
||||||
|
The hostname of an available SMTP server. The default is
|
||||||
|
'localhost'.
|
||||||
|
|
||||||
-u
|
-u
|
||||||
Produce a unified diff (smaller).
|
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.
|
||||||
|
|
||||||
|
--charset=charset
|
||||||
|
Add a encoding header to message.
|
||||||
|
|
||||||
--quiet / -q
|
--quiet / -q
|
||||||
Don't print as much status to stdout.
|
Don't print as much status to stdout.
|
||||||
|
|
||||||
--fromhost=hostname
|
--fromhost=hostname
|
||||||
-f hostname
|
-f hostname
|
||||||
The hostname that email messages appear to be coming from. The From:
|
The hostname that email messages appear to be coming from. The From:
|
||||||
header will of the outgoing message will look like user@hostname. By
|
header of the outgoing message will look like user@hostname. By
|
||||||
default, hostname is the machine's fully qualified domain name.
|
default, hostname is the machine's fully qualified domain name.
|
||||||
|
|
||||||
--help / -h
|
--help / -h
|
||||||
|
@ -71,6 +91,8 @@ The rest of the command line arguments are:
|
||||||
email-addrs
|
email-addrs
|
||||||
At least one email address.
|
At least one email address.
|
||||||
"""
|
"""
|
||||||
|
__version__ = '1.2'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
@ -97,12 +119,12 @@ except ImportError:
|
||||||
else:
|
else:
|
||||||
fqdn = 'localhost.localdomain'
|
fqdn = 'localhost.localdomain'
|
||||||
return fqdn
|
return fqdn
|
||||||
|
|
||||||
|
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
# Which SMTP server to do we connect to? Empty string means localhost.
|
# Which SMTP server to do we connect to?
|
||||||
MAILHOST = ''
|
MAILHOST = 'localhost'
|
||||||
MAILPORT = 25
|
MAILPORT = 25
|
||||||
|
|
||||||
# Diff trimming stuff
|
# Diff trimming stuff
|
||||||
|
@ -110,9 +132,6 @@ DIFF_HEAD_LINES = 20
|
||||||
DIFF_TAIL_LINES = 20
|
DIFF_TAIL_LINES = 20
|
||||||
DIFF_TRUNCATE_IF_LARGER = 1000
|
DIFF_TRUNCATE_IF_LARGER = 1000
|
||||||
|
|
||||||
EMPTYSTRING = ''
|
|
||||||
SPACE = ' '
|
|
||||||
DOT = '.'
|
|
||||||
COMMASPACE = ', '
|
COMMASPACE = ', '
|
||||||
|
|
||||||
PROGRAM = sys.argv[0]
|
PROGRAM = sys.argv[0]
|
||||||
|
@ -121,8 +140,7 @@ BINARY_EXPLANATION_LINES = [
|
||||||
"(This appears to be a binary file; contents omitted.)\n"
|
"(This appears to be a binary file; contents omitted.)\n"
|
||||||
]
|
]
|
||||||
|
|
||||||
REVCRE = re.compile("^(NONE|[0-9.]+)$")
|
NOVERSION = "Couldn't generate diff; no version number found for file: %s"
|
||||||
NOVERSION = "Couldn't generate diff; no version number found in filespec: %s"
|
|
||||||
BACKSLASH = "Couldn't generate diff: backslash in filespec's filename: %s"
|
BACKSLASH = "Couldn't generate diff: backslash in filespec's filename: %s"
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,25 +153,20 @@ def usage(code, msg=''):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_diff(filespec, contextlines):
|
def calculate_diff(entry, contextlines):
|
||||||
file, oldrev, newrev = string.split(filespec, ',')
|
file = entry.name
|
||||||
# Make sure we can find a CVS version number
|
oldrev = entry.revision
|
||||||
if not REVCRE.match(oldrev):
|
newrev = entry.new_revision
|
||||||
return NOVERSION % filespec
|
|
||||||
if not REVCRE.match(newrev):
|
|
||||||
return NOVERSION % filespec
|
|
||||||
|
|
||||||
if string.find(file, '\\') <> -1:
|
# Make sure we can find a CVS version number
|
||||||
# I'm sorry, a file name that contains a backslash is just too much.
|
if oldrev is None and newrev is None:
|
||||||
# XXX if someone wants to figure out how to escape the backslashes in
|
return NOVERSION % file
|
||||||
# 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:
|
if string.find(file, "'") <> -1:
|
||||||
# Those crazy users put single-quotes in their file names! Now we
|
# Those crazy users put single-quotes in their file names! Now we
|
||||||
# have to escape everything that is meaningful inside double-quotes.
|
# have to escape everything that is meaningful inside double-quotes.
|
||||||
filestr = string.replace(file, '`', '\`')
|
filestr = string.replace(file, '\\', '\\\\')
|
||||||
|
filestr = string.replace(filestr, '`', '\`')
|
||||||
filestr = string.replace(filestr, '"', '\"')
|
filestr = string.replace(filestr, '"', '\"')
|
||||||
filestr = string.replace(filestr, '$', '\$')
|
filestr = string.replace(filestr, '$', '\$')
|
||||||
# and quote it with double-quotes.
|
# and quote it with double-quotes.
|
||||||
|
@ -161,7 +174,8 @@ def calculate_diff(filespec, contextlines):
|
||||||
else:
|
else:
|
||||||
# quote it with single-quotes.
|
# quote it with single-quotes.
|
||||||
filestr = "'" + file + "'"
|
filestr = "'" + file + "'"
|
||||||
if oldrev == 'NONE':
|
if oldrev is None:
|
||||||
|
# File is being added.
|
||||||
try:
|
try:
|
||||||
if os.path.exists(file):
|
if os.path.exists(file):
|
||||||
fp = open(file)
|
fp = open(file)
|
||||||
|
@ -183,9 +197,10 @@ def calculate_diff(filespec, contextlines):
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
lines = ['***** Error reading new file: ',
|
lines = ['***** Error reading new file: ',
|
||||||
str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()]
|
str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()]
|
||||||
elif newrev == 'NONE':
|
elif newrev is None:
|
||||||
lines = ['--- %s DELETED ---\n' % file]
|
lines = ['--- %s DELETED ---\n' % file]
|
||||||
else:
|
else:
|
||||||
|
# File has been changed.
|
||||||
# This /has/ to happen in the background, otherwise we'll run into CVS
|
# This /has/ to happen in the background, otherwise we'll run into CVS
|
||||||
# lock contention. What a crock.
|
# lock contention. What a crock.
|
||||||
if contextlines > 0:
|
if contextlines > 0:
|
||||||
|
@ -196,21 +211,8 @@ def calculate_diff(filespec, contextlines):
|
||||||
% (difftype, oldrev, newrev, filestr)
|
% (difftype, oldrev, newrev, filestr)
|
||||||
fp = os.popen(diffcmd)
|
fp = os.popen(diffcmd)
|
||||||
lines = fp.readlines()
|
lines = fp.readlines()
|
||||||
sts = fp.close()
|
|
||||||
# ignore the error code, it always seems to be 1 :(
|
# ignore the error code, it always seems to be 1 :(
|
||||||
## if sts:
|
fp.close()
|
||||||
## return 'Error code %d occurred during diff\n' % (sts >> 8)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# On vire du diff les lignes marquées avec *PASS*
|
|
||||||
a=0
|
|
||||||
while 1:
|
|
||||||
a=a+1
|
|
||||||
if string.find(lines[a],'*PASS*') > -1:
|
|
||||||
lines[a]= '[ Mot de passe ]\n'
|
|
||||||
except:
|
|
||||||
a=0
|
|
||||||
|
|
||||||
if len(lines) > DIFF_TRUNCATE_IF_LARGER:
|
if len(lines) > DIFF_TRUNCATE_IF_LARGER:
|
||||||
removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES
|
removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES
|
||||||
del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES]
|
del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES]
|
||||||
|
@ -220,7 +222,17 @@ def calculate_diff(filespec, contextlines):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def blast_mail(subject, people, filestodiff, contextlines, fromhost):
|
rfc822_specials_re = re.compile(r'[\(\)\<\>\@\,\;\:\\\"\.\[\]]')
|
||||||
|
|
||||||
|
def quotename(name):
|
||||||
|
if name and rfc822_specials_re.search(name):
|
||||||
|
return '"%s"' % string.replace(name, '"', '\\"')
|
||||||
|
else:
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def blast_mail(subject, people, entries, contextlines, fromhost, replyto, charset):
|
||||||
# cannot wait for child process or that will cause parent to retain cvs
|
# cannot wait for child process or that will cause parent to retain cvs
|
||||||
# lock for too long. Urg!
|
# lock for too long. Urg!
|
||||||
if not os.fork():
|
if not os.fork():
|
||||||
|
@ -231,55 +243,173 @@ def blast_mail(subject, people, filestodiff, contextlines, fromhost):
|
||||||
conn = smtplib.SMTP()
|
conn = smtplib.SMTP()
|
||||||
conn.connect(MAILHOST, MAILPORT)
|
conn.connect(MAILHOST, MAILPORT)
|
||||||
user = pwd.getpwuid(os.getuid())[0]
|
user = pwd.getpwuid(os.getuid())[0]
|
||||||
|
name = string.split(pwd.getpwuid(os.getuid())[4], ',')[0]
|
||||||
|
|
||||||
|
# Modif pour avoir le bon from (=> signature automatique)
|
||||||
if user=="root" :
|
if user=="root" :
|
||||||
# Obtention du real user => signature automatique des commits
|
|
||||||
for proc in os.popen("ps --no-headers -o user -t $(ps --no-headers -o tty %s)" % os.getpid() ).readlines() :
|
for proc in os.popen("ps --no-headers -o user -t $(ps --no-headers -o tty %s)" % os.getpid() ).readlines() :
|
||||||
userp=string.strip(proc)
|
userp=string.strip(proc)
|
||||||
if userp=="root" : break
|
if userp=="root" : break
|
||||||
else : user=userp
|
else : user=userp
|
||||||
|
name = string.split(pwd.getpwnam(user)[4], ',')[0]
|
||||||
domain = fromhost or getfqdn()
|
|
||||||
#Modif cosmétique pour afficher un sujet explicite :
|
domain = fromhost or getfqdn()
|
||||||
host = string.split(domain,'.')
|
host = string.split(domain,'.')[0]
|
||||||
author = '%s@%s' % (user, domain)
|
address = '%s@%s' % (user, domain)
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
sys.stdout = s
|
sys.stdout = s
|
||||||
|
datestamp = time.strftime('%a, %d %b %Y %H:%M:%S +0000',
|
||||||
|
time.gmtime(time.time()))
|
||||||
try:
|
try:
|
||||||
|
vars = {'address' : address,
|
||||||
|
'name' : quotename(name),
|
||||||
|
'people' : string.join(people, COMMASPACE),
|
||||||
|
'subject' : subject,
|
||||||
|
'host' : host,
|
||||||
|
'version' : __version__,
|
||||||
|
'date' : datestamp,
|
||||||
|
}
|
||||||
print '''\
|
print '''\
|
||||||
From: %(author)s
|
From: %(name)s <%(address)s>
|
||||||
To: %(people)s
|
To: %(people)s''' % vars
|
||||||
Subject: %(subject)s
|
if replyto:
|
||||||
|
print 'Reply-To: %s' % replyto
|
||||||
|
if charset:
|
||||||
|
print 'MIME-Version: 1.0\nContent-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit' % charset
|
||||||
|
print '''\
|
||||||
|
Subject: CVS commit sur %(host)s : %(subject)s
|
||||||
X-CVSinfo: CRANS
|
X-CVSinfo: CRANS
|
||||||
''' % {'author' : author,
|
Date: %(date)s
|
||||||
'people' : string.join(people, COMMASPACE),
|
X-Mailer: Python syncmail %(version)s <http://sf.net/projects/cvs-syncmail>
|
||||||
'subject': 'CVS commit sur '+host[0]+' : '+ subject,
|
''' % vars
|
||||||
}
|
|
||||||
s.write(sys.stdin.read())
|
s.write(sys.stdin.read())
|
||||||
# append the diffs if available
|
# append the diffs if available
|
||||||
print
|
print
|
||||||
for file in filestodiff:
|
for entry in entries:
|
||||||
print calculate_diff(file, contextlines)
|
print calculate_diff(entry, contextlines)
|
||||||
finally:
|
finally:
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
resp = conn.sendmail(author, people, s.getvalue())
|
resp = conn.sendmail(address, people, s.getvalue())
|
||||||
conn.close()
|
conn.close()
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 = string.strip(line)
|
||||||
|
parts = string.split(line, "/")
|
||||||
|
_, name, revision, timestamp, options, tagdate = parts
|
||||||
|
key = namekey(prefix, name)
|
||||||
|
try:
|
||||||
|
entry = mapping[key]
|
||||||
|
except KeyError:
|
||||||
|
if revision == "0":
|
||||||
|
revision = None
|
||||||
|
if string.find(timestamp, "+") != -1:
|
||||||
|
timestamp, conflict = tuple(string.split(timestamp, "+"))
|
||||||
|
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 string.strip(line) == "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 = string.split(line, "/")[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 = string.split(line, "/")[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 = string.strip(f.readline())
|
||||||
|
f.close()
|
||||||
|
if line[:1] == "T":
|
||||||
|
return line[1:]
|
||||||
|
return None
|
||||||
|
|
||||||
# scan args for options
|
# scan args for options
|
||||||
def main():
|
def main():
|
||||||
|
# XXX Should really move all the options to an object, just to
|
||||||
|
# avoid threading so many positional args through everything.
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(
|
opts, args = getopt.getopt(
|
||||||
sys.argv[1:], 'hC:cuqf:',
|
sys.argv[1:], 'hC:cuS:R:qf:m:',
|
||||||
['fromhost=', 'context=', 'cvsroot=', 'help', 'quiet'])
|
['fromhost=', 'context=', 'cvsroot=', 'mailhost=',
|
||||||
|
'subject-prefix=', 'reply-to=',
|
||||||
|
'help', 'quiet', 'charset='])
|
||||||
except getopt.error, msg:
|
except getopt.error, msg:
|
||||||
usage(1, msg)
|
usage(1, msg)
|
||||||
|
|
||||||
# parse the options
|
# parse the options
|
||||||
contextlines = 2
|
contextlines = 2
|
||||||
verbose = 1
|
verbose = 1
|
||||||
|
subject_prefix = ""
|
||||||
|
replyto = None
|
||||||
|
charset = None
|
||||||
fromhost = None
|
fromhost = None
|
||||||
for opt, arg in opts:
|
for opt, arg in opts:
|
||||||
if opt in ('-h', '--help'):
|
if opt in ('-h', '--help'):
|
||||||
|
@ -293,10 +423,19 @@ def main():
|
||||||
contextlines = 2
|
contextlines = 2
|
||||||
elif opt == '-u':
|
elif opt == '-u':
|
||||||
contextlines = 0
|
contextlines = 0
|
||||||
|
elif opt in ('-S', '--subject-prefix'):
|
||||||
|
subject_prefix = arg
|
||||||
|
elif opt in ('-R', '--reply-to'):
|
||||||
|
replyto = arg
|
||||||
|
elif opt == '--charset':
|
||||||
|
charset = arg
|
||||||
elif opt in ('-q', '--quiet'):
|
elif opt in ('-q', '--quiet'):
|
||||||
verbose = 0
|
verbose = 0
|
||||||
elif opt in ('-f', '--fromhost'):
|
elif opt in ('-f', '--fromhost'):
|
||||||
fromhost = arg
|
fromhost = arg
|
||||||
|
elif opt in ('-m', '--mailhost'):
|
||||||
|
global MAILHOST
|
||||||
|
MAILHOST = arg
|
||||||
|
|
||||||
# What follows is the specification containing the files that were
|
# What follows is the specification containing the files that were
|
||||||
# modified. The argument actually must be split, with the first component
|
# modified. The argument actually must be split, with the first component
|
||||||
|
@ -304,17 +443,10 @@ def main():
|
||||||
# $CVSROOT, followed by the list of files that are changing.
|
# $CVSROOT, followed by the list of files that are changing.
|
||||||
if not args:
|
if not args:
|
||||||
usage(1, 'No CVS module specified')
|
usage(1, 'No CVS module specified')
|
||||||
subject = args[0]
|
subject = subject_prefix + args[0]
|
||||||
specs = string.split(args[0])
|
specs = string.split(args[0])
|
||||||
del args[0]
|
del args[0]
|
||||||
|
|
||||||
#Pour ne pas recevoir tout la pollution des batx.cf
|
|
||||||
nom_fichier = specs[0] + '/' + string.split(specs[1],',')[0]
|
|
||||||
Ignore=['CRANS/confs/bat', 'CRANS/confs/personnes.cf??']
|
|
||||||
for ign_fich in Ignore:
|
|
||||||
if string.find(nom_fichier,ign_fich) == 0:
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# The remaining args should be the email addresses
|
# The remaining args should be the email addresses
|
||||||
if not args:
|
if not args:
|
||||||
usage(1, 'No recipients specified')
|
usage(1, 'No recipients specified')
|
||||||
|
@ -322,26 +454,18 @@ def main():
|
||||||
# Now do the mail command
|
# Now do the mail command
|
||||||
people = args
|
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:
|
if verbose:
|
||||||
print 'Mailing %s...' % string.join(people, COMMASPACE)
|
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...'
|
print 'Generating notification message...'
|
||||||
blast_mail(subject, people, specs[1:], contextlines, fromhost)
|
blast_mail(subject, people, changes.values(),
|
||||||
|
contextlines, fromhost, replyto, charset)
|
||||||
if verbose:
|
if verbose:
|
||||||
print 'Generating notification message... done.'
|
print 'Generating notification message... done.'
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue