[PATCH 0 of 2] Show nearest tag in templates and identify command

Gilles Moris gilles.moris at free.fr
Tue Feb 10 21:52:15 UTC 2009


Second draft.
Previous reference: http://www.selenic.com/pipermail/mercurial-devel/2009-February/010180.html

PATCH 1:

# why we need this patch
The first patch is for package builders, for them to create a build label. The patch gives new template keywords to refer to the last tag on which the given changeset is based on.
Example:
% hg log -r  --template '{basetag}.{nancestors}-{node|short}\n'
1.1.2.7720-b6c2cb40e664

# how you've implemented it
Add several template keywords that refers to the first ancestor that contains a tag. Ancestors are searched by date so that the latest comes first.
The added keyword are '{basetag}' which is the first tag found, and '{basedistance}' the number of change up to that tag. When several path are possible the longuest one is selected.
These new template keywords have been implemented as generators to defer the search only when needed.
Additionally, the '{nancestors}' return the number of ancestors of the current changeset.

# what file formats and data structures you've used
I tried to use only context classes to limit the dependancy with revlog.
I have also used the heapq structure (present since python 2.3 for fast sort of dates on the fly.

# what choices you've made
I have supposed that the nightly package builder wants the best/nearest tag, whatever it is. Moreover, I have supposed that he probably have a mq series of patches on top.
So I have made the choices:
- return only the first tag found, whatever it is
- skip the dynamical tags 'tip' and all the mq tags

# why the choices you've made are the right ones
The code change is minimal and straightforward to use once you know the keywords.

# why the choices you didn't make are the wrong ones
If the current changeset is based on the merge of a stable branch and an experimental branch, and on each of them there is a tag, then the nearest tag could be either the one from the experimental or the one from the stable branch. To avoid to do that choice, I have first implemented a plural template keyword that is returning all the tags found on all the branch. This leads to several problem:
- complexity to handle and choose one amonst them
- more difficult to customize, as we need template style file, AFAIK
- less straightforward implementation

# what shortcomings exist
I have made it ignore mq tags but I guess that many other extensions are also generating dynamic tags, and I don't know how to handle that cleanly. As far I understand, contexts include all tags including the one from extensions.

# what compatibility issues exist
-

# what's missing, if anything
Do I need to do the same when searching tags forward ? It would be trivial.
Then of course tests, and documentation of the new keywords.


PATCH 2:

# why we need this patch
I persist to think that we miss a way to locate synthetically a changeset, that is on which tags it is based on, and in which tags it is included.
Currently, there is no easy way to access this information. hg view/hgk leaves you in a maze. The previous patch can start to give an answer, but it requires the user to remember template syntax.

# how you've implemented it
I have finally used the standard verbose flag on the identify command to print additional information from tags around the changeset. Each printed tag is followed by +/- the distance to the tag.
Example:
% hg id -vr 7000
af694c6a888c
based on 1.0.2+20
fixed in 1.1-392

# what file formats and data structures you've used
I have reused the same function than the previous patch to search for nearest tags. I have located this function in cmdutil for several reasons:
- some similar functions like walkchange revs are already there
- templates which also make use of the function is also in cmdutil
- I had no feedback where it should go otherwise

# what choices you've made
To answer (I hope) Dirkjan's comment about to much complexity:
- I used the verbose flag of the id command instead of custom options
- I decided to create additional lines of output when this flag is set. This also help splitting what pertains to the changeset on the first line, from the nearest tags on the 2 other lines.
- to reduce the number of tags found I have obliterated all ancestors (resp. descendants) of the found tags; previously, I was just interrupting the search on the branch a tag was found. But ancestor (resp. descendants) tags could still be raised if other paths lead to it. This was the case for mercurial where the crew repo is never tagged, so that I was always finding a way through this branch. The new implementation should reduce the number of displayed tag (always one for mercurial) and better match user's expectations.

# why the choices you've made are the right ones
That's the less invasive way to implement it I have found so far in term of code and API change. The verbose flag was not used so far for the id command.

# why the choices you didn't make are the wrong ones
Some of the alternatives:
- use a specific 'identify' command option, like --locate, instead of verbose. I like also this one as it it is more explicit. As I was not sure of the naming, I stick to -v.
- use 2 different flags for "based on" and "fixed in". Additional complexity, but can help reducing the computation time if you're interested only in one of the two lines. I have worked on the performance side so that the time to get that information will be below 10 secs, even with 100k revision (fast C2D E8400 though)
- plug to another command like 'hg tags --nearest <rev>', but it would considerably change the initial intended use of the command.

# what shortcomings exist
The computation time depends on the density of tags. I have also to work around the fact that ctx.children() is about 2 orders of magnitude slower the ctx.parents(), so that I had to implement a children cache in my search function. See previous patch code.

# what compatibility issues exist
Using hg id -v breaks 2 tests (test-archive test-tags) for which the verbose flag is already used, even though it has no effect right now.

# what's missing, if anything
Tests and docs.


2 files changed, 112 insertions(+), 1 deletion(-)
mercurial/cmdutil.py  |   97 ++++++++++++++++++++++++++++++++++++++++++++++++-
mercurial/commands.py |   16 ++++++++


More information about the Mercurial-devel mailing list