42
42
control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
43
43
control.create_repository()
44
44
control.create_branch()
45
tree = workingtree_4.WorkingTreeFormat4().initialize(control)
45
workingtree_4.WorkingTreeFormat4().initialize(control)
47
47
# format 'Bazaar Working Tree format 4'
102
102
self.build_tree([relpath + '/'])
103
103
dir = bzrdir.BzrDirMetaFormat1().initialize(url)
104
repo = dir.create_repository()
105
branch = dir.create_branch()
104
dir.create_repository()
107
107
return workingtree_4.WorkingTreeFormat4().initialize(dir)
108
108
except errors.NotLocalUrl:
125
125
# permit lock upgrading.
126
126
subtree.lock_write()
127
127
self.addCleanup(subtree.unlock)
128
self.build_tree(['subdir/file-a',])
128
self.build_tree(['subdir/file-a', ])
129
129
subtree.add(['file-a'], [b'id-a'])
130
130
rev1 = subtree.commit('commit in subdir')
231
231
# dont uncomment this: the revision object must be accessed to
232
232
# answer 'get_parent_ids' for the revision tree- dirstate does not
233
233
# cache the parents of a parent tree at this point.
234
#repo.get_revision = self.fail
234
# repo.get_revision = self.fail
235
235
self.overrideAttr(repo, "get_inventory", self.fail)
236
236
self.overrideAttr(repo, "_get_inventory_xml", self.fail)
237
237
# set the parent trees.
297
297
state = tree.current_dirstate()
299
299
orig_update = state.update_basis_by_delta
300
301
def log_update_basis_by_delta(delta, new_revid):
301
302
called.append(new_revid)
302
303
return orig_update(delta, new_revid)
304
305
basis = tree.basis_tree()
305
306
self.assertEqual(b'a-id', basis.path2id('a'))
306
307
self.assertFalse(basis.is_versioned('b'))
307
309
def fail_set_parent_trees(trees, ghosts):
308
310
raise AssertionError('dirstate.set_parent_trees() was called')
309
311
state.set_parent_trees = fail_set_parent_trees
310
repo = tree.branch.repository
311
312
tree.pull(source_branch, stop_revision=b'B')
312
313
self.assertEqual([b'B'], called)
313
314
basis = tree.basis_tree()
347
348
# until we have detection for when a dirstate can be reused, we
348
349
# want to reparse dirstate on every new lock.
349
350
known_dirstates = set()
350
352
def lock_and_compare_all_current_dirstate(tree, lock_method):
351
353
getattr(tree, lock_method)()
352
354
state = tree.current_dirstate()
366
368
def test_constructing_invalid_interdirstate_raises(self):
367
369
tree = self.make_workingtree()
368
370
rev_id = tree.commit('first post')
369
rev_id2 = tree.commit('second post')
371
tree.commit('second post')
370
372
rev_tree = tree.branch.repository.revision_tree(rev_id)
371
373
# Exception is not a great thing to raise, but this test is
372
374
# very short, and code is used to sanity check other tests, so
388
390
rev_tree2 = tree.branch.repository.revision_tree(rev_id2)
389
391
optimiser = InterTree.get(rev_tree, rev_tree2)
390
392
self.assertIsInstance(optimiser, InterTree)
391
self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
393
self.assertFalse(isinstance(
394
optimiser, workingtree_4.InterDirStateTree))
392
395
optimiser = InterTree.get(rev_tree2, rev_tree)
393
396
self.assertIsInstance(optimiser, InterTree)
394
self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
397
self.assertFalse(isinstance(
398
optimiser, workingtree_4.InterDirStateTree))
396
400
def test_revtree_not_in_dirstate_to_dirstate_not_interdirstate(self):
397
401
# we should not get a dirstate optimiser when the revision id for of
398
402
# the source is not in the dirstate of the target.
399
403
tree = self.make_workingtree()
400
404
rev_id = tree.commit('first post')
401
rev_id2 = tree.commit('second post')
405
tree.commit('second post')
402
406
rev_tree = tree.branch.repository.revision_tree(rev_id)
404
408
optimiser = InterTree.get(rev_tree, tree)
405
409
self.assertIsInstance(optimiser, InterTree)
406
self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
410
self.assertFalse(isinstance(
411
optimiser, workingtree_4.InterDirStateTree))
407
412
optimiser = InterTree.get(tree, rev_tree)
408
413
self.assertIsInstance(optimiser, InterTree)
409
self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
414
self.assertFalse(isinstance(
415
optimiser, workingtree_4.InterDirStateTree))
412
418
def test_empty_basis_to_dirstate_tree(self):
525
531
# each time you initialize a new tree, it gets a different root id
526
532
format_name = 'development-subtree'
527
533
tree1 = self.make_branch_and_tree('tree1',
529
535
tree2 = self.make_branch_and_tree('tree2',
531
537
self.assertNotEqual(tree1.get_root_id(), tree2.get_root_id())
532
538
# when you branch, it inherits the same root id
533
rev1 = tree1.commit('first post')
539
tree1.commit('first post')
534
540
tree3 = tree1.controldir.sprout('tree3').open_workingtree()
535
541
self.assertEqual(tree3.get_root_id(), tree1.get_root_id())
572
578
# for testing easily.
573
579
tree.set_root_id(b'root')
574
580
tree.add(['dir'], [b'dir-id'])
575
subtree = self.make_branch_and_tree('dir')
581
self.make_branch_and_tree('dir')
576
582
# the most primitive operation: kind
577
583
self.assertEqual('directory', tree.kind('dir'))
578
584
# a diff against the basis should give us a directory and the root (as
579
585
# the root is new too).
581
587
expected = [(b'dir-id',
589
(b'root', (None, u''), True, (False, True), (None, None),
590
(None, u''), (None, 'directory'), (None, 0))]
591
self.assertEqual(expected, list(tree.iter_changes(tree.basis_tree(),
592
specific_files=['dir'])))
595
(b'root', (None, u''), True, (False, True), (None, None),
596
(None, u''), (None, 'directory'), (None, 0))]
599
list(tree.iter_changes(tree.basis_tree(), specific_files=['dir'])))
594
601
# do a commit, we want to trigger the dirstate fast-path too
595
602
tree.commit('first post')
635
642
'versioned2/unversioned/',
636
643
'versioned2/unversioned/a',
637
644
'versioned2/unversioned/b/',
639
646
tree.add(['versioned', 'versioned2', 'versioned2/a'])
640
647
tree.commit('one', rev_id=b'rev-1')
641
648
# Trap osutils._walkdirs_utf8 to spy on what dirs have been accessed.
643
651
def walkdirs_spy(*args, **kwargs):
644
652
for val in orig(*args, **kwargs):
645
653
returned.append(val[0][0])
656
664
self.assertEqual([(None, 'unversioned'),
657
665
(None, 'versioned/unversioned'),
658
666
(None, 'versioned2/unversioned'),
660
668
self.assertEqual([b'', b'versioned', b'versioned2'], returned)
661
del returned[:] # reset
669
del returned[:] # reset
662
670
changes = [c[1] for c in tree.iter_changes(basis)]
663
671
self.assertEqual([], changes)
664
672
self.assertEqual([b'', b'versioned', b'versioned2'], returned)
672
680
tree.add(['bar'], [b'bar-id'])
674
682
self.addCleanup(tree.unlock)
675
tree_iter_changes = lambda files: [
676
c for c in tree.iter_changes(tree.basis_tree(), specific_files=files,
677
require_versioned=True)
684
def tree_iter_changes(files):
686
c for c in tree.iter_changes(
687
tree.basis_tree(), specific_files=files,
688
require_versioned=True)]
679
689
e = self.assertRaises(errors.PathsNotVersionedError,
680
690
tree_iter_changes, ['bar', 'foo'])
681
691
self.assertEqual(e.paths, ['foo'])
686
696
tree = self.make_branch_and_tree('.')
687
697
self.build_tree_contents([('f', b'')])
688
698
tree.add(['f'], [b'f-id'])
689
700
def tree_iter_changes(tree, files):
690
return list(tree.iter_changes(tree.basis_tree(),
691
specific_files=files, require_versioned=True))
701
return list(tree.iter_changes(
702
tree.basis_tree(), specific_files=files,
703
require_versioned=True))
693
705
self.addCleanup(tree.unlock)
694
706
e = self.assertRaises(errors.PathsNotVersionedError,
695
tree_iter_changes, tree, [u'\xa7', u'\u03c0'])
707
tree_iter_changes, tree, [u'\xa7', u'\u03c0'])
696
708
self.assertEqual(set(e.paths), set([u'\xa7', u'\u03c0']))
698
710
def get_tree_with_cachable_file_foo(self):
707
719
def test_commit_updates_hash_cache(self):
708
720
tree = self.get_tree_with_cachable_file_foo()
709
revid = tree.commit('a commit')
721
tree.commit('a commit')
710
722
# tree's dirstate should now have a valid stat entry for foo.
711
723
entry = tree._get_entry(path='foo')
712
724
expected_sha1 = osutils.sha_file_by_name('foo')
739
751
with tree.lock_read():
740
752
current_sha1 = tree._get_entry(path="foo")[1][0][1]
741
753
with tree.lock_write():
742
tree._observed_sha1("foo",
743
(osutils.sha_file_by_name('foo'), os.lstat("foo")))
755
"foo", (osutils.sha_file_by_name('foo'), os.lstat("foo")))
744
756
# Must not have changed
745
757
self.assertEqual(current_sha1,
746
tree._get_entry(path="foo")[1][0][1])
758
tree._get_entry(path="foo")[1][0][1])
748
760
def test_get_file_with_stat_id_only(self):
749
761
# Explicit test to ensure we get a lstat value from WT4 trees.
778
790
state._read_dirblocks_if_needed()
779
791
# Now add in an invalid entry, a rename with a dangling pointer
780
792
state._dirblocks[1][1].append(((b'', b'foo', b'foo-id'),
781
[(b'f', b'', 0, False, b''),
782
(b'r', b'bar', 0, False, b'')]))
793
[(b'f', b'', 0, False, b''),
794
(b'r', b'bar', 0, False, b'')]))
783
795
self.assertListRaises(dirstate.DirstateCorrupt,
784
796
tree.iter_changes, tree.basis_tree())
816
828
(b'', [((b'', b'', root_id), [b'd', b'd'])]),
817
829
(b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
818
830
(b'dir', [((b'dir', b'file', b'file-id'), [b'f', b'f'])]),
819
], self.get_simple_dirblocks(state))
831
], self.get_simple_dirblocks(state))
821
833
tree.remove(['dir/file'])
822
834
self.assertEqual([
823
835
(b'', [((b'', b'', root_id), [b'd', b'd'])]),
824
836
(b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
825
837
(b'dir', [((b'dir', b'file', b'file-id'), [b'a', b'f'])]),
826
], self.get_simple_dirblocks(state))
838
], self.get_simple_dirblocks(state))
827
839
# Make sure the removal is written to disk
832
844
new_dir.revision = b'new-revision-id'
833
845
new_file = inventory.InventoryFile(b'file-id', 'new-file', root_id)
834
846
new_file.revision = b'new-revision-id'
835
self.assertRaises(errors.InconsistentDelta,
848
errors.InconsistentDelta,
836
849
tree.update_basis_by_delta, b'new-revision-id',
837
850
[('dir', 'new-dir', b'dir-id', new_dir),
838
851
('dir/file', 'new-dir/new-file', b'file-id', new_file),
849
862
(b'', [((b'', b'', root_id), [b'd', b'd'])]),
850
863
(b'', [((b'', b'dir', b'dir-id'), [b'd', b'd'])]),
851
864
(b'dir', [((b'dir', b'file', b'file-id'), [b'a', b'f'])]),
852
], self.get_simple_dirblocks(state))
865
], self.get_simple_dirblocks(state))
855
868
class TestInventoryCoherency(TestCaseWithTransport):