Patchwork [8,of,8,V2] fileset: add a 'status(...)' predicate to control evaluation context

login
register
mail settings
Submitter Pierre-Yves David
Date March 6, 2017, 9:36 a.m.
Message ID <41ea8aee85ca16d652df.1488793015@nodosa.octopoid.net>
Download mbox | patch
Permalink /patch/18923/
State Accepted
Headers show

Comments

Pierre-Yves David - March 6, 2017, 9:36 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
# Date 1488546500 -3600
#      Fri Mar 03 14:08:20 2017 +0100
# Node ID 41ea8aee85ca16d652dfdb4afe37053b291702b4
# Parent  9d6e733046b9aa7e2ded8c4207625fedcc2a8c04
# EXP-Topic filesetrev-func
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 41ea8aee85ca
fileset: add a 'status(...)' predicate to control evaluation context

Same as 'revs', this predicate does not select files but switches the evaluation
context. This allow to match file according arbitrary status call. We can now
express the same query as 'hg status'.

The API (two 'revsingle' class) have been picked instead of a single 'revs'
revset for multiple reasons:

 * it is less confusing to express
 * it allow to express more query (eg: backward status, cross branch status)
Yuya Nishihara - March 7, 2017, 2:13 p.m.
On Mon, 06 Mar 2017 10:36:55 +0100, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
> # Date 1488546500 -3600
> #      Fri Mar 03 14:08:20 2017 +0100
> # Node ID 41ea8aee85ca16d652dfdb4afe37053b291702b4
> # Parent  9d6e733046b9aa7e2ded8c4207625fedcc2a8c04
> # EXP-Topic filesetrev-func
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 41ea8aee85ca
> fileset: add a 'status(...)' predicate to control evaluation context

Looks good, thanks. I've marked these as 2nd Review Requested since I was too
involved to this series.

> +@predicate('status(base, rev, pattern)')
> +def status(mctx, x):
> +    """``status(base, rev, revspec)``
> +
> +    Evaluate predicate using status change between ``base`` and
> +    ``rev``. Examples:
> +
> +    - ``status(3, 7, added())`` - matches files added from "3" to "7"
> +    """
> +    repo = mctx.ctx.repo()
> +    # i18n: "status" is a keyword
> +    b, r, x = getargs(x, 3, 3, _("status takes three arguments"))
> +    # i18n: "status" is a keyword
> +    baseerr = _("first argument to status must be a revision")
> +    baserevspec = getstring(b, baseerr)
> +    if not baserevspec:
> +        raise error.ParseError(baseerr)

Nit: need to insert "# i18n: "status" is a keyword" comment here.

> +    reverr = _("second argument to status must be a revision")
> +    revspec = getstring(r, reverr)
> +    if not revspec:
> +        raise error.ParseError(reverr)
> +    basenode, node = scmutil.revpair(repo, [baserevspec, revspec])
> +    basectx = repo[basenode]
> +    ctx = repo[node]
> +    return getset(mctx.switch(ctx, _buildstatus(ctx, x, basectx=basectx)), x)
Augie Fackler - March 7, 2017, 5:22 p.m.
On Mon, Mar 06, 2017 at 10:36:55AM +0100, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
> # Date 1488546500 -3600
> #      Fri Mar 03 14:08:20 2017 +0100
> # Node ID 41ea8aee85ca16d652dfdb4afe37053b291702b4
> # Parent  9d6e733046b9aa7e2ded8c4207625fedcc2a8c04
> # EXP-Topic filesetrev-func
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 41ea8aee85ca
> fileset: add a 'status(...)' predicate to control evaluation context

These are queued, thanks.

Patch

diff --git a/mercurial/fileset.py b/mercurial/fileset.py
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -463,6 +463,32 @@  def revs(mctx, x):
                 result.append(f)
     return result
 
+@predicate('status(base, rev, pattern)')
+def status(mctx, x):
+    """``status(base, rev, revspec)``
+
+    Evaluate predicate using status change between ``base`` and
+    ``rev``. Examples:
+
+    - ``status(3, 7, added())`` - matches files added from "3" to "7"
+    """
+    repo = mctx.ctx.repo()
+    # i18n: "status" is a keyword
+    b, r, x = getargs(x, 3, 3, _("status takes three arguments"))
+    # i18n: "status" is a keyword
+    baseerr = _("first argument to status must be a revision")
+    baserevspec = getstring(b, baseerr)
+    if not baserevspec:
+        raise error.ParseError(baseerr)
+    reverr = _("second argument to status must be a revision")
+    revspec = getstring(r, reverr)
+    if not revspec:
+        raise error.ParseError(reverr)
+    basenode, node = scmutil.revpair(repo, [baserevspec, revspec])
+    basectx = repo[basenode]
+    ctx = repo[node]
+    return getset(mctx.switch(ctx, _buildstatus(ctx, x, basectx=basectx)), x)
+
 @predicate('subrepo([pattern])')
 def subrepo(mctx, x):
     """Subrepositories whose paths match the given pattern.
@@ -538,6 +564,7 @@  class fullmatchctx(matchctx):
 # filesets using matchctx.switch()
 _switchcallers = [
     'revs',
+    'status',
 ]
 
 def _intree(funcs, tree):
diff --git a/tests/test-fileset.t b/tests/test-fileset.t
--- a/tests/test-fileset.t
+++ b/tests/test-fileset.t
@@ -521,3 +521,101 @@  overlapping set
 
   $ fileset "revs('1+2', modified())"
   b2
+
+test 'status(...)'
+=================
+
+Simple case
+-----------
+
+  $ fileset "status(3, 4, added())"
+  .hgsub
+  .hgsubstate
+
+use rev to restrict matched file
+-----------------------------------------
+
+  $ hg status --removed --rev 0 --rev 1
+  R a2
+  $ fileset "status(0, 1, removed())"
+  a2
+  $ fileset "* and status(0, 1, removed())"
+  $ fileset -r 4 "status(0, 1, removed())"
+  a2
+  $ fileset -r 4 "* and status(0, 1, removed())"
+  $ fileset "revs('4', * and status(0, 1, removed()))"
+  $ fileset "revs('0', * and status(0, 1, removed()))"
+  a2
+
+check wdir()
+------------
+
+  $ hg status --removed  --rev 4
+  R con.xml
+  $ fileset "status(4, 'wdir()', removed())"
+  con.xml
+
+  $ hg status --removed --rev 2
+  R a2
+  $ fileset "status('2', 'wdir()', removed())"
+  a2
+
+test backward status
+--------------------
+
+  $ hg status --removed --rev 0 --rev 4
+  R a2
+  $ hg status --added --rev 4 --rev 0
+  A a2
+  $ fileset "status(4, 0, added())"
+  a2
+
+test cross branch status
+------------------------
+
+  $ hg status --added --rev 1 --rev 2
+  A a2
+  $ fileset "status(1, 2, added())"
+  a2
+
+test with multi revs revset
+---------------------------
+  $ hg status --added --rev 0:1 --rev 3:4
+  A .hgsub
+  A .hgsubstate
+  A 1k
+  A 2k
+  A b2link
+  A bin
+  A c1
+  A con.xml
+  $ fileset "status('0:1', '3:4', added())"
+  .hgsub
+  .hgsubstate
+  1k
+  2k
+  b2link
+  bin
+  c1
+  con.xml
+
+tests with empty value
+----------------------
+
+Fully empty revset
+
+  $ fileset "status('', '4', added())"
+  hg: parse error: first argument to status must be a revision
+  [255]
+  $ fileset "status('2', '', added())"
+  hg: parse error: second argument to status must be a revision
+  [255]
+
+Empty revset will error at the revset layer
+
+  $ fileset "status(' ', '4', added())"
+  hg: parse error at 1: not a prefix: end
+  [255]
+  $ fileset "status('2', ' ', added())"
+  hg: parse error at 1: not a prefix: end
+  [255]