give in to tab police

This commit is contained in:
Guido van Rossum 1998-03-24 05:30:29 +00:00
parent 3db0e3713c
commit ed5b3d8b3c
6 changed files with 440 additions and 435 deletions

View file

@ -20,53 +20,53 @@ cutofftime = 0
def main(): def main():
try: try:
opts, args = getopt.getopt(sys.argv[1:], "n:") opts, args = getopt.getopt(sys.argv[1:], "n:")
except getopt.error, msg: except getopt.error, msg:
print msg print msg
print __doc__, print __doc__,
return 1 return 1
global cutofftime global cutofftime
newerfile = None newerfile = None
for o, a in opts: for o, a in opts:
if o == '-n': if o == '-n':
cutofftime = getmtime(a) cutofftime = getmtime(a)
if args: if args:
for arg in args: for arg in args:
process(arg) process(arg)
else: else:
process(".") process(".")
def process(dir): def process(dir):
cvsdir = 0 cvsdir = 0
subdirs = [] subdirs = []
names = os.listdir(dir) names = os.listdir(dir)
for name in names: for name in names:
fullname = os.path.join(dir, name) fullname = os.path.join(dir, name)
if name == "CVS": if name == "CVS":
cvsdir = fullname cvsdir = fullname
else: else:
if os.path.isdir(fullname): if os.path.isdir(fullname):
if not os.path.islink(fullname): if not os.path.islink(fullname):
subdirs.append(fullname) subdirs.append(fullname)
if cvsdir: if cvsdir:
entries = os.path.join(cvsdir, "Entries") entries = os.path.join(cvsdir, "Entries")
for e in open(entries).readlines(): for e in open(entries).readlines():
words = string.split(e, '/') words = string.split(e, '/')
if words[0] == '' and words[1:]: if words[0] == '' and words[1:]:
name = words[1] name = words[1]
fullname = os.path.join(dir, name) fullname = os.path.join(dir, name)
if cutofftime and getmtime(fullname) <= cutofftime: if cutofftime and getmtime(fullname) <= cutofftime:
pass pass
else: else:
print fullname print fullname
for sub in subdirs: for sub in subdirs:
process(sub) process(sub)
def getmtime(filename): def getmtime(filename):
try: try:
st = os.stat(filename) st = os.stat(filename)
except os.error: except os.error:
return 0 return 0
return st[stat.ST_MTIME] return st[stat.ST_MTIME]
sys.exit(main()) sys.exit(main())

View file

@ -50,9 +50,9 @@ import os, sys, string
def main(): def main():
args = sys.argv[1:] args = sys.argv[1:]
if not args: if not args:
print "No arguments." print "No arguments."
for arg in args: for arg in args:
process(arg) process(arg)
def process(arg): def process(arg):
f = open(arg) f = open(arg)
@ -60,8 +60,8 @@ def process(arg):
f.close() f.close()
i = string.find(data, OLD_NOTICE) i = string.find(data, OLD_NOTICE)
if i < 0: if i < 0:
## print "No old notice in", arg ## print "No old notice in", arg
return return
data = data[:i] + NEW_NOTICE + data[i+len(OLD_NOTICE):] data = data[:i] + NEW_NOTICE + data[i+len(OLD_NOTICE):]
new = arg + ".new" new = arg + ".new"
backup = arg + ".bak" backup = arg + ".bak"

View file

@ -55,22 +55,25 @@ def linknames(old, new, link):
print old + ': warning: cannot listdir:', msg print old + ': warning: cannot listdir:', msg
return return
for name in names: for name in names:
if name not in (os.curdir, os.pardir): if name not in (os.curdir, os.pardir):
oldname = os.path.join(old, name) oldname = os.path.join(old, name)
linkname = os.path.join(link, name) linkname = os.path.join(link, name)
newname = os.path.join(new, name) newname = os.path.join(new, name)
if debug > 1: print oldname, newname, linkname if debug > 1: print oldname, newname, linkname
if os.path.isdir(oldname) and not os.path.islink(oldname): if os.path.isdir(oldname) and \
try: not os.path.islink(oldname):
os.mkdir(newname, 0777) try:
ok = 1 os.mkdir(newname, 0777)
except: ok = 1
print newname + ': warning: cannot mkdir:', msg except:
ok = 0 print newname + \
if ok: ': warning: cannot mkdir:', msg
linkname = os.path.join(os.pardir, linkname) ok = 0
linknames(oldname, newname, linkname) if ok:
else: linkname = os.path.join(os.pardir,
os.symlink(linkname, newname) linkname)
linknames(oldname, newname, linkname)
else:
os.symlink(linkname, newname)
sys.exit(main()) sys.exit(main())

View file

@ -26,25 +26,25 @@ from their output.
import os, sys, getopt, string, re import os, sys, getopt, string, re
sep1 = '='*77 + '\n' # file separator sep1 = '='*77 + '\n' # file separator
sep2 = '-'*28 + '\n' # revision separator sep2 = '-'*28 + '\n' # revision separator
def main(): def main():
"""Main program""" """Main program"""
truncate_last = 0 truncate_last = 0
opts, args = getopt.getopt(sys.argv[1:], "-t") opts, args = getopt.getopt(sys.argv[1:], "-t")
for o, a in opts: for o, a in opts:
if o == '-t': if o == '-t':
truncate_last = 1 truncate_last = 1
database = [] database = []
while 1: while 1:
chunk = read_chunk(sys.stdin) chunk = read_chunk(sys.stdin)
if not chunk: if not chunk:
break break
records = digest_chunk(chunk) records = digest_chunk(chunk)
if truncate_last: if truncate_last:
del records[-1] del records[-1]
database[len(database):] = records database[len(database):] = records
database.sort() database.sort()
database.reverse() database.reverse()
format_output(database) format_output(database)
@ -58,19 +58,19 @@ def read_chunk(fp):
chunk = [] chunk = []
lines = [] lines = []
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
if line == sep1: if line == sep1:
if lines: if lines:
chunk.append(lines) chunk.append(lines)
break break
if line == sep2: if line == sep2:
if lines: if lines:
chunk.append(lines) chunk.append(lines)
lines = [] lines = []
else: else:
lines.append(line) lines.append(line)
return chunk return chunk
def digest_chunk(chunk): def digest_chunk(chunk):
@ -79,53 +79,53 @@ def digest_chunk(chunk):
key = 'Working file:' key = 'Working file:'
keylen = len(key) keylen = len(key)
for line in lines: for line in lines:
if line[:keylen] == key: if line[:keylen] == key:
working_file = string.strip(line[keylen:]) working_file = string.strip(line[keylen:])
break break
else: else:
working_file = None working_file = None
records = [] records = []
for lines in chunk[1:]: for lines in chunk[1:]:
revline = lines[0] revline = lines[0]
dateline = lines[1] dateline = lines[1]
text = lines[2:] text = lines[2:]
words = string.split(dateline) words = string.split(dateline)
author = None author = None
if len(words) >= 3 and words[0] == 'date:': if len(words) >= 3 and words[0] == 'date:':
dateword = words[1] dateword = words[1]
timeword = words[2] timeword = words[2]
if timeword[-1:] == ';': if timeword[-1:] == ';':
timeword = timeword[:-1] timeword = timeword[:-1]
date = dateword + ' ' + timeword date = dateword + ' ' + timeword
if len(words) >= 5 and words[3] == 'author:': if len(words) >= 5 and words[3] == 'author:':
author = words[4] author = words[4]
if author[-1:] == ';': if author[-1:] == ';':
author = author[:-1] author = author[:-1]
else: else:
date = None date = None
text.insert(0, revline) text.insert(0, revline)
words = string.split(revline) words = string.split(revline)
if len(words) >= 2 and words[0] == 'revision': if len(words) >= 2 and words[0] == 'revision':
rev = words[1] rev = words[1]
else: else:
rev = None rev = None
text.insert(0, revline) text.insert(0, revline)
records.append((date, working_file, rev, author, text)) records.append((date, working_file, rev, author, text))
return records return records
def format_output(database): def format_output(database):
prevtext = None prevtext = None
prev = [] prev = []
database.append((None, None, None, None, None)) # Sentinel database.append((None, None, None, None, None)) # Sentinel
for (date, working_file, rev, author, text) in database: for (date, working_file, rev, author, text) in database:
if text != prevtext: if text != prevtext:
if prev: if prev:
print sep2, print sep2,
for (p_date, p_working_file, p_rev, p_author) in prev: for (p_date, p_working_file, p_rev, p_author) in prev:
print p_date, p_author, p_working_file print p_date, p_author, p_working_file
sys.stdout.writelines(prevtext) sys.stdout.writelines(prevtext)
prev = [] prev = []
prev.append((date, working_file, rev, author)) prev.append((date, working_file, rev, author))
prevtext = text prevtext = text
main() main()

View file

@ -11,264 +11,266 @@ Unparseable = 'mailerdaemon.Unparseable'
class ErrorMessage(rfc822.Message): class ErrorMessage(rfc822.Message):
def __init__(self, fp): def __init__(self, fp):
rfc822.Message.__init__(self, fp) rfc822.Message.__init__(self, fp)
def is_warning(self): def is_warning(self):
sub = self.getheader('Subject') sub = self.getheader('Subject')
if not sub: if not sub:
return 0 return 0
sub = string.lower(sub) sub = string.lower(sub)
if sub[:12] == 'waiting mail': return 1 if sub[:12] == 'waiting mail': return 1
if string.find(sub, 'warning') >= 0: return 1 if string.find(sub, 'warning') >= 0: return 1
self.sub = sub self.sub = sub
return 0 return 0
def get_errors(self): def get_errors(self):
for p in EMPARSERS: for p in EMPARSERS:
self.rewindbody() self.rewindbody()
try: try:
return p(self.fp, self.sub) return p(self.fp, self.sub)
except Unparseable: except Unparseable:
pass pass
raise Unparseable raise Unparseable
sendmail_pattern = regex.compile('[0-9][0-9][0-9] ') sendmail_pattern = regex.compile('[0-9][0-9][0-9] ')
def emparse_sendmail(fp, sub): def emparse_sendmail(fp, sub):
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
line = line[:-1] line = line[:-1]
# Check that we're not in the returned message yet # Check that we're not in the returned message yet
if string.lower(line)[:5] == 'from:': if string.lower(line)[:5] == 'from:':
raise Unparseable raise Unparseable
line = string.split(line) line = string.split(line)
if len(line) > 3 and \ if len(line) > 3 and \
((line[0] == '-----' and line[1] == 'Transcript') or ((line[0] == '-----' and line[1] == 'Transcript') or
(line[0] == '---' and line[1] == 'The' and (line[0] == '---' and line[1] == 'The' and
line[2] == 'transcript') or line[2] == 'transcript') or
(line[0] == 'While' and line[1] == 'talking' and line[2] == 'to')): (line[0] == 'While' and
# Yes, found it! line[1] == 'talking' and
break line[2] == 'to')):
# Yes, found it!
break
errors = [] errors = []
found_a_line = 0 found_a_line = 0
warnings = 0 warnings = 0
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
line = line[:-1] line = line[:-1]
if not line: if not line:
continue continue
if sendmail_pattern.match(line) == 4: if sendmail_pattern.match(line) == 4:
# Yes, an error/warning line. Ignore 4, remember 5, stop on rest # Yes, an error/warning line. Ignore 4, remember 5, stop on rest
if line[0] == '5': if line[0] == '5':
errors.append(line) errors.append(line)
elif line[0] == '4': elif line[0] == '4':
warnings = 1 warnings = 1
else: else:
raise Unparseable raise Unparseable
line = string.split(line) line = string.split(line)
if line and line[0][:3] == '---': if line and line[0][:3] == '---':
break break
found_a_line = 1 found_a_line = 1
# special case for CWI sendmail # special case for CWI sendmail
if len(line) > 1 and line[1] == 'Undelivered': if len(line) > 1 and line[1] == 'Undelivered':
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
line = string.strip(line) line = string.strip(line)
if not line: if not line:
break break
errors.append(line + ': ' + sub) errors.append(line + ': ' + sub)
# Empty transcripts are ok, others without an error are not. # Empty transcripts are ok, others without an error are not.
if found_a_line and not (errors or warnings): if found_a_line and not (errors or warnings):
raise Unparseable raise Unparseable
return errors return errors
def emparse_cts(fp, sub): def emparse_cts(fp, sub):
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
line = line[:-1] line = line[:-1]
# Check that we're not in the returned message yet # Check that we're not in the returned message yet
if string.lower(line)[:5] == 'from:': if string.lower(line)[:5] == 'from:':
raise Unparseable raise Unparseable
line = string.split(line) line = string.split(line)
if len(line) > 3 and line[0][:2] == '|-' and line[1] == 'Failed' \ if len(line) > 3 and line[0][:2] == '|-' and line[1] == 'Failed' \
and line[2] == 'addresses': and line[2] == 'addresses':
# Yes, found it! # Yes, found it!
break break
errors = [] errors = []
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
line = line[:-1] line = line[:-1]
if not line: if not line:
continue continue
if line[:2] == '|-': if line[:2] == '|-':
break break
errors.append(line) errors.append(line)
return errors return errors
def emparse_aol(fp, sub): def emparse_aol(fp, sub):
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
line = line[:-1] line = line[:-1]
if line: if line:
break break
exp = 'The mail you sent could not be delivered to:' exp = 'The mail you sent could not be delivered to:'
if line[:len(exp)] != exp: if line[:len(exp)] != exp:
raise Unparseable raise Unparseable
errors = [] errors = []
while 1: while 1:
line = fp.readline() line = fp.readline()
if sendmail_pattern.match(line) == 4: if sendmail_pattern.match(line) == 4:
# Yes, an error/warning line. Ignore 4, remember 5, stop on rest # Yes, an error/warning line. Ignore 4, remember 5, stop on rest
if line[0] == '5': if line[0] == '5':
errors.append(line) errors.append(line)
elif line[0] != '4': elif line[0] != '4':
raise Unparseable raise Unparseable
elif line == '\n': elif line == '\n':
break break
else: else:
raise Unparseable raise Unparseable
return errors return errors
def emparse_compuserve(fp, sub): def emparse_compuserve(fp, sub):
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
line = line[:-1] line = line[:-1]
if line: if line:
break break
exp = 'Your message could not be delivered for the following reason:' exp = 'Your message could not be delivered for the following reason:'
if line[:len(exp)] != exp: if line[:len(exp)] != exp:
raise Unparseable raise Unparseable
errors = [] errors = []
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: break if not line: break
if line[:3] == '---': break if line[:3] == '---': break
line = line[:-1] line = line[:-1]
if not line: continue if not line: continue
if line == 'Please resend your message at a later time.': if line == 'Please resend your message at a later time.':
continue continue
line = 'Compuserve: ' + line line = 'Compuserve: ' + line
errors.append(line) errors.append(line)
return errors return errors
prov_pattern = regex.compile('.* | \(.*\)') prov_pattern = regex.compile('.* | \(.*\)')
def emparse_providence(fp, sub): def emparse_providence(fp, sub):
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
line = line[:-1] line = line[:-1]
# Check that we're not in the returned message yet # Check that we're not in the returned message yet
if string.lower(line)[:5] == 'from:': if string.lower(line)[:5] == 'from:':
raise Unparseable raise Unparseable
exp = 'The following errors occurred' exp = 'The following errors occurred'
if line[:len(exp)] == exp: if line[:len(exp)] == exp:
break break
errors = [] errors = []
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
line = line[:-1] line = line[:-1]
if not line: if not line:
continue continue
if line[:4] == '----': if line[:4] == '----':
break break
if prov_pattern.match(line) > 0: if prov_pattern.match(line) > 0:
errors.append(prov_pattern.group(1)) errors.append(prov_pattern.group(1))
if not errors: if not errors:
raise Unparseable raise Unparseable
return errors return errors
def emparse_x400(fp, sub): def emparse_x400(fp, sub):
exp = 'This report relates to your message:' exp = 'This report relates to your message:'
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
line = line[:-1] line = line[:-1]
# Check that we're not in the returned message yet # Check that we're not in the returned message yet
if string.lower(line)[:5] == 'from:': if string.lower(line)[:5] == 'from:':
raise Unparseable raise Unparseable
if line[:len(exp)] == exp: if line[:len(exp)] == exp:
break break
errors = [] errors = []
exp = 'Your message was not delivered to' exp = 'Your message was not delivered to'
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
line = line[:-1] line = line[:-1]
if not line: if not line:
continue continue
if line[:len(exp)] == exp: if line[:len(exp)] == exp:
error = string.strip(line[len(exp):]) error = string.strip(line[len(exp):])
sep = ': ' sep = ': '
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
break break
line = line[:-1] line = line[:-1]
if not line: if not line:
break break
if line[0] == ' ' and line[-1] != ':': if line[0] == ' ' and line[-1] != ':':
error = error + sep + string.strip(line) error = error + sep + string.strip(line)
sep = '; ' sep = '; '
errors.append(error) errors.append(error)
return errors return errors
raise Unparseable raise Unparseable
def emparse_passau(fp, sub): def emparse_passau(fp, sub):
exp = 'Unable to deliver message because' exp = 'Unable to deliver message because'
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
if string.lower(line)[:5] == 'from:': if string.lower(line)[:5] == 'from:':
raise Unparseable raise Unparseable
if line[:len(exp)] == exp: if line[:len(exp)] == exp:
break break
errors = [] errors = []
exp = 'Returned Text follows' exp = 'Returned Text follows'
while 1: while 1:
line = fp.readline() line = fp.readline()
if not line: if not line:
raise Unparseable raise Unparseable
line = line[:-1] line = line[:-1]
# Check that we're not in the returned message yet # Check that we're not in the returned message yet
if string.lower(line)[:5] == 'from:': if string.lower(line)[:5] == 'from:':
raise Unparseable raise Unparseable
if not line: if not line:
continue continue
if line[:len(exp)] == exp: if line[:len(exp)] == exp:
return errors return errors
errors.append(string.strip(line)) errors.append(string.strip(line))
EMPARSERS = [emparse_sendmail, emparse_aol, emparse_cts, emparse_compuserve, EMPARSERS = [emparse_sendmail, emparse_aol, emparse_cts, emparse_compuserve,
emparse_providence, emparse_x400, emparse_passau] emparse_providence, emparse_x400, emparse_passau]
def sort_numeric(a, b): def sort_numeric(a, b):
a = string.atoi(a) a = string.atoi(a)
@ -290,62 +292,62 @@ def parsedir(dir, modify):
files.sort(sort_numeric) files.sort(sort_numeric)
for fn in files: for fn in files:
# Lets try to parse the file. # Lets try to parse the file.
fp = open(fn) fp = open(fn)
m = ErrorMessage(fp) m = ErrorMessage(fp)
sender = m.getaddr('From') sender = m.getaddr('From')
print '%s\t%-40s\t'%(fn, sender[1]), print '%s\t%-40s\t'%(fn, sender[1]),
if m.is_warning(): if m.is_warning():
print 'warning only' print 'warning only'
nwarn = nwarn + 1 nwarn = nwarn + 1
if modify: if modify:
os.unlink(fn) os.unlink(fn)
continue continue
try: try:
errors = m.get_errors() errors = m.get_errors()
except Unparseable: except Unparseable:
print '** Not parseable' print '** Not parseable'
nbad = nbad + 1 nbad = nbad + 1
continue continue
print len(errors), 'errors' print len(errors), 'errors'
# Remember them # Remember them
for e in errors: for e in errors:
try: try:
mm, dd = m.getdate('date')[1:1+2] mm, dd = m.getdate('date')[1:1+2]
date = '%s %02d' % (calendar.month_abbr[mm], dd) date = '%s %02d' % (calendar.month_abbr[mm], dd)
except: except:
date = '??????' date = '??????'
if not errordict.has_key(e): if not errordict.has_key(e):
errordict[e] = 1 errordict[e] = 1
errorfirst[e] = '%s (%s)' % (fn, date) errorfirst[e] = '%s (%s)' % (fn, date)
else: else:
errordict[e] = errordict[e] + 1 errordict[e] = errordict[e] + 1
errorlast[e] = '%s (%s)' % (fn, date) errorlast[e] = '%s (%s)' % (fn, date)
nok = nok + 1 nok = nok + 1
if modify: if modify:
os.unlink(fn) os.unlink(fn)
print '--------------' print '--------------'
print nok, 'files parsed,',nwarn,'files warning-only,', print nok, 'files parsed,',nwarn,'files warning-only,',
print nbad,'files unparseable' print nbad,'files unparseable'
print '--------------' print '--------------'
for e in errordict.keys(): for e in errordict.keys():
print errordict[e], errorfirst[e], '-', errorlast[e], '\t', e print errordict[e], errorfirst[e], '-', errorlast[e], '\t', e
def main(): def main():
modify = 0 modify = 0
if len(sys.argv) > 1 and sys.argv[1] == '-d': if len(sys.argv) > 1 and sys.argv[1] == '-d':
modify = 1 modify = 1
del sys.argv[1] del sys.argv[1]
if len(sys.argv) > 1: if len(sys.argv) > 1:
for folder in sys.argv[1:]: for folder in sys.argv[1:]:
parsedir(folder, modify) parsedir(folder, modify)
else: else:
parsedir('/ufs/jack/Mail/errorsinbox', modify) parsedir('/ufs/jack/Mail/errorsinbox', modify)
if __name__ == '__main__' or sys.argv[0] == __name__: if __name__ == '__main__' or sys.argv[0] == __name__:
main() main()

View file

@ -12,11 +12,11 @@ entry in the master tree are synchronized. This means:
If the files differ: If the files differ:
if the slave file is newer: if the slave file is newer:
normalize the slave file normalize the slave file
if the files still differ: if the files still differ:
copy the slave to the master copy the slave to the master
else (the master is newer): else (the master is newer):
copy the master to the slave copy the master to the slave
normalizing the slave means replacing CRLF with LF when the master normalizing the slave means replacing CRLF with LF when the master
doesn't use CRLF doesn't use CRLF
@ -37,107 +37,107 @@ def main():
global create_directories, write_master, write_slave global create_directories, write_master, write_slave
opts, args = getopt.getopt(sys.argv[1:], "nym:s:d:f:a:") opts, args = getopt.getopt(sys.argv[1:], "nym:s:d:f:a:")
for o, a in opts: for o, a in opts:
if o == '-y': if o == '-y':
default_answer = "yes" default_answer = "yes"
if o == '-n': if o == '-n':
default_answer = "no" default_answer = "no"
if o == '-s': if o == '-s':
write_slave = a write_slave = a
if o == '-m': if o == '-m':
write_master = a write_master = a
if o == '-d': if o == '-d':
create_directories = a create_directories = a
if o == '-f': if o == '-f':
create_files = a create_files = a
if o == '-a': if o == '-a':
create_files = create_directories = write_slave = write_master = a create_files = create_directories = write_slave = write_master = a
try: try:
[slave, master] = args [slave, master] = args
except ValueError: except ValueError:
print "usage: python", sys.argv[0] or "treesync.py", print "usage: python", sys.argv[0] or "treesync.py",
print "[-n] [-y] [-m y|n|a] [-s y|n|a] [-d y|n|a] [-f n|y|a]", print "[-n] [-y] [-m y|n|a] [-s y|n|a] [-d y|n|a] [-f n|y|a]",
print "slavedir masterdir" print "slavedir masterdir"
return return
process(slave, master) process(slave, master)
def process(slave, master): def process(slave, master):
cvsdir = os.path.join(master, "CVS") cvsdir = os.path.join(master, "CVS")
if not os.path.isdir(cvsdir): if not os.path.isdir(cvsdir):
print "skipping master subdirectory", master print "skipping master subdirectory", master
print "-- not under CVS" print "-- not under CVS"
return return
print "-"*40 print "-"*40
print "slave ", slave print "slave ", slave
print "master", master print "master", master
if not os.path.isdir(slave): if not os.path.isdir(slave):
if not okay("create slave directory %s?" % slave, if not okay("create slave directory %s?" % slave,
answer=create_directories): answer=create_directories):
print "skipping master subdirectory", master print "skipping master subdirectory", master
print "-- no corresponding slave", slave print "-- no corresponding slave", slave
return return
print "creating slave directory", slave print "creating slave directory", slave
try: try:
os.mkdir(slave) os.mkdir(slave)
except os.error, msg: except os.error, msg:
print "can't make slave directory", slave, ":", msg print "can't make slave directory", slave, ":", msg
return return
else: else:
print "made slave directory", slave print "made slave directory", slave
cvsdir = None cvsdir = None
subdirs = [] subdirs = []
names = os.listdir(master) names = os.listdir(master)
for name in names: for name in names:
mastername = os.path.join(master, name) mastername = os.path.join(master, name)
slavename = os.path.join(slave, name) slavename = os.path.join(slave, name)
if name == "CVS": if name == "CVS":
cvsdir = mastername cvsdir = mastername
else: else:
if os.path.isdir(mastername) and not os.path.islink(mastername): if os.path.isdir(mastername) and not os.path.islink(mastername):
subdirs.append((slavename, mastername)) subdirs.append((slavename, mastername))
if cvsdir: if cvsdir:
entries = os.path.join(cvsdir, "Entries") entries = os.path.join(cvsdir, "Entries")
for e in open(entries).readlines(): for e in open(entries).readlines():
words = string.split(e, '/') words = string.split(e, '/')
if words[0] == '' and words[1:]: if words[0] == '' and words[1:]:
name = words[1] name = words[1]
s = os.path.join(slave, name) s = os.path.join(slave, name)
m = os.path.join(master, name) m = os.path.join(master, name)
compare(s, m) compare(s, m)
for (s, m) in subdirs: for (s, m) in subdirs:
process(s, m) process(s, m)
def compare(slave, master): def compare(slave, master):
try: try:
sf = open(slave, 'r') sf = open(slave, 'r')
except IOError: except IOError:
sf = None sf = None
try: try:
mf = open(master, 'rb') mf = open(master, 'rb')
except IOError: except IOError:
mf = None mf = None
if not sf: if not sf:
if not mf: if not mf:
print "Neither master nor slave exists", master print "Neither master nor slave exists", master
return return
print "Creating missing slave", slave print "Creating missing slave", slave
copy(master, slave, answer=create_files) copy(master, slave, answer=create_files)
return return
if not mf: if not mf:
print "Not updating missing master", master print "Not updating missing master", master
return return
if sf and mf: if sf and mf:
if identical(sf, mf): if identical(sf, mf):
return return
sft = mtime(sf) sft = mtime(sf)
mft = mtime(mf) mft = mtime(mf)
if mft > sft: if mft > sft:
# Master is newer -- copy master to slave # Master is newer -- copy master to slave
sf.close() sf.close()
mf.close() mf.close()
print "Master ", master print "Master ", master
print "is newer than slave", slave print "is newer than slave", slave
copy(master, slave, answer=write_slave) copy(master, slave, answer=write_slave)
return return
# Slave is newer -- copy slave to master # Slave is newer -- copy slave to master
print "Slave is", sft-mft, "seconds newer than master" print "Slave is", sft-mft, "seconds newer than master"
# But first check what to do about CRLF # But first check what to do about CRLF
@ -146,20 +146,20 @@ def compare(slave, master):
mf.close() mf.close()
sf.close() sf.close()
if fun: if fun:
print "***UPDATING MASTER (BINARY COPY)***" print "***UPDATING MASTER (BINARY COPY)***"
copy(slave, master, "rb", answer=write_master) copy(slave, master, "rb", answer=write_master)
else: else:
print "***UPDATING MASTER***" print "***UPDATING MASTER***"
copy(slave, master, "r", answer=write_master) copy(slave, master, "r", answer=write_master)
BUFSIZE = 16*1024 BUFSIZE = 16*1024
def identical(sf, mf): def identical(sf, mf):
while 1: while 1:
sd = sf.read(BUFSIZE) sd = sf.read(BUFSIZE)
md = mf.read(BUFSIZE) md = mf.read(BUFSIZE)
if sd != md: return 0 if sd != md: return 0
if not sd: break if not sd: break
return 1 return 1
def mtime(f): def mtime(f):
@ -168,36 +168,36 @@ def mtime(f):
def funnychars(f): def funnychars(f):
while 1: while 1:
buf = f.read(BUFSIZE) buf = f.read(BUFSIZE)
if not buf: break if not buf: break
if '\r' in buf or '\0' in buf: return 1 if '\r' in buf or '\0' in buf: return 1
return 0 return 0
def copy(src, dst, rmode="rb", wmode="wb", answer='ask'): def copy(src, dst, rmode="rb", wmode="wb", answer='ask'):
print "copying", src print "copying", src
print " to", dst print " to", dst
if not okay("okay to copy? ", answer): if not okay("okay to copy? ", answer):
return return
f = open(src, rmode) f = open(src, rmode)
g = open(dst, wmode) g = open(dst, wmode)
while 1: while 1:
buf = f.read(BUFSIZE) buf = f.read(BUFSIZE)
if not buf: break if not buf: break
g.write(buf) g.write(buf)
f.close() f.close()
g.close() g.close()
def okay(prompt, answer='ask'): def okay(prompt, answer='ask'):
answer = string.lower(string.strip(answer)) answer = string.lower(string.strip(answer))
if not answer or answer[0] not in 'ny': if not answer or answer[0] not in 'ny':
answer = raw_input(prompt) answer = raw_input(prompt)
answer = string.lower(string.strip(answer)) answer = string.lower(string.strip(answer))
if not answer: if not answer:
answer = default_answer answer = default_answer
if answer[:1] == 'y': if answer[:1] == 'y':
return 1 return 1
if answer[:1] == 'n': if answer[:1] == 'n':
return 0 return 0
print "Yes or No please -- try again:" print "Yes or No please -- try again:"
return okay(prompt) return okay(prompt)