Enriching a file log by branches, tags and bookmarks

Simon King simon at simonking.org.uk
Tue Apr 7 19:01:09 CDT 2015


> On 8 Apr 2015, at 00:25, Simon King <simon at simonking.org.uk> wrote:
> 
> 
>> On 7 Apr 2015, at 14:55, Marc Strapetz <marc.strapetz at syntevo.com> wrote:
>> 
>> I'm taking this thread from the main list to the developers list:
>> 
>> I'm looking for a way to enrich a file log (or sub-tree log) by branches, tags and bookmarks: every such "tag" should be displayed at the "closest" commit of the file log, i.e. at that commit which contains the file in identical state (content).
>> 
>> Here is an example of how this should look like for setup.py of the Mercurial repository (note that this repository is quite outdated, so most recent tags do not show up):
>> 
>> http://i.imgur.com/AYt885I.png
>> 
>> Using a loop of revset queries gives me the information I'm looking for, but is too inefficient (pseudo-code):
>> 
>> $ for all $X in tags(): hg log -r "max(ancestors(tagged(X)) and
>> file(setup.py))" -T "$X {rev}\n"
>> 
>> For this approach, e.g. ancestors() as well as file(setup.py) is run for every tag (N times), while I'm having in mind a solution which would traverse the commit hierarchy only once or twice, possibly increasing memory usage by O(N) for the sake of constant running time. (Is that reasonable for large repositories, like for the CPython repository?)
>> 
>> Unfortunately my Python and Mercurial knowledge are quite limited and hence I'm looking here for someone who is able to write an extension to solve this problem on a work-for-hire basis.
>> 
>> -Marc
>> 
>> 
> 
> 
> Below is an extension that horribly abuses revsets to do something like what you are asking for. I’ve only tested it with hg 3.2.3. I hope that with the lazy revset functions in recent versions of mercurial it is fairly efficient. In particular, that iterating over "sort(::n, -rev)” is an efficient way to travel down the ancestry for a revision.
> 
> It’s a horrible abuse because there’s a revset function that doesn’t actually do any filtering or searching. Instead, it loads the tags from the repository, then looks through the revisions passed to it to find the last ancestor of each tagged revision. I called it “pushtags” because it pushes the tags down to the revision that is going to appear in the output, but this is an awful name because “push” normally means something very different in mercurial.
> 
> Once the pushtags revset function has done its work, you can extract the results using the “pushedtags” template function. Here’s some example usage:
> 
> $: hg log -r 'pushtags(file("setup.py"))' --template '{pad(rev, 8)} {pushedtags}\n' -l 12
> 0        0.4c
> 16       0.4d
> 63       0.4e 0.4f
> 67
> 72
> 152
> 155
> 157
> 188      0.5
> 193      0.5b
> 218
> 240
> 
> $: hg log -G -r 'pushtags(file("mercurial/util.py"))' --template '{pad(rev, 8)} {pushedtags}\n' -l 12
> o    24605    tip
> |\
> | o  24439
> |/|
> | o  24236
> |/|
> | o    24188
> |/|\
> o---+  24164    3.3.2 3.3.3
> / /
> | o  24155    3.3.1
> |/
> o  23917    3.3-rc 3.3
> |
> o  23899
> |
> o  23864
> |
> o  23832
> |
> o  23789
> |
> o  23543
> |
> 

Actually, on further testing I see this is buggy. I was trying to reproduce your screenshot but it is putting the 2.5-related tags on the same revision as the 2.4 ones.

o    18900
|\
| \
| |\
| | \
| | |\
| | | \
| | | |\
+-+-+---o  18866 2.5.4
| | | |/
| | | o  18755 2.5.3
| | | |
+-+---o  18754
| | |/
+---o  17926
| |/
| o    17732 2.4-rc 2.4 2.4.1 2.4.2 2.5-rc 2.5 2.5.1 2.5.2


I can’t look into it any more right now, but I suspect it is related to the order in which revisions are traversed when a changeset has more than one parent.

Sorry,

Simon


More information about the Mercurial-devel mailing list