Rev 2441: Handle the case when a directory has been removed, and isn't the last entry. in http://bazaar.launchpad.net/%7Ebzr/bzr/dirstate

John Arbash Meinel john at arbash-meinel.com
Wed Feb 28 23:37:44 GMT 2007


At http://bazaar.launchpad.net/%7Ebzr/bzr/dirstate

------------------------------------------------------------
revno: 2441
revision-id: john at arbash-meinel.com-20070228233639-kt8judz9w3x27ve4
parent: john at arbash-meinel.com-20070228224054-11e83q8puulllfuh
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate
timestamp: Wed 2007-02-28 17:36:39 -0600
message:
  Handle the case when a directory has been removed, and isn't the last entry.
modified:
  bzrlib/tests/intertree_implementations/test_compare.py test_compare.py-20060724101752-09ysswo1a92uqyoz-2
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
-------------- next part --------------
=== modified file 'bzrlib/tests/intertree_implementations/test_compare.py'
--- a/bzrlib/tests/intertree_implementations/test_compare.py	2007-02-28 22:40:54 +0000
+++ b/bzrlib/tests/intertree_implementations/test_compare.py	2007-02-28 23:36:39 +0000
@@ -788,3 +788,30 @@
             self.content_changed(tree2, 'c-id'),
             ])
         self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
+
+    def test_trees_with_missing_dir(self):
+        tree1 = self.make_branch_and_tree('tree1')
+        tree2 = self.make_to_branch_and_tree('tree2')
+        self.build_tree(['tree1/a', 'tree1/b/', 'tree1/b/c',
+                         'tree1/b/d/', 'tree1/b/d/e', 'tree1/f/', 'tree1/f/g',
+                         'tree2/a', 'tree2/f/', 'tree2/f/g'])
+        tree1.add(['a', 'b', 'b/c', 'b/d/', 'b/d/e', 'f', 'f/g'],
+                  ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id', 'g-id'])
+        tree2.add(['a', 'f', 'f/g'], ['a-id', 'f-id', 'g-id'])
+
+        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+        tree1.lock_read()
+        self.addCleanup(tree1.unlock)
+        tree2.lock_read()
+        self.addCleanup(tree2.unlock)
+        # We should notice that 'b' and all its children are missing
+        expected = sorted([
+            self.content_changed(tree2, 'a-id'),
+            self.content_changed(tree2, 'g-id'),
+            self.deleted(tree1, 'b-id'),
+            self.deleted(tree1, 'c-id'),
+            self.deleted(tree1, 'd-id'),
+            self.deleted(tree1, 'e-id'),
+            ])
+
+        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-02-28 22:40:54 +0000
+++ b/bzrlib/workingtree_4.py	2007-02-28 23:36:39 +0000
@@ -1771,26 +1771,56 @@
             else:
                 current_block = None
             while (current_dir_info is not None or
-                current_block is not None):
-                if current_dir_info and current_block and current_dir_info[0][0] != current_block[0]:
-                    if current_block[0] < current_dir_info[0][0]:
-                        # extra dir on disk: pass for now? should del from info ?
-                        import pdb;pdb.set_trace()
-                        print 'unversioned dir'
-                    else:
-                        # directory data refers to paths not covered by the dirblock.
+                   current_block is not None):
+                if (current_dir_info and current_block
+                    and current_dir_info[0][0] != current_block[0]):
+                    if current_dir_info[0][0] < current_block[0] :
+                        # import pdb; pdb.set_trace()
+                        # print 'unversioned dir'
+                        # filesystem data refers to paths not covered by the dirblock.
                         # this has two possibilities:
                         # A) it is versioned but empty, so there is no block for it
                         # B) it is not versioned.
                         # in either case it was processed by the containing directories walk:
                         # if it is root/foo, when we walked root we emitted it,
                         # or if we ere given root/foo to walk specifically, we
-                        # emitted it when checking the walk-root entries 
+                        # emitted it when checking the walk-root entries
                         # advance the iterator and loop - we dont need to emit it.
                         try:
                             current_dir_info = dir_iterator.next()
                         except StopIteration:
                             current_dir_info = None
+                    else:
+                        # We have a dirblock entry for this location, but there
+                        # is no filesystem path for this. This is most likely
+                        # because a directory was removed from the disk.
+                        # We don't have to report the missing directory,
+                        # because that should have already been handled, but we
+                        # need to handle all of the files that are contained
+                        # within.
+                        for current_entry in current_block[1]:
+                            # entry referring to file not present on disk.
+                            # advance the entry only, after processing.
+                            for result in _process_entry(current_entry, None):
+                                # this check should probably be outside the loop: one
+                                # 'iterate two trees' api, and then _iter_changes filters
+                                # unchanged pairs. - RBC 20070226
+                                if (include_unchanged
+                                    or result[2]                    # content change
+                                    or result[3][0] != result[3][1] # versioned status
+                                    or result[4][0] != result[4][1] # parent id
+                                    or result[5][0] != result[5][1] # name
+                                    or result[6][0] != result[6][1] # kind
+                                    or result[7][0] != result[7][1] # executable
+                                    ):
+                                    yield result
+                        block_index +=1
+                        if (block_index < len(state._dirblocks) and
+                            osutils.is_inside(current_root,
+                                              state._dirblocks[block_index][0])):
+                            current_block = state._dirblocks[block_index]
+                        else:
+                            current_block = None
                     continue
                 entry_index = 0
                 if current_block and entry_index < len(current_block[1]):



More information about the bazaar-commits mailing list