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