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'
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
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
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
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
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
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
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)
# 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
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)
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
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
('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,
('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,
'/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'],
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,
('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)
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
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):
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)
% (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),))
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:
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.
"""
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):