Rev 2326: Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately. in file:///home/robertc/source/baz/dirstate.0.15/

Robert Collins robertc at robertcollins.net
Fri Mar 9 01:52:07 GMT 2007


At file:///home/robertc/source/baz/dirstate.0.15/

------------------------------------------------------------
revno: 2326
revision-id: robertc at robertcollins.net-20070309015201-18fbvytw3qi0fh09
parent: robertc at robertcollins.net-20070308235512-ubrfi3dy7qb52zz0
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate.0.15
timestamp: Fri 2007-03-09 12:52:01 +1100
message:
  Fix the behaviour of dirstate optimised iter_changes recursing its disk iterator into subtrees inappropriately.
modified:
  bzrlib/mutabletree.py          mutabletree.py-20060906023413-4wlkalbdpsxi2r4y-2
  bzrlib/tests/intertree_implementations/test_compare.py test_compare.py-20060724101752-09ysswo1a92uqyoz-2
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'bzrlib/mutabletree.py'
--- a/bzrlib/mutabletree.py	2007-03-06 11:04:03 +0000
+++ b/bzrlib/mutabletree.py	2007-03-09 01:52:01 +0000
@@ -90,6 +90,8 @@
             if kinds is not None:
                 kinds = [kinds]
 
+        files = [path.strip('/') for path in files]
+
         if ids is None:
             ids = [None] * len(files)
         else:

=== modified file 'bzrlib/tests/intertree_implementations/test_compare.py'
--- a/bzrlib/tests/intertree_implementations/test_compare.py	2007-03-07 03:09:14 +0000
+++ b/bzrlib/tests/intertree_implementations/test_compare.py	2007-03-09 01:52:01 +0000
@@ -700,11 +700,9 @@
             self.do_iter_changes(tree1, tree2, include_unchanged=True))
 
     def test_compare_subtrees(self):
-        """want_unchanged should generate a list of unchanged entries."""
         tree1 = self.make_branch_and_tree('1')
         if not tree1.supports_tree_reference():
-            raise tests.TestSkipped('Tree %s does not support references'
-                % (tree1,))
+            return
         tree1.set_root_id('root-id')
         subtree1 = self.make_branch_and_tree('1/sub')
         subtree1.set_root_id('subtree-id')
@@ -712,8 +710,7 @@
 
         tree2 = self.make_to_branch_and_tree('2')
         if not tree2.supports_tree_reference():
-            raise tests.TestSkipped('Tree %s does not support references'
-                % (tree2,))
+            return
         tree2.set_root_id('root-id')
         subtree2 = self.make_to_branch_and_tree('2/sub')
         subtree2.set_root_id('subtree-id')
@@ -745,6 +742,36 @@
                          list(tree2._iter_changes(tree1,
                              include_unchanged=True)))
 
+    def test_disk_in_subtrees_skipped(self):
+        """subtrees are considered not-in-the-current-tree.
+        
+        This test tests the trivial case, where the basis has no paths in the
+        current trees subtree.
+        """
+        tree1 = self.make_branch_and_tree('1')
+        tree1.set_root_id('root-id')
+        tree2 = self.make_to_branch_and_tree('2')
+        if not tree2.supports_tree_reference():
+            return
+        tree2.set_root_id('root-id')
+        subtree2 = self.make_to_branch_and_tree('2/sub')
+        subtree2.set_root_id('subtree-id')
+        tree2.add(['sub'], ['subtree-id'])
+        self.build_tree(['2/sub/file'])
+        subtree2.add(['file'])
+        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+        tree1.lock_read()
+        self.addCleanup(tree1.unlock)
+        tree2.lock_read()
+        self.addCleanup(tree2.unlock)
+        # this should filter correctly from above
+        self.assertEqual([self.added(tree2, 'subtree-id')],
+            self.do_iter_changes(tree1, tree2, want_unversioned=True))
+        # and when the path is named
+        self.assertEqual([self.added(tree2, 'subtree-id')],
+            self.do_iter_changes(tree1, tree2, specific_files=['sub'],
+                want_unversioned=True))
+
     def test_default_ignores_unversioned_files(self):
         tree1 = self.make_branch_and_tree('tree1')
         tree2 = self.make_to_branch_and_tree('tree2')

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-03-07 03:09:14 +0000
+++ b/bzrlib/workingtree_4.py	2007-03-09 01:52:01 +0000
@@ -305,6 +305,13 @@
         self._inventory = None
         self._dirty = False
 
+    @needs_tree_write_lock
+    def _gather_kinds(self, files, kinds):
+        """See MutableTree._gather_kinds."""
+        for pos, f in enumerate(files):
+            if kinds[pos] is None:
+                kinds[pos] = self._kind(f)
+
     def _generate_inventory(self):
         """Create and set self.inventory from the dirstate object.
         
@@ -1863,7 +1870,6 @@
                         last_source_parent[0] = old_dirname
                         last_source_parent[1] = source_parent_id
                         last_source_parent[2] = source_parent_entry
-
                 new_dirname = entry[0][0]
                 if new_dirname == last_target_parent[0]:
                     target_parent_id = last_target_parent[1]
@@ -1950,6 +1956,7 @@
                     % (source_minikind, target_minikind))
                 ## import pdb;pdb.set_trace()
             return ()
+
         while search_specific_files:
             # TODO: the pending list should be lexically sorted?  the
             # interface doesn't require it.
@@ -2008,29 +2015,32 @@
                     (None, None),
                     (None, splitpath(current_root)[-1]),
                     (None, root_dir_info[2]), (None, new_executable))
-            dir_iterator = osutils._walkdirs_utf8(root_abspath, prefix=current_root)
             initial_key = (current_root, '', '')
             block_index, _ = state._find_block_index_from_key(initial_key)
             if block_index == 0:
                 # we have processed the total root already, but because the
                 # initial key matched it we should skip it here.
                 block_index +=1
-            try:
-                current_dir_info = dir_iterator.next()
-            except OSError, e:
-                if e.errno in (errno.ENOENT, errno.ENOTDIR):
-                    # there may be directories in the inventory even though
-                    # this path is not a file on disk: so mark it as end of
-                    # iterator
-                    current_dir_info = None
+            if root_dir_info and root_dir_info[2] == 'tree-reference':
+                current_dir_info = None
+            else:
+                dir_iterator = osutils._walkdirs_utf8(root_abspath, prefix=current_root)
+                try:
+                    current_dir_info = dir_iterator.next()
+                except OSError, e:
+                    if e.errno in (errno.ENOENT, errno.ENOTDIR):
+                        # there may be directories in the inventory even though
+                        # this path is not a file on disk: so mark it as end of
+                        # iterator
+                        current_dir_info = None
+                    else:
+                        raise
                 else:
-                    raise
-            else:
-                if current_dir_info[0][0] == '':
-                    # remove .bzr from iteration
-                    bzr_index = bisect_left(current_dir_info[1], ('.bzr',))
-                    assert current_dir_info[1][bzr_index][0] == '.bzr'
-                    del current_dir_info[1][bzr_index]
+                    if current_dir_info[0][0] == '':
+                        # remove .bzr from iteration
+                        bzr_index = bisect_left(current_dir_info[1], ('.bzr',))
+                        assert current_dir_info[1][bzr_index][0] == '.bzr'
+                        del current_dir_info[1][bzr_index]
             # walk until both the directory listing and the versioned metadata
             # are exhausted. 
             if (block_index < len(state._dirblocks) and
@@ -2202,10 +2212,14 @@
                                         (None, new_executable))
                             # dont descend into this unversioned path if it is
                             # a dir
-                            if current_path_info[2] in (
-                                'directory', 'tree-referene'):
+                            if current_path_info[2] in ('directory'):
                                 del current_dir_info[1][path_index]
                                 path_index -= 1
+                        # dont descend the disk iterator into any tree 
+                        # paths.
+                        if current_path_info[2] == 'tree-reference':
+                            del current_dir_info[1][path_index]
+                            path_index -= 1
                         path_index += 1
                         if path_index < len(current_dir_info[1]):
                             current_path_info = current_dir_info[1][path_index]



More information about the bazaar-commits mailing list