Rev 3222: Tweaked fix for #187169: if an illegal update is made to the dirstate, don't allow it to be written out. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Feb 13 03:19:11 GMT 2008
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3222
revision-id:pqm at pqm.ubuntu.com-20080213031902-4xhmwps49vclfhh6
parent: pqm at pqm.ubuntu.com-20080208064756-bg0zu0y4e789j50r
parent: mbp at sourcefrog.net-20080213014247-buajf9y91w5xuaa8
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2008-02-13 03:19:02 +0000
message:
Tweaked fix for #187169: if an illegal update is made to the dirstate, don't allow it to be written out.
modified:
bzrlib/bundle/commands.py __init__.py-20050617152058-1b6530d9ab85c11c
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/blackbox/test_bundle_info.py test_bundle_info.py-20070816181255-eiuodwxuqu7w7gxf-1
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 3221.1.8
revision-id:mbp at sourcefrog.net-20080213014247-buajf9y91w5xuaa8
parent: mbp at sourcefrog.net-20080213013527-ml201846kikzon42
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Wed 2008-02-13 12:42:47 +1100
message:
Update error format in test_inconsistent_delta
modified:
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
------------------------------------------------------------
revno: 3221.1.7
revision-id:mbp at sourcefrog.net-20080213013527-ml201846kikzon42
parent: mbp at sourcefrog.net-20080213013133-x41bshcx7i5ozpo1
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Wed 2008-02-13 12:35:27 +1100
message:
Update and rename test for Dirstate._changes_aborted
modified:
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
------------------------------------------------------------
revno: 3221.1.6
revision-id:mbp at sourcefrog.net-20080213013133-x41bshcx7i5ozpo1
parent: mbp at sourcefrog.net-20080212021404-j0okfr3zla2sv351
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Wed 2008-02-13 12:31:33 +1100
message:
Better error message from bundle-info
modified:
bzrlib/bundle/commands.py __init__.py-20050617152058-1b6530d9ab85c11c
bzrlib/tests/blackbox/test_bundle_info.py test_bundle_info.py-20070816181255-eiuodwxuqu7w7gxf-1
------------------------------------------------------------
revno: 3221.1.5
revision-id:mbp at sourcefrog.net-20080212021404-j0okfr3zla2sv351
parent: mbp at sourcefrog.net-20080212021343-3r7l8xi9lsrt4gzu
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Tue 2008-02-12 13:14:04 +1100
message:
Fix incorrect indent in dirstate error handling
modified:
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
------------------------------------------------------------
revno: 3221.1.4
revision-id:mbp at sourcefrog.net-20080212021343-3r7l8xi9lsrt4gzu
parent: mbp at sourcefrog.net-20080211112411-j07kfvsserr68aha
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Tue 2008-02-12 13:13:43 +1100
message:
Fix format string for InconsistentDelta
modified:
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
------------------------------------------------------------
revno: 3221.1.3
revision-id:mbp at sourcefrog.net-20080211112411-j07kfvsserr68aha
parent: mbp at sourcefrog.net-20080211111556-qs2fntphg1ytv6ne
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Mon 2008-02-11 22:24:11 +1100
message:
Review cleanups for CorruptDirstate: use the path everywhere rather than the object, and use more standard phrasing.
modified:
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 3221.1.2
revision-id:mbp at sourcefrog.net-20080211111556-qs2fntphg1ytv6ne
parent: mbp at sourcefrog.net-20080211110224-u78ya6vu5wmmswju
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Mon 2008-02-11 22:15:56 +1100
message:
Mark problems in a Dirstate that should prevent saving with a _changes_aborted flag rather than _consistency
modified:
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
------------------------------------------------------------
revno: 3221.1.1
revision-id:mbp at sourcefrog.net-20080211110224-u78ya6vu5wmmswju
parent: pqm at pqm.ubuntu.com-20080208064756-bg0zu0y4e789j50r
parent: john at arbash-meinel.com-20080204211249-cb49xtg70j5okbw7
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: prepare-1.2rc1
timestamp: Mon 2008-02-11 22:02:24 +1100
message:
Merge John's invalid-dirstate rollback patch
modified:
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 3207.2.2
revision-id:john at arbash-meinel.com-20080204211249-cb49xtg70j5okbw7
parent: jameinel at samus-20080130201600-rhtzr6r55k604rbb
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate_187169
timestamp: Mon 2008-02-04 15:12:49 -0600
message:
Fix bug #187169, when an invalid delta is supplied to update_basis_by_delta
modified:
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
------------------------------------------------------------
revno: 3207.2.1
revision-id:jameinel at samus-20080130201600-rhtzr6r55k604rbb
parent: pqm at pqm.ubuntu.com-20080130100306-p0uqnxt3hodnyiej
committer: jameinel <jameinel at SAMUS>
branch nick: dirstate_187169
timestamp: Wed 2008-01-30 14:16:00 -0600
message:
Add a test that _iter_changes raises a clearer error when we encounter an invalid rename.
modified:
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'bzrlib/bundle/commands.py'
--- a/bzrlib/bundle/commands.py 2007-10-16 16:02:01 +0000
+++ b/bzrlib/bundle/commands.py 2008-02-13 01:31:33 +0000
@@ -59,8 +59,8 @@
bundle_info = read_bundle(bundle_file)
else:
if verbose:
- raise errors.BzrCommandError('Verbose requires a merge'
- ' directive')
+ raise errors.BzrCommandError('--verbose requires a merge'
+ ' directive')
reader_method = getattr(bundle_info, 'get_bundle_reader', None)
if reader_method is None:
raise errors.BzrCommandError('Bundle format not supported')
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2007-12-19 08:12:34 +0000
+++ b/bzrlib/dirstate.py 2008-02-12 02:14:04 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007 Canonical Ltd
+# Copyright (C) 2006, 2007, 2008 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -321,6 +321,9 @@
# modified states.
self._header_state = DirState.NOT_IN_MEMORY
self._dirblock_state = DirState.NOT_IN_MEMORY
+ # If true, an error has been detected while updating the dirstate, and
+ # for safety we're not going to commit to disk.
+ self._changes_aborted = False
self._dirblocks = []
self._ghosts = []
self._parents = []
@@ -1292,13 +1295,15 @@
assert old_path is None
# the entry for this file_id must be in tree 0.
entry = self._get_entry(0, file_id, new_path)
- if entry[0][2] != file_id:
- raise errors.BzrError('dirstate: cannot apply delta, working'
- ' tree does not contain new entry %r %r' %
- (new_path, file_id))
+ if entry[0] is None or entry[0][2] != file_id:
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(new_path, file_id,
+ 'working tree does not contain new entry')
if real_add and entry[1][1][0] not in absent:
- raise errors.BzrError('dirstate: inconsistent delta, with '
- 'tree 0. %r %r' % (new_path, file_id))
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(new_path, file_id,
+ 'The entry was considered to be a genuinely new record,'
+ ' but there was already an old record for it.')
# We don't need to update the target of an 'r' because the handling
# of renames turns all 'r' situations into a delete at the original
# location.
@@ -1315,14 +1320,15 @@
assert old_path == new_path
# the entry for this file_id must be in tree 0.
entry = self._get_entry(0, file_id, new_path)
- if entry[0][2] != file_id:
- raise errors.BzrError('dirstate: cannot apply delta, working'
- ' tree does not contain new entry %r %r' %
- (new_path, file_id))
+ if entry[0] is None or entry[0][2] != file_id:
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(new_path, file_id,
+ 'working tree does not contain new entry')
if (entry[1][0][0] in absent or
entry[1][1][0] in absent):
- raise errors.BzrError('dirstate: inconsistent delta, with '
- 'tree 0. %r %r' % (new_path, file_id))
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(new_path, file_id,
+ 'changed considered absent')
entry[1][1] = new_details
def _update_basis_apply_deletes(self, deletes):
@@ -1348,22 +1354,31 @@
block_index, entry_index, dir_present, file_present = \
self._get_block_entry_index(dirname, basename, 1)
if not file_present:
- raise errors.BzrError('dirstate: cannot apply delta, basis'
- ' tree does not contain new entry %r %r' %
- (old_path, file_id))
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(old_path, file_id,
+ 'basis tree does not contain removed entry')
entry = self._dirblocks[block_index][1][entry_index]
if entry[0][2] != file_id:
- raise errors.BzrError('mismatched file_id in tree 1 %r %r' %
- (old_path, file_id))
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(old_path, file_id,
+ 'mismatched file_id in tree 1')
if real_delete:
if entry[1][0][0] != 'a':
- raise errors.BzrError('dirstate: inconsistent delta, with '
- 'tree 0. %r %r' % (old_path, file_id))
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(old_path, file_id,
+ 'This was marked as a real delete, but the WT state'
+ ' claims that it still exists and is versioned.')
del self._dirblocks[block_index][1][entry_index]
else:
if entry[1][0][0] == 'a':
- raise errors.BzrError('dirstate: inconsistent delta, with '
- 'tree 0. %r %r' % (old_path, file_id))
+ self._changes_aborted = True
+ raise errors.InconsistentDelta(old_path, file_id,
+ 'The entry was considered a rename, but the source path'
+ ' is marked as absent.')
+ # For whatever reason, we were asked to rename an entry
+ # that was originally marked as deleted. This could be
+ # because we are renaming the parent directory, and the WT
+ # current state has the file marked as deleted.
elif entry[1][0][0] == 'r':
# implement the rename
del self._dirblocks[block_index][1][entry_index]
@@ -1666,6 +1681,7 @@
assert entry[0][2] and entry[1][tree_index][0] not in ('a', 'r'), 'unversioned entry?!?!'
if fileid_utf8:
if entry[0][2] != fileid_utf8:
+ self._changes_aborted = True
raise errors.BzrError('integrity error ? : mismatching'
' tree_index, file_id and path')
return entry
@@ -1954,6 +1970,12 @@
start over, to allow for fine grained read lock duration, so 'status'
wont block 'commit' - for example.
"""
+ if self._changes_aborted:
+ # Should this be a warning? For now, I'm expecting that places that
+ # mark it inconsistent will warn, making a warning here redundant.
+ trace.mutter('Not saving DirState because '
+ '_changes_aborted is set.')
+ return
if (self._header_state == DirState.IN_MEMORY_MODIFIED or
self._dirblock_state == DirState.IN_MEMORY_MODIFIED):
@@ -2598,6 +2620,7 @@
"""Forget all state information about the dirstate."""
self._header_state = DirState.NOT_IN_MEMORY
self._dirblock_state = DirState.NOT_IN_MEMORY
+ self._changes_aborted = False
self._parents = []
self._ghosts = []
self._dirblocks = []
=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py 2008-02-06 16:38:04 +0000
+++ b/bzrlib/errors.py 2008-02-12 02:13:43 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
+# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -1981,6 +1981,17 @@
_fmt = "Format error in conflict listings"
+class CorruptDirstate(BzrError):
+
+ _fmt = ("Inconsistency in dirstate file %(dirstate_path)s.\n"
+ "Error: %(description)s")
+
+ def __init__(self, dirstate_path, description):
+ BzrError.__init__(self)
+ self.dirstate_path = dirstate_path
+ self.description = description
+
+
class CorruptRepository(BzrError):
_fmt = ("An error has been detected in the repository %(repo_path)s.\n"
@@ -1991,6 +2002,19 @@
self.repo_path = repo.bzrdir.root_transport.base
+class InconsistentDelta(BzrError):
+ """Used when we get a delta that is not valid."""
+
+ _fmt = ("An inconsistent delta was supplied involving %(path)r,"
+ " %(file_id)r\nreason: %(reason)s")
+
+ def __init__(self, path, file_id, reason):
+ BzrError.__init__(self)
+ self.path = path
+ self.file_id = file_id
+ self.reason = reason
+
+
class UpgradeRequired(BzrError):
_fmt = "To use this feature you must upgrade your branch at %(path)s."
=== modified file 'bzrlib/tests/blackbox/test_bundle_info.py'
--- a/bzrlib/tests/blackbox/test_bundle_info.py 2007-08-16 18:23:13 +0000
+++ b/bzrlib/tests/blackbox/test_bundle_info.py 2008-02-13 01:31:33 +0000
@@ -38,7 +38,7 @@
self.assertContainsRe(info, 'file: 1 .0 multiparent.')
self.assertContainsRe(info, 'nicks: source')
self.assertNotContainsRe(info, 'foo')
- self.run_bzr_error(['Verbose requires a merge directive'],
+ self.run_bzr_error(['--verbose requires a merge directive'],
'bundle-info -v bundle')
target = self.make_branch('target')
md = merge_directive.MergeDirective2.from_objects(
=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py 2007-11-21 22:16:20 +0000
+++ b/bzrlib/tests/test_dirstate.py 2008-02-13 01:35:27 +0000
@@ -646,6 +646,45 @@
finally:
state.unlock()
+ def test_save_refuses_if_changes_aborted(self):
+ self.build_tree(['a-file', 'a-dir/'])
+ state = dirstate.DirState.initialize('dirstate')
+ try:
+ # No stat and no sha1 sum.
+ state.add('a-file', 'a-file-id', 'file', None, '')
+ state.save()
+ finally:
+ state.unlock()
+
+ # The dirstate should include TREE_ROOT and 'a-file' and nothing else
+ expected_blocks = [
+ ('', [(('', '', 'TREE_ROOT'),
+ [('d', '', 0, False, dirstate.DirState.NULLSTAT)])]),
+ ('', [(('', 'a-file', 'a-file-id'),
+ [('f', '', 0, False, dirstate.DirState.NULLSTAT)])]),
+ ]
+
+ state = dirstate.DirState.on_file('dirstate')
+ state.lock_write()
+ try:
+ state._read_dirblocks_if_needed()
+ self.assertEqual(expected_blocks, state._dirblocks)
+
+ # Now modify the state, but mark it as inconsistent
+ state.add('a-dir', 'a-dir-id', 'directory', None, '')
+ state._changes_aborted = True
+ state.save()
+ finally:
+ state.unlock()
+
+ state = dirstate.DirState.on_file('dirstate')
+ state.lock_read()
+ try:
+ state._read_dirblocks_if_needed()
+ self.assertEqual(expected_blocks, state._dirblocks)
+ finally:
+ state.unlock()
+
class TestDirStateInitialize(TestCaseWithDirState):
=== modified file 'bzrlib/tests/test_errors.py'
--- a/bzrlib/tests/test_errors.py 2008-01-25 10:46:10 +0000
+++ b/bzrlib/tests/test_errors.py 2008-02-13 01:42:47 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007 Canonical Ltd
+# Copyright (C) 2006, 2007, 2008 Canonical Ltd
# Authors: Robert Collins <robert.collins at canonical.com>
# and others
#
@@ -29,6 +29,13 @@
class TestErrors(TestCaseWithTransport):
+ def test_corrupt_dirstate(self):
+ error = errors.CorruptDirstate('path/to/dirstate', 'the reason why')
+ self.assertEqualDiff(
+ "Inconsistency in dirstate file path/to/dirstate.\n"
+ "Error: the reason why",
+ str(error))
+
def test_disabled_method(self):
error = errors.DisabledMethod("class name")
self.assertEqualDiff(
@@ -51,6 +58,13 @@
'It supports versions "(4, 5, 6)" to "(7, 8, 9)".',
str(error))
+ def test_inconsistent_delta(self):
+ error = errors.InconsistentDelta('path', 'file-id', 'reason for foo')
+ self.assertEqualDiff(
+ "An inconsistent delta was supplied involving 'path', 'file-id'\n"
+ "reason: reason for foo",
+ str(error))
+
def test_in_process_transport(self):
error = errors.InProcessTransport('fpp')
self.assertEqualDiff(
=== modified file 'bzrlib/tests/test_workingtree_4.py'
--- a/bzrlib/tests/test_workingtree_4.py 2007-09-17 05:33:56 +0000
+++ b/bzrlib/tests/test_workingtree_4.py 2008-02-04 21:12:49 +0000
@@ -574,3 +574,99 @@
changes = [c[1] for c in tree._iter_changes(basis)]
self.assertEqual([], changes)
self.assertEqual(['', 'versioned', 'versioned2'], returned)
+
+
+class TestCorruptDirstate(TestCaseWithTransport):
+ """Tests for how we handle when the dirstate has been corrupted."""
+
+ def create_wt4(self):
+ control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
+ control.create_repository()
+ control.create_branch()
+ tree = workingtree_4.WorkingTreeFormat4().initialize(control)
+ return tree
+
+ def test_invalid_rename(self):
+ tree = self.create_wt4()
+ # Create a corrupted dirstate
+ tree.lock_write()
+ try:
+ tree.commit('init') # We need a parent, or we always compare with NULL
+ state = tree.current_dirstate()
+ state._read_dirblocks_if_needed()
+ # Now add in an invalid entry, a rename with a dangling pointer
+ state._dirblocks[1][1].append((('', 'foo', 'foo-id'),
+ [('f', '', 0, False, ''),
+ ('r', 'bar', 0 , False, '')]))
+ self.assertListRaises(errors.CorruptDirstate,
+ tree._iter_changes, tree.basis_tree())
+ finally:
+ tree.unlock()
+
+ def get_simple_dirblocks(self, state):
+ """Extract the simple information from the DirState.
+
+ This returns the dirblocks, only with the sha1sum and stat details
+ filtered out.
+ """
+ simple_blocks = []
+ for block in state._dirblocks:
+ simple_block = (block[0], [])
+ for entry in block[1]:
+ # Include the key for each entry, and for each parent include
+ # just the minikind, so we know if it was
+ # present/absent/renamed/etc
+ simple_block[1].append((entry[0], [i[0] for i in entry[1]]))
+ simple_blocks.append(simple_block)
+ return simple_blocks
+
+ def test_update_basis_with_invalid_delta(self):
+ """When given an invalid delta, it should abort, and not be saved."""
+ self.build_tree(['dir/', 'dir/file'])
+ tree = self.create_wt4()
+ tree.lock_write()
+ self.addCleanup(tree.unlock)
+ tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
+ first_revision_id = tree.commit('init')
+
+ root_id = tree.path2id('')
+ state = tree.current_dirstate()
+ state._read_dirblocks_if_needed()
+ self.assertEqual([
+ ('', [(('', '', root_id), ['d', 'd'])]),
+ ('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
+ ('dir', [(('dir', 'file', 'file-id'), ['f', 'f'])]),
+ ], self.get_simple_dirblocks(state))
+
+ tree.remove(['dir/file'])
+ self.assertEqual([
+ ('', [(('', '', root_id), ['d', 'd'])]),
+ ('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
+ ('dir', [(('dir', 'file', 'file-id'), ['a', 'f'])]),
+ ], self.get_simple_dirblocks(state))
+ # Make sure the removal is written to disk
+ tree.flush()
+
+ # self.assertRaises(Exception, tree.update_basis_by_delta,
+ new_dir = inventory.InventoryDirectory('dir-id', 'new-dir', root_id)
+ new_dir.revision = 'new-revision-id'
+ new_file = inventory.InventoryFile('file-id', 'new-file', root_id)
+ new_file.revision = 'new-revision-id'
+ self.assertRaises(errors.InconsistentDelta,
+ tree.update_basis_by_delta, 'new-revision-id',
+ [('dir', 'new-dir', 'dir-id', new_dir),
+ ('dir/file', 'new-dir/new-file', 'file-id', new_file),
+ ])
+ del state
+
+ # Now when we re-read the file it should not have been modified
+ tree.unlock()
+ tree.lock_read()
+ self.assertEqual(first_revision_id, tree.last_revision())
+ state = tree.current_dirstate()
+ state._read_dirblocks_if_needed()
+ self.assertEqual([
+ ('', [(('', '', root_id), ['d', 'd'])]),
+ ('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
+ ('dir', [(('dir', 'file', 'file-id'), ['a', 'f'])]),
+ ], self.get_simple_dirblocks(state))
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-12-29 21:28:32 +0000
+++ b/bzrlib/workingtree_4.py 2008-02-11 11:24:11 +0000
@@ -1951,6 +1951,11 @@
path_utf8=old_path)
# update the source details variable to be the real
# location.
+ if old_entry == (None, None):
+ raise errors.CorruptDirstate(state._filename,
+ "entry '%s/%s' is considered renamed from %r"
+ " but source does not exist\n"
+ "entry: %s" % (entry[0][0], entry[0][1], old_path, entry))
source_details = old_entry[1][source_index]
source_minikind = source_details[0]
else:
More information about the bazaar-commits
mailing list