Patchwork templates: add built-in fileset() function

login
register
mail settings
Submitter Hannes Oldenburg
Date Sept. 20, 2016, 3:57 p.m.
Message ID <cf2156395bff0e3fc4a6.1474387061@localhost.localdomain>
Download mbox | patch
Permalink /patch/16684/
State Changes Requested
Headers show

Comments

Hannes Oldenburg - Sept. 20, 2016, 3:57 p.m.
# HG changeset patch
# User Hannes Oldenburg <hannes.christian.oldenburg@gmail.com>
# Date 1474379333 0
#      Tue Sep 20 13:48:53 2016 +0000
# Node ID cf2156395bff0e3fc4a6604b8aa45b5b7829ba98
# Parent  285a8c3e53f2183438f0cdbc238e4ab851d0d110
templates: add built-in fileset() function

We already support multiple primitive for listing files, which were
affected by the current changeset.
This patch adds fileset() which runs a fileset query with the current
changeset.
Katsunori FUJIWARA - Sept. 21, 2016, 10:59 a.m.
At Tue, 20 Sep 2016 15:57:41 +0000,
Hannes Oldenburg wrote:
> 
> # HG changeset patch
> # User Hannes Oldenburg <hannes.christian.oldenburg@gmail.com>
> # Date 1474379333 0
> #      Tue Sep 20 13:48:53 2016 +0000
> # Node ID cf2156395bff0e3fc4a6604b8aa45b5b7829ba98
> # Parent  285a8c3e53f2183438f0cdbc238e4ab851d0d110
> templates: add built-in fileset() function
> 
> We already support multiple primitive for listing files, which were
> affected by the current changeset.
> This patch adds fileset() which runs a fileset query with the current
> changeset.
> 
> diff -r 285a8c3e53f2 -r cf2156395bff mercurial/help/templates.txt
> --- a/mercurial/help/templates.txt	Tue May 03 13:36:12 2016 +0900
> +++ b/mercurial/help/templates.txt	Tue Sep 20 13:48:53 2016 +0000
> @@ -95,6 +95,10 @@
>  
>     $ hg log -r 0 --template "files: {join(files, ', ')}\n"
>  
> +- Join the list of files with .py ending Filesets
> +
> +   $ hg log -r 0 --template "pythonfiles: {join(fileset('**.py'), ', ')}\n"
> +
>  - Separate non-empty arguments by a " "::
>  
>     $ hg log -r 0 --template "{separate(' ', node, bookmarks, tags}\n"
> diff -r 285a8c3e53f2 -r cf2156395bff mercurial/templater.py
> --- a/mercurial/templater.py	Tue May 03 13:36:12 2016 +0900
> +++ b/mercurial/templater.py	Tue Sep 20 13:48:53 2016 +0000
> @@ -699,6 +699,24 @@
>          tzoffset = util.makedate()[1]
>      return (date[0], tzoffset)
>  
> +@templatefunc('fileset(query)')
> +def fileset(context, mapping, args):
> +    """Execute a fileset set query with the current changeset. See
> +    :hg:`help fileset`."""
> +    if not len(args) == 1:
> +        # i18n: "revset" is a keyword

nitpicking: "fileset" is a keyword

> +        raise error.ParseError(_("fileset expects no arguments"))
> +
> +    raw = evalstring(context, mapping, args[0])
> +    ctx = mapping['ctx']
> +    filesetcache = mapping['cache'].setdefault("filesetcache", {})
> +    if raw in filesetcache:
> +        files  = filesetcache[raw]
> +    else:
> +        files = ctx.getfileset(raw)
> +        filesetcache[raw] = files

fileset query should be evaluated for each templated changesets, but
mapping['cache'] is shared between those changesets.

Therefore, fileset() template function returns unexpected result for
the second or later changesets in templating.

IMHO, 'revcache' instead of 'cache' seems appropriate for this
purpose.

> +    return templatekw.showlist("file", files, **mapping)
> +
>  @templatefunc('revset(query[, formatargs...])')
>  def revset(context, mapping, args):
>      """Execute a revision set query. See
> diff -r 285a8c3e53f2 -r cf2156395bff tests/test-command-template.t
> --- a/tests/test-command-template.t	Tue May 03 13:36:12 2016 +0900
> +++ b/tests/test-command-template.t	Tue Sep 20 13:48:53 2016 +0000
> @@ -3501,6 +3501,12 @@
>    5:13207e5a10d9fd28ec424934298e176197f2c67f,
>    4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
>  
> +Test fileset function
> +
> +  $ hg log -r 0 -T "{rev}\n{join(fileset('*'), '\n')}\n"
> +  0
> +  a

Applying fileset query on all templated changesets is useful to detect
unintentional behavior described before.

For example, if template "{rev}\n{join(fileset('*'), '\n')}\n" is
applied in this test context, expected result is:

   2
   a
   aa
   b
   1
   a
   0
   a

but sharing the result of fileset query between changesets causes:

   2
   a
   aa
   b
   1
   a
   aa
   b
   0
   a
   aa
   b

>  Test active bookmark templating
>  
>    $ hg book foo
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy@lares.dti.ne.jp
Yuya Nishihara - Sept. 21, 2016, 2:08 p.m.
On Wed, 21 Sep 2016 19:59:45 +0900, FUJIWARA Katsunori wrote:
> At Tue, 20 Sep 2016 15:57:41 +0000,
> Hannes Oldenburg wrote:
> > # HG changeset patch
> > # User Hannes Oldenburg <hannes.christian.oldenburg@gmail.com>
> > # Date 1474379333 0
> > #      Tue Sep 20 13:48:53 2016 +0000
> > # Node ID cf2156395bff0e3fc4a6604b8aa45b5b7829ba98
> > # Parent  285a8c3e53f2183438f0cdbc238e4ab851d0d110
> > templates: add built-in fileset() function

> > +@templatefunc('fileset(query)')
> > +def fileset(context, mapping, args):
> > +    """Execute a fileset set query with the current changeset. See
> > +    :hg:`help fileset`."""
> > +    if not len(args) == 1:
> > +        # i18n: "revset" is a keyword
> 
> nitpicking: "fileset" is a keyword
> 
> > +        raise error.ParseError(_("fileset expects no arguments"))
> > +
> > +    raw = evalstring(context, mapping, args[0])
> > +    ctx = mapping['ctx']
> > +    filesetcache = mapping['cache'].setdefault("filesetcache", {})
> > +    if raw in filesetcache:
> > +        files  = filesetcache[raw]
> > +    else:
> > +        files = ctx.getfileset(raw)

Unlike revset, fileset is a low-level function behind matcher and enabled
by 'set:' prefix. I think this function should use ctx.match() (i.e. glob
pattern by default), and be named as 'files(pattern)'.

> > +        filesetcache[raw] = files
> 
> fileset query should be evaluated for each templated changesets, but
> mapping['cache'] is shared between those changesets.
> 
> Therefore, fileset() template function returns unexpected result for
> the second or later changesets in templating.
> 
> IMHO, 'revcache' instead of 'cache' seems appropriate for this
> purpose.

or simply go without cache. I don't think the cached data would be reused in
most cases.

Patch

diff -r 285a8c3e53f2 -r cf2156395bff mercurial/help/templates.txt
--- a/mercurial/help/templates.txt	Tue May 03 13:36:12 2016 +0900
+++ b/mercurial/help/templates.txt	Tue Sep 20 13:48:53 2016 +0000
@@ -95,6 +95,10 @@ 
 
    $ hg log -r 0 --template "files: {join(files, ', ')}\n"
 
+- Join the list of files with .py ending Filesets
+
+   $ hg log -r 0 --template "pythonfiles: {join(fileset('**.py'), ', ')}\n"
+
 - Separate non-empty arguments by a " "::
 
    $ hg log -r 0 --template "{separate(' ', node, bookmarks, tags}\n"
diff -r 285a8c3e53f2 -r cf2156395bff mercurial/templater.py
--- a/mercurial/templater.py	Tue May 03 13:36:12 2016 +0900
+++ b/mercurial/templater.py	Tue Sep 20 13:48:53 2016 +0000
@@ -699,6 +699,24 @@ 
         tzoffset = util.makedate()[1]
     return (date[0], tzoffset)
 
+@templatefunc('fileset(query)')
+def fileset(context, mapping, args):
+    """Execute a fileset set query with the current changeset. See
+    :hg:`help fileset`."""
+    if not len(args) == 1:
+        # i18n: "revset" is a keyword
+        raise error.ParseError(_("fileset expects no arguments"))
+
+    raw = evalstring(context, mapping, args[0])
+    ctx = mapping['ctx']
+    filesetcache = mapping['cache'].setdefault("filesetcache", {})
+    if raw in filesetcache:
+        files  = filesetcache[raw]
+    else:
+        files = ctx.getfileset(raw)
+        filesetcache[raw] = files
+    return templatekw.showlist("file", files, **mapping)
+
 @templatefunc('revset(query[, formatargs...])')
 def revset(context, mapping, args):
     """Execute a revision set query. See
diff -r 285a8c3e53f2 -r cf2156395bff tests/test-command-template.t
--- a/tests/test-command-template.t	Tue May 03 13:36:12 2016 +0900
+++ b/tests/test-command-template.t	Tue Sep 20 13:48:53 2016 +0000
@@ -3501,6 +3501,12 @@ 
   5:13207e5a10d9fd28ec424934298e176197f2c67f,
   4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
 
+Test fileset function
+
+  $ hg log -r 0 -T "{rev}\n{join(fileset('*'), '\n')}\n"
+  0
+  a
+
 Test active bookmark templating
 
   $ hg book foo