The root cause is in dirstate's iter_changes. The following test will exercise it:
=== modified file 'bzrlib/tests/per_intertree/test_compare.py'
--- bzrlib/tests/per_intertree/test_compare.py 2009-07-14 10:12:30 +0000
+++ bzrlib/tests/per_intertree/test_compare.py 2009-07-16 05:31:32 +0000
@@ -757,6 +757,26 @@
(None, root_id), (None, 'file'), (None, None), (None, False))]
self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
+ def test_only_in_target_missing_subtree_specific_bug_367632(self):
+ tree1 = self.make_branch_and_tree('tree1')
+ tree2 = self.make_to_branch_and_tree('tree2')
+ tree2.set_root_id(tree1.get_root_id())
+ self.build_tree(['tree2/dir/', 'tree2/dir/file'])
+ tree2.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
+ os.unlink('tree2/dir/file')
+ os.rmdir('tree2/dir')
+ tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
+ self.not_applicable_if_missing_in('dir', tree2)
+ root_id = tree1.path2id('')
+ expected = [
+ ('dir-id', (None, 'dir'), False, (False, True),
+ (None, root_id), (None, 'directory'), (None, None), (None, False)),
+ ('file-id', (None, 'dir/file'), False, (False, True),
+ (None, root_id), (None, 'dir-id'), (None, None), (None, False))
+ ]
+ self.assertEqual(expected,
+ self.do_iter_changes(tree1, tree2, specific_files=['']))
+
def test_unchanged_with_renames_and_modifications(self):
"""want_unchanged should generate a list of unchanged entries."""
tree1 = self.make_branch_and_tree('1')
The corruption is a missing changes-aborted flag on dirstate, I'll roll that into my apply_inventory_delta branch.
The '.' in the revert is required to trigger this dirstate corruption. I'm whittling down a smaller case.