Rev 5069: Fix a bug in update_minimal. in http://bazaar.launchpad.net/~jameinel/bzr/2.2-dirstate-update-minimal-bug

John Arbash Meinel john at arbash-meinel.com
Mon Aug 2 22:31:25 BST 2010


At http://bazaar.launchpad.net/~jameinel/bzr/2.2-dirstate-update-minimal-bug

------------------------------------------------------------
revno: 5069
revision-id: john at arbash-meinel.com-20100802213115-a2x1bdjcze9iwwdb
parent: pqm at pqm.ubuntu.com-20100729120106-psygyxky8i3jh7j7
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.2-dirstate-update-minimal-bug
timestamp: Mon 2010-08-02 16:31:15 -0500
message:
  Fix a bug in update_minimal.
  
  If the _maybe_remove_row actually removes a row, then we can't
  be positive that our pointer is still correct.
  In fact, in this test it is wrong, and leads to an incorrectly
  sorted dirstate.
-------------- next part --------------
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2010-01-13 23:06:42 +0000
+++ b/bzrlib/dirstate.py	2010-08-02 21:31:15 +0000
@@ -1566,7 +1566,7 @@
             return
         id_index = self._get_id_index()
         for file_id in new_ids:
-            for key in id_index.get(file_id, []):
+            for key in id_index.get(file_id, ()):
                 block_i, entry_i, d_present, f_present = \
                     self._get_block_entry_index(key[0], key[1], tree_index)
                 if not f_present:
@@ -1980,7 +1980,7 @@
                                           ' tree_index, file_id and path')
             return entry
         else:
-            possible_keys = self._get_id_index().get(fileid_utf8, None)
+            possible_keys = self._get_id_index().get(fileid_utf8, ())
             if not possible_keys:
                 return None, None
             for key in possible_keys:
@@ -2785,8 +2785,11 @@
                     # loop.
                     other_entry = other_block[other_entry_index]
                     other_entry[1][0] = ('r', path_utf8, 0, False, '')
-                    self._maybe_remove_row(other_block, other_entry_index,
-                        id_index)
+                    if self._maybe_remove_row(other_block, other_entry_index,
+                                              id_index):
+                        # If the row holding this was removed, we need to
+                        # recompute where this entry goes
+                        entry_index, _ = self._find_entry_index(key, block)
 
                 # This loop:
                 # adds a tuple to the new details for each column
@@ -2833,7 +2836,8 @@
             # converted to relocated.
             if path_utf8 is None:
                 raise AssertionError('no path')
-            for entry_key in id_index.setdefault(key[2], set()):
+            assert key in id_index[key[2]]
+            for entry_key in id_index.get(key[2], ()):
                 # TODO:PROFILING: It might be faster to just update
                 # rather than checking if we need to, and then overwrite
                 # the one we are located at.
@@ -2850,6 +2854,7 @@
                         raise AssertionError('not present: %r', entry_key)
                     self._dirblocks[block_index][1][entry_index][1][0] = \
                         ('r', path_utf8, 0, False, '')
+            assert key in id_index[key[2]]
         # add a containing dirblock if needed.
         if new_details[0] == 'd':
             subdir_key = (osutils.pathjoin(*key[0:2]), '', '')
@@ -2863,6 +2868,7 @@
         """Remove index if it is absent or relocated across the row.
         
         id_index is updated accordingly.
+        :return: True if we removed the row, False otherwise
         """
         present_in_row = False
         entry = block[index]
@@ -2873,6 +2879,8 @@
         if not present_in_row:
             block.pop(index)
             id_index[entry[0][2]].remove(entry[0])
+            return True
+        return False
 
     def _validate(self):
         """Check that invariants on the dirblock are correct.

=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py	2010-01-25 17:48:22 +0000
+++ b/bzrlib/tests/test_dirstate.py	2010-08-02 21:31:15 +0000
@@ -730,6 +730,22 @@
 
 class TestDirStateManipulations(TestCaseWithDirState):
 
+    def test_update_minimal_updates_id_index(self):
+        state = self.create_dirstate_with_root_and_subdir()
+        self.addCleanup(state.unlock)
+        id_index = state._get_id_index()
+        self.assertEqual(['a-root-value', 'subdir-id'], sorted(id_index))
+        state.add('file-name', 'file-id', 'file', None, '')
+        self.assertEqual(['a-root-value', 'file-id', 'subdir-id'],
+                         sorted(id_index))
+        state.update_minimal(('', 'new-name', 'file-id'), 'f',
+                             path_utf8='new-name')
+        self.assertEqual(['a-root-value', 'file-id', 'subdir-id'],
+                         sorted(id_index))
+        self.assertEqual([('', 'new-name', 'file-id')],
+                         sorted(id_index['file-id']))
+        state._validate()
+
     def test_set_state_from_inventory_no_content_no_parents(self):
         # setting the current inventory is a slow but important api to support.
         tree1 = self.make_branch_and_memory_tree('tree1')



More information about the bazaar-commits mailing list