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