3 bup_python="$(dirname "$0")/../cmd/bup-python" || exit $?
4 exec "$bup_python" "$0" ${1+"$@"}
8 from __future__ import print_function
9 from errno import ENOENT
10 from os import chdir, environ, getcwd, mkdir, rename
11 from os.path import abspath, dirname
12 from pipes import quote
13 from shutil import rmtree
14 from subprocess import PIPE
17 script_home = abspath(dirname(sys.argv[0] or '.'))
18 sys.path[:0] = [abspath(script_home + '/../lib'), abspath(script_home + '/..')]
20 from bup import compat
21 from bup.helpers import merge_dict, unlink
22 from buptest import ex, exo, test_tempdir
23 from wvtest import wvcheck, wvfail, wvmsg, wvpass, wvpasseq, wvpassne, wvstart
25 # FIXME: per-test function
26 environ['GIT_AUTHOR_NAME'] = 'bup test-get'
27 environ['GIT_COMMITTER_NAME'] = 'bup test-get'
28 environ['GIT_AUTHOR_EMAIL'] = 'bup@85430dcca2b611e4b2c3-8f5691723476'
29 environ['GIT_COMMITTER_EMAIL'] = 'bup@85430dcca2b611e4b2c3-8f5691723476'
31 # The clean-repo test can probably be applied more broadly. It was
32 # initially just applied to test-pick to catch a bug.
35 bup_cmd = top + '/bup'
38 err = [] # because python's scoping mess...
39 def onerror(function, path, excinfo):
40 err.append((function, path, excinfo))
41 rmtree(path, onerror=onerror)
43 function, path, excinfo = err[0]
44 ex_type, ex, traceback = excinfo
45 if (not isinstance(ex, OSError)) or ex.errno != ENOENT:
48 def verify_trees_match(path1, path2):
50 exr = exo((top + '/t/compare-trees', '-c', path1, path2), check=False)
53 wvcheck(exr.rc == 0, 'process exit %d == 0' % exr.rc)
55 def verify_rcz(cmd, **kwargs):
56 assert not kwargs.get('check')
57 kwargs['check'] = False
58 result = exo(cmd, **kwargs)
60 rc = result.proc.returncode
61 wvcheck(rc == 0, 'process exit %d == 0' % rc)
64 # FIXME: multline, or allow opts generally?
66 def verify_rx(rx, string):
67 wvcheck(re.search(rx, string), 'rx %r matches %r' % (rx, string))
69 def verify_nrx(rx, string):
70 wvcheck(not re.search(rx, string), "rx %r doesn't match %r" % (rx, string))
72 def validate_clean_repo():
73 out = verify_rcz(('git', '--git-dir', 'get-dest', 'fsck')).out
74 verify_nrx(r'dangling|mismatch|missing|unreachable', out)
76 def validate_blob(src_id, dest_id):
80 cat_tree = top + '/t/git-cat-tree'
81 src_blob = verify_rcz((cat_tree, '--git-dir', 'get-src', src_id)).out
82 dest_blob = verify_rcz((cat_tree, '--git-dir', 'get-src', src_id)).out
83 wvpasseq(src_blob, dest_blob)
85 def validate_tree(src_id, dest_id):
92 commit_env = merge_dict(environ, {'GIT_COMMITTER_DATE': '2014-01-01 01:01'})
94 # Create a commit so the archive contents will have matching timestamps.
95 src_c = exo(('git', '--git-dir', 'get-src',
96 'commit-tree', '-m', 'foo', src_id),
97 env=commit_env).out.strip()
98 dest_c = exo(('git', '--git-dir', 'get-dest',
99 'commit-tree', '-m', 'foo', dest_id),
100 env=commit_env).out.strip()
101 exr = verify_rcz('git --git-dir get-src archive %s | tar xvf - -C restore-src'
104 if exr.rc != 0: return False
105 exr = verify_rcz('git --git-dir get-dest archive %s | tar xvf - -C restore-dest'
108 if exr.rc != 0: return False
110 # git archive doesn't include an entry for ./.
111 unlink('restore-src/pax_global_header')
112 unlink('restore-dest/pax_global_header')
113 ex(('touch', '-r', 'restore-src', 'restore-dest'))
114 verify_trees_match('restore-src/', 'restore-dest/')
118 def validate_commit(src_id, dest_id):
119 exr = verify_rcz(('git', '--git-dir', 'get-src', 'cat-file', 'commit', src_id))
120 if exr.rc != 0: return False
122 exr = verify_rcz(('git', '--git-dir', 'get-dest', 'cat-file', 'commit', dest_id))
123 if exr.rc != 0: return False
125 wvpasseq(src_cat, dest_cat)
126 if src_cat != dest_cat: return False
131 mkdir('restore-dest')
133 qdest = quote(dest_id)
134 exr = verify_rcz(('git --git-dir get-src archive ' + qsrc
135 + ' | tar xf - -C restore-src'),
137 if exr.rc != 0: return False
138 exr = verify_rcz(('git --git-dir get-dest archive ' + qdest +
139 ' | tar xf - -C restore-dest'),
141 if exr.rc != 0: return False
143 # git archive doesn't include an entry for ./.
144 ex(('touch', '-r', 'restore-src', 'restore-dest'))
145 verify_trees_match('restore-src/', 'restore-dest/')
149 def _validate_save(orig_dir, save_path, commit_id, tree_id):
152 exr = verify_rcz((bup_cmd, '-d', 'get-dest',
153 'restore', '-C', 'restore', save_path + '/.'))
154 if exr.rc: return False
155 verify_trees_match(orig_dir + '/', 'restore/')
157 # FIXME: double check that get-dest is correct
158 exr = verify_rcz(('git', '--git-dir', 'get-dest', 'ls-tree', tree_id))
159 if exr.rc: return False
160 cat = verify_rcz(('git', '--git-dir', 'get-dest',
161 'cat-file', 'commit', commit_id))
162 if cat.rc: return False
163 wvpasseq('tree ' + tree_id, cat.out.splitlines()[0])
165 # FIXME: re-merge save and new_save?
167 def validate_save(dest_name, restore_subpath, commit_id, tree_id, orig_value,
169 out = get_out.splitlines()
170 wvpasseq(2, len(out))
172 get_commit_id = out[1]
173 wvpasseq(tree_id, get_tree_id)
174 wvpasseq(commit_id, get_commit_id)
175 _validate_save(orig_value, dest_name + restore_subpath, commit_id, tree_id)
177 def validate_new_save(dest_name, restore_subpath, commit_id, tree_id, orig_value,
179 out = get_out.splitlines()
180 wvpasseq(2, len(out))
182 get_commit_id = out[1]
183 wvpasseq(tree_id, get_tree_id)
184 wvpassne(commit_id, get_commit_id)
185 _validate_save(orig_value, dest_name + restore_subpath, get_commit_id, tree_id)
187 def validate_tagged_save(tag_name, restore_subpath,
188 commit_id, tree_id, orig_value, get_out):
189 out = get_out.splitlines()
190 wvpasseq(1, len(out))
192 wvpasseq(commit_id, get_tag_id)
193 # Make sure tmp doesn't already exist.
194 exr = exo(('git', '--git-dir', 'get-dest', 'show-ref', 'tmp-branch-for-tag'),
198 ex(('git', '--git-dir', 'get-dest', 'branch', 'tmp-branch-for-tag',
199 'refs/tags/' + tag_name))
200 _validate_save(orig_value, 'tmp-branch-for-tag/latest' + restore_subpath,
202 ex(('git', '--git-dir', 'get-dest', 'branch', '-D', 'tmp-branch-for-tag'))
204 def validate_new_tagged_commit(tag_name, commit_id, tree_id, get_out):
205 out = get_out.splitlines()
206 wvpasseq(1, len(out))
208 wvpassne(commit_id, get_tag_id)
209 validate_tree(tree_id, tag_name + ':')
215 def _run_get(disposition, method, what):
218 if disposition == 'get':
219 get_cmd = (bup_cmd, '-d', 'get-dest',
220 'get', '-vvct', '--print-tags', '-s', 'get-src')
221 elif disposition == 'get-on':
222 get_cmd = (bup_cmd, '-d', 'get-dest',
223 'on', '-', 'get', '-vvct', '--print-tags', '-s', 'get-src')
224 elif disposition == 'get-to':
225 get_cmd = (bup_cmd, '-d', 'get-dest',
226 'get', '-vvct', '--print-tags', '-s', 'get-src',
227 '-r', '-:' + getcwd() + '/get-dest')
229 raise Exception('error: unexpected get disposition ' + disposition)
231 global get_cases_tested
232 if isinstance(what, compat.str_type):
233 cmd = get_cmd + (method, what)
235 if method in ('--ff', '--append', '--pick', '--force-pick', '--new-tag',
239 cmd = get_cmd + (method, src, dest)
240 result = exo(cmd, check=False, stderr=PIPE)
241 get_cases_tested += 1
242 fsck = ex((bup_cmd, '-d', 'get-dest', 'fsck'), check=False)
246 def run_get(disposition, method, what=None, given=None):
249 ex((bup_cmd, '-d', 'get-dest', 'init'))
252 # FIXME: replace bup-get with independent commands as is feasible
253 exr = _run_get(disposition, '--replace', given)
255 return _run_get(disposition, method, what)
257 def test_universal_behaviors(get_disposition):
258 methods = ('--ff', '--append', '--pick', '--force-pick', '--new-tag',
259 '--replace', '--unnamed')
260 for method in methods:
261 wvstart(get_disposition + ' ' + method + ', missing source, fails')
262 exr = run_get(get_disposition, method, 'not-there')
264 verify_rx(r'cannot find source', exr.err)
265 for method in methods:
266 wvstart(get_disposition + ' ' + method + ' / fails')
267 exr = run_get(get_disposition, method, '/')
269 verify_rx('cannot fetch entire repository', exr.err)
271 def verify_only_refs(**kwargs):
272 for kind, refs in kwargs.iteritems():
274 abs_refs = ['refs/heads/' + ref for ref in refs]
277 abs_refs = ['refs/tags/' + ref for ref in refs]
280 raise TypeError('unexpected keyword argument %r' % kind)
282 verify_rcz(['git', '--git-dir', 'get-dest',
283 'show-ref', '--verify', karg] + abs_refs)
284 exr = exo(('git', '--git-dir', 'get-dest', 'show-ref', karg),
287 expected_refs = sorted(abs_refs)
288 repo_refs = sorted([x.split()[1] for x in exr.out.splitlines()])
289 wvpasseq(expected_refs, repo_refs)
291 # FIXME: can we just check "git show-ref --heads == ''"?
292 exr = exo(('git', '--git-dir', 'get-dest', 'show-ref', karg),
295 wvpasseq('', exr.out.strip())
297 def test_replace(get_disposition, src_info):
299 wvstart(get_disposition + ' --replace to root fails')
300 for item in ('.tag/tinyfile',
301 'src/latest' + src_info['tinyfile-path'],
303 'src/latest' + src_info['subtree-vfs-path'],
307 exr = run_get(get_disposition, '--replace', (item, '/'))
309 verify_rx(r'impossible; can only overwrite branch or tag', exr.err)
311 tinyfile_id = src_info['tinyfile-id']
312 tinyfile_path = src_info['tinyfile-path']
313 subtree_vfs_path = src_info['subtree-vfs-path']
314 subtree_id = src_info['subtree-id']
315 commit_2_id = src_info['commit-2-id']
316 tree_2_id = src_info['tree-2-id']
319 existing_items = {'nothing' : None,
320 'blob' : ('.tag/tinyfile', '.tag/obj'),
321 'tree' : ('.tag/tree-1', '.tag/obj'),
322 'commit': ('.tag/commit-1', '.tag/obj')}
323 for ex_type, ex_ref in existing_items.iteritems():
324 wvstart(get_disposition + ' --replace ' + ex_type + ' with blob tag')
325 for item in ('.tag/tinyfile', 'src/latest' + tinyfile_path):
326 exr = run_get(get_disposition, '--replace', (item ,'.tag/obj'),
329 validate_blob(tinyfile_id, tinyfile_id)
330 verify_only_refs(heads=[], tags=('obj',))
331 wvstart(get_disposition + ' --replace ' + ex_type + ' with tree tag')
332 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
333 exr = run_get(get_disposition, '--replace', (item, '.tag/obj'),
335 validate_tree(subtree_id, subtree_id)
336 verify_only_refs(heads=[], tags=('obj',))
337 wvstart(get_disposition + ' --replace ' + ex_type + ' with commitish tag')
338 for item in ('.tag/commit-2', 'src/latest', 'src'):
339 exr = run_get(get_disposition, '--replace', (item, '.tag/obj'),
341 validate_tagged_save('obj', getcwd() + '/src',
342 commit_2_id, tree_2_id, 'src-2', exr.out)
343 verify_only_refs(heads=[], tags=('obj',))
345 # Committish to branch.
346 existing_items = (('nothing', None),
347 ('branch', ('.tag/commit-1', 'obj')))
348 for ex_type, ex_ref in existing_items:
349 for item_type, item in (('commit', '.tag/commit-2'),
350 ('save', 'src/latest'),
352 wvstart(get_disposition + ' --replace '
353 + ex_type + ' with ' + item_type)
354 exr = run_get(get_disposition, '--replace', (item, 'obj'),
356 validate_save('obj/latest', getcwd() + '/src',
357 commit_2_id, tree_2_id, 'src-2', exr.out)
358 verify_only_refs(heads=('obj',), tags=[])
360 # Not committish to branch
361 existing_items = (('nothing', None),
362 ('branch', ('.tag/commit-1', 'obj')))
363 for ex_type, ex_ref in existing_items:
364 for item_type, item in (('blob', '.tag/tinyfile'),
365 ('blob', 'src/latest' + tinyfile_path),
366 ('tree', '.tag/subtree'),
367 ('tree', 'src/latest' + subtree_vfs_path)):
368 wvstart(get_disposition + ' --replace branch with '
369 + item_type + ' given ' + ex_type + ' fails')
371 exr = run_get(get_disposition, '--replace', (item, 'obj'),
374 verify_rx(r'cannot overwrite branch with .+ for', exr.err)
376 wvstart(get_disposition + ' --replace, implicit destinations')
378 exr = run_get(get_disposition, '--replace', 'src')
379 validate_save('src/latest', getcwd() + '/src',
380 commit_2_id, tree_2_id, 'src-2', exr.out)
381 verify_only_refs(heads=('src',), tags=[])
383 exr = run_get(get_disposition, '--replace', '.tag/commit-2')
384 validate_tagged_save('commit-2', getcwd() + '/src',
385 commit_2_id, tree_2_id, 'src-2', exr.out)
386 verify_only_refs(heads=[], tags=('commit-2',))
388 def test_ff(get_disposition, src_info):
390 wvstart(get_disposition + ' --ff to root fails')
391 tinyfile_path = src_info['tinyfile-path']
392 for item in ('.tag/tinyfile', 'src/latest' + tinyfile_path):
393 exr = run_get(get_disposition, '--ff', (item, '/'))
395 verify_rx(r'source for .+ must be a branch, save, or commit', exr.err)
396 subtree_vfs_path = src_info['subtree-vfs-path']
397 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
398 exr = run_get(get_disposition, '--ff', (item, '/'))
400 verify_rx(r'is impossible; can only --append a tree to a branch',
402 for item in ('.tag/commit-1', 'src/latest', 'src'):
403 exr = run_get(get_disposition, '--ff', (item, '/'))
405 verify_rx(r'destination for .+ is a root, not a branch', exr.err)
407 wvstart(get_disposition + ' --ff of not-committish fails')
408 for src in ('.tag/tinyfile', 'src/latest' + tinyfile_path):
409 # FIXME: use get_item elsewhere?
410 for given, get_item in ((None, (src, 'obj')),
411 (None, (src, '.tag/obj')),
412 (('.tag/tinyfile', '.tag/obj'), (src, '.tag/obj')),
413 (('.tag/tree-1', '.tag/obj'), (src, '.tag/obj')),
414 (('.tag/commit-1', '.tag/obj'), (src, '.tag/obj')),
415 (('.tag/commit-1', 'obj'), (src, 'obj'))):
416 exr = run_get(get_disposition, '--ff', get_item, given=given)
418 verify_rx(r'must be a branch, save, or commit', exr.err)
419 for src in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
420 for given, get_item in ((None, (src, 'obj')),
421 (None, (src, '.tag/obj')),
422 (('.tag/tinyfile', '.tag/obj'), (src, '.tag/obj')),
423 (('.tag/tree-1', '.tag/obj'), (src, '.tag/obj')),
424 (('.tag/commit-1', '.tag/obj'), (src, '.tag/obj')),
425 (('.tag/commit-1', 'obj'), (src, 'obj'))):
426 exr = run_get(get_disposition, '--ff', get_item, given=given)
428 verify_rx(r'can only --append a tree to a branch', exr.err)
430 wvstart(get_disposition + ' --ff committish, ff possible')
431 save_2 = src_info['save-2']
432 for src in ('.tag/commit-2', 'src/' + save_2, 'src'):
433 for given, get_item, complaint in \
434 ((None, (src, '.tag/obj'),
435 r'destination .+ must be a valid branch name'),
436 (('.tag/tinyfile', '.tag/obj'), (src, '.tag/obj'),
437 r'destination .+ is a blob, not a branch'),
438 (('.tag/tree-1', '.tag/obj'), (src, '.tag/obj'),
439 r'destination .+ is a tree, not a branch'),
440 (('.tag/commit-1', '.tag/obj'), (src, '.tag/obj'),
441 r'destination .+ is a tagged commit, not a branch'),
442 (('.tag/commit-2', '.tag/obj'), (src, '.tag/obj'),
443 r'destination .+ is a tagged commit, not a branch')):
444 exr = run_get(get_disposition, '--ff', get_item, given=given)
446 verify_rx(complaint, exr.err)
447 # FIXME: use src or item and given or existing consistently in loops...
448 commit_2_id = src_info['commit-2-id']
449 tree_2_id = src_info['tree-2-id']
450 for src in ('.tag/commit-2', 'src/' + save_2, 'src'):
451 for given in (None, ('.tag/commit-1', 'obj'), ('.tag/commit-2', 'obj')):
452 exr = run_get(get_disposition, '--ff', (src, 'obj'), given=given)
454 validate_save('obj/latest', getcwd() + '/src',
455 commit_2_id, tree_2_id, 'src-2', exr.out)
456 verify_only_refs(heads=('obj',), tags=[])
458 wvstart(get_disposition + ' --ff, implicit destinations')
459 for item in ('src', 'src/latest'):
460 exr = run_get(get_disposition, '--ff', item)
463 ex(('find', 'get-dest/refs'))
464 ex((bup_cmd, '-d', 'get-dest', 'ls'))
466 validate_save('src/latest', getcwd() + '/src',
467 commit_2_id, tree_2_id, 'src-2', exr.out)
468 #verify_only_refs(heads=('src',), tags=[])
470 wvstart(get_disposition + ' --ff, ff impossible')
471 for given, get_item in ((('unrelated-branch', 'src'), 'src'),
472 (('.tag/commit-2', 'src'), ('.tag/commit-1', 'src'))):
473 exr = run_get(get_disposition, '--ff', get_item, given=given)
475 verify_rx(r'destination is not an ancestor of source', exr.err)
477 def test_append(get_disposition, src_info):
478 tinyfile_path = src_info['tinyfile-path']
479 subtree_vfs_path = src_info['subtree-vfs-path']
481 wvstart(get_disposition + ' --append to root fails')
482 for item in ('.tag/tinyfile', 'src/latest' + tinyfile_path):
483 exr = run_get(get_disposition, '--append', (item, '/'))
485 verify_rx(r'source for .+ must be a branch, save, commit, or tree',
487 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path,
488 '.tag/commit-1', 'src/latest', 'src'):
489 exr = run_get(get_disposition, '--append', (item, '/'))
491 verify_rx(r'destination for .+ is a root, not a branch', exr.err)
493 wvstart(get_disposition + ' --append of not-treeish fails')
494 for src in ('.tag/tinyfile', 'src/latest' + tinyfile_path):
495 for given, item in ((None, (src, 'obj')),
496 (None, (src, '.tag/obj')),
497 (('.tag/tinyfile', '.tag/obj'), (src, '.tag/obj')),
498 (('.tag/tree-1', '.tag/obj'), (src, '.tag/obj')),
499 (('.tag/commit-1', '.tag/obj'), (src, '.tag/obj')),
500 (('.tag/commit-1', 'obj'), (src, 'obj'))):
501 exr = run_get(get_disposition, '--append', item, given=given)
503 verify_rx(r'must be a branch, save, commit, or tree', exr.err)
505 wvstart(get_disposition + ' --append committish failure cases')
506 save_2 = src_info['save-2']
507 for src in ('.tag/subtree', 'src/latest' + subtree_vfs_path,
508 '.tag/commit-2', 'src/' + save_2, 'src'):
509 for given, item, complaint in \
510 ((None, (src, '.tag/obj'),
511 r'destination .+ must be a valid branch name'),
512 (('.tag/tinyfile', '.tag/obj'), (src, '.tag/obj'),
513 r'destination .+ is a blob, not a branch'),
514 (('.tag/tree-1', '.tag/obj'), (src, '.tag/obj'),
515 r'destination .+ is a tree, not a branch'),
516 (('.tag/commit-1', '.tag/obj'), (src, '.tag/obj'),
517 r'destination .+ is a tagged commit, not a branch'),
518 (('.tag/commit-2', '.tag/obj'), (src, '.tag/obj'),
519 r'destination .+ is a tagged commit, not a branch')):
520 exr = run_get(get_disposition, '--append', item, given=given)
522 verify_rx(complaint, exr.err)
524 wvstart(get_disposition + ' --append committish')
525 commit_2_id = src_info['commit-2-id']
526 tree_2_id = src_info['tree-2-id']
527 for item in ('.tag/commit-2', 'src/' + save_2, 'src'):
528 for existing in (None, ('.tag/commit-1', 'obj'),
529 ('.tag/commit-2', 'obj'),
530 ('unrelated-branch', 'obj')):
531 exr = run_get(get_disposition, '--append', (item, 'obj'),
534 validate_new_save('obj/latest', getcwd() + '/src',
535 commit_2_id, tree_2_id, 'src-2', exr.out)
536 verify_only_refs(heads=('obj',), tags=[])
538 save_1 = src_info['save-1']
539 commit_1_id = src_info['commit-1-id']
540 tree_1_id = src_info['tree-1-id']
541 for item in ('.tag/commit-1', 'src/' + save_1, 'src-1'):
542 exr = run_get(get_disposition, '--append', (item, 'obj'),
543 given=('.tag/commit-2', 'obj'))
545 validate_new_save('obj/latest', getcwd() + '/src',
546 commit_1_id, tree_1_id, 'src-1', exr.out)
547 verify_only_refs(heads=('obj',), tags=[])
549 wvstart(get_disposition + ' --append tree')
550 subtree_path = src_info['subtree-path']
551 subtree_id = src_info['subtree-id']
552 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
553 for existing in (None, ('.tag/commit-1', 'obj'), ('.tag/commit-2','obj')):
554 exr = run_get(get_disposition, '--append', (item, 'obj'),
557 validate_new_save('obj/latest', '/', None, subtree_id, subtree_path,
559 verify_only_refs(heads=('obj',), tags=[])
561 wvstart(get_disposition + ' --append, implicit destinations')
563 for item in ('src', 'src/latest'):
564 exr = run_get(get_disposition, '--append', item)
566 validate_new_save('src/latest', getcwd() + '/src', commit_2_id, tree_2_id,
568 verify_only_refs(heads=('src',), tags=[])
570 def test_pick(get_disposition, src_info, force=False):
571 flavor = '--force-pick' if force else '--pick'
572 tinyfile_path = src_info['tinyfile-path']
573 subtree_vfs_path = src_info['subtree-vfs-path']
575 wvstart(get_disposition + ' ' + flavor + ' to root fails')
576 for item in ('.tag/tinyfile', 'src/latest' + tinyfile_path, 'src'):
577 exr = run_get(get_disposition, flavor, (item, '/'))
579 verify_rx(r'can only pick a commit or save', exr.err)
580 for item in ('.tag/commit-1', 'src/latest'):
581 exr = run_get(get_disposition, flavor, (item, '/'))
583 verify_rx(r'destination is not a tag or branch', exr.err)
584 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
585 exr = run_get(get_disposition, flavor, (item, '/'))
587 verify_rx(r'is impossible; can only --append a tree', exr.err)
589 wvstart(get_disposition + ' ' + flavor + ' of blob or branch fails')
590 for item in ('.tag/tinyfile', 'src/latest' + tinyfile_path, 'src'):
591 for given, get_item in ((None, (item, 'obj')),
592 (None, (item, '.tag/obj')),
593 (('.tag/tinyfile', '.tag/obj'), (item, '.tag/obj')),
594 (('.tag/tree-1', '.tag/obj'), (item, '.tag/obj')),
595 (('.tag/commit-1', '.tag/obj'), (item, '.tag/obj')),
596 (('.tag/commit-1', 'obj'), (item, 'obj'))):
597 exr = run_get(get_disposition, flavor, get_item, given=given)
599 verify_rx(r'impossible; can only pick a commit or save', exr.err)
601 wvstart(get_disposition + ' ' + flavor + ' of tree fails')
602 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
603 for given, get_item in ((None, (item, 'obj')),
604 (None, (item, '.tag/obj')),
605 (('.tag/tinyfile', '.tag/obj'), (item, '.tag/obj')),
606 (('.tag/tree-1', '.tag/obj'), (item, '.tag/obj')),
607 (('.tag/commit-1', '.tag/obj'), (item, '.tag/obj')),
608 (('.tag/commit-1', 'obj'), (item, 'obj'))):
609 exr = run_get(get_disposition, flavor, get_item, given=given)
611 verify_rx(r'impossible; can only --append a tree', exr.err)
613 save_2 = src_info['save-2']
614 commit_2_id = src_info['commit-2-id']
615 tree_2_id = src_info['tree-2-id']
616 # FIXME: these two wvstart texts?
618 wvstart(get_disposition + ' ' + flavor + ' commit/save to existing tag')
619 for item in ('.tag/commit-2', 'src/' + save_2):
620 for given in (('.tag/tinyfile', '.tag/obj'),
621 ('.tag/tree-1', '.tag/obj'),
622 ('.tag/commit-1', '.tag/obj')):
623 exr = run_get(get_disposition, flavor, (item, '.tag/obj'),
626 validate_new_tagged_commit('obj', commit_2_id, tree_2_id,
628 verify_only_refs(heads=[], tags=('obj',))
630 wvstart(get_disposition + ' ' + flavor
631 + ' commit/save to existing tag fails')
632 for item in ('.tag/commit-2', 'src/' + save_2):
633 for given in (('.tag/tinyfile', '.tag/obj'),
634 ('.tag/tree-1', '.tag/obj'),
635 ('.tag/commit-1', '.tag/obj')):
636 exr = run_get(get_disposition, flavor, (item, '.tag/obj'), given=given)
638 verify_rx(r'cannot overwrite existing tag', exr.err)
640 wvstart(get_disposition + ' ' + flavor + ' commit/save to tag')
641 for item in ('.tag/commit-2', 'src/' + save_2):
642 exr = run_get(get_disposition, flavor, (item, '.tag/obj'))
644 validate_clean_repo()
645 validate_new_tagged_commit('obj', commit_2_id, tree_2_id, exr.out)
646 verify_only_refs(heads=[], tags=('obj',))
648 wvstart(get_disposition + ' ' + flavor + ' commit/save to branch')
649 for item in ('.tag/commit-2', 'src/' + save_2):
650 for given in (None, ('.tag/commit-1', 'obj'), ('.tag/commit-2', 'obj')):
651 exr = run_get(get_disposition, flavor, (item, 'obj'), given=given)
653 validate_clean_repo()
654 validate_new_save('obj/latest', getcwd() + '/src',
655 commit_2_id, tree_2_id, 'src-2', exr.out)
656 verify_only_refs(heads=('obj',), tags=[])
658 wvstart(get_disposition + ' ' + flavor
659 + ' commit/save unrelated commit to branch')
660 for item in('.tag/commit-2', 'src/' + save_2):
661 exr = run_get(get_disposition, flavor, (item, 'obj'),
662 given=('unrelated-branch', 'obj'))
664 validate_clean_repo()
665 validate_new_save('obj/latest', getcwd() + '/src',
666 commit_2_id, tree_2_id, 'src-2', exr.out)
667 verify_only_refs(heads=('obj',), tags=[])
669 wvstart(get_disposition + ' ' + flavor + ' commit/save ancestor to branch')
670 save_1 = src_info['save-1']
671 commit_1_id = src_info['commit-1-id']
672 tree_1_id = src_info['tree-1-id']
673 for item in ('.tag/commit-1', 'src/' + save_1):
674 exr = run_get(get_disposition, flavor, (item, 'obj'),
675 given=('.tag/commit-2', 'obj'))
677 validate_clean_repo()
678 validate_new_save('obj/latest', getcwd() + '/src',
679 commit_1_id, tree_1_id, 'src-1', exr.out)
680 verify_only_refs(heads=('obj',), tags=[])
683 wvstart(get_disposition + ' ' + flavor + ', implicit destinations')
684 exr = run_get(get_disposition, flavor, '.tag/commit-2')
686 validate_clean_repo()
687 validate_new_tagged_commit('commit-2', commit_2_id, tree_2_id, exr.out)
688 verify_only_refs(heads=[], tags=('commit-2',))
690 exr = run_get(get_disposition, flavor, 'src/latest')
692 validate_clean_repo()
693 validate_new_save('src/latest', getcwd() + '/src',
694 commit_2_id, tree_2_id, 'src-2', exr.out)
695 verify_only_refs(heads=('src',), tags=[])
697 def test_new_tag(get_disposition, src_info):
698 tinyfile_id = src_info['tinyfile-id']
699 tinyfile_path = src_info['tinyfile-path']
700 commit_2_id = src_info['commit-2-id']
701 tree_2_id = src_info['tree-2-id']
702 subtree_id = src_info['subtree-id']
703 subtree_vfs_path = src_info['subtree-vfs-path']
705 wvstart(get_disposition + ' --new-tag to root fails')
706 for item in ('.tag/tinyfile',
707 'src/latest' + tinyfile_path,
709 'src/latest' + subtree_vfs_path,
713 exr = run_get(get_disposition, '--new-tag', (item, '/'))
715 verify_rx(r'destination for .+ must be a VFS tag', exr.err)
717 # Anything to new tag.
718 wvstart(get_disposition + ' --new-tag, blob tag')
719 for item in ('.tag/tinyfile', 'src/latest' + tinyfile_path):
720 exr = run_get(get_disposition, '--new-tag', (item, '.tag/obj'))
722 validate_blob(tinyfile_id, tinyfile_id)
723 verify_only_refs(heads=[], tags=('obj',))
725 wvstart(get_disposition + ' --new-tag, tree tag')
726 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
727 exr = run_get(get_disposition, '--new-tag', (item, '.tag/obj'))
729 validate_tree(subtree_id, subtree_id)
730 verify_only_refs(heads=[], tags=('obj',))
732 wvstart(get_disposition + ' --new-tag, committish tag')
733 for item in ('.tag/commit-2', 'src/latest', 'src'):
734 exr = run_get(get_disposition, '--new-tag', (item, '.tag/obj'))
736 validate_tagged_save('obj', getcwd() + '/src/', commit_2_id, tree_2_id,
738 verify_only_refs(heads=[], tags=('obj',))
740 # Anything to existing tag (fails).
741 for ex_type, ex_tag in (('blob', ('.tag/tinyfile', '.tag/obj')),
742 ('tree', ('.tag/tree-1', '.tag/obj')),
743 ('commit', ('.tag/commit-1', '.tag/obj'))):
744 for item_type, item in (('blob tag', '.tag/tinyfile'),
745 ('blob path', 'src/latest' + tinyfile_path),
746 ('tree tag', '.tag/subtree'),
747 ('tree path', 'src/latest' + subtree_vfs_path),
748 ('commit tag', '.tag/commit-2'),
749 ('save', 'src/latest'),
751 wvstart(get_disposition + ' --new-tag of ' + item_type
752 + ', given existing ' + ex_type + ' tag, fails')
753 exr = run_get(get_disposition, '--new-tag', (item, '.tag/obj'),
756 verify_rx(r'cannot overwrite existing tag .* \(requires --replace\)',
759 # Anything to branch (fails).
760 for ex_type, ex_tag in (('nothing', None),
761 ('blob', ('.tag/tinyfile', '.tag/obj')),
762 ('tree', ('.tag/tree-1', '.tag/obj')),
763 ('commit', ('.tag/commit-1', '.tag/obj'))):
764 for item_type, item in (('blob tag', '.tag/tinyfile'),
765 ('blob path', 'src/latest' + tinyfile_path),
766 ('tree tag', '.tag/subtree'),
767 ('tree path', 'src/latest' + subtree_vfs_path),
768 ('commit tag', '.tag/commit-2'),
769 ('save', 'src/latest'),
771 wvstart(get_disposition + ' --new-tag to branch of ' + item_type
772 + ', given existing ' + ex_type + ' tag, fails')
773 exr = run_get(get_disposition, '--new-tag', (item, 'obj'),
776 verify_rx(r'destination for .+ must be a VFS tag', exr.err)
778 wvstart(get_disposition + ' --new-tag, implicit destinations')
779 exr = run_get(get_disposition, '--new-tag', '.tag/commit-2')
781 validate_tagged_save('commit-2', getcwd() + '/src/', commit_2_id, tree_2_id,
783 verify_only_refs(heads=[], tags=('commit-2',))
785 def test_unnamed(get_disposition, src_info):
786 tinyfile_id = src_info['tinyfile-id']
787 tinyfile_path = src_info['tinyfile-path']
788 subtree_vfs_path = src_info['subtree-vfs-path']
789 wvstart(get_disposition + ' --unnamed to root fails')
790 for item in ('.tag/tinyfile',
791 'src/latest' + tinyfile_path,
793 'src/latest' + subtree_vfs_path,
797 for ex_ref in (None, (item, '.tag/obj')):
798 exr = run_get(get_disposition, '--unnamed', (item, '/'),
801 verify_rx(r'usage: bup get ', exr.err)
803 wvstart(get_disposition + ' --unnamed file')
804 for item in ('.tag/tinyfile', 'src/latest' + tinyfile_path):
805 exr = run_get(get_disposition, '--unnamed', item)
807 validate_blob(tinyfile_id, tinyfile_id)
808 verify_only_refs(heads=[], tags=[])
810 exr = run_get(get_disposition, '--unnamed', item,
811 given=(item, '.tag/obj'))
813 validate_blob(tinyfile_id, tinyfile_id)
814 verify_only_refs(heads=[], tags=('obj',))
816 wvstart(get_disposition + ' --unnamed tree')
817 subtree_id = src_info['subtree-id']
818 for item in ('.tag/subtree', 'src/latest' + subtree_vfs_path):
819 exr = run_get(get_disposition, '--unnamed', item)
821 validate_tree(subtree_id, subtree_id)
822 verify_only_refs(heads=[], tags=[])
824 exr = run_get(get_disposition, '--unnamed', item,
825 given=(item, '.tag/obj'))
827 validate_tree(subtree_id, subtree_id)
828 verify_only_refs(heads=[], tags=('obj',))
830 wvstart(get_disposition + ' --unnamed committish')
831 save_2 = src_info['save-2']
832 commit_2_id = src_info['commit-2-id']
833 for item in ('.tag/commit-2', 'src/' + save_2, 'src'):
834 exr = run_get(get_disposition, '--unnamed', item)
836 validate_commit(commit_2_id, commit_2_id)
837 verify_only_refs(heads=[], tags=[])
839 exr = run_get(get_disposition, '--unnamed', item,
840 given=(item, '.tag/obj'))
842 validate_commit(commit_2_id, commit_2_id)
843 verify_only_refs(heads=[], tags=('obj',))
845 def create_get_src():
846 global bup_cmd, src_info
848 ex((bup_cmd, '-d', 'get-src', 'init'))
851 open('src/unrelated', 'a').close()
852 ex((bup_cmd, '-d', 'get-src', 'index', 'src'))
853 ex((bup_cmd, '-d', 'get-src', 'save', '-tcn', 'unrelated-branch', 'src'))
855 ex((bup_cmd, '-d', 'get-src', 'index', '--clear'))
858 open('src/zero', 'a').close()
859 ex((bup_cmd, '-d', 'get-src', 'index', 'src'))
860 exr = exo((bup_cmd, '-d', 'get-src', 'save', '-tcn', 'src', 'src'))
861 out = exr.out.splitlines()
863 commit_0_id = out[-1]
864 exr = exo((bup_cmd, '-d', 'get-src', 'ls', 'src'))
865 save_0 = exr.out.splitlines()[0]
866 ex(('git', '--git-dir', 'get-src', 'branch', 'src-0', 'src'))
867 ex(('cp', '-RPp', 'src', 'src-0'))
873 ex((bup_cmd + ' -d get-src random 1k > src/1'), shell=True)
874 ex((bup_cmd + ' -d get-src random 1k > src/x/2'), shell=True)
875 ex((bup_cmd, '-d', 'get-src', 'index', 'src'))
876 exr = exo((bup_cmd, '-d', 'get-src', 'save', '-tcn', 'src', 'src'))
877 out = exr.out.splitlines()
879 commit_1_id = out[-1]
880 exr = exo((bup_cmd, '-d', 'get-src', 'ls', 'src'))
881 save_1 = exr.out.splitlines()[1]
882 ex(('git', '--git-dir', 'get-src', 'branch', 'src-1', 'src'))
883 ex(('cp', '-RPp', 'src', 'src-1'))
885 # Make a copy the current state of src so we'll have an ancestor.
887 'get-src/refs/heads/src', 'get-src/refs/heads/src-ancestor'))
889 with open('src/tiny-file', 'a') as f: f.write('xyzzy')
890 ex((bup_cmd, '-d', 'get-src', 'index', 'src'))
891 ex((bup_cmd, '-d', 'get-src', 'tick')) # Ensure the save names differ
892 exr = exo((bup_cmd, '-d', 'get-src', 'save', '-tcn', 'src', 'src'))
893 out = exr.out.splitlines()
895 commit_2_id = out[-1]
896 exr = exo((bup_cmd, '-d', 'get-src', 'ls', 'src'))
897 save_2 = exr.out.splitlines()[2]
898 rename('src', 'src-2')
900 src_root = getcwd() + '/src'
902 subtree_path = 'src-2/x'
903 subtree_vfs_path = src_root + '/x'
905 # No support for "ls -d", so grep...
906 exr = exo((bup_cmd, '-d', 'get-src', 'ls', '-s', 'src/latest' + src_root))
907 out = exr.out.splitlines()
911 subtree_id = line.split()[0]
914 # With a tiny file, we'll get a single blob, not a chunked tree
915 tinyfile_path = src_root + '/tiny-file'
916 exr = exo((bup_cmd, '-d', 'get-src', 'ls', '-s', 'src/latest' + tinyfile_path))
917 tinyfile_id = exr.out.splitlines()[0].split()[0]
919 ex((bup_cmd, '-d', 'get-src', 'tag', 'tinyfile', tinyfile_id))
920 ex((bup_cmd, '-d', 'get-src', 'tag', 'subtree', subtree_id))
921 ex((bup_cmd, '-d', 'get-src', 'tag', 'tree-0', tree_0_id))
922 ex((bup_cmd, '-d', 'get-src', 'tag', 'tree-1', tree_1_id))
923 ex((bup_cmd, '-d', 'get-src', 'tag', 'tree-2', tree_2_id))
924 ex((bup_cmd, '-d', 'get-src', 'tag', 'commit-0', commit_0_id))
925 ex((bup_cmd, '-d', 'get-src', 'tag', 'commit-1', commit_1_id))
926 ex((bup_cmd, '-d', 'get-src', 'tag', 'commit-2', commit_2_id))
927 ex(('git', '--git-dir', 'get-src', 'branch', 'commit-1', commit_1_id))
928 ex(('git', '--git-dir', 'get-src', 'branch', 'commit-2', commit_2_id))
930 return {'tinyfile-path' : tinyfile_path,
931 'tinyfile-id' : tinyfile_id,
932 'subtree-id' : subtree_id,
933 'tree-0-id' : tree_0_id,
934 'tree-1-id' : tree_1_id,
935 'tree-2-id' : tree_2_id,
936 'commit-0-id' : commit_0_id,
937 'commit-1-id' : commit_1_id,
938 'commit-2-id' : commit_2_id,
941 'subtree-path' : subtree_path,
942 'subtree-vfs-path' : subtree_vfs_path}
944 # FIXME: this fails in a strange way:
945 # WVPASS given nothing get --ff not-there
947 dispositions_to_test = ('get',)
949 if int(environ.get('BUP_TEST_LEVEL', '0')) >= 11:
950 dispositions_to_test += ('get-on', 'get-to')
952 if len(sys.argv) == 1:
953 categories = ('replace', 'universal', 'ff', 'append', 'pick', 'new-tag',
956 categories = sys.argv[1:]
958 with test_tempdir('get-') as tmpdir:
961 src_info = create_get_src()
962 for category in categories:
963 for disposition in dispositions_to_test:
964 # given=FOO depends on --replace, so test it early
965 if category == 'replace':
966 test_replace(disposition, src_info)
967 elif category == 'universal':
968 test_universal_behaviors(disposition)
969 elif category == 'ff':
970 test_ff(disposition, src_info)
971 elif category == 'append':
972 test_append(disposition, src_info)
973 elif category == 'pick':
974 test_pick(disposition, src_info, force=False)
975 test_pick(disposition, src_info, force=True)
976 elif category == 'new-tag':
977 test_new_tag(disposition, src_info)
978 elif category == 'unnamed':
979 test_unnamed(disposition, src_info)
981 raise Exception('unrecognized get test category')
982 except Exception, ex:
987 wvmsg('checked %d cases' % get_cases_tested)