diff mercurial/manifest.py @ 24646:5693c834bcb4

manifest: move changectx.walk() to manifests The logic of walking a manifest to yield files matching a match object is currently being done by context, not the manifest itself. This moves the walk() function to both manifestdict and treemanifest. This separate implementation will also permit differing, optimized implementations for each manifest.
author Drew Gottlieb <drgott@google.com>
date Tue, 07 Apr 2015 15:18:52 -0700
parents 36872036169b
children fb446c57f8f9
line wrap: on
line diff
--- a/mercurial/manifest.py	Sun Apr 05 15:08:55 2015 -0400
+++ b/mercurial/manifest.py	Tue Apr 07 15:18:52 2015 -0700
@@ -225,6 +225,38 @@
     def hasdir(self, dir):
         return dir in self._dirs
 
+    def walk(self, match):
+        '''Generates matching file names.
+
+        Equivalent to manifest.matches(match).iterkeys(), but without creating
+        an entirely new manifest.
+
+        It also reports nonexistent files by marking them bad with match.bad().
+        '''
+        fset = set(match.files())
+
+        # avoid the entire walk if we're only looking for specific files
+        if fset and not match.anypats():
+            if util.all(fn in self for fn in fset):
+                for fn in sorted(fset):
+                    yield fn
+                raise StopIteration
+
+        for fn in self:
+            if fn in fset:
+                # specified pattern is the exact name
+                fset.remove(fn)
+            if match(fn):
+                yield fn
+
+        # for dirstate.walk, files=['.'] means "walk the whole tree".
+        # follow that here, too
+        fset.discard('.')
+
+        for fn in sorted(fset):
+            if not self.hasdir(fn):
+                match.bad(fn, None)
+
     def matches(self, match):
         '''generate a new manifest filtered by the match argument'''
         if match.always():
@@ -574,6 +606,38 @@
             return False
         return (dir + '/') in self._dirs
 
+    def walk(self, match):
+        '''Generates matching file names.
+
+        Equivalent to manifest.matches(match).iterkeys(), but without creating
+        an entirely new manifest.
+
+        It also reports nonexistent files by marking them bad with match.bad().
+        '''
+        fset = set(match.files())
+
+        # avoid the entire walk if we're only looking for specific files
+        if fset and not match.anypats():
+            if util.all(fn in self for fn in fset):
+                for fn in sorted(fset):
+                    yield fn
+                raise StopIteration
+
+        for fn in self:
+            if fn in fset:
+                # specified pattern is the exact name
+                fset.remove(fn)
+            if match(fn):
+                yield fn
+
+        # for dirstate.walk, files=['.'] means "walk the whole tree".
+        # follow that here, too
+        fset.discard('.')
+
+        for fn in sorted(fset):
+            if not self.hasdir(fn):
+                match.bad(fn, None)
+
     def matches(self, match):
         '''generate a new manifest filtered by the match argument'''
         if match.always():