623
624
tree.lock_write()
625
626
tree._observed_sha1("foo-id", "foo",
626
osutils.sha_file_by_name('foo'))
627
(osutils.sha_file_by_name('foo'), os.lstat("foo")))
627
628
# Must not have changed
628
629
self.assertEqual(current_sha1,
629
630
tree._get_entry(path="foo")[1][0][1])
634
def test_get_file_with_stat_id_only(self):
635
# Explicit test to ensure we get a lstat value from WT4 trees.
636
tree = self.make_branch_and_tree('.')
637
self.build_tree(['foo'])
638
tree.add(['foo'], ['foo-id'])
640
self.addCleanup(tree.unlock)
641
file_obj, statvalue = tree.get_file_with_stat('foo-id')
642
expected = os.lstat('foo')
643
self.assertEqualStat(expected, statvalue)
644
self.assertEqual(["contents of foo\n"], file_obj.readlines())
647
class TestCorruptDirstate(TestCaseWithTransport):
648
"""Tests for how we handle when the dirstate has been corrupted."""
650
def create_wt4(self):
651
control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
652
control.create_repository()
653
control.create_branch()
654
tree = workingtree_4.WorkingTreeFormat4().initialize(control)
657
def test_invalid_rename(self):
658
tree = self.create_wt4()
659
# Create a corrupted dirstate
662
tree.commit('init') # We need a parent, or we always compare with NULL
663
state = tree.current_dirstate()
664
state._read_dirblocks_if_needed()
665
# Now add in an invalid entry, a rename with a dangling pointer
666
state._dirblocks[1][1].append((('', 'foo', 'foo-id'),
667
[('f', '', 0, False, ''),
668
('r', 'bar', 0 , False, '')]))
669
self.assertListRaises(errors.CorruptDirstate,
670
tree.iter_changes, tree.basis_tree())
674
def get_simple_dirblocks(self, state):
675
"""Extract the simple information from the DirState.
677
This returns the dirblocks, only with the sha1sum and stat details
681
for block in state._dirblocks:
682
simple_block = (block[0], [])
683
for entry in block[1]:
684
# Include the key for each entry, and for each parent include
685
# just the minikind, so we know if it was
686
# present/absent/renamed/etc
687
simple_block[1].append((entry[0], [i[0] for i in entry[1]]))
688
simple_blocks.append(simple_block)
691
def test_update_basis_with_invalid_delta(self):
692
"""When given an invalid delta, it should abort, and not be saved."""
693
self.build_tree(['dir/', 'dir/file'])
694
tree = self.create_wt4()
696
self.addCleanup(tree.unlock)
697
tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
698
first_revision_id = tree.commit('init')
700
root_id = tree.path2id('')
701
state = tree.current_dirstate()
702
state._read_dirblocks_if_needed()
704
('', [(('', '', root_id), ['d', 'd'])]),
705
('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
706
('dir', [(('dir', 'file', 'file-id'), ['f', 'f'])]),
707
], self.get_simple_dirblocks(state))
709
tree.remove(['dir/file'])
711
('', [(('', '', root_id), ['d', 'd'])]),
712
('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
713
('dir', [(('dir', 'file', 'file-id'), ['a', 'f'])]),
714
], self.get_simple_dirblocks(state))
715
# Make sure the removal is written to disk
718
# self.assertRaises(Exception, tree.update_basis_by_delta,
719
new_dir = inventory.InventoryDirectory('dir-id', 'new-dir', root_id)
720
new_dir.revision = 'new-revision-id'
721
new_file = inventory.InventoryFile('file-id', 'new-file', root_id)
722
new_file.revision = 'new-revision-id'
723
self.assertRaises(errors.InconsistentDelta,
724
tree.update_basis_by_delta, 'new-revision-id',
725
[('dir', 'new-dir', 'dir-id', new_dir),
726
('dir/file', 'new-dir/new-file', 'file-id', new_file),
730
# Now when we re-read the file it should not have been modified
733
self.assertEqual(first_revision_id, tree.last_revision())
734
state = tree.current_dirstate()
735
state._read_dirblocks_if_needed()
737
('', [(('', '', root_id), ['d', 'd'])]),
738
('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
739
('dir', [(('dir', 'file', 'file-id'), ['a', 'f'])]),
740
], self.get_simple_dirblocks(state))