]> arthur.barton.de Git - bup.git/commitdiff
Replace lresolve with resolve(..., follow=False)
authorRob Browning <rlb@defaultvalue.org>
Tue, 27 Feb 2018 07:32:54 +0000 (23:32 -0800)
committerRob Browning <rlb@defaultvalue.org>
Sat, 12 Jan 2019 20:57:30 +0000 (14:57 -0600)
Although there's the NOFOLLOW precedent, this is really just to narrow
the API before we add it as a repo method, i.e. so we only have to
handle one function instead of two.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Tested-by: Rob Browning <rlb@defaultvalue.org>
cmd/cat-file-cmd.py
cmd/fuse-cmd.py
cmd/restore-cmd.py
lib/bup/ls.py
lib/bup/rm.py
lib/bup/t/tmetadata.py
lib/bup/t/tvfs.py
lib/bup/vfs.py

index 06e14f69a38cca150cf31b508ad1d1cd9858a7fc..9cb6961f081645be1cf3f0f7ac0dc0896dfba832 100755 (executable)
@@ -39,7 +39,7 @@ if not re.match(r'/*[^/]+/[^/]+', target):
     o.fatal("path %r doesn't include a branch and revision" % target)
 
 repo = LocalRepo()
-resolved = vfs.lresolve(repo, target)
+resolved = vfs.resolve(repo, target, follow=False)
 leaf_name, leaf_item = resolved[-1]
 if not leaf_item:
     log('error: cannot access %r in %r\n'
index 747d25b26607c3cc6322b3bd0b7bfd2140d04d3b..8e57ab6f937dab330f4f7fd6e5c4618e1812dfe6 100755 (executable)
@@ -34,7 +34,8 @@ class BupFs(fuse.Fuse):
         global opt
         if self.verbose > 0:
             log('--getattr(%r)\n' % path)
-        res = vfs.lresolve(self.repo, path, want_meta=(not self.fake_metadata))
+        res = vfs.resolve(self.repo, path, want_meta=(not self.fake_metadata),
+                          follow=False)
         name, item = res[-1]
         if not item:
             return -errno.ENOENT
@@ -56,7 +57,7 @@ class BupFs(fuse.Fuse):
 
     def readdir(self, path, offset):
         assert not offset  # We don't return offsets, so offset should be unused
-        res = vfs.lresolve(self.repo, path)
+        res = vfs.resolve(self.repo, path, follow=False)
         dir_name, dir_item = res[-1]
         if not dir_item:
             yield -errno.ENOENT
@@ -68,7 +69,7 @@ class BupFs(fuse.Fuse):
     def readlink(self, path):
         if self.verbose > 0:
             log('--readlink(%r)\n' % path)
-        res = vfs.lresolve(self.repo, path)
+        res = vfs.resolve(self.repo, path, follow=False)
         name, item = res[-1]
         if not item:
             return -errno.ENOENT
@@ -77,7 +78,7 @@ class BupFs(fuse.Fuse):
     def open(self, path, flags):
         if self.verbose > 0:
             log('--open(%r)\n' % path)
-        res = vfs.lresolve(self.repo, path)
+        res = vfs.resolve(self.repo, path, follow=False)
         name, item = res[-1]
         if not item:
             return -errno.ENOENT
@@ -91,7 +92,7 @@ class BupFs(fuse.Fuse):
     def read(self, path, size, offset):
         if self.verbose > 0:
             log('--read(%r)\n' % path)
-        res = vfs.lresolve(self.repo, path)
+        res = vfs.resolve(self.repo, path, follow=False)
         name, item = res[-1]
         if not item:
             return -errno.ENOENT
index 6544a24b908e966fd4796a784958957fa13ff79f..0edbdefff1395dff0ca101efdb8f3728bae306c7 100755 (executable)
@@ -246,7 +246,7 @@ def main():
             add_error("path %r doesn't include a branch and revision" % path)
             continue
         try:
-            resolved = vfs.lresolve(repo, path, want_meta=True)
+            resolved = vfs.resolve(repo, path, want_meta=True, follow=False)
         except vfs.IOError as e:
             add_error(e)
             continue
index 7b3d9eae681ada1995b901bbcbb15647913d7f98..4a05b397cfc0a77c12f443321797d1efed752c37 100644 (file)
@@ -113,7 +113,7 @@ def within_repo(repo, opt):
     for path in opt.paths:
         try:
             if opt.directory:
-                resolved = vfs.lresolve(repo, path)
+                resolved = vfs.resolve(repo, path, follow=False)
             else:
                 resolved = vfs.try_resolve(repo, path)
 
index 5345114289eaea8c7b3945f38eccc4d2a7fe2aad..d0e0551402ad6860e856b15dbff54c4552551e7f 100644 (file)
@@ -68,7 +68,7 @@ def dead_items(repo, paths):
     # Scan for bad requests, and opportunities to optimize
     for path in paths:
         try:
-            resolved = vfs.lresolve(repo, path)
+            resolved = vfs.resolve(repo, path, follow=False)
         except vfs.IOError as e:
             add_error(e)
             continue
index 347f874f78581ad1432082f1042df631a7813f4c..2bf7780576dce3754f2dcd6593fbcf1aa4a4a9d2 100644 (file)
@@ -146,8 +146,9 @@ def test_metadata_method():
             ex(bup_path, '-d', bup_dir, 'save', '-tvvn', 'test', data_path)
             git.check_repo_or_die(bup_dir)
             repo = LocalRepo()
-            resolved = vfs.lresolve(repo,
-                                    '/test/latest' + resolve_parent(data_path))
+            resolved = vfs.resolve(repo,
+                                   '/test/latest' + resolve_parent(data_path),
+                                   follow=False)
             leaf_name, leaf_item = resolved[-1]
             m = leaf_item.meta
             WVPASS(m.mtime == test_time2)
index 7cfe2f0330ae124ccaba3f01349b4c864cfbe8a7..127acb672009bd87bd82ffa2bd0e8bcbe79a3f1a 100644 (file)
@@ -117,7 +117,7 @@ def run_augment_item_meta_tests(repo,
                                 file_path, file_size,
                                 link_path, link_target):
     _, file_item = vfs.resolve(repo, file_path)[-1]
-    _, link_item = vfs.lresolve(repo, link_path)[-1]
+    _, link_item = vfs.resolve(repo, link_path, follow=False)[-1]
     wvpass(isinstance(file_item.meta, Metadata))
     wvpass(isinstance(link_item.meta, Metadata))
     # Note: normally, modifying item.meta values is forbidden
@@ -253,7 +253,6 @@ def test_resolve():
     with no_lingering_errors():
         with test_tempdir('bup-tvfs-') as tmpdir:
             resolve = vfs.resolve
-            lresolve = vfs.lresolve
             bup_dir = tmpdir + '/bup'
             environ['GIT_DIR'] = bup_dir
             environ['BUP_DIR'] = bup_dir
@@ -391,9 +390,9 @@ def test_resolve():
                         ('not-there', None))
             wvpasseq(expected, res)
 
-            wvstart('lresolve: /test/latest/bad-symlink')
+            wvstart('resolve nofollow: /test/latest/bad-symlink')
             vfs.clear_cache()
-            res = lresolve(repo, '/test/latest/bad-symlink')
+            res = resolve(repo, '/test/latest/bad-symlink', follow=False)
             wvpasseq(4, len(res))
             bad_symlink_value = tip_tree['bad-symlink']
             expected_bad_symlink_item_w_meta = vfs.Item(meta=bad_symlink_value.meta,
@@ -414,9 +413,9 @@ def test_resolve():
                         ('file', expected_file_item_w_meta))
             wvpasseq(expected, res)
 
-            wvstart('lresolve: /test/latest/file-symlink')
+            wvstart('resolve nofollow: /test/latest/file-symlink')
             vfs.clear_cache()
-            res = lresolve(repo, '/test/latest/file-symlink')
+            res = resolve(repo, '/test/latest/file-symlink', follow=False)
             wvpasseq(4, len(res))
             file_symlink_value = tip_tree['file-symlink']
             expected_file_symlink_item_w_meta = vfs.Item(meta=file_symlink_value.meta,
@@ -457,10 +456,10 @@ def test_resolve():
                          '/test/latest/file-symlink/../',
                          '/test/latest/file-symlink/../.',
                          '/test/latest/file-symlink/../..'):
-                wvstart('lresolve: ' + path)
+                wvstart('resolve nofollow: ' + path)
                 vfs.clear_cache()
                 try:
-                    lresolve(repo, path)
+                    resolve(repo, path, follow=False)
                 except vfs.IOError as res_ex:
                     wvpasseq(ENOTDIR, res_ex.errno)
                     wvpasseq(['', 'test', save_time_str, 'file'],
@@ -475,9 +474,9 @@ def test_resolve():
                 wvpasseq(ENOTDIR, res_ex.errno)
                 wvpasseq(None, res_ex.terminus)
 
-            wvstart('lresolve: /test/latest/dir-symlink')
+            wvstart('resolve nofollow: /test/latest/dir-symlink')
             vfs.clear_cache()
-            res = lresolve(repo, '/test/latest/dir-symlink')
+            res = resolve(repo, '/test/latest/dir-symlink', follow=False)
             wvpasseq(4, len(res))
             dir_symlink_value = tip_tree['dir-symlink']
             expected_dir_symlink_item_w_meta = vfs.Item(meta=dir_symlink_value.meta,
@@ -495,8 +494,10 @@ def test_resolve():
                         ('test', test_revlist_w_meta),
                         (save_time_str, expected_latest_item_w_meta),
                         ('dir', expected_dir_item))
+            def lresolve(*args, **keys):
+                return resolve(*args, **dict(keys, follow=False))
             for resname, resolver in (('resolve', resolve),
-                                      ('lresolve', lresolve)):
+                                      ('resolve nofollow', lresolve)):
                 for path in ('/test/latest/dir-symlink/',
                              '/test/latest/dir-symlink/.'):
                     wvstart(resname + ': ' + path)
@@ -611,7 +612,6 @@ def test_resolve_loop():
     with no_lingering_errors():
         with test_tempdir('bup-tvfs-resloop-') as tmpdir:
             resolve = vfs.resolve
-            lresolve = vfs.lresolve
             bup_dir = tmpdir + '/bup'
             environ['GIT_DIR'] = bup_dir
             environ['BUP_DIR'] = bup_dir
index e36df64d936347eb288f01a67ee1aba49abd7049..e3ea16ffae505d95c28a8d61ad7238f98730a94c 100644 (file)
@@ -60,7 +60,6 @@ from bup.compat import range
 from bup.git import BUP_CHUNKED, cp, get_commit_items, parse_commit, tree_decode
 from bup.helpers import debug2, last
 from bup.metadata import Metadata
-from bup.repo import LocalRepo, RemoteRepo
 
 
 class IOError(exceptions.IOError):
@@ -780,9 +779,9 @@ def contents(repo, item, names=None, want_meta=True):
     for x in item_gen:
         yield x
 
-def _resolve_path(repo, path, parent=None, want_meta=True, deref=False):
+def _resolve_path(repo, path, parent=None, want_meta=True, follow=True):
     cache_key = b'res:%d%d%d:%s\0%s' \
-                % (bool(want_meta), bool(deref), repo.id(),
+                % (bool(want_meta), bool(follow), repo.id(),
                    ('/'.join(x[0] for x in parent) if parent else ''),
                    '/'.join(path))
     resolution = cache_get(cache_key)
@@ -815,7 +814,7 @@ def _resolve_path(repo, path, parent=None, want_meta=True, deref=False):
                           % (parent,))
     is_absolute, must_be_dir, future = _decompose_path(path)
     if must_be_dir:
-        deref = True
+        follow = True
     if not future:  # path was effectively '.' or '/'
         if is_absolute:
             return notice_resolution((('', _root),))
@@ -874,7 +873,7 @@ def _resolve_path(repo, path, parent=None, want_meta=True, deref=False):
                         item = item._replace(meta=dir_meta)
                 past.append((segment, item))
             else:  # symlink
-                if not future and not deref:
+                if not future and not follow:
                     past.append((segment, item),)
                     continue
                 if hops > 100:
@@ -893,21 +892,15 @@ def _resolve_path(repo, path, parent=None, want_meta=True, deref=False):
                     future.extend(target_future)
                 hops += 1
                 
-def lresolve(repo, path, parent=None, want_meta=True):
-    """Perform exactly the same function as resolve(), except if the final
-    path element is a symbolic link, don't follow it, just return it
-    in the result.
-
-    """
-    return _resolve_path(repo, path, parent=parent, want_meta=want_meta,
-                         deref=False)
-
-def resolve(repo, path, parent=None, want_meta=True):
+def resolve(repo, path, parent=None, want_meta=True, follow=True):
     """Follow the path in the virtual filesystem and return a tuple
     representing the location, if any, denoted by the path.  Each
     element in the result tuple will be (name, info), where info will
     be a VFS item that can be passed to functions like item_mode().
 
+    If follow is false, and if the final path element is a symbolic
+    link, don't follow it, just return it in the result.
+
     If a path segment that does not exist is encountered during
     resolution, the result will represent the location of the missing
     item, and that item in the result will be None.
@@ -948,28 +941,29 @@ def resolve(repo, path, parent=None, want_meta=True):
 
     """
     result = _resolve_path(repo, path, parent=parent, want_meta=want_meta,
-                           deref=True)
+                           follow=follow)
     _, leaf_item = result[-1]
-    if leaf_item:
+    if leaf_item and follow:
         assert not S_ISLNK(item_mode(leaf_item))
     return result
 
 def try_resolve(repo, path, parent=None, want_meta=True):
     """If path does not refer to a symlink, does not exist, or refers to a
-    valid symlink, behave exactly like resolve().  If path refers to
-    an invalid symlink, behave like lresolve.
+    valid symlink, behave exactly like resolve(..., follow=True).  If
+    path refers to an invalid symlink, behave like resolve(...,
+    follow=False).
 
     """
-    res = lresolve(repo, path, parent=parent, want_meta=want_meta)
+    res = resolve(repo, path, parent=parent, want_meta=want_meta, follow=False)
     leaf_name, leaf_item = res[-1]
     if not leaf_item:
         return res
     if not S_ISLNK(item_mode(leaf_item)):
         return res
-    deref = resolve(repo, leaf_name, parent=res[:-1], want_meta=want_meta)
-    deref_name, deref_item = deref[-1]
-    if deref_item:
-        return deref
+    follow = resolve(repo, leaf_name, parent=res[:-1], want_meta=want_meta)
+    follow_name, follow_item = follow[-1]
+    if follow_item:
+        return follow
     return res
 
 def augment_item_meta(repo, item, include_size=False):