Versioning builds from repos

Dirkjan Ochtman dirkjan at ochtman.nl
Thu Jul 9 15:00:27 CDT 2009


On Wed, Jul 8, 2009 at 23:34, Gilles Moris<gilles.moris at free.fr> wrote:
> 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)

I still think adding this code in that method as another nested
function is a bad idea. The function is way too cluttered already.
Even doing a separate closure would be better, IMO.

Cheers,

Dirkjan



More information about the Mercurial-devel mailing list