Rev 4538: Make CHKInventory generate safer parent_id_basename deltas. in http://bazaar.launchpad.net/~lifeless/bzr/apply-inventory-delta

Robert Collins robertc at robertcollins.net
Fri Jul 17 01:46:43 BST 2009


At http://bazaar.launchpad.net/~lifeless/bzr/apply-inventory-delta

------------------------------------------------------------
revno: 4538
revision-id: robertc at robertcollins.net-20090717004637-vtnjnop8z4tv9enx
parent: robertc at robertcollins.net-20090716232849-u7u6g658j7qn7rp2
committer: Robert Collins <robertc at robertcollins.net>
branch nick: apply-inventory-delta
timestamp: Fri 2009-07-17 10:46:37 +1000
message:
  Make CHKInventory generate safer parent_id_basename deltas.
=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py	2009-07-14 05:17:23 +0000
+++ b/bzrlib/inventory.py	2009-07-17 00:46:37 +0000
@@ -1614,7 +1614,12 @@
             search_key_func=search_key_func)
         result.id_to_entry._ensure_root()
         result.id_to_entry._root_node.set_maximum_size(maximum_size)
-        parent_id_basename_delta = []
+        # Change to apply to the parent_id_basename delta. The dict maps
+        # (parent_id, basename) -> (old_key, new_value). We use a dict because
+        # when a path has its id replaced (e.g. the root is changed, or someone
+        # does bzr mv a b, bzr mv c a, we should output a single change to this
+        # map rather than two.
+        parent_id_basename_delta = {}
         if self.parent_id_basename_to_file_id is not None:
             result.parent_id_basename_to_file_id = chk_map.CHKMap(
                 self.parent_id_basename_to_file_id._store,
@@ -1697,10 +1702,17 @@
                 else:
                     new_key = self._parent_id_basename_key(entry)
                     new_value = file_id
+                # If the two keys are the same, the value will be unchanged
+                # as its always the file id for this entry.
                 if old_key != new_key:
-                    # If the two keys are the same, the value will be unchanged
-                    # as its always the file id.
-                    parent_id_basename_delta.append((old_key, new_key, new_value))
+                    # Transform a change into explicit delete/add preserving
+                    # a possible match on the key from a different file id.
+                    if old_key is not None:
+                        parent_id_basename_delta.setdefault(
+                            old_key, [None, None])[0] = old_key
+                    if new_key is not None:
+                        parent_id_basename_delta.setdefault(
+                            new_key, [None, None])[1] = new_value
         # validate that deletes are complete.
         for file_id in deletes:
             entry = self[file_id]
@@ -1715,7 +1727,14 @@
                         "parent deleted.")
         result.id_to_entry.apply_delta(id_to_entry_delta)
         if parent_id_basename_delta:
-            result.parent_id_basename_to_file_id.apply_delta(parent_id_basename_delta)
+            # Transform the parent_id_basename delta data into a linear delta
+            # with only one record for a given key. Optimally this would allow
+            # re-keying, but its simpler to just output that as a delete+add
+            # to spend less time calculating the delta.
+            delta_list = []
+            for key, (old_key, value) in parent_id_basename_delta.iteritems():
+                delta_list.append((old_key, key, value))
+            result.parent_id_basename_to_file_id.apply_delta(delta_list)
         parents.discard(('', None))
         for parent_path, parent in parents:
             try:




More information about the bazaar-commits mailing list