from __future__ import absolute_import, print_function
from binascii import hexlify
-from errno import EACCES
+from errno import ENOENT
from io import BytesIO
import math, os, stat, sys, time
from bup import compat, hashsplit, git, options, index, client, metadata
from bup import hlinkdb
-from bup.compat import argv_bytes, environ
+from bup.compat import argv_bytes, environ, nullcontext
from bup.hashsplit import GIT_MODE_TREE, GIT_MODE_FILE, GIT_MODE_SYMLINK
from bup.helpers import (add_error, grafted_path_components, handle_ctrl_c,
hostname, istty2, log, parse_date_or_fatal, parse_num,
return opt
-def save_tree(opt, w):
+def save_tree(opt, reader, hlink_db, msr, w):
# Metadata is stored in a file named .bupm in each directory. The
# first metadata entry will be the metadata for the current directory.
# The remaining entries will be for each of the other directory
remainstr, kpsstr))
- indexfile = opt.indexfile or git.repo(b'bupindex')
- r = index.Reader(indexfile)
- try:
- msr = index.MetaStoreReader(indexfile + b'.meta')
- except IOError as ex:
- if ex.errno != EACCES:
- raise
- log('error: cannot access %r; have you run bup index?'
- % path_msg(indexfile))
- sys.exit(1)
- hlink_db = hlinkdb.HLinkDB(indexfile + b'.hlink')
-
def already_saved(ent):
return ent.is_valid() and w.exists(ent.sha) and ent.sha
total = ftotal = 0
if opt.progress:
- for transname, ent in r.filter(opt.sources,
- wantrecurse=wantrecurse_pre):
+ for transname, ent in reader.filter(opt.sources,
+ wantrecurse=wantrecurse_pre):
if not (ftotal % 10024):
qprogress('Reading index: %d\r' % ftotal)
exists = ent.exists()
fcount = 0
lastskip_name = None
lastdir = b''
- for transname, ent in r.filter(opt.sources, wantrecurse=wantrecurse_during):
+ for transname, ent in reader.filter(opt.sources,
+ wantrecurse=wantrecurse_during):
(dir, file) = os.path.split(ent.name)
exists = (ent.flags & index.IX_EXISTS)
hashvalid = already_saved(ent)
# When there's a collision, use empty metadata for the root.
tree = _pop(dir_metadata = metadata.Metadata() if root_collision else None)
- msr.close()
return tree
remote_dest = opt.remote or opt.is_reverse
if not remote_dest:
repo = git
- cli = None
- w = git.PackWriter(compression_level=opt.compress)
+ cli = nullcontext()
else:
try:
cli = repo = client.Client(opt.remote)
except client.ClientError as e:
log('error: %s' % e)
sys.exit(1)
- w = cli.new_packwriter(compression_level=opt.compress)
-
- sys.stdout.flush()
- out = byte_stream(sys.stdout)
-
- if opt.name:
- refname = b'refs/heads/%s' % opt.name
- parent = repo.read_ref(refname)
- else:
- refname = parent = None
- tree = save_tree(opt, w)
- if opt.tree:
- out.write(hexlify(tree))
- out.write(b'\n')
- if opt.commit or opt.name:
- commit = commit_tree(tree, parent, opt.date, argv, w)
- if opt.commit:
- out.write(hexlify(commit))
- out.write(b'\n')
+ # cli creation must be last nontrivial command in each if clause above
+ with cli:
+ if not remote_dest:
+ w = git.PackWriter(compression_level=opt.compress)
+ else:
+ w = cli.new_packwriter(compression_level=opt.compress)
- w.close()
+ with w:
+ sys.stdout.flush()
+ out = byte_stream(sys.stdout)
- # packwriter must be closed before we can update the ref
- if opt.name:
- repo.update_ref(refname, commit, parent)
+ if opt.name:
+ refname = b'refs/heads/%s' % opt.name
+ parent = repo.read_ref(refname)
+ else:
+ refname = parent = None
- if cli:
- cli.close()
+ indexfile = opt.indexfile or git.repo(b'bupindex')
+ try:
+ msr = index.MetaStoreReader(indexfile + b'.meta')
+ except IOError as ex:
+ if ex.errno != ENOENT:
+ raise
+ log('error: cannot access %r; have you run bup index?'
+ % path_msg(indexfile))
+ sys.exit(1)
+ with msr, \
+ hlinkdb.HLinkDB(indexfile + b'.hlink') as hlink_db, \
+ index.Reader(indexfile) as reader:
+ tree = save_tree(opt, reader, hlink_db, msr, w)
+ if opt.tree:
+ out.write(hexlify(tree))
+ out.write(b'\n')
+ if opt.commit or opt.name:
+ commit = commit_tree(tree, parent, opt.date, argv, w)
+ if opt.commit:
+ out.write(hexlify(commit))
+ out.write(b'\n')
+
+ # packwriter must be closed before we can update the ref
+ if opt.name:
+ repo.update_ref(refname, commit, parent)
if saved_errors:
log('WARNING: %d errors encountered while saving.\n' % len(saved_errors))