]> arthur.barton.de Git - bup.git/blob - lib/bup/t/tgit.py
c57e8cd75e4b866bbe1c0fe5ed384f10c9f8c389
[bup.git] / lib / bup / t / tgit.py
1 import struct, os, tempfile, time
2 from subprocess import check_call
3 from bup import git
4 from bup.helpers import *
5 from wvtest import *
6
7
8 top_dir = os.path.realpath('../../..')
9 bup_exe = top_dir + '/bup'
10 bup_tmp = top_dir + '/t/tmp'
11
12
13 def exc(*cmd):
14     cmd_str = ' '.join(cmd)
15     print >> sys.stderr, cmd_str
16     check_call(cmd)
17
18
19 def exo(*cmd):
20     cmd_str = ' '.join(cmd)
21     print >> sys.stderr, cmd_str
22     return readpipe(cmd)
23
24
25 @wvtest
26 def testmangle():
27     afile  = 0100644
28     afile2 = 0100770
29     alink  = 0120000
30     adir   = 0040000
31     adir2  = 0040777
32     WVPASSEQ(git.mangle_name("a", adir2, adir), "a")
33     WVPASSEQ(git.mangle_name(".bup", adir2, adir), ".bup.bupl")
34     WVPASSEQ(git.mangle_name("a.bupa", adir2, adir), "a.bupa.bupl")
35     WVPASSEQ(git.mangle_name("b.bup", alink, alink), "b.bup.bupl")
36     WVPASSEQ(git.mangle_name("b.bu", alink, alink), "b.bu")
37     WVPASSEQ(git.mangle_name("f", afile, afile2), "f")
38     WVPASSEQ(git.mangle_name("f.bup", afile, afile2), "f.bup.bupl")
39     WVPASSEQ(git.mangle_name("f.bup", afile, adir), "f.bup.bup")
40     WVPASSEQ(git.mangle_name("f", afile, adir), "f.bup")
41
42     WVPASSEQ(git.demangle_name("f.bup", afile), ("f", git.BUP_CHUNKED))
43     WVPASSEQ(git.demangle_name("f.bupl", afile), ("f", git.BUP_NORMAL))
44     WVPASSEQ(git.demangle_name("f.bup.bupl", afile), ("f.bup", git.BUP_NORMAL))
45
46     WVPASSEQ(git.demangle_name(".bupm", afile), ('', git.BUP_NORMAL))
47     WVPASSEQ(git.demangle_name(".bupm", adir), ('', git.BUP_CHUNKED))
48
49     # for safety, we ignore .bup? suffixes we don't recognize.  Future
50     # versions might implement a .bup[a-z] extension as something other
51     # than BUP_NORMAL.
52     WVPASSEQ(git.demangle_name("f.bupa", afile), ("f.bupa", git.BUP_NORMAL))
53
54
55 @wvtest
56 def testencode():
57     s = 'hello world'
58     looseb = ''.join(git._encode_looseobj('blob', s))
59     looset = ''.join(git._encode_looseobj('tree', s))
60     loosec = ''.join(git._encode_looseobj('commit', s))
61     packb = ''.join(git._encode_packobj('blob', s))
62     packt = ''.join(git._encode_packobj('tree', s))
63     packc = ''.join(git._encode_packobj('commit', s))
64     WVPASSEQ(git._decode_looseobj(looseb), ('blob', s))
65     WVPASSEQ(git._decode_looseobj(looset), ('tree', s))
66     WVPASSEQ(git._decode_looseobj(loosec), ('commit', s))
67     WVPASSEQ(git._decode_packobj(packb), ('blob', s))
68     WVPASSEQ(git._decode_packobj(packt), ('tree', s))
69     WVPASSEQ(git._decode_packobj(packc), ('commit', s))
70
71
72 @wvtest
73 def testpacks():
74     initial_failures = wvfailure_count()
75     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
76     os.environ['BUP_MAIN_EXE'] = bup_exe
77     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
78     git.init_repo(bupdir)
79     git.verbose = 1
80
81     w = git.PackWriter()
82     w.new_blob(os.urandom(100))
83     w.new_blob(os.urandom(100))
84     w.abort()
85
86     w = git.PackWriter()
87     hashes = []
88     nobj = 1000
89     for i in range(nobj):
90         hashes.append(w.new_blob(str(i)))
91     log('\n')
92     nameprefix = w.close()
93     print repr(nameprefix)
94     WVPASS(os.path.exists(nameprefix + '.pack'))
95     WVPASS(os.path.exists(nameprefix + '.idx'))
96
97     r = git.open_idx(nameprefix + '.idx')
98     print repr(r.fanout)
99
100     for i in range(nobj):
101         WVPASS(r.find_offset(hashes[i]) > 0)
102     WVPASS(r.exists(hashes[99]))
103     WVFAIL(r.exists('\0'*20))
104
105     pi = iter(r)
106     for h in sorted(hashes):
107         WVPASSEQ(str(pi.next()).encode('hex'), h.encode('hex'))
108
109     WVFAIL(r.find_offset('\0'*20))
110
111     r = git.PackIdxList(bupdir + '/objects/pack')
112     WVPASS(r.exists(hashes[5]))
113     WVPASS(r.exists(hashes[6]))
114     WVFAIL(r.exists('\0'*20))
115     if wvfailure_count() == initial_failures:
116         subprocess.call(['rm', '-rf', tmpdir])
117
118 @wvtest
119 def test_pack_name_lookup():
120     initial_failures = wvfailure_count()
121     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
122     os.environ['BUP_MAIN_EXE'] = bup_exe
123     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
124     git.init_repo(bupdir)
125     git.verbose = 1
126     packdir = git.repo('objects/pack')
127
128     idxnames = []
129     hashes = []
130
131     for start in range(0,28,2):
132         w = git.PackWriter()
133         for i in range(start, start+2):
134             hashes.append(w.new_blob(str(i)))
135         log('\n')
136         idxnames.append(os.path.basename(w.close() + '.idx'))
137
138     r = git.PackIdxList(packdir)
139     WVPASSEQ(len(r.packs), 2)
140     for e,idxname in enumerate(idxnames):
141         for i in range(e*2, (e+1)*2):
142             WVPASSEQ(r.exists(hashes[i], want_source=True), idxname)
143     if wvfailure_count() == initial_failures:
144         subprocess.call(['rm', '-rf', tmpdir])
145
146
147 @wvtest
148 def test_long_index():
149     initial_failures = wvfailure_count()
150     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
151     os.environ['BUP_MAIN_EXE'] = bup_exe
152     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
153     git.init_repo(bupdir)
154     w = git.PackWriter()
155     obj_bin = struct.pack('!IIIII',
156             0x00112233, 0x44556677, 0x88990011, 0x22334455, 0x66778899)
157     obj2_bin = struct.pack('!IIIII',
158             0x11223344, 0x55667788, 0x99001122, 0x33445566, 0x77889900)
159     obj3_bin = struct.pack('!IIIII',
160             0x22334455, 0x66778899, 0x00112233, 0x44556677, 0x88990011)
161     pack_bin = struct.pack('!IIIII',
162             0x99887766, 0x55443322, 0x11009988, 0x77665544, 0x33221100)
163     idx = list(list() for i in xrange(256))
164     idx[0].append((obj_bin, 1, 0xfffffffff))
165     idx[0x11].append((obj2_bin, 2, 0xffffffffff))
166     idx[0x22].append((obj3_bin, 3, 0xff))
167     (fd,name) = tempfile.mkstemp(suffix='.idx', dir=git.repo('objects'))
168     os.close(fd)
169     w.count = 3
170     r = w._write_pack_idx_v2(name, idx, pack_bin)
171     i = git.PackIdxV2(name, open(name, 'rb'))
172     WVPASSEQ(i.find_offset(obj_bin), 0xfffffffff)
173     WVPASSEQ(i.find_offset(obj2_bin), 0xffffffffff)
174     WVPASSEQ(i.find_offset(obj3_bin), 0xff)
175     if wvfailure_count() == initial_failures:
176         os.remove(name)
177         subprocess.call(['rm', '-rf', tmpdir])
178
179
180 @wvtest
181 def test_check_repo_or_die():
182     initial_failures = wvfailure_count()
183     orig_cwd = os.getcwd()
184     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
185     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
186     try:
187         os.chdir(tmpdir)
188         git.init_repo(bupdir)
189         git.check_repo_or_die()
190         WVPASS('check_repo_or_die')  # if we reach this point the call above passed
191
192         os.rename(bupdir + '/objects/pack', bupdir + '/objects/pack.tmp')
193         open(bupdir + '/objects/pack', 'w').close()
194         try:
195             git.check_repo_or_die()
196         except SystemExit as e:
197             WVPASSEQ(e.code, 14)
198         else:
199             WVFAIL()
200         os.unlink(bupdir + '/objects/pack')
201         os.rename(bupdir + '/objects/pack.tmp', bupdir + '/objects/pack')
202
203         try:
204             git.check_repo_or_die('nonexistantbup.tmp')
205         except SystemExit as e:
206             WVPASSEQ(e.code, 15)
207         else:
208             WVFAIL()
209     finally:
210         os.chdir(orig_cwd)
211     if wvfailure_count() == initial_failures:
212         subprocess.call(['rm', '-rf', tmpdir])
213
214
215 @wvtest
216 def test_commit_parsing():
217     def restore_env_var(name, val):
218         if val is None:
219             del os.environ[name]
220         else:
221             os.environ[name] = val
222     def showval(commit, val):
223         return readpipe(['git', 'show', '-s',
224                          '--pretty=format:%s' % val, commit]).strip()
225     initial_failures = wvfailure_count()
226     orig_cwd = os.getcwd()
227     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
228     workdir = tmpdir + "/work"
229     repodir = workdir + '/.git'
230     orig_author_name = os.environ.get('GIT_AUTHOR_NAME')
231     orig_author_email = os.environ.get('GIT_AUTHOR_EMAIL')
232     orig_committer_name = os.environ.get('GIT_COMMITTER_NAME')
233     orig_committer_email = os.environ.get('GIT_COMMITTER_EMAIL')
234     os.environ['GIT_AUTHOR_NAME'] = 'bup test'
235     os.environ['GIT_COMMITTER_NAME'] = os.environ['GIT_AUTHOR_NAME']
236     os.environ['GIT_AUTHOR_EMAIL'] = 'bup@a425bc70a02811e49bdf73ee56450e6f'
237     os.environ['GIT_COMMITTER_EMAIL'] = os.environ['GIT_AUTHOR_EMAIL']
238     try:
239         readpipe(['git', 'init', workdir])
240         os.environ['GIT_DIR'] = os.environ['BUP_DIR'] = repodir
241         git.check_repo_or_die(repodir)
242         os.chdir(workdir)
243         with open('foo', 'w') as f:
244             print >> f, 'bar'
245         readpipe(['git', 'add', '.'])
246         readpipe(['git', 'commit', '-am', 'Do something',
247                   '--author', 'Someone <someone@somewhere>',
248                   '--date', 'Sat Oct 3 19:48:49 2009 -0400'])
249         commit = readpipe(['git', 'show-ref', '-s', 'master']).strip()
250         parents = showval(commit, '%P')
251         tree = showval(commit, '%T')
252         cname = showval(commit, '%cn')
253         cmail = showval(commit, '%ce')
254         cdate = showval(commit, '%ct')
255         coffs = showval(commit, '%ci')
256         coffs = coffs[-5:]
257         coff = (int(coffs[-4:-2]) * 60 * 60) + (int(coffs[-2:]) * 60)
258         if coffs[-5] == '-':
259             coff = - coff
260         commit_items = git.get_commit_items(commit, git.cp())
261         WVPASSEQ(commit_items.parents, [])
262         WVPASSEQ(commit_items.tree, tree)
263         WVPASSEQ(commit_items.author_name, 'Someone')
264         WVPASSEQ(commit_items.author_mail, 'someone@somewhere')
265         WVPASSEQ(commit_items.author_sec, 1254613729)
266         WVPASSEQ(commit_items.author_offset, -(4 * 60 * 60))
267         WVPASSEQ(commit_items.committer_name, cname)
268         WVPASSEQ(commit_items.committer_mail, cmail)
269         WVPASSEQ(commit_items.committer_sec, int(cdate))
270         WVPASSEQ(commit_items.committer_offset, coff)
271         WVPASSEQ(commit_items.message, 'Do something\n')
272         with open('bar', 'w') as f:
273             print >> f, 'baz'
274         readpipe(['git', 'add', '.'])
275         readpipe(['git', 'commit', '-am', 'Do something else'])
276         child = readpipe(['git', 'show-ref', '-s', 'master']).strip()
277         parents = showval(child, '%P')
278         commit_items = git.get_commit_items(child, git.cp())
279         WVPASSEQ(commit_items.parents, [commit])
280     finally:
281         os.chdir(orig_cwd)
282         restore_env_var('GIT_AUTHOR_NAME', orig_author_name)
283         restore_env_var('GIT_AUTHOR_EMAIL', orig_author_email)
284         restore_env_var('GIT_COMMITTER_NAME', orig_committer_name)
285         restore_env_var('GIT_COMMITTER_EMAIL', orig_committer_email)
286     if wvfailure_count() == initial_failures:
287         subprocess.call(['rm', '-rf', tmpdir])
288
289
290 @wvtest
291 def test_list_refs():
292     initial_failures = wvfailure_count()
293     tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tgit-')
294     os.environ['BUP_MAIN_EXE'] = bup_exe
295     os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
296     src = tmpdir + '/src'
297     mkdirp(src)
298     with open(src + '/1', 'w+') as f:
299         print f, 'something'
300     with open(src + '/2', 'w+') as f:
301         print f, 'something else'
302     git.init_repo(bupdir)
303     emptyset = frozenset()
304     WVPASSEQ(frozenset(git.list_refs()), emptyset)
305     WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
306     WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), emptyset)
307     exc(bup_exe, 'index', src)
308     exc(bup_exe, 'save', '-n', 'src', '--strip', src)
309     src_hash = exo('git', '--git-dir', bupdir,
310                    'rev-parse', 'src').strip().split('\n')
311     assert(len(src_hash) == 1)
312     src_hash = src_hash[0].decode('hex')
313     tree_hash = exo('git', '--git-dir', bupdir,
314                    'rev-parse', 'src:').strip().split('\n')[0].decode('hex')
315     blob_hash = exo('git', '--git-dir', bupdir,
316                    'rev-parse', 'src:1').strip().split('\n')[0].decode('hex')
317     WVPASSEQ(frozenset(git.list_refs()),
318              frozenset([('refs/heads/src', src_hash)]))
319     WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
320     WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
321              frozenset([('refs/heads/src', src_hash)]))
322     exc('git', '--git-dir', bupdir, 'tag', 'commit-tag', 'src')
323     WVPASSEQ(frozenset(git.list_refs()),
324              frozenset([('refs/heads/src', src_hash),
325                         ('refs/tags/commit-tag', src_hash)]))
326     WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)),
327              frozenset([('refs/tags/commit-tag', src_hash)]))
328     WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
329              frozenset([('refs/heads/src', src_hash)]))
330     exc('git', '--git-dir', bupdir, 'tag', 'tree-tag', 'src:')
331     exc('git', '--git-dir', bupdir, 'tag', 'blob-tag', 'src:1')
332     os.unlink(bupdir + '/refs/heads/src')
333     expected_tags = frozenset([('refs/tags/commit-tag', src_hash),
334                                ('refs/tags/tree-tag', tree_hash),
335                                ('refs/tags/blob-tag', blob_hash)])
336     WVPASSEQ(frozenset(git.list_refs()), expected_tags)
337     WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), frozenset([]))
338     WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), expected_tags)
339     if wvfailure_count() == initial_failures:
340         subprocess.call(['rm', '-rf', tmpdir])