]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/rm.py
index: remove vestigial buffer and sys imports
[bup.git] / lib / bup / rm.py
index 4f5742d2ef922f8010c0e8450490f0ebc99923bf..e43abc5b7e1de1ac3b08e892dea71e35e6961447 100644 (file)
@@ -1,8 +1,10 @@
 
+from __future__ import absolute_import
 import sys
 
-from bup import git, vfs
+from bup import compat, git, vfs
 from bup.client import ClientError
+from bup.compat import hexstr
 from bup.git import get_commit_items
 from bup.helpers import add_error, die_if_errors, log, saved_errors
 
@@ -38,14 +40,19 @@ def filter_branch(tip_commit_hex, exclude, writer):
         last_c, tree = append_commit(c.encode('hex'), last_c, git.cp(), writer)
     return last_c
 
+def commit_oid(item):
+    if isinstance(item, vfs.Commit):
+        return item.coid
+    assert isinstance(item, vfs.RevList)
+    return item.oid
 
 def rm_saves(saves, writer):
     assert(saves)
-    branch_node = saves[0].parent
-    for save in saves: # Be certain they're all on the same branch
-        assert(save.parent == branch_node)
-    rm_commits = frozenset([x.dereference().hash for x in saves])
-    orig_tip = branch_node.hash
+    first_branch_item = saves[0][1]
+    for save, branch in saves: # Be certain they're all on the same branch
+        assert(branch == first_branch_item)
+    rm_commits = frozenset([commit_oid(save) for save, branch in saves])
+    orig_tip = commit_oid(first_branch_item)
     new_tip = filter_branch(orig_tip.encode('hex'),
                             lambda x: x in rm_commits,
                             writer)
@@ -54,7 +61,7 @@ def rm_saves(saves, writer):
     return orig_tip, new_tip
 
 
-def dead_items(vfs_top, paths):
+def dead_items(repo, paths):
     """Return an optimized set of removals, reporting errors via
     add_error, and if there are any errors, return None, None."""
     dead_branches = {}
@@ -62,46 +69,51 @@ def dead_items(vfs_top, paths):
     # Scan for bad requests, and opportunities to optimize
     for path in paths:
         try:
-            n = vfs_top.lresolve(path)
-        except vfs.NodeError as e:
-            add_error('unable to resolve %s: %s' % (path, e))
+            resolved = vfs.resolve(repo, path, follow=False)
+        except vfs.IOError as e:
+            add_error(e)
+            continue
         else:
-            if isinstance(n, vfs.BranchList): # rm /foo
-                branchname = n.name
-                dead_branches[branchname] = n
-                dead_saves.pop(branchname, None) # rm /foo obviates rm /foo/bar
-            elif isinstance(n, vfs.FakeSymlink) and isinstance(n.parent,
-                                                               vfs.BranchList):
-                if n.name == 'latest':
+            leaf_name, leaf_item = resolved[-1]
+            if not leaf_item:
+                add_error('error: cannot access %r in %r'
+                          % ('/'.join(name for name, item in resolved),
+                             path))
+                continue
+            if isinstance(leaf_item, vfs.RevList):  # rm /foo
+                branchname = leaf_name
+                dead_branches[branchname] = leaf_item
+                dead_saves.pop(branchname, None)  # rm /foo obviates rm /foo/bar
+            elif isinstance(leaf_item, vfs.Commit):  # rm /foo/bar
+                if leaf_name == 'latest':
                     add_error("error: cannot delete 'latest' symlink")
                 else:
-                    branchname = n.parent.name
+                    branchname, branchitem = resolved[-2]
                     if branchname not in dead_branches:
-                        dead_saves.setdefault(branchname, []).append(n)
+                        dead = leaf_item, branchitem
+                        dead_saves.setdefault(branchname, []).append(dead)
             else:
-                add_error("don't know how to remove %r yet" % n.fullname())
+                add_error("don't know how to remove %r yet" % path)
     if saved_errors:
         return None, None
     return dead_branches, dead_saves
 
 
-def bup_rm(paths, compression=6, verbosity=None):
-    root = vfs.RefList(None)
-
-    dead_branches, dead_saves = dead_items(root, paths)
+def bup_rm(repo, paths, compression=6, verbosity=None):
+    dead_branches, dead_saves = dead_items(repo, paths)
     die_if_errors('not proceeding with any removals\n')
 
     updated_refs = {}  # ref_name -> (original_ref, tip_commit(bin))
 
-    for branch, node in dead_branches.iteritems():
-        ref = 'refs/heads/' + branch
+    for branchname, branchitem in compat.items(dead_branches):
+        ref = 'refs/heads/' + branchname
         assert(not ref in updated_refs)
-        updated_refs[ref] = (node.hash, None)
+        updated_refs[ref] = (branchitem.oid, None)
 
     if dead_saves:
         writer = git.PackWriter(compression_level=compression)
         try:
-            for branch, saves in dead_saves.iteritems():
+            for branch, saves in compat.items(dead_saves):
                 assert(saves)
                 updated_refs['refs/heads/' + branch] = rm_saves(saves, writer)
         except:
@@ -116,7 +128,7 @@ def bup_rm(paths, compression=6, verbosity=None):
     # Only update the refs here, at the very end, so that if something
     # goes wrong above, the old refs will be undisturbed.  Make an attempt
     # to update each ref.
-    for ref_name, info in updated_refs.iteritems():
+    for ref_name, info in compat.items(updated_refs):
         orig_ref, new_ref = info
         try:
             if not new_ref:
@@ -124,17 +136,17 @@ def bup_rm(paths, compression=6, verbosity=None):
             else:
                 git.update_ref(ref_name, new_ref, orig_ref)
                 if verbosity:
-                    new_hex = new_ref.encode('hex')
-                    if orig_ref:
-                        orig_hex = orig_ref.encode('hex')
-                        log('updated %r (%s -> %s)\n'
-                            % (ref_name, orig_hex, new_hex))
-                    else:
-                        log('updated %r (%s)\n' % (ref_name, new_hex))
+                    log('updated %r (%s%s)\n'
+                        % (ref_name,
+                           hexstr(orig_ref) + ' -> ' if orig_ref else '',
+                           hexstr(new_ref)))
         except (git.GitError, ClientError) as ex:
             if new_ref:
-                add_error('while trying to update %r (%s -> %s): %s'
-                          % (ref_name, orig_ref, new_ref, ex))
+                add_error('while trying to update %r (%s%s): %s'
+                          % (ref_name,
+                             hexstr(orig_ref) + ' -> ' if orig_ref else '',
+                             hexstr(new_ref),
+                             ex))
             else:
                 add_error('while trying to delete %r (%s): %s'
-                          % (ref_name, orig_ref, ex))
+                          % (ref_name, hexstr(orig_ref), ex))