]> arthur.barton.de Git - bup.git/blob - cmd-split.py
Add a 'bup' wrapper program.
[bup.git] / cmd-split.py
1 #!/usr/bin/env python
2 import sys, os, subprocess, errno, zlib, time
3 import hashsplit
4 from sha import sha
5
6 # FIXME: duplicated in C module.  This shouldn't really be here at all...
7 BLOBBITS = 14
8 BLOBSIZE = 1 << (BLOBBITS-1)
9
10
11 def log(s):
12     sys.stderr.write('%s\n' % s)
13
14
15 class Buf:
16     def __init__(self):
17         self.data = ''
18         self.start = 0
19
20     def put(self, s):
21         #log('oldsize=%d+%d adding=%d' % (len(self.data), self.start, len(s)))
22         if s:
23             self.data = buffer(self.data, self.start) + s
24             self.start = 0
25             
26     def peek(self, count):
27         return buffer(self.data, self.start, count)
28     
29     def eat(self, count):
30         self.start += count
31
32     def get(self, count):
33         v = buffer(self.data, self.start, count)
34         self.start += count
35         return v
36
37     def used(self):
38         return len(self.data) - self.start
39
40
41 def splitbuf(buf):
42     #return buf.get(BLOBSIZE)
43     b = buf.peek(buf.used())
44     ofs = hashsplit.splitbuf(b)
45     if ofs:
46         buf.eat(ofs)
47         return buffer(b, 0, ofs)
48     return None
49
50
51 ocache = {}
52 def save_blob(blob):
53     header = 'blob %d\0' % len(blob)
54     sum = sha(header)
55     sum.update(blob)
56     hex = sum.hexdigest()
57     dir = '.git/objects/%s' % hex[0:2]
58     fn = '%s/%s' % (dir, hex[2:])
59     if not ocache.get(hex) and not os.path.exists(fn):
60         #log('creating %s' % fn)
61         try:
62             os.mkdir(dir)
63         except OSError, e:
64             if e.errno != errno.EEXIST:
65                 raise
66         tfn = '%s.%d' % (fn, os.getpid())
67         f = open(tfn, 'w')
68         z = zlib.compressobj(1)
69         f.write(z.compress(header))
70         f.write(z.compress(blob))
71         f.write(z.flush())
72         f.close()
73         os.rename(tfn, fn)
74     else:
75         #log('exists %s' % fn)
76         pass
77     ocache[hex] = 1
78     print hex
79     return hex
80
81
82 def do_main():
83     start_time = time.time()
84     ofs = 0
85     buf = Buf()
86     blob = 1
87
88     eof = 0
89     lv = 0
90     while blob or not eof:
91         if not eof and (buf.used() < BLOBSIZE*2 or not blob):
92             bnew = sys.stdin.read(1024*1024)
93             if not len(bnew): eof = 1
94             #log('got %d, total %d' % (len(bnew), buf.used()))
95             buf.put(bnew)
96
97         blob = splitbuf(buf)
98         if eof and not blob:
99             blob = buf.get(buf.used())
100         if not blob and buf.used() >= BLOBSIZE*8:
101             blob = buf.get(BLOBSIZE*4)  # limit max blob size
102         if not blob and not eof:
103             continue
104
105         if blob:
106             ofs += len(blob)
107             #log('SPLIT @ %-8d size=%-8d (blobsize=%d)'
108             #    % (ofs, len(blob), BLOBSIZE))
109             save_blob(blob)
110           
111         nv = (ofs + buf.used())/1000000
112         if nv != lv:
113             log(nv)
114             lv = nv
115     secs = time.time() - start_time
116     log('\n%.2fkbytes in %.2f secs = %.2f kbytes/sec' 
117         % (ofs/1024., secs, ofs/1024./secs))
118
119
120 assert(BLOBSIZE >= 32)
121 do_main()