]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/cmd/save.py
chmod -x lib/bup/cmd/*.py
[bup.git] / lib / bup / cmd / save.py
old mode 100755 (executable)
new mode 100644 (file)
index 0e8ea50..88f74d7
@@ -1,13 +1,13 @@
 
 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,
@@ -109,7 +109,7 @@ def opts_from_cmdline(argv):
 
     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
@@ -225,18 +225,6 @@ def save_tree(opt, w):
                      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
 
@@ -255,8 +243,8 @@ def save_tree(opt, w):
 
     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()
@@ -286,7 +274,8 @@ def save_tree(opt, w):
     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)
@@ -470,7 +459,6 @@ def save_tree(opt, w):
     # 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
 
 
@@ -496,43 +484,56 @@ def main(argv):
     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))