# HG changeset patch # User Frank Kingswood # Date 2013-01-08 20:11:20 # Node ID 1b7b5975793f7b72d2ed9337be543389d7b1ba4c # Parent 580274a1f1c2856a7d4f814d9da4c3d5ef64199d cvsps: use commitids (when present) to detect changesets Simplify core logic by no longer attempting to work around missing class attributes. Instead always generate the attributes and ignore the cache if the attributes are missing diff --git a/hgext/convert/cvsps.py b/hgext/convert/cvsps.py --- a/hgext/convert/cvsps.py +++ b/hgext/convert/cvsps.py @@ -19,6 +19,7 @@ class logentry(object): .branch - name of branch this revision is on .branches - revision tuple of branches starting at this revision .comment - commit message + .commitid - CVS commitid or None .date - the commit date as a (time, tz) tuple .dead - true if file revision is dead .file - Name of file @@ -28,19 +29,17 @@ class logentry(object): .revision - revision number as tuple .tags - list of tags on the file .synthetic - is this a synthetic "file ... added on ..." revision? - .mergepoint- the branch that has been merged from - (if present in rlog output) - .branchpoints- the branches that start at the current entry + .mergepoint - the branch that has been merged from (if present in + rlog output) or None + .branchpoints - the branches that start at the current entry or empty ''' def __init__(self, **entries): self.synthetic = False self.__dict__.update(entries) def __repr__(self): - return "<%s at 0x%x: %s %s>" % (self.__class__.__name__, - id(self), - self.file, - ".".join(map(str, self.revision))) + items = ("%s=%r"%(k, self.__dict__[k]) for k in sorted(self.__dict__)) + return "%s(%s)"%(type(self).__name__, ", ".join(items)) class logerror(Exception): pass @@ -113,6 +112,7 @@ def createlog(ui, directory=None, root=" re_50 = re.compile('revision ([\\d.]+)(\s+locked by:\s+.+;)?$') re_60 = re.compile(r'date:\s+(.+);\s+author:\s+(.+);\s+state:\s+(.+?);' r'(\s+lines:\s+(\+\d+)?\s+(-\d+)?;)?' + r'(\s+commitid:\s+([^;]+);)?' r'(.*mergepoint:\s+([^;]+);)?') re_70 = re.compile('branches: (.+);$') @@ -171,6 +171,14 @@ def createlog(ui, directory=None, root=" try: ui.note(_('reading cvs log cache %s\n') % cachefile) oldlog = pickle.load(open(cachefile)) + for e in oldlog: + if not (util.safehasattr(e, 'branchpoints') and + util.safehasattr(e, 'commitid') and + util.safehasattr(e, 'mergepoint')): + ui.status(_('ignoring old cache\n')) + oldlog = [] + break + ui.note(_('cache has %d log entries\n') % len(oldlog)) except Exception, e: ui.note(_('error reading cache: %r\n') % e) @@ -298,7 +306,8 @@ def createlog(ui, directory=None, root=" assert match, _('expected revision number') e = logentry(rcs=scache(rcs), file=scache(filename), revision=tuple([int(x) for x in match.group(1).split('.')]), - branches=[], parent=None) + branches=[], parent=None, commitid=None, mergepoint=None, branchpoints=set()) + state = 6 elif state == 6: @@ -329,8 +338,11 @@ def createlog(ui, directory=None, root=" else: e.lines = None - if match.group(7): # cvsnt mergepoint - myrev = match.group(8).split('.') + if match.group(7): # cvs 1.12 commitid + e.commitid = match.group(8) + + if match.group(9): # cvsnt mergepoint + myrev = match.group(10).split('.') if len(myrev) == 2: # head e.mergepoint = 'HEAD' else: @@ -339,8 +351,7 @@ def createlog(ui, directory=None, root=" assert len(branches) == 1, ('unknown branch: %s' % e.mergepoint) e.mergepoint = branches[0] - else: - e.mergepoint = None + e.comment = [] state = 7 @@ -469,23 +480,22 @@ class changeset(object): .author - author name as CVS knows it .branch - name of branch this changeset is on, or None .comment - commit message + .commitid - CVS commitid or None .date - the commit date as a (time,tz) tuple .entries - list of logentry objects in this changeset .parents - list of one or two parent changesets .tags - list of tags on this changeset .synthetic - from synthetic revision "file ... added on branch ..." - .mergepoint- the branch that has been merged from - (if present in rlog output) - .branchpoints- the branches that start at the current entry + .mergepoint- the branch that has been merged from or None + .branchpoints- the branches that start at the current entry or empty ''' def __init__(self, **entries): self.synthetic = False self.__dict__.update(entries) def __repr__(self): - return "<%s at 0x%x: %s>" % (self.__class__.__name__, - id(self), - getattr(self, 'id', "(no id)")) + items = ("%s=%r"%(k, self.__dict__[k]) for k in sorted(self.__dict__)) + return "%s(%s)"%(type(self).__name__, ", ".join(items)) def createchangeset(ui, log, fuzz=60, mergefrom=None, mergeto=None): '''Convert log into changesets.''' @@ -493,8 +503,7 @@ def createchangeset(ui, log, fuzz=60, me ui.status(_('creating changesets\n')) # Merge changesets - - log.sort(key=lambda x: (x.comment, x.author, x.branch, x.date)) + log.sort(key=lambda x: (x.commitid, x.comment, x.author, x.branch, x.date, x.branchpoints)) changesets = [] files = set() @@ -517,22 +526,27 @@ def createchangeset(ui, log, fuzz=60, me # first changeset and bar the next and MYBRANCH and MYBRANCH2 # should both start off of the bar changeset. No provisions are # made to ensure that this is, in fact, what happens. - if not (c and - e.comment == c.comment and - e.author == c.author and - e.branch == c.branch and - (not util.safehasattr(e, 'branchpoints') or - not util.safehasattr (c, 'branchpoints') or - e.branchpoints == c.branchpoints) and - ((c.date[0] + c.date[1]) <= - (e.date[0] + e.date[1]) <= - (c.date[0] + c.date[1]) + fuzz) and - e.file not in files): + if not (c and e.branchpoints == c.branchpoints and + ( # cvs commitids + (e.commitid is not None and e.commitid == c.commitid) + or + ( # no commitids, use fuzzy commit detection + (e.commitid is None or c.commitid is None) and + e.comment == c.comment and + e.author == c.author and + e.branch == c.branch and + ((c.date[0] + c.date[1]) <= + (e.date[0] + e.date[1]) <= + (c.date[0] + c.date[1]) + fuzz) and + e.file not in files + ) + )): c = changeset(comment=e.comment, author=e.author, - branch=e.branch, date=e.date, entries=[], - mergepoint=getattr(e, 'mergepoint', None), - branchpoints=getattr(e, 'branchpoints', set())) + branch=e.branch, date=e.date, + entries=[], mergepoint=e.mergepoint, + branchpoints=e.branchpoints, commitid=e.commitid) changesets.append(c) + files = set() if len(changesets) % 100 == 0: t = '%d %s' % (len(changesets), repr(e.comment)[1:-1]) @@ -808,9 +822,8 @@ def debugcvsps(ui, *args, **opts): ui.write(('Branch: %s\n' % (cs.branch or 'HEAD'))) ui.write(('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1], ','.join(cs.tags) or '(none)'))) - branchpoints = getattr(cs, 'branchpoints', None) - if branchpoints: - ui.write(('Branchpoints: %s \n' % ', '.join(branchpoints))) + if cs.branchpoints: + ui.write('Branchpoints: %s \n' % ', '.join(cs.branchpoints)) if opts["parents"] and cs.parents: if len(cs.parents) > 1: ui.write(('Parents: %s\n' %