3

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
    Instead of using style and grepping output you can use template, which output only needed data (tag-name in your case) `hg log --template "{tags}\n" -r "$REVSET"` – Lazy Badger May 26 '14 at 19:10
  • Do you know full list of branches before building command or it have to be dynamically created? – Lazy Badger May 26 '14 at 19:31
  • @LazyBadger Yeah, this command was lifted from a larger program which uses the XML output. The grep is incidental (I didn't want to paste the entire output here). It is not so easy to define the list of branches, since I sometimes have tags on some anonymous branches but not others, in addition to on named branches directly. The definition of "latest tag on each branch" in that sense seems more topological – Robert Q. Oftenwrong May 27 '14 at 14:35
  • Well, will be `command | xargs` or `hg log | gawk` pipes acceptable for you (without pre-known list of branches single `hg log` isn't possible, AFAICS) – Lazy Badger May 27 '14 at 15:51
  • I already do something conceptually similar (post-process/filter the log entries in code), although this post-processing only infers the concept of "latest tag" from the tag version number components, and doesn't correctly deal with the real DAG when tags on anonymous branches are involved. To improve on this solution, any post-processing (regardless of how implemented, using the shell and its utilities, in code, or in some other way) would have to demonstrate additional DAG awareness. – Robert Q. Oftenwrong May 27 '14 at 18:27

1 Answers1

1

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)

Lazy Badger
  • 94,711
  • 9
  • 78
  • 110