Rev 4527: Add WorkingTree.apply_inventory_delta to the set of delta implementations interface tested. in http://bazaar.launchpad.net/~lifeless/bzr/apply-inventory-delta
Robert Collins
robertc at robertcollins.net
Mon Jul 13 02:16:34 BST 2009
At http://bazaar.launchpad.net/~lifeless/bzr/apply-inventory-delta
------------------------------------------------------------
revno: 4527
revision-id: robertc at robertcollins.net-20090713011624-s41u6bywgdm7c0of
parent: pqm at pqm.ubuntu.com-20090710140021-2kq4yhui3de6mwt7
committer: Robert Collins <robertc at robertcollins.net>
branch nick: apply-inventory-delta
timestamp: Mon 2009-07-13 11:16:24 +1000
message:
Add WorkingTree.apply_inventory_delta to the set of delta implementations interface tested.
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2009-07-10 05:33:07 +0000
+++ b/bzrlib/dirstate.py 2009-07-13 01:16:24 +0000
@@ -1277,13 +1277,25 @@
def update_by_delta(self, delta):
"""Apply an inventory delta to the dirstate for tree 0
+ This is the workhorse for apply_inventory_delta in dirstate based
+ trees.
+
:param delta: An inventory delta. See Inventory.apply_delta for
details.
"""
self._read_dirblocks_if_needed()
+ encode = cache_utf8.encode
insertions = {}
removals = {}
- for old_path, new_path, file_id, inv_entry in sorted(delta, reverse=True):
+ # Accumulate parent references (path_utf8, id), to check for parentless
+ # items or items placed under files/links/tree-references. We get
+ # references from every item in the delta that is not a deletion and
+ # is not itself the root.
+ parents = set()
+ for old_path, new_path, file_id, inv_entry in sorted(
+ inventory._check_delta_unique_old_paths(
+ inventory._check_delta_unique_new_paths(
+ inventory._check_delta_ids_match_entry(delta))), reverse=True):
if (file_id in insertions) or (file_id in removals):
raise errors.InconsistentDelta(old_path or new_path, file_id,
"repeated file_id")
@@ -1293,6 +1305,9 @@
if new_path is not None:
new_path = new_path.encode('utf-8')
dirname, basename = osutils.split(new_path)
+ dirname_utf8 = encode(dirname)
+ if basename:
+ parents.add((dirname_utf8, inv_entry.parent_id))
key = (dirname, basename, file_id)
minikind = DirState._kind_to_minikind[inv_entry.kind]
if minikind == 't':
@@ -1323,6 +1338,8 @@
fingerprint, new_child_path)
self._apply_removals(removals.values())
self._apply_insertions(insertions.values())
+ # Validate parents
+ self._after_delta_check_parents(parents, 0)
def _apply_removals(self, removals):
for path in sorted(removals, reverse=True):
@@ -1348,9 +1365,13 @@
"not deleted.")
def _apply_insertions(self, adds):
- for key, minikind, executable, fingerprint, path_utf8 in sorted(adds):
- self.update_minimal(key, minikind, executable, fingerprint,
- path_utf8=path_utf8)
+ try:
+ for key, minikind, executable, fingerprint, path_utf8 in sorted(adds):
+ self.update_minimal(key, minikind, executable, fingerprint,
+ path_utf8=path_utf8)
+ except errors.NotVersionedError:
+ raise errors.InconsistentDelta(path_utf8.decode('utf8'), key[2],
+ "Missing parent")
def update_basis_by_delta(self, delta, new_revid):
"""Update the parents of this tree after a commit.
@@ -1400,7 +1421,7 @@
# At the same time, to reduce interface friction we convert the input
# inventory entries to dirstate.
root_only = ('', '')
- # Accumulate parent references (path and id), to check for parentless
+ # Accumulate parent references (path_utf8, id), to check for parentless
# items or items placed under files/links/tree-references. We get
# references from every item in the delta that is not a deletion and
# is not itself the root.
@@ -1475,7 +1496,7 @@
# Apply in-situ changes.
self._update_basis_apply_changes(changes)
# Validate parents
- self._update_basis_check_parents(parents)
+ self._after_delta_check_parents(parents, 1)
except errors.BzrError, e:
if 'integrity error' not in str(e):
raise
@@ -1600,18 +1621,24 @@
# it is being resurrected here, so blank it out temporarily.
self._dirblocks[block_index][1][entry_index][1][1] = null
- def _update_basis_check_parents(self, parents):
- """Check that parents required by the delta are all intact."""
+ def _after_delta_check_parents(self, parents, index):
+ """Check that parents required by the delta are all intact.
+
+ :param parents: An iterable of (path_utf8, file_id) tuples which are
+ required to be present in tree 'index' at path_utf8 with id file_id
+ and be a directory.
+ :param index: The column in the dirstate to check for parents in.
+ """
for dirname_utf8, file_id in parents:
# Get the entry - the ensures that file_id, dirname_utf8 exists and
# has the right file id.
- entry = self._get_entry(1, file_id, dirname_utf8)
+ entry = self._get_entry(index, file_id, dirname_utf8)
if entry[1] is None:
self._changes_aborted = True
raise errors.InconsistentDelta(dirname_utf8.decode('utf8'),
file_id, "This parent is not present.")
# Parents of things must be directories
- if entry[1][1][0] != 'd':
+ if entry[1][index][0] != 'd':
self._changes_aborted = True
raise errors.InconsistentDelta(dirname_utf8.decode('utf8'),
file_id, "This parent is not a directory.")
=== modified file 'bzrlib/tests/test_inv.py'
--- a/bzrlib/tests/test_inv.py 2009-07-10 12:40:36 +0000
+++ b/bzrlib/tests/test_inv.py 2009-07-13 01:16:24 +0000
@@ -57,6 +57,9 @@
scenarios.append((str(format.__class__.__name__), {
'apply_delta':apply_inventory_WT_basis,
'format':format}))
+ scenarios.append((str(format.__class__.__name__), {
+ 'apply_delta':apply_inventory_WT,
+ 'format':format}))
return multiply_tests(to_adapt, scenarios, result)
@@ -71,6 +74,42 @@
return basis
+def apply_inventory_WT(self, basis, delta):
+ """Apply delta to basis and return the result.
+
+ This sets the tree state to be basis, and then calls apply_inventory_delta.
+
+ :param basis: An inventory to be used as the basis.
+ :param delta: The inventory delta to apply:
+ :return: An inventory resulting from the application.
+ """
+ control = self.make_bzrdir('tree', format=self.format._matchingbzrdir)
+ control.create_repository()
+ control.create_branch()
+ tree = self.format.initialize(control)
+ tree.lock_write()
+ try:
+ tree._write_inventory(basis)
+ finally:
+ tree.unlock()
+ # Fresh object, reads disk again.
+ tree = tree.bzrdir.open_workingtree()
+ tree.lock_write()
+ try:
+ tree.apply_inventory_delta(delta)
+ finally:
+ tree.unlock()
+ # reload tree - ensure we get what was written.
+ tree = tree.bzrdir.open_workingtree()
+ tree.lock_read()
+ self.addCleanup(tree.unlock)
+ # One could add 'tree._validate' here but that would cause 'early' failues
+ # as far as higher level code is concerned. Possibly adding an
+ # expect_fail parameter to this function and if that is False then do a
+ # validate call.
+ return tree.inventory
+
+
def apply_inventory_WT_basis(self, basis, delta):
"""Apply delta to basis and return the result.
More information about the bazaar-commits
mailing list