# HG changeset patch # User Matt Harbison # Date 1440387898 14400 # Node ID 43bf9471fae93218bedc97f6fde2bd886fa0def2 # Parent 93c80e7ed8c82c733a121a990bb70291bba797e6 templater: introduce {latesttag()} function to match a pattern (issue4184) This allows the latest class of tag to be found, such as a release candidate or final build, instead of just the absolute latest. It doesn't appear that the existing keyword can be given an optional argument. There is a keyword, function and filter for 'date', so it doesn't seem harmful to introduce a new function with the same name as an existing keyword. Most functions are pretty Mercurial agnostic, but there is {revset()} as precedent. Even though templatekw.getlatesttags() returns a single tuple, one entry of which is a list, it is simplest to present this as a list of tags instead of a single item, with each tag having a distance and change count attribute. It is also closer to how {latesttag} returns a list of tags, and how this function works when not given a '%' operator. diff -r 93c80e7ed8c8 -r 43bf9471fae9 mercurial/help/templates.txt --- a/mercurial/help/templates.txt Mon Aug 24 23:07:00 2015 -0400 +++ b/mercurial/help/templates.txt Sun Aug 23 23:44:58 2015 -0400 @@ -102,6 +102,10 @@ $ hg log --template "{bookmarks % '{bookmark}{ifeq(bookmark, active, '*')} '}\n" +- Find the previous release candidate tag, the distance and changes since the tag:: + + $ hg log -r . --template "{latesttag('re:^.*-rc$') % '{tag}, {changes}, {distance}'}\n" + - Mark the working copy parent with '@':: $ hg log --template "{ifcontains(rev, revset('.'), '@')}\n" diff -r 93c80e7ed8c8 -r 43bf9471fae9 mercurial/templater.py --- a/mercurial/templater.py Mon Aug 24 23:07:00 2015 -0400 +++ b/mercurial/templater.py Sun Aug 23 23:44:58 2015 -0400 @@ -512,6 +512,19 @@ # ignore args[0] (the label string) since this is supposed to be a a no-op yield args[1][0](context, mapping, args[1][1]) +def latesttag(context, mapping, args): + """:latesttag([pattern]): The global tags matching the given pattern on the + most recent globally tagged ancestor of this changeset.""" + if len(args) > 1: + # i18n: "latesttag" is a keyword + raise error.ParseError(_("latesttag expects at most one argument")) + + pattern = None + if len(args) == 1: + pattern = stringify(args[0][0](context, mapping, args[0][1])) + + return templatekw.showlatesttags(pattern, **mapping) + def localdate(context, mapping, args): """:localdate(date[, tz]): Converts a date to the specified timezone. The default is local date.""" @@ -733,6 +746,7 @@ "indent": indent, "join": join, "label": label, + "latesttag": latesttag, "localdate": localdate, "pad": pad, "revset": revset, diff -r 93c80e7ed8c8 -r 43bf9471fae9 tests/test-command-template.t --- a/tests/test-command-template.t Mon Aug 24 23:07:00 2015 -0400 +++ b/tests/test-command-template.t Sun Aug 23 23:44:58 2015 -0400 @@ -2690,6 +2690,19 @@ 1: t1+0 0: null+1 + $ hg log --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n" + 10: t3, C: 8, D: 7 + 9: t3, C: 7, D: 6 + 8: t3, C: 6, D: 5 + 7: t3, C: 5, D: 4 + 6: t3, C: 4, D: 3 + 5: t3, C: 3, D: 2 + 4: t3, C: 1, D: 1 + 3: t3, C: 0, D: 0 + 2: t1, C: 1, D: 1 + 1: t1, C: 0, D: 0 + 0: null, C: 1, D: 1 + $ cd .. diff -r 93c80e7ed8c8 -r 43bf9471fae9 tests/test-tag.t --- a/tests/test-tag.t Mon Aug 24 23:07:00 2015 -0400 +++ b/tests/test-tag.t Sun Aug 23 23:44:58 2015 -0400 @@ -461,6 +461,13 @@ $ hg log -r '.' -T "{latesttag % '{latesttag}\n'}" t4 t6 + $ hg log -r '.' -T "{latesttag('t4') % 'T: {tag}, C: {changes}, D: {distance}\n'}" + T: t4, C: 2, D: 2 + $ hg log -r '.' -T "{latesttag('re:\d') % 'T: {tag}, C: {changes}, D: {distance}\n'}" + T: t4, C: 2, D: 2 + T: t6, C: 2, D: 2 + $ hg log -r . -T '{join(latesttag(), "*")}\n' + t4*t6 $ hg ci -A -m4 adding f4 $ hg log -r 'wdir()' -T "{changessincelatesttag} changes since {latesttag}\n"