RFC: Perfarce extension change of behaviour in "latest" calculation
Frank Kingswood
frank at kingswood-consulting.co.uk
Tue Jun 15 07:39:10 UTC 2010
Hi!
The perfarce extension currently uses a naive algorithm to detemine the
latest p4 revision, which is reported by "hg p4id" and (more importantly) as
the base revision on which to apply incoming p4 changelists.
The current algorithm counts back from the highest hg revision number until
it finds a revision with the p4 changelist number set. It then searches the
child revisions for any that change only .hgtags, and will use the first one
it finds. The algorithm ignores the shape of the revision graph and named
branches.
This is not usually a problem because the p4 revision history itself is
strictly linear. However, if there are branches in the hg tree then it may
lead to problems. The scan for .hgtags is also problematic, there could be
multiple child revisions. Finally, the test for .hgtags needs extending to
cover other not-pushed-or-pulled files (everything starting with .hg in the
hg root).
I've been running with a patch that walks the revision graph from the tip of
the default branch back, and remembers any nodes with only changes to .hg*,
and this works fine for me.
If you're a perfarce user, will this cause problems for you?
Frank
diff -r dbdcbe5c15bb -r c4d342f969dc perfarce.py
--- a/perfarce.py Wed May 19 11:40:45 2010 +0100
+++ b/perfarce.py Tue Jun 01 10:13:08 2010 +0100
@@ -192,18 +192,29 @@
def latest(self, tags=False):
'''Find the most recent changelist which has the p4 extra data which
- gives the p4 changelist it was converted from'''
- for rev in xrange(len(self.repo)-1, -1, -1):
- ctx = self.repo[rev]
+ gives the p4 changelist it was converted from.
+ Returns the revision and p4 changelist number'''
+
+ def dothgonly(ctx):
+ 'returns True if only .hg files in this context'
+ for f in ctx.files():
+ if not f.startswith('.hg'):
+ return False
+ return True
+
+ lasthg = None
+ ctx = self.repo['default']
+ while ctx.node() != node.nullid:
extra = ctx.extra()
if 'p4' in extra:
- if tags:
- # if there is a child with p4 tags then return the child
revision
- for ctx2 in ctx.children():
- if ctx2.description().startswith('p4 tags\n') and
".hgtags" in ctx2:
- ctx = ctx2
- break
- return ctx.node(), int(extra['p4'])
+ return (tags and lasthg or ctx).node(), int(extra['p4'])
+ elif dothgonly(ctx):
+ if lasthg is None:
+ lasthg = ctx
+ else:
+ lasthg = None
+ ctx = ctx.parents()[0]
+
raise util.Abort(_('no p4 changelist revision found'))
--
------------------------------------------------------------------------
Frank A. Kingswood frank at kingswood-consulting.co.uk
Cambridge, United Kingdom +44-870-095 0000
More information about the Mercurial-devel
mailing list