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

login
register
mail settings
Submitter Matt Harbison
Date March 4, 2017, 4:35 a.m.
Message ID <op.ywj60qgd9lwrgf@envy>
Download mbox | patch
Permalink /patch/18907/
State Not Applicable
Delegated to: Augie Fackler
Headers show

Comments

Matt Harbison - March 4, 2017, 4:35 a.m.
On Fri, 03 Mar 2017 08:40:45 -0500, Pierre-Yves David  
<pierre-yves.david@ens-lyon.org> 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 3e95bf7ed38189f6f56de89571fffc667280bb56
> # 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  
> 3e95bf7ed381
> fileset: add a 'status(...)' predicate to control evaluation context

This is awesome!  It unlocks the "what merge conflicts might I run into?"  
pre update/rebase test that I mentioned last week.  I did a test to see if  
the files listed for the 13bbcd56c57a merge agreed with TortoiseHg:

$ ../hg files --rev 'ancestor(6483e49204ee, a91c62752d08)'  
"set:status('ancestor(6483e49204ee, a91c62752d08)', 6483e49204ee,  
added()+modified()+removed()) & status('ancestor(6483e49204ee,  
a91c62752d08)', a91c62752d08, added()+modified()+removed())"
..\mercurial\ui.py
..\mercurial\worker.py

It does, but that's quite a mouthful.  Granted, doing this for real  
pre-merge would likely use the branch names, but not necessarily.   
(Consider an anonymous branch after pulling.)

I wonder if the parameters to this can have default values, to make it  
more concise, and more like the status command.  For example, leaving out  
the 3rd parameter implies added()+modified()+removed()+missing() (status  
doesn't list clean or ignored by default).  It seems like it would be  
convenient if one of the revisions (base?) defaulted to what --rev  
specified for the command.  The second --rev for status defaults to wdir().

I know this is meant for aggregating files _across_ revisions, but then  
`hg status` and `hg files 'set:status()'` would agree, without ORing  
together the MAR! predicates.

I did run into an oddity when testing with subrepos:


I'd expect .hgsub to show up in the main repo.  There may be some more  
missing in the subrepos for the second command, but I don't have any more  
time to investigate tonight.  I'll see if I can figure it out over the  
weekend.

When I quote 3rd parameter in those tests, the output is different.  It's  
unfortunate that revsets in arg 1 or 2 requires quoting, but quoting is  
wrong for the 3rd arg.

   $ hg files 'set:status(0, "wdir()", "added()+modified()+removed()")'
   [1]

   $ hg files -S 'set:status(0, tip, "added()+modified()+removed()")'
   abort: added()+modified()+removed() not under root  
'$TESTTMP\cloned\sub1' (in subrepo sub1)
   (consider using '--cwd sub1')
   [255]

If this is just because of the way the parser needs to be, mentioning it  
in the help may be sufficient.

> 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)
>
> diff --git a/mercurial/fileset.py b/mercurial/fileset.py
> --- a/mercurial/fileset.py
> +++ b/mercurial/fileset.py
> @@ -463,6 +463,25 @@ 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
> +    baserevspec = getstring(b, _("first argument to revs must be a  
> revision"))
> +    revspec = getstring(r, _("second argument to revs must be a  
> revision"))
> +    basectx = scmutil.revsingle(repo, baserevspec)
> +    ctx = scmutil.revsingle(repo, revspec)
> +    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 +557,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,59 @@ 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
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff --git a/tests/test-subrepo-deep-nested-change.t  
b/tests/test-subrepo-deep-nested-change.t
--- a/tests/test-subrepo-deep-nested-change.t
+++ b/tests/test-subrepo-deep-nested-change.t
@@ -455,6 +455,17 @@ 
    sub1/sub2/sub2 (glob)
    sub1/sub2/test.txt (glob)

+  $ hg files 'set:status(0, "wdir()", added()+modified()+removed())'
+  .hgsubstate
+  foo\bar\abc
+
+  $ hg files -S 'set:status(0, tip, added()+modified()+removed())'
+  .hgsubstate
+  foo\bar\abc
+  sub1\.hgsubstate
+  sub1\foo
+  sub1\sub2\folder\bar
+
    $ hg files sub1
    sub1/.hgsub (glob)
    sub1/.hgsubstate (glob)