Rev 2502: Change _iter_changes interface to yield both old and new paths. in http://bazaar.launchpad.net/~bzr/bzr/dirstate

Robert Collins robertc at robertcollins.net
Mon Mar 5 01:17:49 GMT 2007


At http://bazaar.launchpad.net/~bzr/bzr/dirstate

------------------------------------------------------------
revno: 2502
revision-id: robertc at robertcollins.net-20070305011525-fakb9irlbxyxaukb
parent: robertc at robertcollins.net-20070304221043-gxthr6yo2w4yy6mx
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Mon 2007-03-05 12:15:25 +1100
message:
  Change _iter_changes interface to yield both old and new paths.
modified:
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/delta.py                delta.py-20050729221636-54cf14ef94783d0a
  bzrlib/status.py               status.py-20050505062338-431bfa63ec9b19e6
  bzrlib/tests/blackbox/test_revert.py test_revert.py-20060124160917-485ce9de629c182c
  bzrlib/tests/intertree_implementations/test_compare.py test_compare.py-20060724101752-09ysswo1a92uqyoz-2
  bzrlib/tests/test_delta.py     test_delta.py-20070110134455-sqpd1y7mbjndelxf-1
  bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
  bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
  bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2007-03-01 09:46:42 +0000
+++ b/bzrlib/builtins.py	2007-03-05 01:15:25 +0000
@@ -607,15 +607,8 @@
 
         old_rh = branch_to.revision_history()
         if tree_to is not None:
-            # lock the tree we are pulling too, so that its inventory is
-            # stable. This is a hack to workaround the _iter_changes interface
-            # not exposing the old path, which will be fixed soon. RBC 20070301
-            tree_to.lock_write()
-            try:
-                count = tree_to.pull(branch_from, overwrite, rev_id,
-                    delta.ChangeReporter(tree_to.inventory))
-            finally:
-                tree_to.unlock()
+            count = tree_to.pull(branch_from, overwrite, rev_id,
+                delta.ChangeReporter())
         else:
             count = branch_to.pull(branch_from, overwrite, rev_id)
         note('%d revision(s) pulled.' % (count,))
@@ -2484,14 +2477,9 @@
         #      However, cmd_merge open's its own tree in _merge_helper, which
         #      means if we lock here, the later lock_write() will always block.
         #      Either the merge helper code should be updated to take a tree,
-        #      or the ChangeReporter should be updated to not require an
-        #      inventory. (What about tree.merge_from_branch?)
+        #      (What about tree.merge_from_branch?)
         tree = WorkingTree.open_containing(directory)[0]
-        tree.lock_read()
-        try:
-            change_reporter = delta.ChangeReporter(tree.inventory)
-        finally:
-            tree.unlock()
+        change_reporter = delta.ChangeReporter()
 
         if branch is not None:
             try:

=== modified file 'bzrlib/delta.py'
--- a/bzrlib/delta.py	2007-03-02 04:40:12 +0000
+++ b/bzrlib/delta.py	2007-03-05 01:15:25 +0000
@@ -221,7 +221,7 @@
             specific_files, extra_trees=extra_trees,
             want_unversioned=want_unversioned):
         if versioned == (False, False):
-            delta.unversioned.append((path, None, kind[1]))
+            delta.unversioned.append((path[1], None, kind[1]))
             continue
         if not include_root and (None, None) == parent_id:
             continue
@@ -229,32 +229,30 @@
                               x in range(2))
         if fully_present[0] != fully_present[1]:
             if fully_present[1] is True:
-                delta.added.append((path, file_id, kind[1]))
+                delta.added.append((path[1], file_id, kind[1]))
             else:
                 assert fully_present[0] is True
-                old_path = old_tree.id2path(file_id)
-                delta.removed.append((old_path, file_id, kind[0]))
+                delta.removed.append((path[0], file_id, kind[0]))
         elif fully_present[0] is False:
             continue
         elif name[0] != name[1] or parent_id[0] != parent_id[1]:
             # If the name changes, or the parent_id changes, we have a rename
             # (if we move a parent, that doesn't count as a rename for the
             # file)
-            old_path = old_tree.id2path(file_id)
-            delta.renamed.append((old_path,
-                                  path,
-                                  file_id, 
+            delta.renamed.append((path[0],
+                                  path[1],
+                                  file_id,
                                   kind[1],
-                                  content_change, 
+                                  content_change,
                                   (executable[0] != executable[1])))
         elif kind[0] != kind[1]:
-            delta.kind_changed.append((path, file_id, kind[0], kind[1]))
+            delta.kind_changed.append((path[1], file_id, kind[0], kind[1]))
         elif content_change is True or executable[0] != executable[1]:
-            delta.modified.append((path, file_id, kind[1],
-                                   content_change, 
+            delta.modified.append((path[1], file_id, kind[1],
+                                   content_change,
                                    (executable[0] != executable[1])))
         else:
-            delta.unchanged.append((path, file_id, kind[1]))
+            delta.unchanged.append((path[1], file_id, kind[1]))
 
     delta.removed.sort()
     delta.added.sort()
@@ -270,11 +268,10 @@
 class ChangeReporter(object):
     """Report changes between two trees"""
 
-    def __init__(self, old_inventory, output=None, suppress_root_add=True,
+    def __init__(self, output=None, suppress_root_add=True,
                  output_file=None):
         """Constructor
 
-        :param old_inventory: The inventory of the old tree
         :param output: a function with the signature of trace.note, i.e.
             accepts a format and parameters.
         :param supress_root_add: If true, adding the root will be ignored
@@ -282,7 +279,6 @@
         :param output_file: If supplied, a file-like object to write to.
             Only one of output and output_file may be supplied.
         """
-        self.old_inventory = old_inventory
         if output_file is not None:
             if output is not None:
                 raise BzrError('Cannot specify both output and output_file')
@@ -293,14 +289,21 @@
             from bzrlib import trace
             self.output = trace.note
         self.suppress_root_add = suppress_root_add
+        self.modified_map = {'kind changed': 'K',
+                             'unchanged': ' ',
+                             'created': 'N',
+                             'modified': 'M',
+                             'deleted': 'D'}
+        self.versioned_map = {'added': '+',
+                              'unchanged': ' ',
+                              'removed': '-'}
 
-    def report(self, file_id, path, versioned, renamed, modified, exe_change,
+    def report(self, file_id, paths, versioned, renamed, modified, exe_change,
                kind):
         """Report one change to a file
 
         :param file_id: The file_id of the file
-        :param path: The path the file has (or would have) in the tree (as
-            generated by Tree._iter_changes)
+        :param path: The old and new paths as generated by Tree._iter_changes.
         :param versioned: may be 'added', 'removed', or 'unchanged'
         :param renamed: may be True or False
         :param modified: may be 'created', 'deleted', 'kind changed',
@@ -309,38 +312,44 @@
         :param kind: A pair of file kinds, as generated by Tree._iter_changes.
             None indicates no file present.
         """
-        if path == '' and versioned == 'added' and self.suppress_root_add:
+        if paths[1] == '' and versioned == 'added' and self.suppress_root_add:
             return
-        modified_map = {'kind changed': 'K',
-                        'unchanged': ' ',
-                        'created': 'N',
-                        'modified': 'M',
-                        'deleted': 'D'}
-        versioned_map = {'added': '+',
-                         'unchanged': ' ',
-                         'removed': '-'}
-        old_path = ""
+        # we show both paths in the following situations:
+        # the file versioning is unchanged AND
+        # ( the path is different OR
+        #   the kind is different)
+        if (versioned == 'unchanged' and
+            (renamed or modified == 'kind changed')):
+            if renamed:
+                # on a rename, we show old and new
+                old_path, path = paths
+            else:
+                # if its not renamed, we're showing both for kind changes
+                # so only show the new path
+                old_path, path = paths[1], paths[1]
+            # if the file is not missing in the source, we show its kind
+            # when we show two paths.
+            if kind[0] is not None:
+                old_path += osutils.kind_marker(kind[0])
+            old_path += " => "
+        else:
+            old_path = ""
+            path = paths[1]
         if renamed:
-            old_path = self.old_inventory.id2path(file_id)
             rename = "R"
         else:
-            rename = versioned_map[versioned]
-        if modified == 'kind changed':
-            if old_path == "":
-                old_path = path
+            rename = self.versioned_map[versioned]
+        # we show the old kind on the new path when the content is deleted.
         if modified == 'deleted':
             path += osutils.kind_marker(kind[0])
+        # otherwise we always show the current kind when there is one
         elif kind[1] is not None:
             path += osutils.kind_marker(kind[1])
-        if old_path != "":
-            if kind[0] is not None:
-                old_path += osutils.kind_marker(kind[0])
-            old_path += " => "
         if exe_change:
             exe = '*'
         else:
             exe = ' '
-        self.output("%s%s%s %s%s", rename, modified_map[modified], exe,
+        self.output("%s%s%s %s%s", rename, self.modified_map[modified], exe,
                     old_path, path)
 
 

=== modified file 'bzrlib/status.py'
--- a/bzrlib/status.py	2007-03-02 04:40:12 +0000
+++ b/bzrlib/status.py	2007-03-05 01:15:25 +0000
@@ -145,8 +145,7 @@
             if short:
                 changes = new._iter_changes(old, show_unchanged, specific_files,
                     require_versioned=False)
-                reporter = _mod_delta.ChangeReporter(old.inventory,
-                    output_file=to_file)
+                reporter = _mod_delta.ChangeReporter(output_file=to_file)
                 _mod_delta.report_changes(changes, reporter)
                 short_status_letter = '? '
                 list_paths('unknown', new.unknowns(), specific_files, to_file,

=== modified file 'bzrlib/tests/blackbox/test_revert.py'
--- a/bzrlib/tests/blackbox/test_revert.py	2007-02-09 17:09:47 +0000
+++ b/bzrlib/tests/blackbox/test_revert.py	2007-03-05 01:15:25 +0000
@@ -106,12 +106,15 @@
     def test_revert_chatter(self):
         self._prepare_rename_mod_tree()
         chatter = self.run_bzr('revert')[1]
-        self.assertEqualDiff('R   j/b => a/b\n'
-                             'R   j/d/ => a/d/\n'
-                             'R   j/e => a/d/e\n'
-                             'R   j/ => f/\n'
-                             'R   a/g => f/g\n'
-                             'R   h => f/h\n', chatter)
+        self.assertEqualDiff(
+            'R   a/g => f/g\n'
+            'R   h => f/h\n'
+            'R   j/ => f/\n'
+            'R   j/b => a/b\n'
+            'R   j/d/ => a/d/\n'
+            'R   j/e => a/d/e\n',
+            chatter)
+
     def test_revert(self):
         self.run_bzr('init')
 

=== modified file 'bzrlib/tests/intertree_implementations/test_compare.py'
--- a/bzrlib/tests/intertree_implementations/test_compare.py	2007-03-02 04:40:12 +0000
+++ b/bzrlib/tests/intertree_implementations/test_compare.py	2007-03-05 01:15:25 +0000
@@ -403,14 +403,14 @@
     def added(self, tree, file_id):
         entry = tree.inventory[file_id]
         path = tree.id2path(file_id)
-        return (file_id, path, True, (False, True), (None, entry.parent_id),
+        return (file_id, (None, path), True, (False, True), (None, entry.parent_id),
                 (None, entry.name), (None, entry.kind),
                 (None, entry.executable))
 
     def content_changed(self, tree, file_id):
         entry = tree.inventory[file_id]
         path = tree.id2path(file_id)
-        return (file_id, path, True, (True, True), (entry.parent_id, entry.parent_id),
+        return (file_id, (path, path), True, (True, True), (entry.parent_id, entry.parent_id),
                 (entry.name, entry.name), (entry.kind, entry.kind),
                 (entry.executable, entry.executable))
 
@@ -418,19 +418,23 @@
         old_entry = from_tree.inventory[file_id]
         new_entry = to_tree.inventory[file_id]
         path = to_tree.id2path(file_id)
-        return (file_id, path, True, (True, True), (old_entry.parent_id, new_entry.parent_id),
+        from_path = from_tree.id2path(file_id)
+        return (file_id, (from_path, path), True, (True, True), (old_entry.parent_id, new_entry.parent_id),
                 (old_entry.name, new_entry.name), (old_entry.kind, new_entry.kind),
                 (old_entry.executable, new_entry.executable))
 
-    def missing(self, file_id, path, parent_id, kind):
-        _, basename = os.path.split(path)
-        return (file_id, path, True, (True, True), (parent_id, parent_id),
-            (basename, basename), (kind, None), (False, False))
+    def missing(self, file_id, from_path, to_path, parent_id, kind):
+        _, from_basename = os.path.split(from_path)
+        _, to_basename = os.path.split(to_path)
+        # missing files have both paths, but no kind.
+        return (file_id, (from_path, to_path), True, (True, True),
+            (parent_id, parent_id),
+            (from_basename, to_basename), (kind, None), (False, False))
 
     def deleted(self, tree, file_id):
         entry = tree.inventory[file_id]
         path = tree.id2path(file_id)
-        return (file_id, path, True, (True, False), (entry.parent_id, None),
+        return (file_id, (path, None), True, (True, False), (entry.parent_id, None),
                 (entry.name, None), (entry.kind, None),
                 (entry.executable, None))
 
@@ -439,7 +443,7 @@
         to_entry = to_tree.inventory[file_id]
         from_path = from_tree.id2path(file_id)
         to_path = to_tree.id2path(file_id)
-        return (file_id, to_path, content_changed, (True, True),
+        return (file_id, (from_path, to_path), content_changed, (True, True),
             (from_entry.parent_id, to_entry.parent_id),
             (from_entry.name, to_entry.name),
             (from_entry.kind, to_entry.kind),
@@ -451,7 +455,8 @@
         name = entry.name
         kind = entry.kind
         executable = entry.executable
-        return (file_id, tree.id2path(file_id), False, (True, True),
+        path = tree.id2path(file_id)
+        return (file_id, (path, path), False, (True, True),
                (parent, parent), (name, name), (kind, kind),
                (executable, executable))
 
@@ -459,7 +464,7 @@
         """Create an unversioned result."""
         _, basename = os.path.split(path)
         kind = file_kind(tree.abspath(path))
-        return (None, path, True, (False, False), (None, None),
+        return (None, (None, path), True, (False, False), (None, None),
                 (None, basename), (None, kind),
                 (None, False))
 
@@ -534,13 +539,14 @@
         def deleted(file_id):
             entry = tree1.inventory[file_id]
             path = tree1.id2path(file_id)
-            return (file_id, path, True, (True, False),
+            return (file_id, (path, None), True, (True, False),
                     (entry.parent_id, None),
                     (entry.name, None), (entry.kind, None),
                     (entry.executable, None))
-        expected_results = sorted([self.added(tree2, 'empty-root-id'),
-                          deleted('root-id'), deleted('a-id'),
-                          deleted('b-id'), deleted('c-id')])
+        expected_results = sorted([
+            self.added(tree2, 'empty-root-id'),
+            deleted('root-id'), deleted('a-id'),
+            deleted('b-id'), deleted('c-id')])
         tree1.unlock()
         tree2.unlock()
         self.assertEqual(
@@ -554,9 +560,9 @@
         tree2 = self.get_tree_no_parents_abc_content_2(tree2)
         tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
         root_id = tree1.path2id('')
-        self.assertEqual([('a-id', 'a', True, (True, True),
-                          (root_id, root_id), ('a', 'a'),
-                          ('file', 'file'), (False, False))],
+        self.assertEqual([('a-id', ('a', 'a'), True, (True, True),
+                           (root_id, root_id), ('a', 'a'),
+                           ('file', 'file'), (False, False))],
                          self.do_iter_changes(tree1, tree2))
 
     def test_meta_modification(self):
@@ -565,8 +571,8 @@
         tree1 = self.get_tree_no_parents_abc_content(tree1)
         tree2 = self.get_tree_no_parents_abc_content_3(tree2)
         tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
-        self.assertEqual([('c-id', 'b/c', False, (True, True),
-                          ('b-id', 'b-id'), ('c', 'c'), ('file', 'file'),
+        self.assertEqual([('c-id', ('b/c', 'b/c'), False, (True, True),
+                           ('b-id', 'b-id'), ('c', 'c'), ('file', 'file'),
                           (False, True))],
                          self.do_iter_changes(tree1, tree2))
 
@@ -591,9 +597,9 @@
         tree2 = self.get_tree_no_parents_abc_content_4(tree2)
         tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
         root_id = tree1.path2id('')
-        self.assertEqual([('a-id', 'd', False, (True, True),
-                          (root_id, root_id), ('a', 'd'), ('file', 'file'),
-                          (False, False))],
+        self.assertEqual([('a-id', ('a', 'd'), False, (True, True),
+                           (root_id, root_id), ('a', 'd'), ('file', 'file'),
+                           (False, False))],
                          self.do_iter_changes(tree1, tree2))
 
     def test_file_rename_and_modification(self):
@@ -603,8 +609,8 @@
         tree2 = self.get_tree_no_parents_abc_content_5(tree2)
         tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
         root_id = tree1.path2id('')
-        self.assertEqual([('a-id', 'd', True, (True, True),
-                          (root_id, root_id), ('a', 'd'), ('file', 'file'),
+        self.assertEqual([('a-id', ('a', 'd'), True, (True, True),
+                           (root_id, root_id), ('a', 'd'), ('file', 'file'),
                            (False, False))],
                          self.do_iter_changes(tree1, tree2))
 
@@ -615,9 +621,9 @@
         tree2 = self.get_tree_no_parents_abc_content_6(tree2)
         tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
         root_id = tree1.path2id('')
-        self.assertEqual([('c-id', 'e', False, (True, True),
-                          ('b-id', root_id), ('c', 'e'), ('file', 'file'),
-                          (False, True))],
+        self.assertEqual([('c-id', ('b/c', 'e'), False, (True, True),
+                           ('b-id', root_id), ('c', 'e'), ('file', 'file'),
+                           (False, True))],
                          self.do_iter_changes(tree1, tree2))
 
     def test_missing_in_target(self):
@@ -632,9 +638,28 @@
         tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
         root_id = tree1.path2id('')
         expected = sorted([
-            self.missing('a-id', 'a', root_id, 'file'),
-            self.missing('b-id', 'b', root_id, 'directory'),
-            self.missing('c-id', 'b/c', 'b-id', 'file'),
+            self.missing('a-id', 'a', 'a', root_id, 'file'),
+            self.missing('b-id', 'b', 'b', root_id, 'directory'),
+            self.missing('c-id', 'b/c', 'b/c', 'b-id', 'file'),
+            ])
+        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
+
+    def test_missing_and_renamed(self):
+        tree1 = self.make_branch_and_tree('tree1')
+        tree2 = self.make_to_branch_and_tree('tree2')
+        self.build_tree(['tree1/file'])
+        tree1.add(['file'], ['file-id'])
+        self.build_tree(['tree2/directory/'])
+        tree2.add(['directory'], ['file-id'])
+        os.rmdir('tree2/directory')
+        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+        tree1.lock_read()
+        self.addCleanup(tree1.unlock)
+        tree2.lock_read()
+        self.addCleanup(tree2.unlock)
+        root_id = tree1.path2id('')
+        expected = sorted([
+            self.missing('file-id', 'file', 'directory', root_id, 'file'),
             ])
         self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
 
@@ -651,8 +676,9 @@
         tree2.lock_read()
         self.addCleanup(tree2.unlock)
         self.assertEqual(sorted([self.unchanged(tree1, root_id),
-            self.unchanged(tree1, 'b-id'), ('a-id', 'd', True, (True, True),
-            (root_id, root_id), ('a', 'd'), ('file', 'file'),
+            self.unchanged(tree1, 'b-id'),
+            ('a-id', ('a', 'd'), True, (True, True),
+             (root_id, root_id), ('a', 'd'), ('file', 'file'),
             (False, False)), self.unchanged(tree1, 'c-id')]),
             self.do_iter_changes(tree1, tree2, include_unchanged=True))
 
@@ -900,7 +926,7 @@
                           if f_id.endswith('_f-id'))
         self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
 
-    def test_trees_with_missing_dir(self):
+    def test_trees_with_deleted_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',
@@ -915,7 +941,7 @@
         self.addCleanup(tree1.unlock)
         tree2.lock_read()
         self.addCleanup(tree2.unlock)
-        # We should notice that 'b' and all its children are missing
+        # We should notice that 'b' and all its children are deleted
         expected = sorted([
             self.content_changed(tree2, 'a-id'),
             self.content_changed(tree2, 'g-id'),

=== modified file 'bzrlib/tests/test_delta.py'
--- a/bzrlib/tests/test_delta.py	2007-03-02 03:47:56 +0000
+++ b/bzrlib/tests/test_delta.py	2007-03-05 01:15:25 +0000
@@ -19,7 +19,6 @@
 
 from bzrlib import (
     delta as _mod_delta,
-    inventory,
     tests,
     )
 
@@ -44,13 +43,9 @@
         result = []
         def result_line(format, *args):
             result.append(format % args)
-        inv = inventory.Inventory()
-        if old_path is not None:
-            inv.add(inventory.InventoryFile(file_id, old_path,
-                                            inv.root.file_id))
-        reporter = _mod_delta.ChangeReporter(inv, result_line)
-        reporter.report(file_id, path, versioned_change, renamed, modified,
-                         exe_change, kind)
+        reporter = _mod_delta.ChangeReporter(result_line)
+        reporter.report(file_id, (old_path, path), versioned_change, renamed,
+            modified, exe_change, kind)
         self.assertEqualDiff(expected, result[0])
 
     def test_rename(self):
@@ -61,7 +56,7 @@
 
     def test_kind(self):
         self.assertReport(' K  path => path/', modified='kind changed',
-                          kind=('file', 'directory'))
+                          kind=('file', 'directory'), old_path='path')
         self.assertReport(' K  path/ => path', modified='kind changed',
                           kind=('directory', 'file'), old_path='old')
         self.assertReport('RK  old => path/', renamed=True,
@@ -78,8 +73,6 @@
                           modified='created', kind=(None, 'directory'))
         self.assertReport('+M  path/', versioned_change='added',
                           modified='modified', kind=(None, 'directory'))
-        self.assertReport('+K  path => path/', versioned_change='added',
-                          modified='kind changed', kind=('file', 'directory'))
 
     def test_removal(self):
         self.assertReport(' D  path/', modified='deleted',

=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py	2007-03-01 04:13:07 +0000
+++ b/bzrlib/tests/test_transform.py	2007-03-05 01:15:25 +0000
@@ -596,11 +596,11 @@
             self.assertEqual([], list(transform._iter_changes()))
             old = transform.trans_id_tree_file_id('id-1')
             transform.unversion_file(old)
-            self.assertEqual([('id-1', 'old', False, (True, False),
+            self.assertEqual([('id-1', ('old', None), False, (True, False),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
                 (True, True))], list(transform._iter_changes()))
             transform.new_directory('new', root, 'id-1')
-            self.assertEqual([('id-1', 'new', True, (True, True),
+            self.assertEqual([('id-1', ('old', 'new'), True, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'new'),
                 ('file', 'directory'),
                 (True, False))], list(transform._iter_changes()))
@@ -615,7 +615,7 @@
         try:
             old = transform.trans_id_tree_path('old')
             transform.version_file('id-1', old)
-            self.assertEqual([('id-1', 'old', False, (False, True),
+            self.assertEqual([('id-1', (None, 'old'), False, (False, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
                 (False, False))], list(transform._iter_changes()))
         finally:
@@ -636,17 +636,17 @@
 
             #content deletion
             transform.delete_contents(old)
-            self.assertEqual([('id-1', 'old', True, (True, True),
+            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', None),
                 (False, False))], list(transform._iter_changes()))
 
             #content change
             transform.create_file('blah', old)
-            self.assertEqual([('id-1', 'old', True, (True, True),
+            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
                 (False, False))], list(transform._iter_changes()))
             transform.cancel_deletion(old)
-            self.assertEqual([('id-1', 'old', True, (True, True),
+            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
                 (False, False))], list(transform._iter_changes()))
             transform.cancel_creation(old)
@@ -656,7 +656,7 @@
             transform.unversion_file(old)
             transform.version_file('id-1', new)
             transform.adjust_path('old', root, new)
-            self.assertEqual([('id-1', 'old', True, (True, True),
+            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
                 (False, False))], list(transform._iter_changes()))
             transform.cancel_versioning(new)
@@ -665,7 +665,7 @@
             #execute bit
             self.assertEqual([], list(transform._iter_changes()))
             transform.set_executability(True, old)
-            self.assertEqual([('id-1', 'old', False, (True, True),
+            self.assertEqual([('id-1', ('old', 'old'), False, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
                 (False, True))], list(transform._iter_changes()))
             transform.set_executability(None, old)
@@ -674,7 +674,7 @@
             self.assertEqual([], list(transform._iter_changes()))
             transform.adjust_path('new', root, old)
             transform._new_parent = {}
-            self.assertEqual([('id-1', 'new', False, (True, True),
+            self.assertEqual([('id-1', ('old', 'new'), False, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('old', 'new'), ('file', 'file'),
                 (False, False))], list(transform._iter_changes()))
             transform._new_name = {}
@@ -683,9 +683,10 @@
             self.assertEqual([], list(transform._iter_changes()))
             transform.adjust_path('new', subdir, old)
             transform._new_name = {}
-            self.assertEqual([('id-1', 'subdir/old', False, (True, True),
-                ('TREE_ROOT', 'subdir-id'), ('old', 'old'), ('file', 'file'),
-                (False, False))], list(transform._iter_changes()))
+            self.assertEqual([('id-1', ('old', 'subdir/old'), False,
+                (True, True), ('TREE_ROOT', 'subdir-id'), ('old', 'old'),
+                ('file', 'file'), (False, False))],
+                list(transform._iter_changes()))
             transform._new_path = {}
 
         finally:
@@ -706,10 +707,10 @@
             transform.delete_contents(transform.trans_id_file_id('id-1'))
             transform.set_executability(True,
             transform.trans_id_file_id('id-2'))
-            self.assertEqual([('id-1', u'file1', True, (True, True),
+            self.assertEqual([('id-1', (u'file1', u'file1'), True, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('file1', u'file1'),
                 ('file', None), (False, False)),
-                ('id-2', u'file2', False, (True, True),
+                ('id-2', (u'file2', u'file2'), False, (True, True),
                 ('TREE_ROOT', 'TREE_ROOT'), ('file2', u'file2'),
                 ('file', 'file'), (False, True))],
                 list(transform._iter_changes()))

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2007-03-01 04:20:42 +0000
+++ b/bzrlib/transform.py	2007-03-05 01:15:25 +0000
@@ -1021,7 +1021,14 @@
             to_name, to_parent, to_kind, to_executable = \
                 self._to_file_data(to_trans_id, from_trans_id, from_executable)
 
-            to_path = final_paths.get_path(to_trans_id)
+            if not from_versioned:
+                from_path = None
+            else:
+                from_path = self._tree_id_paths.get(from_trans_id)
+            if not to_versioned:
+                to_path = None
+            else:
+                to_path = final_paths.get_path(to_trans_id)
             if from_kind != to_kind:
                 modified = True
             elif to_kind in ('file' or 'symlink') and (
@@ -1032,7 +1039,7 @@
                 from_parent==to_parent and from_name == to_name and
                 from_executable == to_executable):
                 continue
-            results.append((file_id, to_path, modified,
+            results.append((file_id, (from_path, to_path), modified,
                    (from_versioned, to_versioned),
                    (from_parent, to_parent),
                    (from_name, to_name),
@@ -1380,7 +1387,7 @@
             child_pb.finished()
         conflicts = cook_conflicts(raw_conflicts, tt)
         if change_reporter:
-            change_reporter = delta.ChangeReporter(working_tree.inventory)
+            change_reporter = delta.ChangeReporter()
             delta.report_changes(tt._iter_changes(), change_reporter)
         for conflict in conflicts:
             warning(conflict)

=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py	2007-03-02 04:40:12 +0000
+++ b/bzrlib/tree.py	2007-03-05 01:15:25 +0000
@@ -577,12 +577,12 @@
         """Generate an iterator of changes between trees.
 
         A tuple is returned:
-        (file_id, path, changed_content, versioned, parent, name, kind,
+        (file_id, (path_in_source, path_in_target),
+         changed_content, versioned, parent, name, kind,
          executable)
 
-        Path is relative to the target tree.  changed_content is True if the
-        file's content has changed.  This includes changes to its kind, and to
-        a symlink's target.
+        Changed_content is True if the file's content has changed.  This
+        includes changes to its kind, and to a symlink's target.
 
         versioned, parent, name, kind, executable are tuples of (from, to).
         If a file is missing in a tree, its kind is None.
@@ -630,7 +630,7 @@
                 unversioned_path = all_unversioned.popleft()
                 to_kind, to_executable, to_stat = \
                     self.target._comparison_data(fake_entry, unversioned_path[1])
-                yield (None, unversioned_path[1], True, (False, False),
+                yield (None, (None, unversioned_path[1]), True, (False, False),
                     (None, None),
                     (None, unversioned_path[0][-1]),
                     (None, to_kind),
@@ -680,35 +680,43 @@
             if (changed_content is not False or versioned[0] != versioned[1]
                 or parent[0] != parent[1] or name[0] != name[1] or 
                 executable[0] != executable[1] or include_unchanged):
-                yield (file_id, to_path, changed_content, versioned, parent,
-                       name, kind, executable)
+                yield (file_id, (from_path, to_path), changed_content,
+                    versioned, parent, name, kind, executable)
+
         while all_unversioned:
             # yield any trailing unversioned paths
             unversioned_path = all_unversioned.popleft()
             to_kind, to_executable, to_stat = \
                 self.target._comparison_data(fake_entry, unversioned_path[1])
-            yield (None, unversioned_path[1], True, (False, False),
+            yield (None, (None, unversioned_path[1]), True, (False, False),
                 (None, None),
                 (None, unversioned_path[0][-1]),
                 (None, to_kind),
                 (None, to_executable))
 
-        def get_to_path(from_entry):
-            if from_entry.parent_id is None:
-                to_path = ''
+        def get_to_path(to_entry):
+            if to_entry.parent_id is None:
+                to_path = '' # the root
             else:
-                if from_entry.parent_id not in to_paths:
-                    get_to_path(self.source.inventory[from_entry.parent_id])
-                to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
-                                           from_entry.name)
-            to_paths[from_entry.file_id] = to_path
+                if to_entry.parent_id not in to_paths:
+                    # recurse up
+                    return get_to_path(self.target.inventory[to_entry.parent_id])
+                to_path = osutils.pathjoin(to_paths[to_entry.parent_id],
+                                           to_entry.name)
+            to_paths[to_entry.file_id] = to_path
             return to_path
 
         for path, from_entry in from_entries_by_dir:
             file_id = from_entry.file_id
             if file_id in to_paths:
+                # already returned
                 continue
-            to_path = get_to_path(from_entry)
+            if not file_id in self.target.inventory:
+                # common case - paths we have not emitted are not present in
+                # target.
+                to_path = None
+            else:
+                to_path = get_to_path(self.target.inventory[file_id])
             entry_count += 1
             if pb is not None:
                 pb.update('comparing files', entry_count, num_entries)
@@ -721,7 +729,7 @@
             executable = (from_executable, None)
             changed_content = True
             # the parent's path is necessarily known at this point.
-            yield(file_id, to_path, changed_content, versioned, parent,
+            yield(file_id, (path, to_path), changed_content, versioned, parent,
                   name, kind, executable)
 
 

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-03-02 07:57:54 +0000
+++ b/bzrlib/workingtree_4.py	2007-03-05 01:15:25 +0000
@@ -1459,7 +1459,7 @@
             output. An unversioned file is defined as one with (False, False)
             for the versioned pair.
         """
-        utf8_decode = cache_utf8._utf8_decode
+        utf8_decode = cache_utf8._utf8_decode_with_None
         _minikind_to_kind = dirstate.DirState._minikind_to_kind
         # NB: show_status depends on being able to pass in non-versioned files
         # and report them as unknown
@@ -1645,7 +1645,6 @@
                     old_path = path = pathjoin(old_dirname, old_basename)
                 if path_info is None:
                     # the file is missing on disk, show as removed.
-                    old_path = pathjoin(entry[0][0], entry[0][1])
                     content_change = True
                     target_kind = None
                     target_exec = False
@@ -1711,7 +1710,7 @@
                         last_target_parent[2] = target_parent_entry
 
                 source_exec = source_details[3]
-                return ((entry[0][2], path, content_change,
+                return ((entry[0][2], (old_path, path), content_change,
                         (True, True),
                         (source_parent_id, target_parent_id),
                         (old_basename, entry[0][1]),
@@ -1730,7 +1729,7 @@
                     target_exec = bool(
                         stat.S_ISREG(path_info[3].st_mode)
                         and stat.S_IEXEC & path_info[3].st_mode)
-                    return ((entry[0][2], path, True,
+                    return ((entry[0][2], (None, path), True,
                             (False, True),
                             (None, parent_id),
                             (None, entry[0][1]),
@@ -1750,7 +1749,7 @@
                 parent_id = state._get_entry(source_index, path_utf8=entry[0][0])[0][2]
                 if parent_id == entry[0][2]:
                     parent_id = None
-                return ((entry[0][2], old_path, True,
+                return ((entry[0][2], (old_path, None), True,
                         (True, False),
                         (parent_id, None),
                         (entry[0][1], None),
@@ -1812,13 +1811,15 @@
                         or result[7][0] != result[7][1] # executable
                         ):
                         result = (result[0],
-                                  utf8_decode(result[1])[0]) + result[2:]
+                            ((utf8_decode(result[1][0])[0]),
+                             utf8_decode(result[1][1])[0]),) + result[2:]
                         yield result
             if want_unversioned and not path_handled:
                 new_executable = bool(
                     stat.S_ISREG(root_dir_info[3].st_mode)
                     and stat.S_IEXEC & root_dir_info[3].st_mode)
-                yield (None, current_root, True, (False, False), (None, None),
+                yield (None, (None, current_root), True, (False, False),
+                    (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)
@@ -1896,7 +1897,8 @@
                                     or result[7][0] != result[7][1] # executable
                                     ):
                                     result = (result[0],
-                                              utf8_decode(result[1])[0]) + result[2:]
+                                        ((utf8_decode(result[1][0])[0]),
+                                         utf8_decode(result[1][1])[0]),) + result[2:]
                                     yield result
                         block_index +=1
                         if (block_index < len(state._dirblocks) and
@@ -1940,7 +1942,8 @@
                                 or result[7][0] != result[7][1] # executable
                                 ):
                                 result = (result[0],
-                                          utf8_decode(result[1])[0]) + result[2:]
+                                    ((utf8_decode(result[1][0])[0]),
+                                     utf8_decode(result[1][1])[0]),) + result[2:]
                                 yield result
                     elif current_entry[0][1] != current_path_info[1]:
                         if current_path_info[1] < current_entry[0][1]:
@@ -1966,7 +1969,8 @@
                                     or result[7][0] != result[7][1] # executable
                                     ):
                                     result = (result[0],
-                                              utf8_decode(result[1])[0]) + result[2:]
+                                        ((utf8_decode(result[1][0])[0]),
+                                         utf8_decode(result[1][1])[0]),) + result[2:]
                                     yield result
                             advance_path = False
                     else:
@@ -1984,7 +1988,8 @@
                                 or result[7][0] != result[7][1] # executable
                                 ):
                                 result = (result[0],
-                                          utf8_decode(result[1])[0]) + result[2:]
+                                    ((utf8_decode(result[1][0])[0]),
+                                     utf8_decode(result[1][1])[0]),) + result[2:]
                                 yield result
                     if advance_entry and current_entry is not None:
                         entry_index += 1
@@ -2002,12 +2007,13 @@
                                     stat.S_ISREG(current_path_info[3].st_mode)
                                     and stat.S_IEXEC & current_path_info[3].st_mode)
                                 if want_unversioned:
-                                    yield (None, current_path_info[0], True,
-                                           (False, False),
-                                           (None, None),
-                                           (None, current_path_info[1]),
-                                           (None, current_path_info[2]),
-                                           (None, new_executable))
+                                    yield (None, (None, current_path_info[0]),
+                                        True,
+                                        (False, False),
+                                        (None, None),
+                                        (None, current_path_info[1]),
+                                        (None, current_path_info[2]),
+                                        (None, new_executable))
                             # dont descend into this unversioned path if it is
                             # a dir
                             if current_path_info[2] == 'directory':



More information about the bazaar-commits mailing list