[PATCH 1 of 2] Add {basetag} {basedistance} and {nancestors} template keywords
Gilles Moris
gilles.moris at free.fr
Tue Feb 10 15:52:16 CST 2009
1 file changed, 96 insertions(+), 1 deletion(-)
mercurial/cmdutil.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++++-
# HG changeset patch
# User Gilles Moris <gilles.moris at free.fr>
# Date 1234301937 -3600
# Node ID 7ac8dcbc6eeffa86e944ec41a00f8e8fb789e08e
# Parent 16e74cc6ec63a180649b3a1e3a02eb8686b16321
Add {basetag} {basedistance} and {nancestors} template keywords.
This enables to display nearest tag on which a changeset is based on.
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
@@ -822,6 +822,27 @@
node=hex(changes[0])))
return self.t('manifest', **args)
+ def shownancestors(**args):
+ na = 0
+ for c in ctx.ancestors():
+ na += 1
+ yield na
+
+ def getbasetag():
+ if not hasattr(self, 'basetagdistance'):
+ self.basetagdistance = -1
+ for c, d in nearesttagsdateh(self.repo, ctx, fwd=False):
+ self.basetagctx = c
+ self.basetagdistance = d
+ break
+ return self.basetagdistance
+ def showbasetag(**args):
+ if getbasetag() >= 0:
+ yield self.basetagctx.tags()[0]
+ def showbasedistance(**args):
+ if getbasetag() >= 0:
+ yield self.basetagdistance
+
defprops = {
'author': changes[1],
'branches': showbranches,
@@ -838,6 +859,9 @@
'rev': rev,
'tags': showtags,
'extras': showextras,
+ 'nancestors': shownancestors,
+ 'basetag': showbasetag,
+ 'basedistance': showbasedistance,
}
props = props.copy()
props.update(defprops)
@@ -1184,3 +1208,74 @@
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
+ """
+ # initialize the search algorithm depending on the search direction
+ if fwd:
+ excltags = []
+ 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:
+ try:
+ qparent = repo['qparent']
+ qtip = repo['qtip']
+ if qparent.rev() < ctx.rev() and ctx.rev() <= qtip.rev():
+ ctx = qparent
+ excltags = ['qparent']
+ else:
+ excltags = ['tip']
+ except error.RepoError:
+ excltags = ['tip']
+ heuristic = lambda c: - c.date()[0]
+ infants = lambda r: [ p.rev() for p in repo[r].parents() ]
+
+ # 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))
+ 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 ctx, 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
+
More information about the Mercurial-devel
mailing list