[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