1 import os, errno, zlib, time, sha, subprocess, struct
5 def _old_write_object(bin, type, content):
6 hex = bin.encode('hex')
7 header = '%s %d\0' % (type, len(content))
8 dir = '.git/objects/%s' % hex[0:2]
9 fn = '%s/%s' % (dir, hex[2:])
10 if not os.path.exists(fn):
11 #log('creating %s' % fn)
15 if e.errno != errno.EEXIST:
17 tfn = '.git/objects/bup%d.tmp' % os.getpid()
19 z = zlib.compressobj(1)
20 f.write(z.compress(header))
21 f.write(z.compress(content))
27 _typemap = dict(blob=3, tree=2, commit=1, tag=8)
32 self.filename = '.git/objects/bup%d' % os.getpid()
33 self.file = open(self.filename + '.pack', 'w+')
34 self.file.write('PACK\0\0\0\2\0\0\0\0')
36 def write(self, bin, type, content):
41 szbits = (sz & 0x0f) | (_typemap[type]<<4)
51 z = zlib.compressobj(1)
52 f.write(z.compress(content))
56 self.binlist.append(bin)
63 cp = struct.pack('!i', self.count)
67 # calculate the pack sha1sum
78 p = subprocess.Popen(['git', 'index-pack', '-v',
79 self.filename + '.pack'],
80 preexec_fn = lambda: _gitenv('.git'),
81 stdout = subprocess.PIPE)
82 out = p.stdout.read().strip()
83 if p.wait() or not out:
84 raise Exception('git index-pack returned an error')
85 os.rename(self.filename + '.pack', '.git/objects/pack/%s.pack' % out)
86 os.rename(self.filename + '.idx', '.git/objects/pack/%s.idx' % out)
89 def _write_object(bin, type, content):
92 _packout = PackWriter()
93 _packout.write(bin, type, content)
103 def hash_raw(type, s):
105 header = '%s %d\0' % (type, len(s))
106 sum = sha.sha(header)
109 hex = sum.hexdigest()
113 _write_object(bin, type, s)
119 return hash_raw('blob', blob)
122 def gen_tree(shalist):
123 shalist = sorted(shalist, key = lambda x: x[1])
124 l = ['%s %s\0%s' % (mode,name,hex.decode('hex'))
125 for (mode,name,hex) in shalist]
126 return hash_raw('tree', ''.join(l))
130 return time.strftime('%s %z', time.localtime(date))
134 os.environ['GIT_DIR'] = os.path.abspath(repo)
137 def _read_ref(repo, refname):
138 p = subprocess.Popen(['git', 'show-ref', '--', refname],
139 preexec_fn = lambda: _gitenv(repo),
140 stdout = subprocess.PIPE)
141 out = p.stdout.read().strip()
144 return out.split()[0]
149 def _update_ref(repo, refname, newval, oldval):
152 p = subprocess.Popen(['git', 'update-ref', '--', refname, newval, oldval],
153 preexec_fn = lambda: _gitenv(repo))
158 def gen_commit(tree, parent, author, adate, committer, cdate, msg):
160 if tree: l.append('tree %s' % tree)
161 if parent: l.append('parent %s' % parent)
162 if author: l.append('author %s %s' % (author, _git_date(adate)))
163 if committer: l.append('committer %s %s' % (committer, _git_date(cdate)))
166 return hash_raw('commit', '\n'.join(l))
169 def gen_commit_easy(ref, tree, msg):
171 userline = '%s <%s@%s>' % (userfullname(), username(), hostname())
172 oldref = ref and _read_ref('.git', ref) or None
173 commit = gen_commit(tree, oldref, userline, now, userline, now, msg)
175 _update_ref('.git', ref, commit, oldref)