1 #!/usr/bin/env python2.5
2 import sys, re, errno, stat
3 import hashsplit, git, options
16 if stat.S_ISDIR(st.st_mode):
17 for sub in os.listdir(name):
18 subfull = os.path.join(name, sub)
19 for fn_st in _direxpand(subfull):
24 if e.errno in [errno.ENOENT, errno.EPERM, errno.EACCES]:
32 for fn_st in _direxpand(n):
37 p = os.path.normpath(dir)
38 return (p != '.') and p or ''
42 def __init__(self, parent, name):
44 assert(not (parent and not name))
50 self.parent.children[self.name] = self
54 return os.path.join(self.parent.fullpath(), self.name)
64 def getdir(self, dir):
65 # FIXME: deal with '..' somehow (look at how tar does it)
67 if dir.startswith('/'):
72 for part in dir.split('/'):
73 sub = top.children.get(part)
75 sub = top.children[part] = Tree(top, part)
79 def addfile(self, mode, fullname, id):
80 (dir, name) = os.path.split(fullname)
81 self.getdir(dir).children[name] = (mode, name, id)
84 for c in self.children.values():
85 if isinstance(c, tuple): # sha1 entry for a file
88 t = ('40000', c.name, c.gen_tree(w))
91 def gen_tree(self, w):
93 self.sha = w.new_tree(self.shalist(w))
98 bup save [-tc] [-n name] <filenames...>
100 t,tree output a tree id
101 c,commit output a commit id
102 n,name= name of backup set to update (if any)
103 v,verbose increase log output (can be used more than once)
105 o = options.Options('bup save', optspec)
106 (opt, flags, extra) = o.parse(sys.argv[1:])
108 git.check_repo_or_die()
109 if not (opt.tree or opt.commit or opt.name):
110 log("bup save: use one or more of -t, -c, -n\n")
114 git.verbose = opt.verbose - 1
115 hashsplit.split_verbosely = opt.verbose - 1
118 root = Tree(None, '')
119 for (fn,st) in direxpand(extra):
123 if stat.S_ISREG(st.st_mode): # regular file
125 (mode, id) = hashsplit.split_to_blob_or_tree(w, [f])
126 elif stat.S_ISLNK(st.st_mode): # symlink
127 (mode, id) = ('120000', w.new_blob(os.readlink(fn)))
129 add_error(Exception('skipping special file "%s"' % fn))
135 root.addfile(mode, fn, id)
136 tree = root.gen_tree(w)
140 print tree.encode('hex')
141 if opt.commit or opt.name:
142 msg = 'bup save\n\nGenerated by command:\n%r' % sys.argv
143 ref = opt.name and ('refs/heads/%s' % opt.name) or None
144 commit = w.new_commit(ref, tree, msg)
148 print commit.encode('hex')
153 log('WARNING: %d errors encountered while saving.\n' % len(saved_errors))