Versioning builds from repos

Gilles Moris gilles.moris at free.fr
Wed Jul 8 16:34:01 CDT 2009


On Thu June 25 2009 00:59:30 Mads Kiilerich wrote:
> Something like the "nearest" extension could perhaps be useful. Longest 
> distance to an official tag seems to be a good measure. Perhaps that 
> extension could be distributed with Mercurial and used, or a lightweight 
> version could be built in?
> 
> Obviously any good technical method would have to adjust or be adjusted 
> to conventions for how tags are used and how releases are made.
> 
> I think it would be nice if both the rpm version and the version 
> reported by hg could be something like "1.2.1-917-f0a7accf1d68".
> 
> Do you have any thoughts or comments about this?
> 

I worked back on a patch using templates, which the crew seems looking for.
So to get what you want with my patch, you would do:
hg parent --template '{basedontags|stringify|strip}-{node|short}\n'

Note that the template is actually returning a list. This is the case for
that configuration:

o-o-a-o-x
\       /
 \o-b-o/

If a and b are tags, then I return both tags for x, because I consider x
as based on the two branches. I am pretty sure it does not happen for
mercurial given the tagging strategy, but it can happen on other projects.
In this case, we need also the 'first' template filter from Paolo Bonzini:
http://www.selenic.com/pipermail/mercurial-devel/2009-June/013329.html

I changed my implementation to be constant time whatever the number of
changesets looked up. This is not necessary for this workflow but necessary
if somebody has the idea to use it with hg log on the whole repo.

Comments before I continue to work on that ?


# HG changeset patch
# User Gilles Moris <gilles.moris at free.fr>
# Date 1247087563 -7200
# Node ID 84d8e4818c6038a07eba9db660ead8983a91556c
# Parent  de29540d44ecce9a13df9c3bf1a3c93d30dc6c20
templates: add a {basedontags}

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -735,11 +735,13 @@
     def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
         changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
         formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
+        self.basedonmap = None
         self.t = templater.templater(mapfile, {'formatnode': formatnode},
                                      cache={
                                          'parent': '{rev}:{node|formatnode} ',
                                          'manifest': '{rev}:{node|formatnode}',
-                                         'filecopy': '{name} ({source})'})
+                                         'filecopy': '{name} ({source})',
+                                         'basedontag': '{basetag}+{basedistance} '})
 
     def use_template(self, t):
         '''set template string to use'''
@@ -874,6 +876,42 @@
                 removes += i[2]
             return '%s: +%s/-%s' % (files, adds, removes)
 
+        def computebasedon():
+            bmap = [{}] * len(self.repo)
+            deps = {}
+
+            for r in xrange(len(self.repo)):
+                ctx = self.repo[r]
+
+                # get longuest path to changeset with tags
+                bmap[r] = {}
+                for p in ctx.parents():
+                    for tr, td in bmap[p.rev()].iteritems():
+                        if tr not in bmap[r] or td + 1 > bmap[r][tr]:
+                            bmap[r][tr] = td + 1
+
+                # filter out descendant
+                for rr in bmap[r].keys():
+                    for dr in deps[rr]:
+                        if dr in bmap[r].keys():
+                            del bmap[r][dr]
+
+                if ctx.tags() and ctx.rev() != len(self.repo) - 1:
+                    # if some tags found, record their descendant
+                    deps[r] = list(bmap[r].keys())
+                    bmap[r] = {r: 0}
+
+            return bmap
+
+        def showbasedontags(**args):
+            if not self.basedonmap:
+                self.basedonmap = computebasedon()
+            bot = [ (str(td), '='.join(self.repo[tr].tags()))
+                    for tr, td in self.basedonmap[ctx.rev()].iteritems() ]
+            bot.sort()
+            bot = [ { 'basedistance': td, 'basetag': tr } for td, tr in bot ]
+            return showlist('basedontag', bot, **args)
+
         defprops = {
             'author': ctx.user(),
             'branches': showbranches,
@@ -891,6 +929,7 @@
             'tags': showtags,
             'extras': showextras,
             'diffstat': showdiffstat,
+            'basedontags': showbasedontags,
             }
         props = props.copy()
         props.update(defprops)




More information about the Mercurial-devel mailing list