Patchwork [2,of,3,V2] template: add revset() template function

login
register
mail settings
Submitter Durham Goode
Date Feb. 14, 2014, 8:23 p.m.
Message ID <c30dc74862faaf6e4a5a.1392409436@dev010.prn1.facebook.com>
Download mbox | patch
Permalink /patch/3660/
State Accepted
Commit cda9d2b6beabffca30efb9c70dad418239da9c52
Headers show

Comments

Durham Goode - Feb. 14, 2014, 8:23 p.m.
# HG changeset patch
# User Durham Goode <durham@fb.com>
# Date 1392181452 28800
#      Tue Feb 11 21:04:12 2014 -0800
# Node ID c30dc74862faaf6e4a5a701799506b4dcfe0697b
# Parent  b796fd0082a7712047f99324ef4b8b5df8843f2e
template: add revset() template function

Adds a template function that executes a revset and returns the list of
revisions as the result. It has the signature 'revset(query [, args...])'. The
args are optional and are applied to the query string using the standard
python string.format(args) pattern. This allows things like:
'{revset("parents({0})", rev)}' to produce the parents of each individual
commit in the log output.  If no args are specified, the revset result is
cached for the duration of the templater; so it's better to not use args if
performance is a concern.

By itself, revset() can be used to print commit parents, print the common
ancestor of a commit with the main branch, etc.

It can be used with the ifcontains() function to do things like
'{ifcontains(rev, revset('.'), label(...), ...)}' to color the working copy
parent, to color certain branches, to color draft commits, etc.

Patch

diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -7,7 +7,7 @@ 
 
 from i18n import _
 import sys, os, re
-import util, config, templatefilters, parser, error
+import util, config, templatefilters, templatekw, parser, error
 import types
 import minirst
 
@@ -356,6 +356,32 @@ 
     # ignore args[0] (the label string) since this is supposed to be a a no-op
     yield _evalifliteral(args[1], context, mapping)
 
+def revset(context, mapping, args):
+    """usage: revset(query[, formatargs...])
+    """
+    if not len(args) > 0:
+        # i18n: "revset" is a keyword
+        raise error.ParseError(_("revset expects one or more arguments"))
+
+    raw = args[0][1]
+    ctx = mapping['ctx']
+    repo = ctx._repo
+
+    if len(args) > 1:
+        formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
+        revs = repo.revs(raw, *formatargs)
+        revs = list([str(r) for r in revs])
+    else:
+        revsetcache = mapping['cache'].setdefault("revsetcache", {})
+        if raw in revsetcache:
+            revs = revsetcache[raw]
+        else:
+            revs = repo.revs(raw)
+            revs = list([str(r) for r in revs])
+            revsetcache[raw] = revs
+
+    return templatekw.showlist("revision", revs, **mapping)
+
 def rstdoc(context, mapping, args):
     if len(args) != 2:
         # i18n: "rstdoc" is a keyword
@@ -454,6 +480,7 @@ 
     "join": join,
     "label": label,
     "pad": pad,
+    "revset": revset,
     "rstdoc": rstdoc,
     "shortest": shortest,
     "strip": strip,
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -1657,3 +1657,22 @@ 
   $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
   1 did not add a
   0 added a
+
+Test revset function
+
+  $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
+  1 current rev
+  0 not current rev
+
+  $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
+  1 Parents: 0
+  0 Parents: 
+
+  $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
+  Rev: 1
+  Ancestor: 0
+  Ancestor: 1
+  
+  Rev: 0
+  Ancestor: 0
+  
diff --git a/tests/test-module-imports.t b/tests/test-module-imports.t
--- a/tests/test-module-imports.t
+++ b/tests/test-module-imports.t
@@ -34,7 +34,7 @@ 
      relative:  discovery, error, hbisect, phases, util
   mercurial/templater.py mixed imports
      stdlib:    parser
-     relative:  config, error, templatefilters, util
+     relative:  config, error, templatefilters, templatekw, util
   mercurial/ui.py mixed imports
      stdlib:    formatter
      relative:  config, error, scmutil, util