Rev 2427: Get iter_changes working again, by fixing set_parent_trees to in http://bazaar.launchpad.net/%7Ebzr/bzr/dirstate

John Arbash Meinel john at arbash-meinel.com
Tue Feb 27 21:33:27 GMT 2007


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

------------------------------------------------------------
revno: 2427
revision-id: john at arbash-meinel.com-20070227213216-a6kogwpq49j6dgpm
parent: john at arbash-meinel.com-20070227030928-bkhmkqvf3mbymqge
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate
timestamp: Tue 2007-02-27 15:32:16 -0600
message:
  Get iter_changes working again, by fixing set_parent_trees to
  create trees with the correct block order.
modified:
  bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
  bzrlib/tests/intertree_implementations/test_compare.py test_compare.py-20060724101752-09ysswo1a92uqyoz-2
  bzrlib/tests/test_dirstate.py  test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
-------------- next part --------------
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2007-02-27 03:09:28 +0000
+++ b/bzrlib/dirstate.py	2007-02-27 21:32:16 +0000
@@ -849,7 +849,7 @@
         :return: Nothing.
         """
         assert new_entries[0][0][0:2] == ('', ''), \
-            "Missing root row %r" % new_entries[0][0]
+            "Missing root row %r" % (new_entries[0][0],)
         # The two blocks here are deliberate: the root block and the 
         # contents-of-root block.
         self._dirblocks = [('', []), ('', [])]
@@ -1690,7 +1690,8 @@
         # --- end generation of full tree mappings
 
         # sort and output all the entries
-        new_entries = sorted(by_path.items())
+        new_entries = sorted(by_path.items(),
+                        key=lambda entry:(entry[0][0].split('/'), entry[0][1]))
         self._entries_to_current_state(new_entries)
         self._parents = [rev_id for rev_id, tree in trees]
         self._ghosts = list(ghosts)

=== modified file 'bzrlib/tests/intertree_implementations/test_compare.py'
--- a/bzrlib/tests/intertree_implementations/test_compare.py	2007-02-27 02:48:45 +0000
+++ b/bzrlib/tests/intertree_implementations/test_compare.py	2007-02-27 21:32:16 +0000
@@ -729,7 +729,7 @@
             specific_files=['added', 'changed', 'fromdir', 'fromfile',
             'removed', 'unchanged', 'todir', 'tofile']))
 
-    def _disabled_test_tree_with_special_names(self):
+    def test_tree_with_special_names(self):
         tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
         tree1.lock_read()
         self.addCleanup(tree1.unlock)

=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py	2007-02-27 03:09:28 +0000
+++ b/bzrlib/tests/test_dirstate.py	2007-02-27 21:32:16 +0000
@@ -902,11 +902,14 @@
     """Test that DirState adds entries in the right order."""
 
     def test_add_sorting(self):
-        """Add entries in lexicographical order, we get path sorted order."""
-        dirs = ['a', 'a-a', 'a-z',
-                'a/a', 'a/a-a', 'a/a-z', 'a/a/a', 'a/a/z',
-                'a/z', 'a/z-a', 'a/z-z', 'a/z/a', 'a/z/z',
-                'z',
+        """Add entries in lexicographical order, we get path sorted order.
+
+        This tests it to a depth of 4, to make sure we don't just get it right
+        at a single depth. 'a/a' should come before 'a-a', even though it
+        doesn't lexicographically.
+        """
+        dirs = ['a', 'a/a', 'a/a/a', 'a/a/a/a',
+                'a-a', 'a/a-a', 'a/a/a-a', 'a/a/a/a-a',
                ]
         null_sha = ''
         state = dirstate.DirState.initialize('dirstate')
@@ -921,10 +924,38 @@
             state.add(file_path, file_id, 'file', fake_stat, null_sha)
 
         expected = ['', '', 'a',
-                'a/a', 'a/a/a', 'a/a/z', 'a/a-a', 'a/a-z',
-                'a/z', 'a/z/a', 'a/z/z', 'a/z-a', 'a/z-z',
-                'a-a', 'a-z', 'z',
+                'a/a', 'a/a/a', 'a/a/a/a',
+                'a/a/a/a-a', 'a/a/a-a', 'a/a-a', 'a-a',
                ]
+        split = lambda p:p.split('/')
+        self.assertEqual(sorted(expected, key=split), expected)
+        dirblock_names = [d[0] for d in state._dirblocks]
+        self.assertEqual(expected, dirblock_names)
+
+    def test_set_parent_trees_correct_order(self):
+        """After calling set_parent_trees() we should maintain the order."""
+        dirs = ['a', 'a-a', 'a/a']
+        null_sha = ''
+        state = dirstate.DirState.initialize('dirstate')
+        self.addCleanup(state.unlock)
+
+        fake_stat = os.stat('dirstate')
+        for d in dirs:
+            d_id = d.replace('/', '_')+'-id'
+            file_path = d + '/f'
+            file_id = file_path.replace('/', '_')+'-id'
+            state.add(d, d_id, 'directory', fake_stat, null_sha)
+            state.add(file_path, file_id, 'file', fake_stat, null_sha)
+
+        expected = ['', '', 'a', 'a/a', 'a-a']
+        dirblock_names = [d[0] for d in state._dirblocks]
+        self.assertEqual(expected, dirblock_names)
+
+        # *really* cheesy way to just get an empty tree
+        repo = self.make_repository('repo')
+        empty_tree = repo.revision_tree(None)
+        state.set_parent_trees([('null:', empty_tree)], [])
+
         dirblock_names = [d[0] for d in state._dirblocks]
         self.assertEqual(expected, dirblock_names)
 

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-02-27 01:08:04 +0000
+++ b/bzrlib/workingtree_4.py	2007-02-27 21:32:16 +0000
@@ -1546,31 +1546,32 @@
                     # as well.
                     old_path = source_details[1]
                     old_dirname, old_basename = os.path.split(old_path)
-                    path = os.path.join(*entry[0][0:2])
+                    path = os.path.join(entry[0][0], entry[0][1])
                     old_entry = state._get_entry(source_index, path_utf8=old_path)
                     # update the source details variable to be the real
                     # location.
                     source_details = old_entry[1][source_index]
                 else:
-                    old_path = path = os.path.join(*entry[0][0:2])
-                    old_dirname, old_basename = entry[0][0:2]
+                    old_dirname = entry[0][0]
+                    old_basename = entry[0][1]
+                    old_path = path = os.path.join(old_dirname, old_basename)
                 if path_info is None:
                     # the file is missing on disk, show as removed.
-                    old_path = os.path.join(*entry[0][0:2])
+                    old_path = os.path.join(entry[0][0], entry[0][1])
                     content_change = True
                     target_kind = None
                     target_exec = False
                 else:
                     # source and target are both versioned and disk file is present.
                     target_kind = path_info[2]
-                    if path_info[2][0] == 'd':
+                    if target_kind == 'directory':
                         if source_details[0][0] != 'd':
                             content_change = True
                         else:
                             # directories have no fingerprint
                             content_change = False
                         target_exec = False
-                    elif path_info[2][0] == 'f':
+                    elif target_kind == 'file':
                         if source_details[0][0] != 'f':
                             content_change = True
                         else:
@@ -1584,7 +1585,7 @@
                         target_exec = bool(
                             stat.S_ISREG(path_info[3].st_mode)
                             and stat.S_IEXEC & path_info[3].st_mode)
-                    elif path_info[2][0] == 's':
+                    elif target_kind == 'symlink':
                         if source_details[0][0] != 'l':
                             content_change = True
                         else:
@@ -1690,14 +1691,21 @@
                     # 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] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+                    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
             dir_iterator = osutils.walkdirs(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 sould skip it here.
+                # initial key matched it we should skip it here.
                 block_index +=1
             try:
                 current_dir_info = dir_iterator.next()
@@ -1783,7 +1791,14 @@
                             # 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] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+                            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
                     elif current_entry[0][1] != current_path_info[1]:
                         if current_path_info[1] < current_entry[0][1]:
@@ -1797,7 +1812,14 @@
                                 # 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] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+                                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
                             advance_path = False
                     else:
@@ -1805,7 +1827,14 @@
                             # 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] or True in map(lambda x:x[0]!=x[1], result[3:8]):
+                            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
                     if advance_entry and current_entry is not None:
                         entry_index += 1
@@ -1833,11 +1862,18 @@
                 if current_dir_info is not None:
                     try:
                         current_dir_info = dir_iterator.next()
-                        # convert the unicode relpaths in the dir index to uf8 for
+                        # convert the unicode relpaths in the dir index to utf8 for
                         # comparison with dirstate data.
-                        # TODO: keep the utf8 version around for giving to the caller.
-                        current_dir_info = ((current_dir_info[0][0].encode('utf8'), current_dir_info[0][1]),
-                            [(line[0].encode('utf8'), line[1].encode('utf8')) + line[2:] for line in current_dir_info[1]])
+                        # TODO: keep the unicode version around for giving to the caller.
+                        #       We could also use cached_utf8.encode() which
+                        #       maintains utf8=>unicode and unicode=>utf8 maps.
+                        # TODO: change this to a plain tuple assignment rather
+                        #       than doing slicing, since it should be faster.
+                        #       (unless the size of the line is dynamic)
+                        utf8_relpath = current_dir_info[0][0].encode('utf8')
+                        current_dir_info = ((utf8_relpath, current_dir_info[0][1]),
+                            [(line[0].encode('utf8'), line[1].encode('utf8'))
+                              + line[2:] for line in current_dir_info[1]])
                     except StopIteration:
                         current_dir_info = None
 



More information about the bazaar-commits mailing list