2 from __future__ import absolute_import
3 from subprocess import check_call
4 import struct, os, time
9 from bup.helpers import localtime, log, mkdirp, readpipe
10 from buptest import no_lingering_errors, test_tempdir
13 top_dir = os.path.realpath('../../..')
14 bup_exe = top_dir + '/bup'
18 cmd_str = ' '.join(cmd)
19 print >> sys.stderr, cmd_str
24 cmd_str = ' '.join(cmd)
25 print >> sys.stderr, cmd_str
31 with no_lingering_errors():
37 WVPASSEQ(git.mangle_name("a", adir2, adir), "a")
38 WVPASSEQ(git.mangle_name(".bup", adir2, adir), ".bup.bupl")
39 WVPASSEQ(git.mangle_name("a.bupa", adir2, adir), "a.bupa.bupl")
40 WVPASSEQ(git.mangle_name("b.bup", alink, alink), "b.bup.bupl")
41 WVPASSEQ(git.mangle_name("b.bu", alink, alink), "b.bu")
42 WVPASSEQ(git.mangle_name("f", afile, afile2), "f")
43 WVPASSEQ(git.mangle_name("f.bup", afile, afile2), "f.bup.bupl")
44 WVPASSEQ(git.mangle_name("f.bup", afile, adir), "f.bup.bup")
45 WVPASSEQ(git.mangle_name("f", afile, adir), "f.bup")
47 WVPASSEQ(git.demangle_name("f.bup", afile), ("f", git.BUP_CHUNKED))
48 WVPASSEQ(git.demangle_name("f.bupl", afile), ("f", git.BUP_NORMAL))
49 WVPASSEQ(git.demangle_name("f.bup.bupl", afile), ("f.bup", git.BUP_NORMAL))
51 WVPASSEQ(git.demangle_name(".bupm", afile), ('', git.BUP_NORMAL))
52 WVPASSEQ(git.demangle_name(".bupm", adir), ('', git.BUP_CHUNKED))
54 # for safety, we ignore .bup? suffixes we don't recognize. Future
55 # versions might implement a .bup[a-z] extension as something other
57 WVPASSEQ(git.demangle_name("f.bupa", afile), ("f.bupa", git.BUP_NORMAL))
62 with no_lingering_errors():
64 looseb = ''.join(git._encode_looseobj('blob', s))
65 looset = ''.join(git._encode_looseobj('tree', s))
66 loosec = ''.join(git._encode_looseobj('commit', s))
67 packb = ''.join(git._encode_packobj('blob', s))
68 packt = ''.join(git._encode_packobj('tree', s))
69 packc = ''.join(git._encode_packobj('commit', s))
70 WVPASSEQ(git._decode_looseobj(looseb), ('blob', s))
71 WVPASSEQ(git._decode_looseobj(looset), ('tree', s))
72 WVPASSEQ(git._decode_looseobj(loosec), ('commit', s))
73 WVPASSEQ(git._decode_packobj(packb), ('blob', s))
74 WVPASSEQ(git._decode_packobj(packt), ('tree', s))
75 WVPASSEQ(git._decode_packobj(packc), ('commit', s))
77 WVPASS(git._encode_looseobj('blob', s, compression_level=i))
79 return ''.join(git._encode_packobj('blob', s, compression_level=n))
80 WVEXCEPT(ValueError, encode_pobj, -1)
81 WVEXCEPT(ValueError, encode_pobj, 10)
82 WVEXCEPT(ValueError, encode_pobj, 'x')
87 with no_lingering_errors():
88 with test_tempdir('bup-tgit-') as tmpdir:
89 os.environ['BUP_MAIN_EXE'] = bup_exe
90 os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
95 w.new_blob(os.urandom(100))
96 w.new_blob(os.urandom(100))
102 for i in range(nobj):
103 hashes.append(w.new_blob(str(i)))
105 nameprefix = w.close()
106 print repr(nameprefix)
107 WVPASS(os.path.exists(nameprefix + '.pack'))
108 WVPASS(os.path.exists(nameprefix + '.idx'))
110 r = git.open_idx(nameprefix + '.idx')
113 for i in range(nobj):
114 WVPASS(r.find_offset(hashes[i]) > 0)
115 WVPASS(r.exists(hashes[99]))
116 WVFAIL(r.exists('\0'*20))
119 for h in sorted(hashes):
120 WVPASSEQ(str(next(pi)).encode('hex'), h.encode('hex'))
122 WVFAIL(r.find_offset('\0'*20))
124 r = git.PackIdxList(bupdir + '/objects/pack')
125 WVPASS(r.exists(hashes[5]))
126 WVPASS(r.exists(hashes[6]))
127 WVFAIL(r.exists('\0'*20))
131 def test_pack_name_lookup():
132 with no_lingering_errors():
133 with test_tempdir('bup-tgit-') as tmpdir:
134 os.environ['BUP_MAIN_EXE'] = bup_exe
135 os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
136 git.init_repo(bupdir)
138 packdir = git.repo('objects/pack')
143 for start in range(0,28,2):
145 for i in range(start, start+2):
146 hashes.append(w.new_blob(str(i)))
148 idxnames.append(os.path.basename(w.close() + '.idx'))
150 r = git.PackIdxList(packdir)
151 WVPASSEQ(len(r.packs), 2)
152 for e,idxname in enumerate(idxnames):
153 for i in range(e*2, (e+1)*2):
154 WVPASSEQ(r.exists(hashes[i], want_source=True), idxname)
158 def test_long_index():
159 with no_lingering_errors():
160 with test_tempdir('bup-tgit-') as tmpdir:
161 os.environ['BUP_MAIN_EXE'] = bup_exe
162 os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
163 git.init_repo(bupdir)
165 obj_bin = struct.pack('!IIIII',
166 0x00112233, 0x44556677, 0x88990011, 0x22334455, 0x66778899)
167 obj2_bin = struct.pack('!IIIII',
168 0x11223344, 0x55667788, 0x99001122, 0x33445566, 0x77889900)
169 obj3_bin = struct.pack('!IIIII',
170 0x22334455, 0x66778899, 0x00112233, 0x44556677, 0x88990011)
171 pack_bin = struct.pack('!IIIII',
172 0x99887766, 0x55443322, 0x11009988, 0x77665544, 0x33221100)
173 idx = list(list() for i in xrange(256))
174 idx[0].append((obj_bin, 1, 0xfffffffff))
175 idx[0x11].append((obj2_bin, 2, 0xffffffffff))
176 idx[0x22].append((obj3_bin, 3, 0xff))
178 name = tmpdir + '/tmp.idx'
179 r = w._write_pack_idx_v2(name, idx, pack_bin)
180 i = git.PackIdxV2(name, open(name, 'rb'))
181 WVPASSEQ(i.find_offset(obj_bin), 0xfffffffff)
182 WVPASSEQ(i.find_offset(obj2_bin), 0xffffffffff)
183 WVPASSEQ(i.find_offset(obj3_bin), 0xff)
187 def test_check_repo_or_die():
188 with no_lingering_errors():
189 with test_tempdir('bup-tgit-') as tmpdir:
190 os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
191 orig_cwd = os.getcwd()
194 git.init_repo(bupdir)
195 git.check_repo_or_die()
196 # if we reach this point the call above passed
197 WVPASS('check_repo_or_die')
199 os.rename(bupdir + '/objects/pack',
200 bupdir + '/objects/pack.tmp')
201 open(bupdir + '/objects/pack', 'w').close()
203 git.check_repo_or_die()
204 except SystemExit as e:
208 os.unlink(bupdir + '/objects/pack')
209 os.rename(bupdir + '/objects/pack.tmp',
210 bupdir + '/objects/pack')
213 git.check_repo_or_die('nonexistantbup.tmp')
214 except SystemExit as e:
223 def test_commit_parsing():
225 def restore_env_var(name, val):
229 os.environ[name] = val
231 def showval(commit, val):
232 return readpipe(['git', 'show', '-s',
233 '--pretty=format:%s' % val, commit]).strip()
235 with no_lingering_errors():
236 with test_tempdir('bup-tgit-') as tmpdir:
237 orig_cwd = os.getcwd()
238 workdir = tmpdir + "/work"
239 repodir = workdir + '/.git'
240 orig_author_name = os.environ.get('GIT_AUTHOR_NAME')
241 orig_author_email = os.environ.get('GIT_AUTHOR_EMAIL')
242 orig_committer_name = os.environ.get('GIT_COMMITTER_NAME')
243 orig_committer_email = os.environ.get('GIT_COMMITTER_EMAIL')
244 os.environ['GIT_AUTHOR_NAME'] = 'bup test'
245 os.environ['GIT_COMMITTER_NAME'] = os.environ['GIT_AUTHOR_NAME']
246 os.environ['GIT_AUTHOR_EMAIL'] = 'bup@a425bc70a02811e49bdf73ee56450e6f'
247 os.environ['GIT_COMMITTER_EMAIL'] = os.environ['GIT_AUTHOR_EMAIL']
249 readpipe(['git', 'init', workdir])
250 os.environ['GIT_DIR'] = os.environ['BUP_DIR'] = repodir
251 git.check_repo_or_die(repodir)
253 with open('foo', 'w') as f:
255 readpipe(['git', 'add', '.'])
256 readpipe(['git', 'commit', '-am', 'Do something',
257 '--author', 'Someone <someone@somewhere>',
258 '--date', 'Sat Oct 3 19:48:49 2009 -0400'])
259 commit = readpipe(['git', 'show-ref', '-s', 'master']).strip()
260 parents = showval(commit, '%P')
261 tree = showval(commit, '%T')
262 cname = showval(commit, '%cn')
263 cmail = showval(commit, '%ce')
264 cdate = showval(commit, '%ct')
265 coffs = showval(commit, '%ci')
267 coff = (int(coffs[-4:-2]) * 60 * 60) + (int(coffs[-2:]) * 60)
270 commit_items = git.get_commit_items(commit, git.cp())
271 WVPASSEQ(commit_items.parents, [])
272 WVPASSEQ(commit_items.tree, tree)
273 WVPASSEQ(commit_items.author_name, 'Someone')
274 WVPASSEQ(commit_items.author_mail, 'someone@somewhere')
275 WVPASSEQ(commit_items.author_sec, 1254613729)
276 WVPASSEQ(commit_items.author_offset, -(4 * 60 * 60))
277 WVPASSEQ(commit_items.committer_name, cname)
278 WVPASSEQ(commit_items.committer_mail, cmail)
279 WVPASSEQ(commit_items.committer_sec, int(cdate))
280 WVPASSEQ(commit_items.committer_offset, coff)
281 WVPASSEQ(commit_items.message, 'Do something\n')
282 with open('bar', 'w') as f:
284 readpipe(['git', 'add', '.'])
285 readpipe(['git', 'commit', '-am', 'Do something else'])
286 child = readpipe(['git', 'show-ref', '-s', 'master']).strip()
287 parents = showval(child, '%P')
288 commit_items = git.get_commit_items(child, git.cp())
289 WVPASSEQ(commit_items.parents, [commit])
292 restore_env_var('GIT_AUTHOR_NAME', orig_author_name)
293 restore_env_var('GIT_AUTHOR_EMAIL', orig_author_email)
294 restore_env_var('GIT_COMMITTER_NAME', orig_committer_name)
295 restore_env_var('GIT_COMMITTER_EMAIL', orig_committer_email)
299 def test_new_commit():
300 with no_lingering_errors():
301 with test_tempdir('bup-tgit-') as tmpdir:
302 os.environ['BUP_MAIN_EXE'] = bup_exe
303 os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
304 git.init_repo(bupdir)
308 tree = os.urandom(20)
309 parent = os.urandom(20)
310 author_name = 'Author'
311 author_mail = 'author@somewhere'
312 adate_sec = 1439657836
313 cdate_sec = adate_sec + 1
314 committer_name = 'Committer'
315 committer_mail = 'committer@somewhere'
316 adate_tz_sec = cdate_tz_sec = None
317 commit = w.new_commit(tree, parent,
318 '%s <%s>' % (author_name, author_mail),
319 adate_sec, adate_tz_sec,
320 '%s <%s>' % (committer_name, committer_mail),
321 cdate_sec, cdate_tz_sec,
322 'There is a small mailbox here')
323 adate_tz_sec = -60 * 60
324 cdate_tz_sec = 120 * 60
325 commit_off = w.new_commit(tree, parent,
326 '%s <%s>' % (author_name, author_mail),
327 adate_sec, adate_tz_sec,
328 '%s <%s>' % (committer_name, committer_mail),
329 cdate_sec, cdate_tz_sec,
330 'There is a small mailbox here')
333 commit_items = git.get_commit_items(commit.encode('hex'), git.cp())
334 local_author_offset = localtime(adate_sec).tm_gmtoff
335 local_committer_offset = localtime(cdate_sec).tm_gmtoff
336 WVPASSEQ(tree, commit_items.tree.decode('hex'))
337 WVPASSEQ(1, len(commit_items.parents))
338 WVPASSEQ(parent, commit_items.parents[0].decode('hex'))
339 WVPASSEQ(author_name, commit_items.author_name)
340 WVPASSEQ(author_mail, commit_items.author_mail)
341 WVPASSEQ(adate_sec, commit_items.author_sec)
342 WVPASSEQ(local_author_offset, commit_items.author_offset)
343 WVPASSEQ(committer_name, commit_items.committer_name)
344 WVPASSEQ(committer_mail, commit_items.committer_mail)
345 WVPASSEQ(cdate_sec, commit_items.committer_sec)
346 WVPASSEQ(local_committer_offset, commit_items.committer_offset)
348 commit_items = git.get_commit_items(commit_off.encode('hex'), git.cp())
349 WVPASSEQ(tree, commit_items.tree.decode('hex'))
350 WVPASSEQ(1, len(commit_items.parents))
351 WVPASSEQ(parent, commit_items.parents[0].decode('hex'))
352 WVPASSEQ(author_name, commit_items.author_name)
353 WVPASSEQ(author_mail, commit_items.author_mail)
354 WVPASSEQ(adate_sec, commit_items.author_sec)
355 WVPASSEQ(adate_tz_sec, commit_items.author_offset)
356 WVPASSEQ(committer_name, commit_items.committer_name)
357 WVPASSEQ(committer_mail, commit_items.committer_mail)
358 WVPASSEQ(cdate_sec, commit_items.committer_sec)
359 WVPASSEQ(cdate_tz_sec, commit_items.committer_offset)
363 def test_list_refs():
364 with no_lingering_errors():
365 with test_tempdir('bup-tgit-') as tmpdir:
366 os.environ['BUP_MAIN_EXE'] = bup_exe
367 os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
368 src = tmpdir + '/src'
370 with open(src + '/1', 'w+') as f:
372 with open(src + '/2', 'w+') as f:
373 print f, 'something else'
374 git.init_repo(bupdir)
375 emptyset = frozenset()
376 WVPASSEQ(frozenset(git.list_refs()), emptyset)
377 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
378 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), emptyset)
379 exc(bup_exe, 'index', src)
380 exc(bup_exe, 'save', '-n', 'src', '--strip', src)
381 src_hash = exo('git', '--git-dir', bupdir,
382 'rev-parse', 'src').strip().split('\n')
383 assert(len(src_hash) == 1)
384 src_hash = src_hash[0].decode('hex')
385 tree_hash = exo('git', '--git-dir', bupdir,
386 'rev-parse', 'src:').strip().split('\n')[0].decode('hex')
387 blob_hash = exo('git', '--git-dir', bupdir,
388 'rev-parse', 'src:1').strip().split('\n')[0].decode('hex')
389 WVPASSEQ(frozenset(git.list_refs()),
390 frozenset([('refs/heads/src', src_hash)]))
391 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
392 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
393 frozenset([('refs/heads/src', src_hash)]))
394 exc('git', '--git-dir', bupdir, 'tag', 'commit-tag', 'src')
395 WVPASSEQ(frozenset(git.list_refs()),
396 frozenset([('refs/heads/src', src_hash),
397 ('refs/tags/commit-tag', src_hash)]))
398 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)),
399 frozenset([('refs/tags/commit-tag', src_hash)]))
400 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
401 frozenset([('refs/heads/src', src_hash)]))
402 exc('git', '--git-dir', bupdir, 'tag', 'tree-tag', 'src:')
403 exc('git', '--git-dir', bupdir, 'tag', 'blob-tag', 'src:1')
404 os.unlink(bupdir + '/refs/heads/src')
405 expected_tags = frozenset([('refs/tags/commit-tag', src_hash),
406 ('refs/tags/tree-tag', tree_hash),
407 ('refs/tags/blob-tag', blob_hash)])
408 WVPASSEQ(frozenset(git.list_refs()), expected_tags)
409 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), frozenset([]))
410 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), expected_tags)
414 def test__git_date_str():
415 with no_lingering_errors():
416 WVPASSEQ('0 +0000', git._git_date_str(0, 0))
417 WVPASSEQ('0 -0130', git._git_date_str(0, -90 * 60))
418 WVPASSEQ('0 +0130', git._git_date_str(0, 90 * 60))
423 with no_lingering_errors():
424 with test_tempdir('bup-tgit-') as tmpdir:
425 os.environ['BUP_MAIN_EXE'] = bup_exe
426 os.environ['BUP_DIR'] = bupdir = tmpdir + "/bup"
427 src = tmpdir + '/src'
429 with open(src + '/1', 'w+') as f:
431 with open(src + '/2', 'w+') as f:
432 print f, 'something else'
433 git.init_repo(bupdir)
434 exc(bup_exe, 'index', src)
435 oidx = exo(bup_exe, 'save', '-cn', 'src', '--strip', src).strip()
436 typ = exo('git', '--git-dir', bupdir,
437 'cat-file', '-t', 'src').strip()
438 size = int(exo('git', '--git-dir', bupdir,
439 'cat-file', '-s', 'src'))
440 it = git.cp().get('src')
442 for buf in it.next():
444 WVPASSEQ((oidx, typ, size), get_info)