Rev 3516: Handle the case when a record is missing in base in http://bzr.arbash-meinel.com/branches/bzr/1.6-dev/multi_walker

John Arbash Meinel john at arbash-meinel.com
Mon Jun 30 20:48:31 BST 2008


At http://bzr.arbash-meinel.com/branches/bzr/1.6-dev/multi_walker

------------------------------------------------------------
revno: 3516
revision-id: john at arbash-meinel.com-20080630194801-gdodhpossmf1n85a
parent: john at arbash-meinel.com-20080630192436-hv4ppxq7dpp38mii
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: multi_walker
timestamp: Mon 2008-06-30 14:48:01 -0500
message:
  Handle the case when a record is missing in base
-------------- next part --------------
=== modified file 'bzrlib/tests/test_tree.py'
--- a/bzrlib/tests/test_tree.py	2008-06-30 19:24:36 +0000
+++ b/bzrlib/tests/test_tree.py	2008-06-30 19:48:01 +0000
@@ -180,6 +180,32 @@
         self.assertStepOne(False, None, None, iterator)
         self.assertStepOne(False, None, None, iterator)
 
+    def assertWalkerNext(self, exp_path, exp_file_id, master_is_None,
+                         exp_other_paths, iterator):
+        """Check what happens when we step the iterator.
+
+        :param path: The path for this entry
+        :param file_id: The file_id for this entry
+        :param master_is_None: Is this node None for the master tree?
+        :param exp_other_paths: A list of other_path values.
+        :param iterator: The iterator to step
+        """
+        path, file_id, master_ie, other_values = iterator.next()
+        self.assertEqual(exp_path, path)
+        self.assertEqual(exp_file_id, file_id)
+        if master_is_None:
+            self.assertIs(None, master_ie)
+        else:
+            self.assertIsNot(None, master_ie)
+        self.assertEqual(len(exp_other_paths), len(other_values))
+        for exp_other_path, (other_path, other_ie) in \
+                zip(exp_other_paths, other_values):
+            self.assertEqual(exp_other_path, other_path)
+            if exp_other_path is None:
+                self.assertIs(None, other_ie)
+            else:
+                self.assertEqual(file_id, other_ie.file_id)
+
     def test_simple_stepping(self):
         tree = self.make_branch_and_tree('tree')
         self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
@@ -192,39 +218,36 @@
         basis_tree.lock_read()
         self.addCleanup(basis_tree.unlock)
 
-        walker = _mod_tree.MultiWalker(tree, [basis_tree])
-        iterator = walker.iter_all()
-        master_path, file_id, master_ie, other_values = iterator.next()
-        root_id = tree.path2id('')
-        self.assertEqual('', master_path)
-        self.assertEqual(root_id, file_id)
-        self.assertEqual(1, len(other_values))
-        other_path, other_ie = other_values[0]
-        self.assertEqual('', other_path)
-        self.assertEqual(root_id, other_ie.file_id)
-
-        master_path, file_id, master_ie, other_values = iterator.next()
-        self.assertEqual(u'a', master_path)
-        self.assertEqual('a-id', file_id)
-        self.assertEqual(1, len(other_values))
-        other_path, other_ie = other_values[0]
-        self.assertEqual(u'a', other_path)
-        self.assertEqual('a-id', other_ie.file_id)
-
-        master_path, file_id, master_ie, other_values = iterator.next()
-        self.assertEqual(u'b', master_path)
-        self.assertEqual('b-id', file_id)
-        self.assertEqual(1, len(other_values))
-        other_path, other_ie = other_values[0]
-        self.assertEqual(u'b', other_path)
-        self.assertEqual('b-id', other_ie.file_id)
-
-        master_path, file_id, master_ie, other_values = iterator.next()
-        self.assertEqual(u'b/c', master_path)
-        self.assertEqual('c-id', file_id)
-        self.assertEqual(1, len(other_values))
-        other_path, other_ie = other_values[0]
-        self.assertEqual(u'b/c', other_path)
-        self.assertEqual('c-id', other_ie.file_id)
-
+        root_id = tree.path2id('')
+
+        walker = _mod_tree.MultiWalker(tree, [basis_tree])
+        iterator = walker.iter_all()
+        self.assertWalkerNext(u'', root_id, False, [u''], iterator)
+        self.assertWalkerNext(u'a', 'a-id', False, [u'a'], iterator)
+        self.assertWalkerNext(u'b', 'b-id', False, [u'b'], iterator)
+        self.assertWalkerNext(u'b/c', 'c-id', False, [u'b/c'], iterator)
+        self.assertRaises(StopIteration, iterator.next)
+
+    def test_master_has_extra(self):
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree(['tree/a', 'tree/b/', 'tree/c', 'tree/d'])
+        tree.add(['a', 'b', 'd'], ['a-id', 'b-id', 'd-id'])
+
+        tree.commit('first', rev_id='first-rev-id')
+        basis_tree = tree.basis_tree()
+
+        tree.add(['c'], ['c-id'])
+        tree.lock_read()
+        self.addCleanup(tree.unlock)
+        basis_tree.lock_read()
+        self.addCleanup(basis_tree.unlock)
+
+        root_id = tree.path2id('')
+        walker = _mod_tree.MultiWalker(tree, [basis_tree])
+        iterator = walker.iter_all()
+        self.assertWalkerNext(u'', root_id, False, [u''], iterator)
+        self.assertWalkerNext(u'a', 'a-id', False, [u'a'], iterator)
+        self.assertWalkerNext(u'b', 'b-id', False, [u'b'], iterator)
+        self.assertWalkerNext(u'c', 'c-id', False, [None], iterator)
+        self.assertWalkerNext(u'd', 'd-id', False, [u'd'], iterator)
         self.assertRaises(StopIteration, iterator.next)

=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py	2008-06-30 19:24:36 +0000
+++ b/bzrlib/tree.py	2008-06-30 19:48:01 +0000
@@ -940,15 +940,44 @@
         else:
             return True, path, ie
 
+    @staticmethod
+    def _cmp_path_by_dirblock(path1, path2):
+        """Compare two paths based on what directory they are in.
+
+        This generates a sort order, such that all children of a directory are
+        sorted together, and grandchildren are in the same order as the
+        children appear. But all grandchildren come after all children.
+
+        :param path1: first path
+        :param path2: the second path
+        :return: negative number if ``path1`` comes first,
+            0 if paths are equal
+            and a positive number if ``path2`` sorts first
+        """
+        # This is stolen from _dirstate_helpers_py.py, only switching it to
+        # Unicode objects. Consider using encode_utf8() and then using the
+        # optimized versions, or maybe writing optimized unicode versions.
+        if not isinstance(path1, unicode):
+            raise TypeError("'path1' must be a unicode string, not %s: %r"
+                            % (type(path1), path1))
+        if not isinstance(path2, unicode):
+            raise TypeError("'path2' must be a unicode string, not %s: %r"
+                            % (type(path2), path2))
+        dirname1, basename1 = os.path.split(path1)
+        key1 = (dirname1.split('/'), basename1)
+        dirname2, basename2 = os.path.split(path2)
+        key2 = (dirname2.split('/'), basename2)
+        return cmp(key1, key2)
+
     def iter_all(self):
         """Match up the values in the different trees."""
-        import pdb; pdb.set_trace()
         master_iterator = self._master_tree.iter_entries_by_dir()
 
         other_walkers = [other.iter_entries_by_dir()
                          for other in self._other_trees]
         other_entries = [self._step_one(walker) for walker in other_walkers]
 
+
         master_has_more = True
         while master_has_more:
             (master_has_more, master_path,
@@ -956,7 +985,7 @@
             if not master_has_more:
                 break
 
-            master_file_id = master_ie.file_id
+            file_id = master_ie.file_id
             other_values = []
             next_other_entries = []
             for other_walker, (other_has_more, other_path, other_ie) in \
@@ -964,7 +993,7 @@
                 if not other_has_more:
                     other_values.append((None, None))
                     next_other_entries.append(False, None, None)
-                elif master_file_id == other_ie.file_id:
+                elif file_id == other_ie.file_id:
                     # This walker matched, so consume this path, and go on to
                     # the next
                     other_values.append((other_path, other_ie))
@@ -972,8 +1001,20 @@
                 else:
                     # This walker did not match, step it until it either
                     # matches, or we know we are past the current walker.
-                    raise NotImplementedError
+                    while (other_has_more and
+                           self._cmp_path_by_dirblock(other_path, master_path) < 0):
+                        other_has_more, other_path, other_ie = \
+                            self._step_one(other_walker)
+                    if other_has_more and other_ie.file_id == file_id:
+                        # We ended up walking to this point, match and continue
+                        other_values.append((other_path, other_ie))
+                        other_has_more, other_path, other_ie = \
+                            self._step_one(other_walker)
+                    else:
+                        other_values.append((None, None))
+                    next_other_entries.append((other_has_more, other_path,
+                                               other_ie))
             other_entries = next_other_entries
 
             # We've matched all the walkers, yield this datapoint
-            yield master_path, master_file_id, master_ie, other_values
+            yield master_path, file_id, master_ie, other_values



More information about the bazaar-commits mailing list