|
|
#!/usr/bin/env python
|
|
|
#
|
|
|
# Commandline front-end for cvsps.py
|
|
|
#
|
|
|
# Copyright 2008, Frank Kingswood <frank@kingswood-consulting.co.uk>
|
|
|
#
|
|
|
# This software may be used and distributed according to the terms
|
|
|
# of the GNU General Public License, incorporated herein by reference.
|
|
|
|
|
|
import sys
|
|
|
from mercurial import util
|
|
|
from mercurial.i18n import _
|
|
|
from optparse import OptionParser, SUPPRESS_HELP
|
|
|
from hgext.convert.cvsps import createlog, createchangeset, logerror
|
|
|
|
|
|
def main():
|
|
|
'''Main program to mimic cvsps.'''
|
|
|
|
|
|
op = OptionParser(usage='%prog [-bpruvxz] path',
|
|
|
description='Read CVS rlog for current directory or named '
|
|
|
'path in repository, and convert the log to changesets '
|
|
|
'based on matching commit log entries and dates.')
|
|
|
|
|
|
# Options that are ignored for compatibility with cvsps-2.1
|
|
|
op.add_option('-A', dest='Ignore', action='store_true', help=SUPPRESS_HELP)
|
|
|
op.add_option('--cvs-direct', dest='Ignore', action='store_true', help=SUPPRESS_HELP)
|
|
|
op.add_option('-q', dest='Ignore', action='store_true', help=SUPPRESS_HELP)
|
|
|
|
|
|
# Main options shared with cvsps-2.1
|
|
|
op.add_option('-b', dest='Branches', action='append', default=[],
|
|
|
help='Only return changes on specified branches')
|
|
|
op.add_option('-p', dest='Prefix', action='store', default='',
|
|
|
help='Prefix to remove from file names')
|
|
|
op.add_option('-r', dest='Revisions', action='append', default=[],
|
|
|
help='Only return changes after or between specified tags')
|
|
|
op.add_option('-u', dest='Cache', action='store_const', const='update',
|
|
|
help="Update cvs log cache")
|
|
|
op.add_option('-v', dest='Verbose', action='count', default=0,
|
|
|
help='Be verbose')
|
|
|
op.add_option('-x', dest='Cache', action='store_const', const='write',
|
|
|
help="Create new cvs log cache")
|
|
|
op.add_option('-z', dest='Fuzz', action='store', type='int', default=60,
|
|
|
help='Set commit time fuzz', metavar='seconds')
|
|
|
op.add_option('--root', dest='Root', action='store', default='',
|
|
|
help='Specify cvsroot', metavar='cvsroot')
|
|
|
|
|
|
# Options specific to this version
|
|
|
op.add_option('--parents', dest='Parents', action='store_true',
|
|
|
help='Show parent changesets')
|
|
|
op.add_option('--ancestors', dest='Ancestors', action='store_true',
|
|
|
help='Show current changeset in ancestor branches')
|
|
|
|
|
|
options, args = op.parse_args()
|
|
|
|
|
|
# Create a ui object for printing progress messages
|
|
|
class UI:
|
|
|
def __init__(self, verbose):
|
|
|
if verbose:
|
|
|
self.status = self.message
|
|
|
if verbose>1:
|
|
|
self.note = self.message
|
|
|
if verbose>2:
|
|
|
self.debug = self.message
|
|
|
def message(self, msg):
|
|
|
sys.stderr.write(msg)
|
|
|
def nomessage(self, msg):
|
|
|
pass
|
|
|
status = nomessage
|
|
|
note = nomessage
|
|
|
debug = nomessage
|
|
|
ui = UI(options.Verbose)
|
|
|
|
|
|
try:
|
|
|
if args:
|
|
|
log = []
|
|
|
for d in args:
|
|
|
log += createlog(ui, d, root=options.Root, cache=options.Cache)
|
|
|
else:
|
|
|
log = createlog(ui, root=options.Root, cache=options.Cache)
|
|
|
except logerror, e:
|
|
|
print e
|
|
|
return
|
|
|
|
|
|
changesets = createchangeset(ui, log, options.Fuzz)
|
|
|
del log
|
|
|
|
|
|
# Print changesets (optionally filtered)
|
|
|
|
|
|
off = len(options.Revisions)
|
|
|
branches = {} # latest version number in each branch
|
|
|
ancestors = {} # parent branch
|
|
|
for cs in changesets:
|
|
|
|
|
|
if options.Ancestors:
|
|
|
if cs.branch not in branches and cs.parents and cs.parents[0].id:
|
|
|
ancestors[cs.branch] = changesets[cs.parents[0].id-1].branch, cs.parents[0].id
|
|
|
branches[cs.branch] = cs.id
|
|
|
|
|
|
# limit by branches
|
|
|
if options.Branches and (cs.branch or 'HEAD') not in options.Branches:
|
|
|
continue
|
|
|
|
|
|
if not off:
|
|
|
# Note: trailing spaces on several lines here are needed to have
|
|
|
# bug-for-bug compatibility with cvsps.
|
|
|
print '---------------------'
|
|
|
print 'PatchSet %d ' % cs.id
|
|
|
print 'Date: %s' % util.datestr(cs.date, '%Y/%m/%d %H:%M:%S %1%2')
|
|
|
print 'Author: %s' % cs.author
|
|
|
print 'Branch: %s' % (cs.branch or 'HEAD')
|
|
|
print 'Tag%s: %s ' % (['', 's'][len(cs.tags)>1],
|
|
|
','.join(cs.tags) or '(none)')
|
|
|
if options.Parents and cs.parents:
|
|
|
if len(cs.parents)>1:
|
|
|
print 'Parents: %s' % (','.join([str(p.id) for p in cs.parents]))
|
|
|
else:
|
|
|
print 'Parent: %d' % cs.parents[0].id
|
|
|
|
|
|
if options.Ancestors:
|
|
|
b = cs.branch
|
|
|
r = []
|
|
|
while b:
|
|
|
b, c = ancestors[b]
|
|
|
r.append('%s:%d:%d' % (b or "HEAD", c, branches[b]))
|
|
|
if r:
|
|
|
print 'Ancestors: %s' % (','.join(r))
|
|
|
|
|
|
print 'Log:'
|
|
|
print cs.comment
|
|
|
print
|
|
|
print 'Members: '
|
|
|
for f in cs.entries:
|
|
|
fn = f.file
|
|
|
if fn.startswith(options.Prefix):
|
|
|
fn = fn[len(options.Prefix):]
|
|
|
print '\t%s:%s->%s%s ' % (fn, '.'.join([str(x) for x in f.parent]) or 'INITIAL',
|
|
|
'.'.join([str(x) for x in f.revision]), ['', '(DEAD)'][f.dead])
|
|
|
print
|
|
|
|
|
|
# have we seen the start tag?
|
|
|
if options.Revisions and off:
|
|
|
if options.Revisions[0] == str(cs.id) or \
|
|
|
options.Revisions[0] in cs.tags:
|
|
|
off = False
|
|
|
|
|
|
# see if we reached the end tag
|
|
|
if len(options.Revisions)>1 and not off:
|
|
|
if options.Revisions[1] == str(cs.id) or \
|
|
|
options.Revisions[1] in cs.tags:
|
|
|
break
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
main()
|
|
|
|