]> arthur.barton.de Git - bup.git/blobdiff - cmd-save.py
Fix some problems running on older Debian.
[bup.git] / cmd-save.py
index 740a6fd687620283bfd9c53e87140307d8c9fdc0..e68539c730a3e57ac6f1213fcd8c78c528bf4404 100755 (executable)
@@ -1,29 +1,36 @@
-#!/usr/bin/env python
-import sys, re, errno
+#!/usr/bin/env python2.5
+import sys, re, errno, stat
 import hashsplit, git, options
 from helpers import *
 
-saved_errors = []
 
+saved_errors = []
 def add_error(e):
     saved_errors.append(e)
     log('\n%s\n' % e)
 
 
+def _direxpand(name):
+    st = os.lstat(name)
+    try:
+        if stat.S_ISDIR(st.st_mode):
+            for sub in os.listdir(name):
+                subfull = os.path.join(name, sub)
+                for fn_st in _direxpand(subfull):
+                    yield fn_st
+        else:
+            yield (name,st)
+    except OSError, e:
+        if e.errno in [errno.ENOENT, errno.EPERM, errno.EACCES]:
+            add_error(e)
+        else:
+            raise
+
+
 def direxpand(names):
     for n in names:
-        try:
-            for sub in os.listdir(n):
-                subfull = os.path.join(n, sub)
-                for sub2 in direxpand([subfull]):
-                    yield sub2
-        except OSError, e:
-            if e.errno == errno.ENOTDIR:
-                yield n
-            elif e.errno in [errno.ENOENT, errno.EPERM, errno.EACCES]:
-                add_error(e)
-            else:
-                raise
+        for fn_st in _direxpand(n):
+            yield fn_st
             
 
 def _normpath(dir):
@@ -55,13 +62,14 @@ class Tree:
         return p
         
     def getdir(self, dir):
-        # FIXME: deal with '..' somehow
+        # FIXME: deal with '..' somehow (look at how tar does it)
+        dir = _normpath(dir)
         if dir.startswith('/'):
             dir = dir[1:]
         top = self.gettop()
         if not dir:
             return top
-        for part in _normpath(dir).split('/'):
+        for part in dir.split('/'):
             sub = top.children.get(part)
             if not sub:
                 sub = top.children[part] = Tree(top, part)
@@ -72,17 +80,17 @@ class Tree:
         (dir, name) = os.path.split(fullname)
         self.getdir(dir).children[name] = (mode, name, id)
         
-    def shalist(self):
+    def shalist(self, w):
         for c in self.children.values():
             if isinstance(c, tuple):  # sha1 entry for a file
                 yield c
             else:  # tree
-                t = ('40000', c.name, c.gen_tree())
+                t = ('40000', c.name, c.gen_tree(w))
                 yield t
         
-    def gen_tree(self):
+    def gen_tree(self, w):
         if not self.sha:
-            self.sha = git.gen_tree(self.shalist())
+            self.sha = w.new_tree(self.shalist(w))
         return self.sha
 
 
@@ -97,6 +105,7 @@ v,verbose  increase log output (can be used more than once)
 o = options.Options('bup save', optspec)
 (opt, flags, extra) = o.parse(sys.argv[1:])
 
+git.check_repo_or_die()
 if not (opt.tree or opt.commit or opt.name):
     log("bup save: use one or more of -t, -c, -n\n")
     o.usage()
@@ -105,22 +114,26 @@ if opt.verbose >= 2:
     git.verbose = opt.verbose - 1
     hashsplit.split_verbosely = opt.verbose - 1
 
+w = git.PackWriter()
 root = Tree(None, '')
-for fn in direxpand(extra):
+for (fn,st) in direxpand(extra):
     if opt.verbose:
         log('\n%s ' % fn)
     try:
-        # FIXME: symlinks etc.
-        f = open(fn)
+        if stat.S_ISREG(st.st_mode):  # regular file
+            f = open(fn)
+            (mode, id) = hashsplit.split_to_blob_or_tree(w, [f])
+        elif stat.S_ISLNK(st.st_mode):  # symlink
+            (mode, id) = ('120000', w.new_blob(os.readlink(fn)))
+        else:
+            add_error(Exception('skipping special file "%s"' % fn))
     except IOError, e:
         add_error(e)
-        continue
     except OSError, e:
         add_error(e)
-        continue
-    (mode, id) = hashsplit.split_to_blob_or_tree([f])
-    root.addfile(mode, fn, id)
-tree = root.gen_tree()
+    else:
+        root.addfile(mode, fn, id)
+tree = root.gen_tree(w)
 if opt.verbose:
     log('\n')
 if opt.tree:
@@ -128,11 +141,13 @@ if opt.tree:
 if opt.commit or opt.name:
     msg = 'bup save\n\nGenerated by command:\n%r' % sys.argv
     ref = opt.name and ('refs/heads/%s' % opt.name) or None
-    commit = git.gen_commit_easy(ref, tree, msg)
+    commit = w.new_commit(ref, tree, msg)
     if opt.commit:
+        if opt.verbose:
+            log('\n')
         print commit.encode('hex')
 
-git.flush_pack()
+w.close()
 
 if saved_errors:
     log('WARNING: %d errors encountered while saving.\n' % len(saved_errors))