[PATCH 1 of 1] identify: use verbose flag to display nearest surrounding tags
Gilles Moris
gilles.moris at free.fr
Sat Feb 14 03:25:22 CST 2009
7 files changed, 183 insertions(+), 5 deletions(-)
mercurial/cmdutil.py | 80 ++++++++++++++++++++++++++++++++++++++++++++++-
mercurial/commands.py | 18 +++++++++-
tests/test-archive | 2 -
tests/test-identify | 63 +++++++++++++++++++++++++++++++++++++
tests/test-identify.out | 23 +++++++++++++
tests/test-tags | 1
tests/test-tags.out | 1
# HG changeset patch
# User Gilles Moris <gilles.moris at free.fr>
# Date 1234603377 -3600
# Node ID 15fb3e8302574b891c6d92e046564fe434941287
# Parent 2d3792e3142dd05251af7264b99c2e2967cd721b
identify: use verbose flag to display nearest surrounding tags
Note that tip and mq tags are ignored as they are temporary, and that the
verbose flag was not used for identify so far.
Add tests for this new feature and fixed the two other tests that were
already using -v.
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -7,7 +7,7 @@
from node import hex, nullid, nullrev, short
from i18n import _
-import os, sys, bisect, stat
+import os, sys, bisect, stat, heapq
import mdiff, bdiff, util, templater, templatefilters, patch, errno, error
import match as _match
@@ -1184,3 +1184,81 @@
return commitfunc(ui, repo, message, m, opts)
except ValueError, inst:
raise util.Abort(str(inst))
+
+def nearesttagsdateh(repo, ctx, fwd):
+ """search for cset with tags trying to return csets ordered by date
+ this is a generator function that returns a tuple
+ (changectx, distancefromnode)
+ it searches like a breadth first search algorithm except that an
+ heuristic is set on date to give them priority over number of hops
+ """
+ # use a distance map and a pseudo sorted list by date
+ # this is a generalised breadth first search with the date as heuristic
+ dmap = [0] * (len(repo))
+
+ try:
+ qparent = repo['qparent']
+ qtip = repo['qtip']
+ excltags = [ 'qparent', 'tip' ]
+ except error.RepoError:
+ qparent = qtip = None
+ excltags = [ 'tip' ]
+
+ # initialize the search algorithm depending on the search direction
+ if fwd:
+ if qparent:
+ if qparent.rev() < ctx.rev() and ctx.rev() <= qtip.rev():
+ return
+ dmap[qparent.rev()+1] = -1
+ heuristic = lambda c: c.date()[0]
+ chldcache = [[]] * len(repo.changelog)
+ for r in xrange(ctx.rev(), len(ctx._repo)):
+ for p in repo[r].parents():
+ pr = p.rev()
+ if not chldcache[pr]:
+ chldcache[pr] = [r]
+ else:
+ chldcache[pr].append(r)
+ infants = lambda r: chldcache[r]
+ else:
+ if qparent:
+ if qparent.rev() < ctx.rev() and ctx.rev() <= qtip.rev():
+ dmap[qparent.rev()] = ctx.rev() - qparent.rev()
+ ctx = qparent
+ heuristic = lambda c: - c.date()[0]
+ infants = lambda r: [ p.rev() for p in repo[r].parents() ]
+
+ # init queue
+ heap = []
+ heapq.heappush(heap, (heuristic(ctx), ctx))
+
+ while heap:
+ # get the highest (resp lowest) date with heappop
+ date, ctx = heapq.heappop(heap)
+ rev = ctx.rev()
+ d = dmap[rev]
+ if d < 0:
+ continue
+ tags = [ t for t in ctx.tags() if t not in excltags ]
+ if tags:
+ yield tags, d
+ # cut branch once a tag is found
+ if fwd:
+ for c in ctx.descendants():
+ dmap[c.rev()] = -1
+ else:
+ for c in ctx.ancestors():
+ dmap[c.rev()] = -1
+ continue
+ # queue neighbours to propagate search
+ for nr in infants(rev):
+ if dmap[nr] > 0:
+ # if a node was already queued, retains the longest path
+ # this also avoid revisiting an already visited node
+ dmap[nr] = max(dmap[nr], d+1)
+ elif dmap[nr] == 0:
+ n = repo[nr]
+ # queue another node keeping the pseudo sorted assertion
+ heapq.heappush(heap, (heuristic(n), n))
+ dmap[nr] = d + 1
+
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1548,7 +1548,7 @@
rev = revs[0]
if not rev:
rev = "tip"
- if num or branch or tags:
+ if num or branch or tags or ui.verbose:
raise util.Abort(
"can't query remote revision number, branch, or tags")
output = [hexfunc(repo.lookup(rev))]
@@ -1589,6 +1589,22 @@
ui.write("%s\n" % ' '.join(output))
+ if ui.verbose:
+ if isinstance(ctx, context.workingctx):
+ ctx = ctx.parents()[0]
+
+ output = ['based on']
+ for t, d in cmdutil.nearesttagsdateh(repo, ctx, fwd=False):
+ output.append('/'.join([ tt for tt in t ]) + ('(-%d)' % d))
+ if len(output) > 1:
+ ui.write("%s\n" % ' '.join(output))
+
+ output = ['fixed in']
+ for t, d in cmdutil.nearesttagsdateh(repo, ctx, fwd=True):
+ output.append('/'.join([ tt for tt in t ]) + ('(+%d)' % d))
+ if len(output) > 1:
+ ui.write("%s\n" % ' '.join(output))
+
def import_(ui, repo, patch1, *patches, **opts):
"""import an ordered set of patches
diff --git a/tests/test-archive b/tests/test-archive
--- a/tests/test-archive
+++ b/tests/test-archive
@@ -42,7 +42,7 @@
"$TESTDIR/get-with-headers.py" localhost:$HGPORT "/archive/tip.invalid" | head -n 1
echo
-TIP=`hg id -v | cut -f1 -d' '`
+TIP=`hg id | cut -f1 -d' '`
QTIP=`hg id -q`
cat > getarchive.py <<EOF
import os, sys, urllib2
diff --git a/tests/test-identify b/tests/test-identify
--- a/tests/test-identify
+++ b/tests/test-identify
@@ -41,4 +41,67 @@
echo % remote with tags?
hg id -t http://localhost:$HGPORT1/
+hg revert a
+hg branch -q stable
+echo fix1 > b
+hg add b
+hg ci -d '1 0' -mfix1
+hg up -q default
+echo feat1 >> a
+hg ci -d '2 0' -mfeat1
+echo feat2 >> a
+hg ci -d '3 0' -mfeat2
+hg merge -q stable
+hg ci -d '4 0' -mmerge1
+
+hg up -q stable
+hg merge -q default
+hg ci -d '5 0' -mmergeback
+
+echo fix2 >> b
+hg ci -d '6 0' -m fix2
+echo fix3 >> b
+hg ci -d '7 0' -m fix3
+hg up -q default
+echo feat3 >> a
+hg ci -d '8 0' -mfeat3
+hg merge -q stable
+hg ci -d '9 0' -mmerge2
+
+echo % test verbose
+echo "[extensions]" >> $HGRCPATH
+echo "mq =" >> $HGRCPATH
+hg qnew -d '10 0' patch1
+echo c > c
+hg add c
+hg qrefresh -d '10 0'
+hg qnew -d '11 0' patch2
+echo c >> c
+hg qrefresh -d '11 0'
+
+echo % at qtip
+hg id -v
+hg id -v -r 4
+
+echo % tags top and bottom
+hg tag -l -r 9 top
+hg tag -l -r 9 alttop
+hg tag -l -r 0 bottom
+hg id -v
+hg id -v -r 4
+
+echo % nearest tags by date
+hg up 4
+hg tag -l -r 2 exp1
+hg tag -l -r 7 st2
+hg id -v
+
+echo % closer tags by hops after
+hg tag -l -r 1 st1
+hg tag -l -r 8 exp2
+hg id -v
+
+echo % remote verbose
+hg id -v http://localhost:$HGPORT1/
+
true # ends with util.Abort -> returns 255
diff --git a/tests/test-identify.out b/tests/test-identify.out
--- a/tests/test-identify.out
+++ b/tests/test-identify.out
@@ -23,3 +23,26 @@
cb9a9f314b8b
% remote with tags?
abort: can't query remote revision number, branch, or tags
+created new head
+created new head
+% test verbose
+% at qtip
+04b2329333f9 qtip/patch2/tip
+7fe7ca622a6b
+% tags top and bottom
+04b2329333f9 qtip/tip/patch2
+based on alttop/top(-2)
+7fe7ca622a6b
+based on bottom(-3)
+fixed in alttop/top(+4)
+% nearest tags by date
+2 files updated, 0 files merged, 1 files removed, 0 files unresolved
+7fe7ca622a6b
+based on exp1(-2)
+fixed in st2(+3)
+% closer tags by hops after
+7fe7ca622a6b
+based on exp1(-2) st1(-1)
+fixed in st2(+3) exp2(+1)
+% remote verbose
+abort: can't query remote revision number, branch, or tags
diff --git a/tests/test-tags b/tests/test-tags
--- a/tests/test-tags
+++ b/tests/test-tags
@@ -24,7 +24,6 @@
hg identify
hg co first
hg id
-hg -v id
hg status
echo 1 > b
hg add b
diff --git a/tests/test-tags.out b/tests/test-tags.out
--- a/tests/test-tags.out
+++ b/tests/test-tags.out
@@ -11,7 +11,6 @@
8a3ca90d111d+ tip
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
0acdaf898367+ first
-0acdaf898367+ first
M a
created new head
8216907a933d tip
More information about the Mercurial-devel
mailing list