From: Rob Browning Date: Tue, 28 Sep 2021 00:58:06 +0000 (-0500) Subject: Replace LocalRepo/RemoteRepo __del__ with context management X-Git-Url: https://arthur.ath.cx/gitweb/?a=commitdiff_plain;h=015ca2d3419e59109b73fa8e37913f4d0e1e3048;p=bup.git Replace LocalRepo/RemoteRepo __del__ with context management Signed-off-by: Rob Browning Tested-by: Rob Browning --- diff --git a/lib/bup/cmd/cat_file.py b/lib/bup/cmd/cat_file.py index 302d8e3..e878e7e 100755 --- a/lib/bup/cmd/cat_file.py +++ b/lib/bup/cmd/cat_file.py @@ -34,36 +34,36 @@ def main(argv): if not re.match(br'/*[^/]+/[^/]+', target): o.fatal("path %r doesn't include a branch and revision" % target) - repo = LocalRepo() - 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' - % (b'/'.join(name for name, item in resolved), target)) - sys.exit(1) + with LocalRepo() as repo: + 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' + % (b'/'.join(name for name, item in resolved), target)) + sys.exit(1) - mode = vfs.item_mode(leaf_item) + mode = vfs.item_mode(leaf_item) - sys.stdout.flush() - out = byte_stream(sys.stdout) + sys.stdout.flush() + out = byte_stream(sys.stdout) - if opt.bupm: - if not stat.S_ISDIR(mode): - o.fatal('%r is not a directory' % target) - _, bupm_oid = vfs.tree_data_and_bupm(repo, leaf_item.oid) - if bupm_oid: - with vfs.tree_data_reader(repo, bupm_oid) as meta_stream: - out.write(meta_stream.read()) - elif opt.meta: - augmented = vfs.augment_item_meta(repo, leaf_item, include_size=True) - out.write(augmented.meta.encode()) - else: - if stat.S_ISREG(mode): - with vfs.fopen(repo, leaf_item) as f: - for b in chunkyreader(f): - out.write(b) + if opt.bupm: + if not stat.S_ISDIR(mode): + o.fatal('%r is not a directory' % target) + _, bupm_oid = vfs.tree_data_and_bupm(repo, leaf_item.oid) + if bupm_oid: + with vfs.tree_data_reader(repo, bupm_oid) as meta_stream: + out.write(meta_stream.read()) + elif opt.meta: + augmented = vfs.augment_item_meta(repo, leaf_item, include_size=True) + out.write(augmented.meta.encode()) else: - o.fatal('%r is not a plain file' % target) + if stat.S_ISREG(mode): + with vfs.fopen(repo, leaf_item) as f: + for b in chunkyreader(f): + out.write(b) + else: + o.fatal('%r is not a plain file' % target) if saved_errors: log('warning: %d errors encountered\n' % len(saved_errors)) diff --git a/lib/bup/cmd/ftp.py b/lib/bup/cmd/ftp.py index 8639230..9a33754 100755 --- a/lib/bup/cmd/ftp.py +++ b/lib/bup/cmd/ftp.py @@ -9,7 +9,7 @@ import os, fnmatch, stat, sys, traceback from bup import _helpers, options, git, shquote, ls, vfs from bup.compat import argv_bytes -from bup.helpers import chunkyreader, log +from bup.helpers import chunkyreader, log, saved_errors from bup.io import byte_stream, path_msg from bup.repo import LocalRepo @@ -94,43 +94,32 @@ optspec = """ bup ftp [commands...] """ -def main(argv): - o = options.Options(optspec) - opt, flags, extra = o.parse_bytes(argv[1:]) - git.check_repo_or_die() +def inputiter(f, pwd, out): + if os.isatty(f.fileno()): + while 1: + prompt = b'bup %s> ' % (b'/'.join(name for name, item in pwd) or b'/', ) + if hasattr(_helpers, 'readline'): + try: + yield _helpers.readline(prompt) + except EOFError: + print() # Clear the line for the terminal's next prompt + break + else: + out.write(prompt) + out.flush() + read_line = f.readline() + if not read_line: + print('') + break + yield read_line + else: + for line in f: + yield line - global repo - sys.stdout.flush() - out = byte_stream(sys.stdout) - stdin = byte_stream(sys.stdin) - repo = LocalRepo() +def present_interface(stdin, out, extra, repo): pwd = vfs.resolve(repo, b'/') - rv = 0 - - def inputiter(f): - if os.isatty(f.fileno()): - while 1: - prompt = b'bup %s> ' % (b'/'.join(name for name, item in pwd) or b'/', ) - if hasattr(_helpers, 'readline'): - try: - yield _helpers.readline(prompt) - except EOFError: - print() # Clear the line for the terminal's next prompt - break - else: - out.write(prompt) - out.flush() - read_line = f.readline() - if not read_line: - print('') - break - yield read_line - else: - for line in f: - yield line - if extra: lines = (argv_bytes(arg) for arg in extra) @@ -143,7 +132,7 @@ def main(argv): # MacOS uses a slightly incompatible clone of libreadline _helpers.parse_and_bind(b'bind ^I rl_complete') _helpers.parse_and_bind(b'tab: complete') - lines = inputiter(stdin) + lines = inputiter(stdin, pwd, out) for line in lines: if not line.strip(): @@ -186,7 +175,6 @@ def main(argv): out.flush() elif cmd == b'get': if len(words) not in [2,3]: - rv = 1 raise Exception('Usage: get [localname]') rname = words[1] (dir,base) = os.path.split(rname) @@ -230,11 +218,23 @@ def main(argv): elif cmd in (b'quit', b'exit', b'bye'): break else: - rv = 1 raise Exception('no such command %r' % cmd) except Exception as e: - rv = 1 log('error: %s\n' % e) raise - sys.exit(rv) +def main(argv): + global repo + + o = options.Options(optspec) + opt, flags, extra = o.parse_bytes(argv[1:]) + + git.check_repo_or_die() + sys.stdout.flush() + out = byte_stream(sys.stdout) + stdin = byte_stream(sys.stdin) + with LocalRepo() as repo: + present_interface(stdin, out, extra, repo) + if saved_errors: + log('warning: %d errors encountered\n' % len(saved_errors)) + sys.exit(1) diff --git a/lib/bup/cmd/fuse.py b/lib/bup/cmd/fuse.py index 385bea9..2793712 100755 --- a/lib/bup/cmd/fuse.py +++ b/lib/bup/cmd/fuse.py @@ -147,17 +147,17 @@ def main(argv): o.fatal('only one mount point argument expected') git.check_repo_or_die() - repo = LocalRepo() - f = BupFs(repo=repo, verbose=opt.verbose, fake_metadata=(not opt.meta)) - - # This is likely wrong, but the fuse module doesn't currently accept bytes - f.fuse_args.mountpoint = extra[0] - - if opt.debug: - f.fuse_args.add('debug') - if opt.foreground: - f.fuse_args.setmod('foreground') - f.multithreaded = False - if opt.allow_other: - f.fuse_args.add('allow_other') - f.main() + with LocalRepo() as repo: + f = BupFs(repo=repo, verbose=opt.verbose, fake_metadata=(not opt.meta)) + + # This is likely wrong, but the fuse module doesn't currently accept bytes + f.fuse_args.mountpoint = extra[0] + + if opt.debug: + f.fuse_args.add('debug') + if opt.foreground: + f.fuse_args.setmod('foreground') + f.multithreaded = False + if opt.allow_other: + f.fuse_args.add('allow_other') + f.main() diff --git a/lib/bup/cmd/join.py b/lib/bup/cmd/join.py index caf524a..bb66585 100755 --- a/lib/bup/cmd/join.py +++ b/lib/bup/cmd/join.py @@ -31,21 +31,21 @@ def main(argv): extra = linereader(stdin) ret = 0 - repo = RemoteRepo(opt.remote) if opt.remote else LocalRepo() - - if opt.o: - outfile = open(opt.o, 'wb') - else: - sys.stdout.flush() - outfile = byte_stream(sys.stdout) - - for ref in [argv_bytes(x) for x in extra]: - try: - for blob in repo.join(ref): - outfile.write(blob) - except KeyError as e: - outfile.flush() - log('error: %s\n' % e) - ret = 1 + with RemoteRepo(opt.remote) if opt.remote else LocalRepo() as repo: + + if opt.o: + outfile = open(opt.o, 'wb') + else: + sys.stdout.flush() + outfile = byte_stream(sys.stdout) + + for ref in [argv_bytes(x) for x in extra]: + try: + for blob in repo.join(ref): + outfile.write(blob) + except KeyError as e: + outfile.flush() + log('error: %s\n' % e) + ret = 1 sys.exit(ret) diff --git a/lib/bup/cmd/prune_older.py b/lib/bup/cmd/prune_older.py index e0f8545..d5a8f1c 100755 --- a/lib/bup/cmd/prune_older.py +++ b/lib/bup/cmd/prune_older.py @@ -153,8 +153,9 @@ def main(argv): if not opt.pretend: die_if_errors() - repo = LocalRepo() - bup_rm(repo, removals, compression=opt.compress, verbosity=opt.verbose) + with LocalRepo() as repo: + bup_rm(repo, removals, compression=opt.compress, + verbosity=opt.verbose) if opt.gc: die_if_errors() bup_gc(threshold=opt.gc_threshold, diff --git a/lib/bup/cmd/restore.py b/lib/bup/cmd/restore.py index ee403b6..0dcee26 100755 --- a/lib/bup/cmd/restore.py +++ b/lib/bup/cmd/restore.py @@ -242,61 +242,61 @@ def main(argv): mkdirp(opt.outdir) os.chdir(opt.outdir) - repo = RemoteRepo(opt.remote) if opt.remote else LocalRepo() - top = fsencode(os.getcwd()) - hardlinks = {} - for path in [argv_bytes(x) for x in extra]: - if not valid_restore_path(path): - add_error("path %r doesn't include a branch and revision" % path) - continue - try: - resolved = vfs.resolve(repo, path, want_meta=True, follow=False) - except vfs.IOError as e: - add_error(e) - continue - if len(resolved) == 3 and resolved[2][0] == b'latest': - # Follow latest symlink to the actual save + with RemoteRepo(opt.remote) if opt.remote else LocalRepo() as repo: + top = fsencode(os.getcwd()) + hardlinks = {} + for path in [argv_bytes(x) for x in extra]: + if not valid_restore_path(path): + add_error("path %r doesn't include a branch and revision" % path) + continue try: - resolved = vfs.resolve(repo, b'latest', parent=resolved[:-1], - want_meta=True) + resolved = vfs.resolve(repo, path, want_meta=True, follow=False) except vfs.IOError as e: add_error(e) continue - # Rename it back to 'latest' - resolved = tuple(elt if i != 2 else (b'latest',) + elt[1:] - for i, elt in enumerate(resolved)) - path_parent, path_name = os.path.split(path) - leaf_name, leaf_item = resolved[-1] - if not leaf_item: - add_error('error: cannot access %r in %r' - % (b'/'.join(name for name, item in resolved), - path)) - continue - if not path_name or path_name == b'.': - # Source is /foo/what/ever/ or /foo/what/ever/. -- extract - # what/ever/* to the current directory, and if name == '.' - # (i.e. /foo/what/ever/.), then also restore what/ever's - # metadata to the current directory. - treeish = vfs.item_mode(leaf_item) - if not treeish: - add_error('%r cannot be restored as a directory' % path) + if len(resolved) == 3 and resolved[2][0] == b'latest': + # Follow latest symlink to the actual save + try: + resolved = vfs.resolve(repo, b'latest', parent=resolved[:-1], + want_meta=True) + except vfs.IOError as e: + add_error(e) + continue + # Rename it back to 'latest' + resolved = tuple(elt if i != 2 else (b'latest',) + elt[1:] + for i, elt in enumerate(resolved)) + path_parent, path_name = os.path.split(path) + leaf_name, leaf_item = resolved[-1] + if not leaf_item: + add_error('error: cannot access %r in %r' + % (b'/'.join(name for name, item in resolved), + path)) + continue + if not path_name or path_name == b'.': + # Source is /foo/what/ever/ or /foo/what/ever/. -- extract + # what/ever/* to the current directory, and if name == '.' + # (i.e. /foo/what/ever/.), then also restore what/ever's + # metadata to the current directory. + treeish = vfs.item_mode(leaf_item) + if not treeish: + add_error('%r cannot be restored as a directory' % path) + else: + items = vfs.contents(repo, leaf_item, want_meta=True) + dot, leaf_item = next(items, None) + assert dot == b'.' + for sub_name, sub_item in items: + restore(repo, b'', sub_name, sub_item, top, + opt.sparse, opt.numeric_ids, owner_map, + exclude_rxs, verbosity, hardlinks) + if path_name == b'.': + leaf_item = vfs.augment_item_meta(repo, leaf_item, + include_size=True) + apply_metadata(leaf_item.meta, b'.', + opt.numeric_ids, owner_map) else: - items = vfs.contents(repo, leaf_item, want_meta=True) - dot, leaf_item = next(items, None) - assert dot == b'.' - for sub_name, sub_item in items: - restore(repo, b'', sub_name, sub_item, top, - opt.sparse, opt.numeric_ids, owner_map, - exclude_rxs, verbosity, hardlinks) - if path_name == b'.': - leaf_item = vfs.augment_item_meta(repo, leaf_item, - include_size=True) - apply_metadata(leaf_item.meta, b'.', - opt.numeric_ids, owner_map) - else: - restore(repo, b'', leaf_name, leaf_item, top, - opt.sparse, opt.numeric_ids, owner_map, - exclude_rxs, verbosity, hardlinks) + restore(repo, b'', leaf_name, leaf_item, top, + opt.sparse, opt.numeric_ids, owner_map, + exclude_rxs, verbosity, hardlinks) if verbosity >= 0: progress('Restoring: %d, done.\n' % total_restored) diff --git a/lib/bup/cmd/rm.py b/lib/bup/cmd/rm.py index 2867657..4c4a0f0 100755 --- a/lib/bup/cmd/rm.py +++ b/lib/bup/cmd/rm.py @@ -27,7 +27,7 @@ def main(argv): o.fatal('no paths specified') check_repo_or_die() - repo = LocalRepo() - bup_rm(repo, [argv_bytes(x) for x in extra], - compression=opt.compress, verbosity=opt.verbose) + with LocalRepo() as repo: + bup_rm(repo, [argv_bytes(x) for x in extra], + compression=opt.compress, verbosity=opt.verbose) die_if_errors() diff --git a/lib/bup/cmd/server.py b/lib/bup/cmd/server.py index 56b6d44..5e2b6af 100755 --- a/lib/bup/cmd/server.py +++ b/lib/bup/cmd/server.py @@ -289,7 +289,7 @@ commands = { } def main(argv): - global suspended_w + global repo, suspended_w o = options.Options(optspec) opt, flags, extra = o.parse_bytes(argv[1:]) @@ -303,7 +303,8 @@ def main(argv): sys.stdout.flush() conn = Conn(byte_stream(sys.stdin), byte_stream(sys.stdout)) lr = linereader(conn) - with finalized(None, lambda _: suspended_w and suspended_w.close()): + with finalized(None, lambda _: repo and repo.close()), \ + finalized(None, lambda _: suspended_w and suspended_w.close()): for _line in lr: line = _line.strip() if not line: diff --git a/lib/bup/cmd/web.py b/lib/bup/cmd/web.py index 20333cb..c609d87 100755 --- a/lib/bup/cmd/web.py +++ b/lib/bup/cmd/web.py @@ -290,30 +290,30 @@ def main(argv): except AttributeError: sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) - application = tornado.web.Application([ - (r"(?P/.*)", BupRequestHandler, dict(repo=LocalRepo())), - ], **settings) - - http_server = HTTPServer(application) - io_loop_pending = IOLoop.instance() - - if isinstance(address, InetAddress): - sockets = tornado.netutil.bind_sockets(address.port, address.host) - http_server.add_sockets(sockets) - print('Serving HTTP on %s:%d...' % sockets[0].getsockname()[0:2]) - if opt.browser: - browser_addr = 'http://' + address[0] + ':' + str(address[1]) - io_loop_pending.add_callback(lambda : webbrowser.open(browser_addr)) - elif isinstance(address, UnixAddress): - unix_socket = bind_unix_socket(address.path) - http_server.add_socket(unix_socket) - print('Serving HTTP on filesystem socket %r' % address.path) - else: - log('error: unexpected address %r', address) - sys.exit(1) + with LocalRepo() as repo: + handlers = [ (r"(?P/.*)", BupRequestHandler, dict(repo=repo))] + application = tornado.web.Application(handlers, **settings) + + http_server = HTTPServer(application) + io_loop_pending = IOLoop.instance() + + if isinstance(address, InetAddress): + sockets = tornado.netutil.bind_sockets(address.port, address.host) + http_server.add_sockets(sockets) + print('Serving HTTP on %s:%d...' % sockets[0].getsockname()[0:2]) + if opt.browser: + browser_addr = 'http://' + address[0] + ':' + str(address[1]) + io_loop_pending.add_callback(lambda : webbrowser.open(browser_addr)) + elif isinstance(address, UnixAddress): + unix_socket = bind_unix_socket(address.path) + http_server.add_socket(unix_socket) + print('Serving HTTP on filesystem socket %r' % address.path) + else: + log('error: unexpected address %r', address) + sys.exit(1) - io_loop = io_loop_pending - io_loop.start() + io_loop = io_loop_pending + io_loop.start() if saved_errors: log('WARNING: %d errors encountered while saving.\n' % len(saved_errors)) diff --git a/lib/bup/ls.py b/lib/bup/ls.py index 755c998..c70fa4e 100644 --- a/lib/bup/ls.py +++ b/lib/bup/ls.py @@ -193,5 +193,6 @@ def via_cmdline(args, out=None, onabort=None): """ assert out opt = opts_from_cmdline(args, onabort=onabort) - repo = RemoteRepo(argv_bytes(opt.remote)) if opt.remote else LocalRepo() - return within_repo(repo, opt, out) + with RemoteRepo(argv_bytes(opt.remote)) if opt.remote \ + else LocalRepo() as repo: + return within_repo(repo, opt, out) diff --git a/lib/bup/repo.py b/lib/bup/repo.py index d52aa0b..64feeb7 100644 --- a/lib/bup/repo.py +++ b/lib/bup/repo.py @@ -6,6 +6,7 @@ from functools import partial from bup import client, git, vfs from bup.compat import pending_raise + _next_repo_id = 0 _repo_ids = {} @@ -29,9 +30,6 @@ class LocalRepo: def close(self): pass - def __del__(self): - self.close() - def __enter__(self): return self @@ -100,9 +98,6 @@ class RemoteRepo: self.client.close() self.client = None - def __del__(self): - self.close() - def __enter__(self): return self diff --git a/test/int/test_metadata.py b/test/int/test_metadata.py index fd3a00c..b3ff3a5 100644 --- a/test/int/test_metadata.py +++ b/test/int/test_metadata.py @@ -138,27 +138,27 @@ def test_metadata_method(tmpdir): ex(bup_path, b'-d', bup_dir, b'index', b'-v', data_path) ex(bup_path, b'-d', bup_dir, b'save', b'-tvvn', b'test', data_path) git.check_repo_or_die(bup_dir) - repo = LocalRepo() - resolved = vfs.resolve(repo, - b'/test/latest' + resolve_parent(data_path), - follow=False) - leaf_name, leaf_item = resolved[-1] - m = leaf_item.meta - WVPASS(m.mtime == test_time2) - WVPASS(leaf_name == b'foo') - contents = tuple(vfs.contents(repo, leaf_item)) - WVPASS(len(contents) == 3) - WVPASSEQ(frozenset(name for name, item in contents), - frozenset((b'.', b'file', b'symlink'))) - for name, item in contents: - if name == b'file': - m = item.meta - WVPASS(m.mtime == test_time1) - elif name == b'symlink': - m = item.meta - WVPASSEQ(m.symlink_target, b'file') - WVPASSEQ(m.size, 4) - WVPASSEQ(m.mtime, 0) + with LocalRepo() as repo: + resolved = vfs.resolve(repo, + b'/test/latest' + resolve_parent(data_path), + follow=False) + leaf_name, leaf_item = resolved[-1] + m = leaf_item.meta + WVPASS(m.mtime == test_time2) + WVPASS(leaf_name == b'foo') + contents = tuple(vfs.contents(repo, leaf_item)) + WVPASS(len(contents) == 3) + WVPASSEQ(frozenset(name for name, item in contents), + frozenset((b'.', b'file', b'symlink'))) + for name, item in contents: + if name == b'file': + m = item.meta + WVPASS(m.mtime == test_time1) + elif name == b'symlink': + m = item.meta + WVPASSEQ(m.symlink_target, b'file') + WVPASSEQ(m.size, 4) + WVPASSEQ(m.mtime, 0) def _first_err(): diff --git a/test/int/test_vfs.py b/test/int/test_vfs.py index f9b3f65..010b39e 100644 --- a/test/int/test_vfs.py +++ b/test/int/test_vfs.py @@ -161,45 +161,45 @@ def test_misc(tmpdir): ex((bup_path, b'index', b'-v', data_path)) ex((bup_path, b'save', b'-d', b'100000', b'-tvvn', b'test', b'--strip', data_path)) - repo = LocalRepo() - - ls_tree = exo((b'git', b'ls-tree', b'test', b'symlink')).out - mode, typ, oidx, name = ls_tree.strip().split(None, 3) - assert name == b'symlink' - link_item = vfs.Item(oid=unhexlify(oidx), meta=int(mode, 8)) - wvpasseq(b'file', vfs.readlink(repo, link_item)) - - ls_tree = exo((b'git', b'ls-tree', b'test', b'file')).out - mode, typ, oidx, name = ls_tree.strip().split(None, 3) - assert name == b'file' - file_item = vfs.Item(oid=unhexlify(oidx), meta=int(mode, 8)) - wvexcept(Exception, vfs.readlink, repo, file_item) - - wvpasseq(4, vfs.item_size(repo, link_item)) - wvpasseq(7, vfs.item_size(repo, file_item)) - meta = metadata.from_path(fsencode(__file__)) - meta.size = 42 - fake_item = file_item._replace(meta=meta) - wvpasseq(42, vfs.item_size(repo, fake_item)) - - _, fakelink_item = vfs.resolve(repo, b'/test/latest', follow=False)[-1] - wvpasseq(17, vfs.item_size(repo, fakelink_item)) - - run_augment_item_meta_tests(repo, - b'/test/latest/file', 7, - b'/test/latest/symlink', b'file') - - # FIXME: this caused StopIteration - #_, file_item = vfs.resolve(repo, '/file')[-1] - _, file_item = vfs.resolve(repo, b'/test/latest/file')[-1] - file_copy = vfs.copy_item(file_item) - wvpass(file_copy is not file_item) - wvpass(file_copy.meta is not file_item.meta) - wvpass(isinstance(file_copy, tuple)) - wvpass(file_item.meta.user) - wvpass(file_copy.meta.user) - file_copy.meta.user = None - wvpass(file_item.meta.user) + + with LocalRepo() as repo: + ls_tree = exo((b'git', b'ls-tree', b'test', b'symlink')).out + mode, typ, oidx, name = ls_tree.strip().split(None, 3) + assert name == b'symlink' + link_item = vfs.Item(oid=unhexlify(oidx), meta=int(mode, 8)) + wvpasseq(b'file', vfs.readlink(repo, link_item)) + + ls_tree = exo((b'git', b'ls-tree', b'test', b'file')).out + mode, typ, oidx, name = ls_tree.strip().split(None, 3) + assert name == b'file' + file_item = vfs.Item(oid=unhexlify(oidx), meta=int(mode, 8)) + wvexcept(Exception, vfs.readlink, repo, file_item) + + wvpasseq(4, vfs.item_size(repo, link_item)) + wvpasseq(7, vfs.item_size(repo, file_item)) + meta = metadata.from_path(fsencode(__file__)) + meta.size = 42 + fake_item = file_item._replace(meta=meta) + wvpasseq(42, vfs.item_size(repo, fake_item)) + + _, fakelink_item = vfs.resolve(repo, b'/test/latest', follow=False)[-1] + wvpasseq(17, vfs.item_size(repo, fakelink_item)) + + run_augment_item_meta_tests(repo, + b'/test/latest/file', 7, + b'/test/latest/symlink', b'file') + + # FIXME: this caused StopIteration + #_, file_item = vfs.resolve(repo, '/file')[-1] + _, file_item = vfs.resolve(repo, b'/test/latest/file')[-1] + file_copy = vfs.copy_item(file_item) + wvpass(file_copy is not file_item) + wvpass(file_copy.meta is not file_item.meta) + wvpass(isinstance(file_copy, tuple)) + wvpass(file_item.meta.user) + wvpass(file_copy.meta.user) + file_copy.meta.user = None + wvpass(file_item.meta.user) def write_sized_random_content(parent_dir, size, seed): verbose = 0 @@ -261,38 +261,38 @@ def test_read_and_seek(tmpdir): environ[b'GIT_DIR'] = bup_dir environ[b'BUP_DIR'] = bup_dir git.repodir = bup_dir - repo = LocalRepo() - data_path = tmpdir + b'/src' - os.mkdir(data_path) - seed = randint(-(1 << 31), (1 << 31) - 1) - rand = Random() - rand.seed(seed) - print('test_read seed:', seed, file=sys.stderr) - max_size = 2 * 1024 * 1024 - sizes = set((rand.randint(1, max_size) for _ in range(5))) - sizes.add(1) - sizes.add(max_size) - for size in sizes: - write_sized_random_content(data_path, size, seed) - ex((bup_path, b'init')) - ex((bup_path, b'index', b'-v', data_path)) - ex((bup_path, b'save', b'-d', b'100000', b'-tvvn', b'test', - b'--strip', data_path)) - read_sizes = set((rand.randint(1, max_size) for _ in range(10))) - sizes.add(1) - sizes.add(max_size) - print('test_read src sizes:', sizes, file=sys.stderr) - print('test_read read sizes:', read_sizes, file=sys.stderr) - for size in sizes: - res = resolve(repo, b'/test/latest/' + str(size).encode('ascii')) - _, item = res[-1] - wvpasseq(size, vfs.item_size(repo, res[-1][1])) - validate_vfs_streaming_read(repo, item, - b'%s/%d' % (data_path, size), - read_sizes) - validate_vfs_seeking_read(repo, item, - b'%s/%d' % (data_path, size), - read_sizes) + with LocalRepo() as repo: + data_path = tmpdir + b'/src' + os.mkdir(data_path) + seed = randint(-(1 << 31), (1 << 31) - 1) + rand = Random() + rand.seed(seed) + print('test_read seed:', seed, file=sys.stderr) + max_size = 2 * 1024 * 1024 + sizes = set((rand.randint(1, max_size) for _ in range(5))) + sizes.add(1) + sizes.add(max_size) + for size in sizes: + write_sized_random_content(data_path, size, seed) + ex((bup_path, b'init')) + ex((bup_path, b'index', b'-v', data_path)) + ex((bup_path, b'save', b'-d', b'100000', b'-tvvn', b'test', + b'--strip', data_path)) + read_sizes = set((rand.randint(1, max_size) for _ in range(10))) + sizes.add(1) + sizes.add(max_size) + print('test_read src sizes:', sizes, file=sys.stderr) + print('test_read read sizes:', read_sizes, file=sys.stderr) + for size in sizes: + res = resolve(repo, b'/test/latest/' + str(size).encode('ascii')) + _, item = res[-1] + wvpasseq(size, vfs.item_size(repo, res[-1][1])) + validate_vfs_streaming_read(repo, item, + b'%s/%d' % (data_path, size), + read_sizes) + validate_vfs_seeking_read(repo, item, + b'%s/%d' % (data_path, size), + read_sizes) def test_contents_with_mismatched_bupm_git_ordering(tmpdir): bup_dir = tmpdir + b'/bup' @@ -310,26 +310,26 @@ def test_contents_with_mismatched_bupm_git_ordering(tmpdir): save_name = strftime('%Y-%m-%d-%H%M%S', localtime(save_utc)).encode('ascii') ex((bup_path, b'save', b'-tvvn', b'test', b'-d', b'%d' % save_utc, b'--strip', data_path)) - repo = LocalRepo() - tip_sref = exo((b'git', b'show-ref', b'refs/heads/test')).out - tip_oidx = tip_sref.strip().split()[0] - tip_tree_oidx = exo((b'git', b'log', b'--pretty=%T', b'-n1', - tip_oidx)).out.strip() - tip_tree_oid = unhexlify(tip_tree_oidx) - tip_tree = tree_dict(repo, tip_tree_oid) - - name, item = vfs.resolve(repo, b'/test/latest')[2] - wvpasseq(save_name, name) - expected = frozenset((x.name, vfs.Item(oid=x.oid, meta=x.meta)) - for x in (tip_tree[name] - for name in (b'.', b'foo', b'foo.'))) - contents = tuple(vfs.contents(repo, item)) - wvpasseq(expected, frozenset(contents)) - # Spot check, in case tree_dict shares too much code with the vfs - name, item = next(((n, i) for n, i in contents if n == b'foo')) - wvpass(S_ISDIR(item.meta)) - name, item = next(((n, i) for n, i in contents if n == b'foo.')) - wvpass(S_ISREG(item.meta.mode)) + with LocalRepo() as repo: + tip_sref = exo((b'git', b'show-ref', b'refs/heads/test')).out + tip_oidx = tip_sref.strip().split()[0] + tip_tree_oidx = exo((b'git', b'log', b'--pretty=%T', b'-n1', + tip_oidx)).out.strip() + tip_tree_oid = unhexlify(tip_tree_oidx) + tip_tree = tree_dict(repo, tip_tree_oid) + + name, item = vfs.resolve(repo, b'/test/latest')[2] + wvpasseq(save_name, name) + expected = frozenset((x.name, vfs.Item(oid=x.oid, meta=x.meta)) + for x in (tip_tree[name] + for name in (b'.', b'foo', b'foo.'))) + contents = tuple(vfs.contents(repo, item)) + wvpasseq(expected, frozenset(contents)) + # Spot check, in case tree_dict shares too much code with the vfs + name, item = next(((n, i) for n, i in contents if n == b'foo')) + wvpass(S_ISDIR(item.meta)) + name, item = next(((n, i) for n, i in contents if n == b'foo.')) + wvpass(S_ISREG(item.meta.mode)) def test_duplicate_save_dates(tmpdir): bup_dir = tmpdir + b'/bup' @@ -348,25 +348,25 @@ def test_duplicate_save_dates(tmpdir): for i in range(11): ex((bup_path, b'save', b'-d', b'100000', b'-n', b'test', data_path)) - repo = LocalRepo() - res = vfs.resolve(repo, b'/test') - wvpasseq(2, len(res)) - name, revlist = res[-1] - wvpasseq(b'test', name) - wvpasseq((b'.', - b'1970-01-02-034640-00', - b'1970-01-02-034640-01', - b'1970-01-02-034640-02', - b'1970-01-02-034640-03', - b'1970-01-02-034640-04', - b'1970-01-02-034640-05', - b'1970-01-02-034640-06', - b'1970-01-02-034640-07', - b'1970-01-02-034640-08', - b'1970-01-02-034640-09', - b'1970-01-02-034640-10', - b'latest'), - tuple(sorted(x[0] for x in vfs.contents(repo, revlist)))) + with LocalRepo() as repo: + res = vfs.resolve(repo, b'/test') + wvpasseq(2, len(res)) + name, revlist = res[-1] + wvpasseq(b'test', name) + wvpasseq((b'.', + b'1970-01-02-034640-00', + b'1970-01-02-034640-01', + b'1970-01-02-034640-02', + b'1970-01-02-034640-03', + b'1970-01-02-034640-04', + b'1970-01-02-034640-05', + b'1970-01-02-034640-06', + b'1970-01-02-034640-07', + b'1970-01-02-034640-08', + b'1970-01-02-034640-09', + b'1970-01-02-034640-10', + b'latest'), + tuple(sorted(x[0] for x in vfs.contents(repo, revlist)))) def test_item_read_write(): x = vfs.Root(meta=13)