[Python-Dev] Checkin Utility
M.-A. Lemburg
mal@lemburg.com
Wed, 28 Jun 2000 19:22:40 +0200
This is a multi-part message in MIME format.
--------------4A599D73348784E859687D01
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
I thought you might have some use for the attached utility. It's
a simple script which helps with checking in patches which I've
been using for a while now. It also hides the CVS options and
parameters away as far as possible, so that CVS knowledge is
not really needed to complete the task.
--
Marc-Andre Lemburg
______________________________________________________________________
Business: http://www.lemburg.com/
Python Pages: http://www.lemburg.com/python/
--------------4A599D73348784E859687D01
Content-Type: text/python; charset=us-ascii;
name="checkin.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="checkin.py"
#!/usr/local/bin/python -u
"""
Tools for (interactive) CVS checkins.
(c) Marc-Andre Lemburg, mal@lemburg.com, All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee or royalty is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation or portions thereof, including modifications,
that you make.
THE AUTHOR MARC-ANDRE LEMBURG DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
"""#"
import string,os,exceptions,tempfile,sys
__version__ = '0.3'
### Configuration
# CVS Options which will always be used
CVSOPTIONS = '-z3'
# Path of the cvs tool
CVS = "/usr/bin/cvs"
# Default name of patcher
default_author = 'Marc-Andre Lemburg'
default_email = 'mal@lemburg.com'
# Check the settings
if not os.path.exists(CVS):
CVS = 'cvs'
# Debug ?
__debug__ = 0
### Errors
class CVSError(exceptions.StandardError):
pass
### Low Level interface
def cvs(command, flags=(), files=(), options=(), test=0):
if options:
options = '-' + string.join(options, ' -')
else:
options = ''
if flags:
flags = '-' + string.join(flags, ' -')
else:
flags = ''
cmd = '%s %s %s %s %s %s' % (CVS,
CVSOPTIONS,
options,
command,
flags,
string.join(files, ' '))
if test:
print '* exec "%s"' % cmd
return ''
try:
p = os.popen(cmd)
except os.error,why:
raise CVSError, why
return p.read()
def check_files(files=('.',), modify=0):
options = options=('q',)
if not modify:
options = options + ('n',)
output = cvs('update', files=files, options=options)
lines = string.split(output, '\n')
added_files = []
modified_files = []
updated_files = []
patched_files = []
for line in lines:
if not line:
continue
try:
marker, filename = string.split(line)
except ValueError:
if __debug__:
print '* could not parse: "%s"' % line
continue
if marker == '?':
list = added_files
elif marker == 'M':
list = modified_files
elif marker == 'U':
list = updated_files
elif marker == 'P':
list = patched_files
else:
if __debug__:
print '* unkown marker: "%s" for file "%s"' % \
(marker, filename)
continue
list.append(filename)
return added_files, modified_files, updated_files, patched_files
def update_files(files=('.',), verbose=0):
return check_files(files, modify=1)
def print_check_results(a, m, u, p):
if a:
print 'Added to work dir:'
for filename in a:
print ' ',filename
if m:
print 'Modified in work dir:'
for filename in m:
print ' ',filename
if u:
print 'Updated in repository:'
for filename in u:
print ' ',filename
if p:
print 'Patched in repository:'
for filename in p:
print ' ',filename
def checkin_files(files, message='', rev=''):
options = ('Q',)
flags = ()
if message:
tempname = tempfile.mktemp()
open(tempname, 'w').write(message)
flags = flags + ('F %s' % tempname,)
else:
tempname = ''
if rev:
flags = flags + ('r %s' % rev,)
try:
if not __debug__:
output = cvs('commit', files=files, options=options, flags=flags)
else:
output = cvs('commit', files=files, options=options, flags=flags,
test=1)
print message
if output:
if __debug__:
print '* commit output:'
print output
finally:
os.unlink(tempname)
def checkin_file(file, message='', rev=''):
return checkin_files((file,), message, rev)
def add_files(files):
if not __debug__:
output = cvs('add', files=files, options=('Q',))
else:
output = cvs('add', files=files, options=('Q',), test=1)
if output:
if __debug__:
print '* add output:'
print output
def add_file(file):
return add_files((file,))
def multiline_input(prompt='', term='.', linesep='\n'):
lines = []
while 1:
line = raw_input(prompt)
if not lines and \
not line:
return ''
if line == term or \
lines and lines[-1] == line:
return string.join(lines, linesep)
lines.append(line)
def format_message(message, author, email=''):
if email:
header = '%s <%s>:\n' % (author, email)
elif author:
header = '%s:\n' % (author)
else:
header = ''
msg = header + message
return string.strip(msg)
if __name__ == '__main__':
# -f cmd line switch
if len(sys.argv) > 1 and sys.argv[1] == '-f':
force = 1
else:
force = 0
print '='*72
print 'CVS Checkin Utility'
print '-'*72
print
print 'Checking work dir...',
a,m,u,p = check_files()
if not force and \
(u or p):
print
print '* Files changed in the repository since the last update.'
print '* Please update before proceeding with the checkin or run'
print '* this script with switch -f.'
print
print 'For your information, these files were found to be out'
print 'of sync:'
print
print_check_results((),(),u,p)
sys.exit(1)
print 'done.'
print
if not a and not m:
print '* No files need to be checked in.'
print
sys.exit(1)
print 'These files will be checked in:'
print
print_check_results(a,m,u,p)
print
print '='*72
print 'Please enter the name and email of the patch author:'
print
author = raw_input('Name: [%s] ' % default_author) or default_author
email = raw_input('EMail: [%s] ' % default_email) or default_email
print
print '='*72
print 'Please enter the commit messages for each file below...'
print
print '[Emtpy entries will be skipped, comments must be terminated by'
print ' line containing a single dot or two consecutive empty lines]'
if a:
print
print '# New Files:'
for file in a:
print
print '%s' % file
print '-'*72
message = multiline_input(term='.')
print '-'*72
if not message:
print '>>> (commit skipped)'
continue
print '>>> Adding to CVS Repository...',
message = format_message(message, author, email)
add_file(file)
checkin_file(file, message)
print 'done.'
if m:
print
print '# Modified Files:'
for file in m:
print
print '%s' % file
print '-'*72
message = multiline_input(term='.')
print '-'*72
if not message:
print '>>> (commit skipped)'
continue
print '>>> Committing to CVS Repository...',
message = format_message(message, author, email)
checkin_file(file, message)
print 'done.'
print
print 'Done. Thanks :-)'
--------------4A599D73348784E859687D01--