Re: [PATCH 4 of 6] match: add prefixdirmatcher to adapt subrepo matcher back

2018-07-27 Thread Matt Harbison

On Sat, 07 Jul 2018 04:38:48 -0400, Yuya Nishihara  wrote:


# HG changeset patch
# User Yuya Nishihara 
# Date 1528549447 -32400
#  Sat Jun 09 22:04:07 2018 +0900
# Node ID 609c30cc3b87da9523988402ad0a1ba8899411cc
# Parent  f037e8dfa6c2047d0ef86efc2e83fece0fa08d80
match: add prefixdirmatcher to adapt subrepo matcher back


This breaks test-doctest.py on Windows.  Any ideas?  I assumed it's a '/'  
vs '\' thing, but the little bit of playing around with it a couple weeks  
ago didn't yield any clues, and it looked like the code that gets called  
handles those differences.


--- c:/Users/Matt/projects/hg/tests/test-doctest.py.out
+++ c:/Users/Matt/projects/hg/tests/test-doctest.py.err
@@ -0,0 +1,142 @@
+**
+File "c:\Users\Matt\projects\hg\mercurial\match.py", line 696, in  
mercurial.match.prefixdirmatcher

+Failed example:
+m1 = match(b'root/d/e', b'f', [b'../a.txt', b'b.txt'])
+Exception raised:
+Traceback (most recent call last):
+  File "c:\Python27\lib\doctest.py", line 1315, in __run
+compileflags, 1) in test.globs
+  File "", line 1, in  


+m1 = match(b'root/d/e', b'f', [b'../a.txt', b'b.txt'])
+  File "c:\Users\Matt\projects\hg\mercurial\match.py", line 176, in  
match

+kindpats = normalize(patterns, default, root, cwd, auditor, warn)
+  File "c:\Users\Matt\projects\hg\mercurial\match.py", line 223, in  
_donormalize

+pat = pathutil.canonpath(root, cwd, pat, auditor)
+  File "c:\Users\Matt\projects\hg\mercurial\pathutil.py", line 236,  
in canonpath

+hint=hint)
+Abort: ../a.txt not under root 'root/d/e'
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 6] match: add prefixdirmatcher to adapt subrepo matcher back

2018-07-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1528549447 -32400
#  Sat Jun 09 22:04:07 2018 +0900
# Node ID 609c30cc3b87da9523988402ad0a1ba8899411cc
# Parent  f037e8dfa6c2047d0ef86efc2e83fece0fa08d80
match: add prefixdirmatcher to adapt subrepo matcher back

This serves as an inverse function to the subdirmatcher, and will be used
to wrap a fileset matcher of subrepositories. One of the root/prefix paths
could be deduced from the matcher attributes to be wrapped, but we don't
since the callers of this class know the root/prefix paths and can simply
pass them in.

diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -684,6 +684,78 @@ class subdirmatcher(basematcher):
 return ('' %
 (self._path, self._matcher))
 
+class prefixdirmatcher(basematcher):
+"""Adapt a matcher to work on a parent directory.
+
+The matcher's non-matching-attributes (root, cwd, bad, explicitdir,
+traversedir) are ignored.
+
+The prefix path should usually be the relative path from the root of
+this matcher to the root of the wrapped matcher.
+
+>>> m1 = match(b'root/d/e', b'f', [b'../a.txt', b'b.txt'])
+>>> m2 = prefixdirmatcher(b'root', b'd/e/f', b'd/e', m1)
+>>> bool(m2(b'a.txt'),)
+False
+>>> bool(m2(b'd/e/a.txt'))
+True
+>>> bool(m2(b'd/e/b.txt'))
+False
+>>> m2.files()
+['d/e/a.txt', 'd/e/f/b.txt']
+>>> m2.exact(b'd/e/a.txt')
+True
+>>> m2.visitdir(b'd')
+True
+>>> m2.visitdir(b'd/e')
+True
+>>> m2.visitdir(b'd/e/f')
+True
+>>> m2.visitdir(b'd/e/g')
+False
+>>> m2.visitdir(b'd/ef')
+False
+"""
+
+def __init__(self, root, cwd, path, matcher, badfn=None):
+super(prefixdirmatcher, self).__init__(root, cwd, badfn)
+if not path:
+raise error.ProgrammingError('prefix path must not be empty')
+self._path = path
+self._pathprefix = path + '/'
+self._matcher = matcher
+
+@propertycache
+def _files(self):
+return [self._pathprefix + f for f in self._matcher._files]
+
+def matchfn(self, f):
+if not f.startswith(self._pathprefix):
+return False
+return self._matcher.matchfn(f[len(self._pathprefix):])
+
+@propertycache
+def _pathdirs(self):
+return set(util.finddirs(self._path)) | {'.'}
+
+def visitdir(self, dir):
+if dir == self._path:
+return self._matcher.visitdir('.')
+if dir.startswith(self._pathprefix):
+return self._matcher.visitdir(dir[len(self._pathprefix):])
+return dir in self._pathdirs
+
+def isexact(self):
+return self._matcher.isexact()
+
+def prefix(self):
+return self._matcher.prefix()
+
+@encoding.strmethod
+def __repr__(self):
+return (''
+% (pycompat.bytestr(self._path), self._matcher))
+
 class unionmatcher(basematcher):
 """A matcher that is the union of several matchers.
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel