Patchwork [5,of,6] fileset: flatten 'or' nodes to unnest unionmatchers

login
register
mail settings
Submitter Yuya Nishihara
Date Aug. 2, 2018, 1:26 p.m.
Message ID <7b744a18768440cdca76.1533216365@mimosa>
Download mbox | patch
Permalink /patch/33104/
State Accepted
Headers show

Comments

Yuya Nishihara - Aug. 2, 2018, 1:26 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1532154236 -32400
#      Sat Jul 21 15:23:56 2018 +0900
# Node ID 7b744a18768440cdca7662db7dc6179c1abd6613
# Parent  4391366a156f0a976460deccaa176217e50a3650
fileset: flatten 'or' nodes to unnest unionmatchers

This also makes it easier to compile a union of basic patterns into a single
regexp pattern.

Patch

diff --git a/mercurial/fileset.py b/mercurial/fileset.py
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -103,7 +103,7 @@  def parse(expr):
     tree, pos = p.parse(tokenize(expr))
     if pos != len(expr):
         raise error.ParseError(_("invalid token"), pos)
-    return parser.simplifyinfixops(tree, {'list'})
+    return parser.simplifyinfixops(tree, {'list', 'or'})
 
 def getsymbol(x):
     if x and x[0] == 'symbol':
@@ -157,10 +157,9 @@  def andmatch(mctx, x, y):
     ym = getmatch(mctx, y)
     return matchmod.intersectmatchers(xm, ym)
 
-def ormatch(mctx, x, y):
-    xm = getmatch(mctx, x)
-    ym = getmatch(mctx, y)
-    return matchmod.unionmatcher([xm, ym])
+def ormatch(mctx, *xs):
+    ms = [getmatch(mctx, x) for x in xs]
+    return matchmod.unionmatcher(ms)
 
 def notmatch(mctx, x):
     m = getmatch(mctx, x)
diff --git a/mercurial/minifileset.py b/mercurial/minifileset.py
--- a/mercurial/minifileset.py
+++ b/mercurial/minifileset.py
@@ -40,9 +40,8 @@  def _compile(tree):
         raise error.ParseError(_("unsupported file pattern: %s") % name,
                                hint=_('paths must be prefixed with "path:"'))
     elif op == 'or':
-        func1 = _compile(tree[1])
-        func2 = _compile(tree[2])
-        return lambda n, s: func1(n, s) or func2(n, s)
+        funcs = [_compile(x) for x in tree[1:]]
+        return lambda n, s: any(f(n, s) for f in funcs)
     elif op == 'and':
         func1 = _compile(tree[1])
         func2 = _compile(tree[2])
diff --git a/tests/test-fileset.t b/tests/test-fileset.t
--- a/tests/test-fileset.t
+++ b/tests/test-fileset.t
@@ -159,9 +159,8 @@  Show parsed tree at stages:
   $ fileset -p all -s 'a1 or a2 or (grep("b") & clean())'
   * parsed:
   (or
-    (or
-      (symbol 'a1')
-      (symbol 'a2'))
+    (symbol 'a1')
+    (symbol 'a2')
     (group
       (and
         (func
@@ -172,9 +171,8 @@  Show parsed tree at stages:
           None))))
   * matcher:
   <unionmatcher matchers=[
-    <unionmatcher matchers=[
-      <patternmatcher patterns='(?:a1$)'>,
-      <patternmatcher patterns='(?:a2$)'>]>,
+    <patternmatcher patterns='(?:a1$)'>,
+    <patternmatcher patterns='(?:a2$)'>,
     <intersectionmatcher
       m1=<predicatenmatcher pred=grep('b')>,
       m2=<predicatenmatcher pred=clean>>]>