[PATCH] templates: add {lasttag} and {lasttagdistance} keywords
Gilles Moris
gilles.moris at free.fr
Tue Jul 21 15:51:48 CDT 2009
On Wed July 15 2009 03:02:33 Mads Kiilerich wrote:
> For revisions without any tagged ancestors I would rather have the
> distance to the first revision than nothing. Using the "null" revision
> would be an obvious choice:
>
> defvalue = 0, 'null', 0
OK, I just put some parenthesis around null to show it is not an actual tag.
>
> > + ltmap = [defvalue] * len(self.repo)
> > +
> > + for r in range(len(self.repo)):
> > + ctx = self.repo[r]
> > +
> > + tags = [t for t in ctx.tags() if self.repo.tagtype(t) == 'global']
> > + if tags:
> > + ltmap[r] = ctx.date(), tags[0], 0
> >
>
> Is the ordering of multiple tags for a revision well-defined? Is it a
> good choice to use the first?
>
> Perhaps
> '-'.join(sorted(tags))
Actually, this is probably more a theoretical question, as I doubt that many
repo with a double global tag exist. I have used the '=' sign to join and show
this is the same rev: '='.join(sorted(tags))
Note however that this tag list is created once, and the distance is just
incremented after. it is only in case of a merge that the same rev can join
with different distances. So it works even with a random ordering.
>
> > + else:
> > + # trick: use tuple comparison to sort by latest date first
> > + # and if the dates (and by construction also the tag) are
> > + # equal, by longuest path.
> >
>
> I think it is fine to be clever. If it so clever that we have to explain
> it then it is less fine. (Not that I am against comments!) But if it is
> so dirty that we call it a trick then we shouldn't use it.
>
> It took me some time to understand the comment. Especially the use of
> "sort" and "by construction" and that it referred to the _tag_ date
> tricked me.
>
> Perhaps
> # the last tag of this rev comes from the parent with
> the latest
> # tag (secondarily the alphabetically latest tag name
> and the
> # longest distance to the tag), achieved by comparing
> the tuples.
>
It is not a totally obscure feature of Python. I remember reading that from
the Python Doc somewhere. However, the comment was possibly confusing so I
restate it following your directions to:
# the last tag of this rev comes from the ancestor with the
# latest tag (secondarily the longest distance to the tag),
# achieved by comparing the tuples.
I will also set the second tuple element to the distance to be even clearer.
> > + lasttag = reduce(max,
> > + [ltmap[p.rev()] for p in ctx.parents()],
> > + defvalue)
> >
>
> This looks unnecessary clever and hard to read. Especially because there
> always are 1 or 2 parents.
>
> And be aware that p.rev() will be -1 for "null" and it will thus look at
> the wrong place in ltmap. It works anyway, but if it is intentional then
> it deserves a comment.
>
> So the same can be achieved with
> ldate, ltag, ldist = max(ltmap[p.rev()] for p in
> ctx.parents())
>
>
> Or slightly more verbose, but without wrong indexing and without relying
> on initialization of ltmap:
> ldate, ltag, ldist = max(
> p.rev() >= 0 and ltmap[p.rev()] or (0, 'null', 0)
> for p in ctx.parents())
>
Well OK, I sometime like to experiment languages possibilities. I agree yours
is clearer.
> > + ldate, ltag, ldist = lasttag
> > + # if no previous tag, nothing to do (leave default value)
> >
> > + if ltag:
> >
>
> Why shouldn't we give useful distances for revisions which just happens
> to not have other tags to count from than "null"? However, with "null"
> as default value as suggested above this is redundant.
>
OK, changed for (null) as default value.
> > + ltmap[r] = ldate, ltag, ldist + 1
> > +
> > + return ltmap
> > +
> > def use_template(self, t):
> > '''set template string to use'''
> > self.t.cache['changeset'] = t
> > @@ -874,6 +903,15 @@
> > removes += i[2]
> > return '%s: +%s/-%s' % (files, adds, removes)
> >
> > + def showlasttag(**args):
> > + return self.lasttagmap[ctx.rev()][1]
> > + def showlasttagdistance(**args):
> > + dist = self.lasttagmap[ctx.rev()][2]
> > + if dist>= 0:
> > + return str(dist)
> > + else:
> > + return ""
> >
>
> As discussed above I would rather always have the distance.
>
> Or actually ... for some uses it would be nice to have a simple template
> which gives "1.3" instead of "1.3-0" or "1.3-" - but it should still
> give for example "1.3-117".
>
> Perhaps a {lasttaganddistance} would be useful too?
>
Personally I prefer it with a '+' to show that it's after the tag.
So I think it's better to stay like that and let the people choose their
format.
> > +
> > defprops = {
> > 'author': ctx.user(),
> > 'branches': showbranches,
> > @@ -891,6 +929,8 @@
> > 'tags': showtags,
> > 'extras': showextras,
> > 'diffstat': showdiffstat,
> > + 'lasttag': showlasttag,
> > + 'lasttagdistance': showlasttagdistance,
> > }
> > props = props.copy()
> > props.update(defprops)
> > diff --git a/mercurial/help.py b/mercurial/help.py
> > --- a/mercurial/help.py
> > +++ b/mercurial/help.py
> > @@ -369,6 +369,9 @@
> > - file_adds: List of strings. Files added by this changeset.
> > - file_mods: List of strings. Files modified by this changeset.
> > - file_dels: List of strings. Files removed by this changeset.
> > + - lasttag: String. Most recent global tag in the ancestors of this
> > + changeset.
> > + - lasttagdistance: String. Longuest path to the last tag.
Now, it will just be an Integer, as I do not need it to be empty.
> > - node: String. The changeset identification hash, as a 40-character
> > hexadecimal string.
> > - parents: List of strings. The parents of the changeset.
> > diff --git a/tests/test-log b/tests/test-log
> > --- a/tests/test-log
> > +++ b/tests/test-log
> >
>
> Do this test really belong in the test of "log"? Wouldn't it be more
> natural in test-command-template ?
>
I didn't saw that most keyword were tested there at first. Changed.
Thx for your input.
Gilles.
More information about the Mercurial-devel
mailing list