mercurial/match.py
changeset 35659 821d8a5ab4ff
parent 35164 6864c405f023
child 36050 c4fa47f880d3
equal deleted inserted replaced
35658:a1222a8cc93b 35659:821d8a5ab4ff
   455     def __repr__(self):
   455     def __repr__(self):
   456         return ('<exactmatcher files=%r>' % self._files)
   456         return ('<exactmatcher files=%r>' % self._files)
   457 
   457 
   458 class differencematcher(basematcher):
   458 class differencematcher(basematcher):
   459     '''Composes two matchers by matching if the first matches and the second
   459     '''Composes two matchers by matching if the first matches and the second
   460     does not. Well, almost... If the user provides a pattern like "-X foo foo",
   460     does not.
   461     Mercurial actually does match "foo" against that. That's because exact
       
   462     matches are treated specially. So, since this differencematcher is used for
       
   463     excludes, it needs to special-case exact matching.
       
   464 
   461 
   465     The second matcher's non-matching-attributes (root, cwd, bad, explicitdir,
   462     The second matcher's non-matching-attributes (root, cwd, bad, explicitdir,
   466     traversedir) are ignored.
   463     traversedir) are ignored.
   467 
       
   468     TODO: If we want to keep the behavior described above for exact matches, we
       
   469     should consider instead treating the above case something like this:
       
   470     union(exact(foo), difference(pattern(foo), include(foo)))
       
   471     '''
   464     '''
   472     def __init__(self, m1, m2):
   465     def __init__(self, m1, m2):
   473         super(differencematcher, self).__init__(m1._root, m1._cwd)
   466         super(differencematcher, self).__init__(m1._root, m1._cwd)
   474         self._m1 = m1
   467         self._m1 = m1
   475         self._m2 = m2
   468         self._m2 = m2
   476         self.bad = m1.bad
   469         self.bad = m1.bad
   477         self.explicitdir = m1.explicitdir
   470         self.explicitdir = m1.explicitdir
   478         self.traversedir = m1.traversedir
   471         self.traversedir = m1.traversedir
   479 
   472 
   480     def matchfn(self, f):
   473     def matchfn(self, f):
   481         return self._m1(f) and (not self._m2(f) or self._m1.exact(f))
   474         return self._m1(f) and not self._m2(f)
   482 
   475 
   483     @propertycache
   476     @propertycache
   484     def _files(self):
   477     def _files(self):
   485         if self.isexact():
   478         if self.isexact():
   486             return [f for f in self._m1.files() if self(f)]
   479             return [f for f in self._m1.files() if self(f)]
   491         # because the "dir" in m1 may not be a file.
   484         # because the "dir" in m1 may not be a file.
   492         return self._m1.files()
   485         return self._m1.files()
   493 
   486 
   494     def visitdir(self, dir):
   487     def visitdir(self, dir):
   495         if self._m2.visitdir(dir) == 'all':
   488         if self._m2.visitdir(dir) == 'all':
   496             # There's a bug here: If m1 matches file 'dir/file' and m2 excludes
       
   497             # 'dir' (recursively), we should still visit 'dir' due to the
       
   498             # exception we have for exact matches.
       
   499             return False
   489             return False
   500         return bool(self._m1.visitdir(dir))
   490         return bool(self._m1.visitdir(dir))
   501 
   491 
   502     def isexact(self):
   492     def isexact(self):
   503         return self._m1.isexact()
   493         return self._m1.isexact()