Patchwork [RFC] fileset: add "tracked()" to explicitly select files in the revision

login
register
mail settings
Submitter Yuya Nishihara
Date June 12, 2018, 2:56 p.m.
Message ID <c66667fd574b35c8d795.1528815398@mimosa>
Download mbox | patch
Permalink /patch/32084/
State New
Headers show

Comments

Yuya Nishihara - June 12, 2018, 2:56 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1528636796 -32400
#      Sun Jun 10 22:19:56 2018 +0900
# Node ID c66667fd574b35c8d7953fce3b5747ed27f23ea1
# Parent  4eb2c19f741f50389c3de234654510deede597e2
fileset: add "tracked()" to explicitly select files in the revision

(This is RFC to show the BC I plan to make. I'll include this patch in a
later series.)

I'm going to rewrite filesets to be matcher predicates, which means basic
patterns such as '*' will no longer be "closed" to the subset constructed
from the ctx.

Good thing is that 'hg status "set:not binary()"' can include unknown files
out of the box, and fileset computation will (hopefully) be faster as we won't
have to walk dirstate twice, for example. Bad thing is that we can't select
files at a certain revision by 'set:revs(REV, **)' since '**' is open to any
paths. So, this patch introduces "tracked()" as a replacement for the '**'
use in the example above.

Some examples of matcher-based filesets:

This works as before, but some matcher attributes (e.g. visitdir()) will
likely be more accurate.

  $ hg debugwalk -v 'set:path:mercurial and size(">100k")'
  * matcher:
  <intersectionmatcher
    m1=<patternmatcher patterns='(?:mercurial(?:/|$))'>,
    m2=<predicatenmatcher pred=size('>100k')>>
  f  mercurial/cmdutil.py        mercurial/cmdutil.py
  f  mercurial/commands.py       mercurial/commands.py
  f  mercurial/debugcommands.py  mercurial/debugcommands.py
  f  mercurial/patch.py          mercurial/patch.py
  f  mercurial/util.py           mercurial/util.py

Since the predicate is open to any paths, it can be applied to ignored files.

  $ hg status --ignored 'set:path:mercurial and size(">100k")'
  I mercurial/cext/bdiff.so
  I mercurial/cext/parsers.so
  I mercurial/commands.pyc
  I mercurial/debugcommands.pyc
  I mercurial/locale/da/LC_MESSAGES/hg.mo
  I mercurial/locale/de/LC_MESSAGES/hg.mo
  I mercurial/locale/it/LC_MESSAGES/hg.mo
  I mercurial/locale/ja/LC_MESSAGES/hg.mo
  I mercurial/locale/pt_BR/LC_MESSAGES/hg.mo
  I mercurial/locale/ru/LC_MESSAGES/hg.mo
  I mercurial/locale/sv/LC_MESSAGES/hg.mo
  I mercurial/util.pyc
  I mercurial/zstd.so

Patch

diff --git a/mercurial/fileset.py b/mercurial/fileset.py
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -253,6 +253,13 @@  def clean(mctx, x):
     s = set(mctx.status().clean)
     return [f for f in mctx.subset if f in s]
 
+@predicate('tracked()')
+def tracked(mctx, x):
+    """File that is under Mercurial control."""
+    # i18n: "tracked" is a keyword
+    getargs(x, 0, 0, _("tracked takes no arguments"))
+    return [f for f in mctx.subset if f in mctx.ctx]
+
 def func(mctx, a, b):
     funcname = getsymbol(a)
     if funcname in symbols:
diff --git a/tests/test-fileset.t b/tests/test-fileset.t
--- a/tests/test-fileset.t
+++ b/tests/test-fileset.t
@@ -524,7 +524,7 @@  small reminder of the repository state
 Test files at -r0 should be filtered by files at wdir
 -----------------------------------------------------
 
-  $ fileset -r0 '* and revs("wdir()", *)'
+  $ fileset -r0 'tracked() and revs("wdir()", tracked())'
   a1
   b1
   b2
@@ -590,12 +590,12 @@  use rev to restrict matched file
   R a2
   $ fileset "status(0, 1, removed())"
   a2
-  $ fileset "* and status(0, 1, removed())"
+  $ fileset "tracked() 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()))"
+  $ fileset -r 4 "tracked() and status(0, 1, removed())"
+  $ fileset "revs('4', tracked() and status(0, 1, removed()))"
+  $ fileset "revs('0', tracked() and status(0, 1, removed()))"
   a2
 
 check wdir()