Mercurial: determine latest tag on each merged branch

1k views Asked by At

To determine which tags have been merged into a given revision, I use a command like this:

$ hg log --style=xml -r "ancestors(471694254d60) and tag()" | grep "<tag>"
<tag>3.27.0.0</tag>
<tag>3.27.0.1</tag>
<tag>3.27.0.2</tag>
<tag>3.27.0.3</tag>
<tag>3.27.0.4</tag>
<tag>3.27.0.5</tag>
<tag>3.28.0.0</tag>
<tag>3.27.0.6</tag>
<tag>3.28.0.1</tag>
<tag>3.28.0.2</tag>
<tag>3.28.0.3</tag>
<tag>3.29.0.0</tag>
<tag>3.28.0.4</tag>
<tag>3.29.0.1</tag>
<tag>3.29.0.2</tag>
<tag>3.29.0.3</tag>
<tag>3.29.0.4</tag>
<tag>3.29.0.5</tag>
<tag>3.29.0.6</tag>

This is ok, but I'd like to improve it by instead reporting only the latest tag from each branch:

$ hg log --style=xml -r "ancestors(471694254d60) and tag() and <MYSTERY CLAUSE>" | grep "<tag>"
<tag>3.27.0.6</tag>
<tag>3.28.0.4</tag>
<tag>3.29.0.6</tag>

Hopefully the implied branch structure is obvious enough.

Does this seem possible (without using multiple hg commands or filtering the results after-the-fact)?

1

There are 1 answers

0
Lazy Badger On BEST ANSWER

Well, 2 (dirty) solutions

Post-processing style

Slightly changed original command as starting point (another repository was used)

>hg log -r "::. & tag()" --template "{branch} {tags}\n"

(short syntax and templating, static leaf-node for testing). Result isn't OK for post-processing

default 1.0
default 1.0.1
default 1.1
default 1.1.1
default 1.1.2
default 1.2
default 1.2.1
default 1.3
default 1.4
default 1.5
stable 1.5.1
default 1.6
stable 1.6.1

because branch's specific tags are fragmented. Sorting by branch will save internal order of tags inside of every branch

>hg log -r "sort(::. & tag(), branch)" --template "{branch} {tags}\n"
default 1.0
default 1.0.1
default 1.1
default 1.1.1
default 1.1.2
default 1.2
default 1.2.1
default 1.3
default 1.4
default 1.5
default 1.6
stable 1.5.1
stable 1.6.1

Output only last record for every branch (+ last string in list) is easy task in any language.

In order to convert hg log | <command> ingot into usable solution, next modifications are applied

ltb = hg log -r "sort(::$1 & tag(), branch)" --template "{branch} {tags}\n"

(and hg ltb 471694254d60 | <command> in shell will produce result)

  • For beautification and shortening full piped command may be additionally converted into shell-alias and ltb becomes

ltb = !$HG log -r "sort(::$1 & tag(), branch)" --template "{branch} {tags}\n" | <command>

(used now as just hg ltb 471694254d60)

Pre-processing style

"Last tagged changeset in branch" in revset's lingo will be (for you case) last(::REV & tag() & branch(BRANCH)), repeated for every branch or

(last(::REV & tag() & branch(BRANCH1))) | (last(::REV & tag() & branch(BRANCH2)) | ... | (last(::REV & tag() & branch(BRANCHN))

in single giant command. Main problem is to list all needed branches for command(s), because you haven't predefined list.

You can

  • Get list of branches (repository-wide)

Easiest way is hg branches

>hg branches
default                     1196:878372849175
stable                      1179:e4b737479302 (inactive)

and insert all branch-names (first field) into log by hand (hg log -r "last(::471694254d60 & tag() & branch(default))" > log.txt + hg log -r "last(::471694254d60 & tag() & branch(stable))" >> log.txt for my repo and your changeset)

  • Get pure branch-list (hg branch again) and pipe it to xargs, which executes hg log for single branch, something like (NOT TESTED!!)

hg branches | gawk {print $1} | \ xargs -I BRANCH hg log -r "last(::471694254d60 & tag() & branch(BRANCH))" --template "{branch} {tags}\n"

(after debugging also can be converted into shell-alias)