Rev 5876: Simplify a bit. Handle that when a directory is added, we need to add its block. in http://bazaar.launchpad.net/~jameinel/bzr/2.4-set-parent-trees-delta-282941

John Arbash Meinel john at arbash-meinel.com
Thu May 19 12:55:07 UTC 2011


At http://bazaar.launchpad.net/~jameinel/bzr/2.4-set-parent-trees-delta-282941

------------------------------------------------------------
revno: 5876
revision-id: john at arbash-meinel.com-20110519125458-9ubn8sn7x7309s4s
parent: john at arbash-meinel.com-20110519112716-cgk61q0iwa104bc2
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.4-set-parent-trees-delta-282941
timestamp: Thu 2011-05-19 14:54:58 +0200
message:
  Simplify a bit. Handle that when a directory is added, we need to add its block.
  Handle that when a directory is removed, if it is the last reference to that path,
  the block should also be removed.
  I'm going to try simplying the remove code now.
-------------- next part --------------
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2011-05-19 11:19:42 +0000
+++ b/bzrlib/dirstate.py	2011-05-19 12:54:58 +0000
@@ -1666,13 +1666,12 @@
         for old_path, new_path, file_id, new_details, real_add in adds:
             dirname, basename = osutils.split(new_path)
             entry_key = st(dirname, basename, file_id)
-            try:
-                # TODO: consider if we need add_if_missing=True
-                _, block = self._find_block(entry_key)
-            except errors.NotVersionedError, e:
+            block_index, present = self._find_block_index_from_key(entry_key)
+            if not present:
                 self._raise_invalid(new_path, file_id,
-                    "Got a not-versioned error trying to add path."
-                    " Is the parent missing? %s" % (e,))
+                    "Unable to find block for this record."
+                    " Was the parent added?")
+            block = self._dirblocks[block_index][1]
             entry_index, present = self._find_entry_index(entry_key, block)
             if real_add:
                 if old_path is not None:
@@ -1761,6 +1760,10 @@
             elif active_kind == 'r':
                 raise NotImplementedError()
 
+            new_kind = new_details[0]
+            if new_kind == 'd':
+                self._ensure_block(block_index, entry_index, new_path)
+
     def _update_basis_apply_changes(self, changes):
         """Apply a sequence of changes to tree 1 during update_basis_by_delta.
 
@@ -1821,6 +1824,18 @@
                     # state, and it is now deleted in the basis state,
                     # so just remove the record entirely
                     del self._dirblocks[block_index][1][entry_index]
+                    old_kind = entry[1][1][0]
+                    if old_kind == 'd':
+                        # This was a directory, and the active tree says it
+                        # doesn't exist, and now the basis tree says it doesn't
+                        # exist. Remove its dirblock if present
+                        (dir_block_index,
+                         present) = self._find_block_index_from_key(
+                            (old_path, '', ''))
+                        if present:
+                            assert not self._dirblocks[dir_block_index][1],\
+                                "dirblock queued for deletion is not empty"
+                            del self._dirblocks[dir_block_index]
                 elif active_kind == 'r':
                     # The active record is found at a different location
                     # we can consider it deleted *here*, but we have to update
@@ -1854,22 +1869,29 @@
                                 "The file id was deleted but its children were "
                                 "not deleted.")
             else:
-                if active_kind == 'a':
+                if active_kind in 'ar':
                     # The active tree doesn't have this file_id.
                     # The basis tree is changing this record. If this is a
                     # rename, then we don't want the record here at all
                     # anymore. If it is just an in-place change, we want the
                     # record here, but we'll add it if we need to. So we just
                     # delete it
-                    del self._dirblocks[block_index][1][entry_index]
-                elif active_kind == 'r':
-                    # The active tree has this record at a different location.
-                    # implement the rename
-                    active_path_utf8 = entry[1][0][1]
-                    rename_targets[old_path] = active_path_utf8
-                    active_entry = self._get_entry(0, file_id, active_path_utf8)
-                    active_entry[1][1] = null
-                    del self._dirblocks[block_index][1][entry_index]
+                    if active_kind == 'r':
+                        active_path = entry[1][0][1]
+                        rename_targets[old_path] = active_path
+                        active_entry = self._get_entry(0, file_id, active_path)
+                        active_entry[1][1] = null
+                    del self._dirblocks[block_index][1][entry_index]
+                    old_kind = entry[1][1][0]
+                    if old_kind == 'd':
+                        # This was a directory, and the active tree says it
+                        # doesn't exist, and now the basis tree says it doesn't
+                        # exist. Remove its dirblock if present
+                        (dir_block_index,
+                         present) = self._find_block_index_from_key(
+                            (old_path, '', ''))
+                        if present and not self._dirblocks[dir_block_index][1]:
+                            del self._dirblocks[dir_block_index]
                 else:
                     # There is still an active record, so just mark this
                     # removed.

=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py	2011-05-19 11:27:16 +0000
+++ b/bzrlib/tests/test_dirstate.py	2011-05-19 12:54:58 +0000
@@ -2457,7 +2457,7 @@
             dir_id = osutils.basename(dirname) + '-id'
         if is_dir:
             ie = inventory.InventoryDirectory(file_id, basename, dir_id)
-            dir_ids[path] = dir_id
+            dir_ids[path] = file_id
         else:
             ie = inventory.InventoryFile(file_id, basename, dir_id)
             ie.text_size = 0
@@ -2672,6 +2672,44 @@
             target=[('file', 'file-id'),
                     ('other-file', 'file-id-2')])
 
+    def test_rename_directory_with_contents(self):
+        state = self.assertUpdate( # active matches basis
+            active=[('dir1/', 'dir-id'),
+                    ('dir1/file', 'file-id')],
+            basis= [('dir1/', 'dir-id'),
+                    ('dir1/file', 'file-id')],
+            target=[('dir2/', 'dir-id'),
+                    ('dir2/file', 'file-id')])
+        state = self.assertUpdate( # active matches target
+            active=[('dir2/', 'dir-id'),
+                    ('dir2/file', 'file-id')],
+            basis= [('dir1/', 'dir-id'),
+                    ('dir1/file', 'file-id')],
+            target=[('dir2/', 'dir-id'),
+                    ('dir2/file', 'file-id')])
+        state = self.assertUpdate( # active empty
+            active=[],
+            basis= [('dir1/', 'dir-id'),
+                    ('dir1/file', 'file-id')],
+            target=[('dir2/', 'dir-id'),
+                    ('dir2/file', 'file-id')])
+        state = self.assertUpdate( # active present at other location
+            active=[('dir3/', 'dir-id'),
+                    ('dir3/file', 'file-id')],
+            basis= [('dir1/', 'dir-id'),
+                    ('dir1/file', 'file-id')],
+            target=[('dir2/', 'dir-id'),
+                    ('dir2/file', 'file-id')])
+        state = self.assertUpdate( # active has different ids
+            active=[('dir1/', 'dir1-id'),
+                    ('dir1/file', 'file1-id'),
+                    ('dir2/', 'dir2-id'),
+                    ('dir2/file', 'file2-id')],
+            basis= [('dir1/', 'dir-id'),
+                    ('dir1/file', 'file-id')],
+            target=[('dir2/', 'dir-id'),
+                    ('dir2/file', 'file-id')])
+
     def test_invalid_file_not_present(self):
         state = self.assertBadDelta(
             active=[('file', 'file-id')],



More information about the bazaar-commits mailing list