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