#!/usr/bin/env python # # Commandline front-end for cvsps.py # # Copyright 2008, Frank Kingswood # # 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()