treemanifest: visit directory 'foo' when given e.g. '-X foo/ba?'
authorMartin von Zweigbergk <martinvonz@google.com>
Wed, 27 May 2015 10:44:04 -0700
changeset 25434 20ad936ac5d2a58877ad2ed8ca389b246f9b1802
parent 25433 1635579f9bafdd80b793f6ecb205d5eeb52e9977
child 25435 3ff4b07412ad709d57e304c139d05469fede8fce
push id14
push usergszorc@mozilla.com
push dateMon, 22 Jun 2015 07:28:19 +0000
treemanifest: visit directory 'foo' when given e.g. '-X foo/ba?' For globs like 'foo/ba?', match._roots() will return 'foo'. Since visitdir(), excludes directories in the excluded roots, it would skip the entire foo directory. This is incorrect, since 'foo/ba?' doesn't mean that everything in foo/ should be exluded. Note that visitdir() is called only from the treemanifest class, so this only affects tree manifests. Fix by adding roots to the set of excluded roots only if there are no excluded patterns. Since 'glob' is the default pattern type for globs, we also need to update some -X patterns in the tests to be of 'path' type to take advantage of the visitdir tricks. For consistency, also update the -I patterns. It seems a little unfortunate that 'foo' in 'hg files -X foo' is considered a pattern because of the implied 'glob' type, but improving that is left for another day.
mercurial/match.py
tests/test-treemanifest.t
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -124,18 +124,19 @@ class match(object):
             self._includeroots.update(_roots(kindpats))
             self._includeroots.discard('.')
             self._includedirs.update(util.dirs(self._includeroots))
             matchfns.append(im)
         if exclude:
             kindpats = self._normalize(exclude, 'glob', root, cwd, auditor)
             self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)',
                                               listsubrepos, root)
-            self._excluderoots.update(_roots(kindpats))
-            self._excluderoots.discard('.')
+            if not _anypats(kindpats):
+                self._excluderoots.update(_roots(kindpats))
+                self._excluderoots.discard('.')
             matchfns.append(lambda f: not em(f))
         if exact:
             if isinstance(patterns, list):
                 self._files = patterns
             else:
                 self._files = list(patterns)
             matchfns.append(self.exact)
         elif patterns:
--- a/tests/test-treemanifest.t
+++ b/tests/test-treemanifest.t
@@ -317,63 +317,70 @@ Test files from the root.
   a/two.txt (glob)
   b/bar/fruits.txt (glob)
   b/bar/orange/fly/gnat.py (glob)
   b/bar/orange/fly/housefly.txt (glob)
   b/foo/apple/bees/flower.py (glob)
   c.txt
   d.py
 
+Excludes with a glob should not exclude everything from the glob's root
+
+  $ hg files -r . -X 'b/fo?' b
+  b/bar/fruits.txt
+  b/bar/orange/fly/gnat.py
+  b/bar/orange/fly/housefly.txt
+
 Test files for a subdirectory.
 
   $ mv .hg/store/meta/a oldmf
   $ hg files -r . b
   b/bar/fruits.txt (glob)
   b/bar/orange/fly/gnat.py (glob)
   b/bar/orange/fly/housefly.txt (glob)
   b/foo/apple/bees/flower.py (glob)
   $ mv oldmf .hg/store/meta/a
 
 Test files with just includes and excludes.
 
   $ mv .hg/store/meta/a oldmf
   $ mv .hg/store/meta/b/bar/orange/fly oldmf2
   $ mv .hg/store/meta/b/foo/apple/bees oldmf3
-  $ hg files -r . -I b/bar -X b/bar/orange/fly -I b/foo -X b/foo/apple/bees
+  $ hg files -r . -I path:b/bar -X path:b/bar/orange/fly -I path:b/foo -X path:b/foo/apple/bees
   b/bar/fruits.txt (glob)
   $ mv oldmf .hg/store/meta/a
   $ mv oldmf2 .hg/store/meta/b/bar/orange/fly
   $ mv oldmf3 .hg/store/meta/b/foo/apple/bees
 
 Test files for a subdirectory, excluding a directory within it.
 
   $ mv .hg/store/meta/a oldmf
   $ mv .hg/store/meta/b/foo oldmf2
-  $ hg files -r . -X b/foo b
+  $ hg files -r . -X path:b/foo b
   b/bar/fruits.txt (glob)
   b/bar/orange/fly/gnat.py (glob)
   b/bar/orange/fly/housefly.txt (glob)
   $ mv oldmf .hg/store/meta/a
   $ mv oldmf2 .hg/store/meta/b/foo
 
 Test files for a sub directory, including only a directory within it, and
 including an unrelated directory.
 
   $ mv .hg/store/meta/a oldmf
   $ mv .hg/store/meta/b/foo oldmf2
-  $ hg files -r . -I b/bar/orange -I a b
+  $ hg files -r . -I path:b/bar/orange -I path:a b
   b/bar/orange/fly/gnat.py (glob)
   b/bar/orange/fly/housefly.txt (glob)
   $ mv oldmf .hg/store/meta/a
   $ mv oldmf2 .hg/store/meta/b/foo
 
 Test files for a pattern, including a directory, and excluding a directory
 within that.
 
   $ mv .hg/store/meta/a oldmf
   $ mv .hg/store/meta/b/foo oldmf2
   $ mv .hg/store/meta/b/bar/orange oldmf3
-  $ hg files -r . glob:**.txt -I b/bar -X b/bar/orange
+  $ hg files -r . glob:**.txt -I path:b/bar -X path:b/bar/orange
   b/bar/fruits.txt (glob)
   $ mv oldmf .hg/store/meta/a
   $ mv oldmf2 .hg/store/meta/b/foo
   $ mv oldmf3 .hg/store/meta/b/bar/orange