changeset 35371:79968f91ad0c

lfs: override walk() in lfsvfs In order to fix the missing lfs store after an upgrade, I attempted to walk the store vfs to hardlink to the upgraded repo's store. But the custom join() clashes with the default walk() implementation. First, 'path=None' blew up in the regex matcher, because it wanted a string. But even if that is fixed, the join to walk the root of the vfs wouldn't match the required xx/xx...xx pattern. The first cut of this was a copy/paste/tweak of the base implementation, but this version of walk() hides the internal directories, and treats the vfs as a flat store. I think this makes sense because most vfs methods call join() on input paths, which wants the simple oid format. It also relieves the caller from having to deal with bogus files/directories in the store.
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 07 Dec 2017 23:44:06 -0500
parents b2f628dd99c3
children b0ba1539af01
files hgext/lfs/blobstore.py
diffstat 1 files changed, 23 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/lfs/blobstore.py	Thu Dec 07 22:36:31 2017 -0500
+++ b/hgext/lfs/blobstore.py	Thu Dec 07 23:44:06 2017 -0500
@@ -15,6 +15,7 @@
 
 from mercurial import (
     error,
+    pathutil,
     url as urlmod,
     util,
     vfs as vfsmod,
@@ -32,6 +33,28 @@
             raise error.ProgrammingError('unexpected lfs path: %s' % path)
         return super(lfsvfs, self).join(path[0:2], path[2:])
 
+    def walk(self, path=None, onerror=None):
+        """Yield (dirpath, '', oids) tuple for blobs under path
+
+        Oids only exist in the root of this vfs, so dirpath is always ''.
+        """
+        root = os.path.normpath(self.base)
+        # when dirpath == root, dirpath[prefixlen:] becomes empty
+        # because len(dirpath) < prefixlen.
+        prefixlen = len(pathutil.normasprefix(root))
+        oids = []
+
+        for dirpath, dirs, files in os.walk(self.reljoin(self.base, path or ''),
+                                            onerror=onerror):
+            dirpath = dirpath[prefixlen:]
+
+            # Silently skip unexpected files and directories
+            if len(dirpath) == 2:
+                oids.extend([dirpath + f for f in files
+                             if _lfsre.match(dirpath + f)])
+
+        yield ('', '', oids)
+
 class filewithprogress(object):
     """a file-like object that supports __len__ and read.