Rev 2377: Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised. in sftp://bazaar.launchpad.net/%7Ebzr/bzr/dirstate/
Robert Collins
robertc at robertcollins.net
Fri Feb 23 05:13:26 GMT 2007
At sftp://bazaar.launchpad.net/%7Ebzr/bzr/dirstate/
------------------------------------------------------------
revno: 2377
revision-id: robertc at robertcollins.net-20070223051206-jqheguu2qeyqab14
parent: john at arbash-meinel.com-20070223030108-da1z3sofjti2xulz
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Fri 2007-02-23 16:12:06 +1100
message:
Alter intertree implementation tests to let dirstate inter-trees be correctly parameterised.
modified:
bzrlib/tests/intertree_implementations/__init__.py __init__.py-20060724101752-09ysswo1a92uqyoz-3
bzrlib/tests/intertree_implementations/test_compare.py test_compare.py-20060724101752-09ysswo1a92uqyoz-2
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'bzrlib/tests/intertree_implementations/__init__.py'
--- a/bzrlib/tests/intertree_implementations/__init__.py 2006-10-11 23:08:27 +0000
+++ b/bzrlib/tests/intertree_implementations/__init__.py 2007-02-23 05:12:06 +0000
@@ -41,6 +41,11 @@
)
+def return_provided_trees(source, target):
+ """Return the source and target tree unaltered."""
+ return source, target
+
+
class TestCaseWithTwoTrees(TestCaseWithTree):
def make_to_branch_and_tree(self, relpath):
@@ -51,27 +56,6 @@
made_control.create_branch()
return self.workingtree_format_to.initialize(made_control)
- def get_to_tree_no_parents_no_content(self, empty_tree):
- return super(TestCaseWithTwoTrees, self).get_tree_no_parents_no_content(empty_tree, converter=self.workingtree_to_test_tree_to)
-
- def get_to_tree_no_parents_abc_content(self, empty_tree):
- return super(TestCaseWithTwoTrees, self).get_tree_no_parents_abc_content(empty_tree, converter=self.workingtree_to_test_tree_to)
-
- def get_to_tree_no_parents_abc_content_2(self, empty_tree):
- return super(TestCaseWithTwoTrees, self).get_tree_no_parents_abc_content_2(empty_tree, converter=self.workingtree_to_test_tree_to)
-
- def get_to_tree_no_parents_abc_content_3(self, empty_tree):
- return super(TestCaseWithTwoTrees, self).get_tree_no_parents_abc_content_3(empty_tree, converter=self.workingtree_to_test_tree_to)
-
- def get_to_tree_no_parents_abc_content_4(self, empty_tree):
- return super(TestCaseWithTwoTrees, self).get_tree_no_parents_abc_content_4(empty_tree, converter=self.workingtree_to_test_tree_to)
-
- def get_to_tree_no_parents_abc_content_5(self, empty_tree):
- return super(TestCaseWithTwoTrees, self).get_tree_no_parents_abc_content_5(empty_tree, converter=self.workingtree_to_test_tree_to)
-
- def get_to_tree_no_parents_abc_content_6(self, empty_tree):
- return super(TestCaseWithTwoTrees, self).get_tree_no_parents_abc_content_6(empty_tree, converter=self.workingtree_to_test_tree_to)
-
class InterTreeTestProviderAdapter(WorkingTreeTestProviderAdapter):
"""Generate test suites for each InterTree implementation in bzrlib."""
@@ -80,18 +64,21 @@
result = TestSuite()
for (intertree_class,
workingtree_format,
- workingtree_to_test_tree,
workingtree_format_to,
- workingtree_to_test_tree_to) in self._formats:
+ mutable_trees_to_test_trees) in self._formats:
new_test = self._clone_test(
test,
workingtree_format._matchingbzrdir,
workingtree_format,
intertree_class.__name__)
new_test.intertree_class = intertree_class
- new_test.workingtree_to_test_tree = workingtree_to_test_tree
new_test.workingtree_format_to = workingtree_format_to
- new_test.workingtree_to_test_tree_to = workingtree_to_test_tree_to
+ # mutable_trees_to_test_trees takes two trees and converts them to
+ # whatever relationship the optimiser under test requires.
+ new_test.mutable_trees_to_test_trees = mutable_trees_to_test_trees
+ # workingtree_to_test_tree is set to disable changing individual
+ # trees: instead the mutable_trees_to_test_trees helper is used.
+ new_test.workingtree_to_test_tree = return_parameter
result.addTest(new_test)
return result
@@ -108,13 +95,14 @@
]
test_intertree_permutations = [
# test InterTree with two default-format working trees.
- (InterTree, default_tree_format, return_parameter,
- default_tree_format, return_parameter)]
+ (InterTree, default_tree_format, default_tree_format,
+ return_provided_trees)]
for optimiser in InterTree._optimisers:
test_intertree_permutations.append(
(optimiser,
- optimiser._matching_from_tree_format, optimiser._from_tree_converter,
- optimiser._matching_to_tree_format, optimiser._to_tree_converter))
+ optimiser._matching_from_tree_format,
+ optimiser._matching_to_tree_format,
+ optimiser._test_mutable_trees_to_test_trees))
adapter = InterTreeTestProviderAdapter(
default_transport,
# None here will cause a readonly decorator to be created
=== modified file 'bzrlib/tests/intertree_implementations/test_compare.py'
--- a/bzrlib/tests/intertree_implementations/test_compare.py 2007-02-23 01:36:02 +0000
+++ b/bzrlib/tests/intertree_implementations/test_compare.py 2007-02-23 05:12:06 +0000
@@ -28,7 +28,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_no_content(tree2)
+ tree2 = self.get_tree_no_parents_no_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([], d.modified)
@@ -40,7 +41,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([('a', 'a-id', 'file'),
('b', 'b-id', 'directory'),
@@ -52,14 +54,24 @@
self.assertEqual([], d.unchanged)
def test_dangling(self):
+ # This test depends on the ability for some trees to have a difference
+ # between a 'versioned present' and 'versioned not present' (aka
+ # dangling) file. In this test there are two trees each with a separate
+ # dangling file, and the dangling files should be considered absent for
+ # the test.
tree1 = self.make_branch_and_tree('1')
- tree2 = self.make_branch_and_tree('2')
+ tree2 = self.make_to_branch_and_tree('2')
self.build_tree(['2/a'])
tree2.add('a')
os.unlink('2/a')
self.build_tree(['1/b'])
tree1.add('b')
os.unlink('1/b')
+ # the conversion to test trees here will leave the trees intact for the
+ # default intertree, but may perform a commit for other tree types,
+ # which may reduce the validity of the test. XXX: Think about how to
+ # address this.
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([], d.modified)
@@ -71,7 +83,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_no_content(tree2)
+ tree2 = self.get_tree_no_parents_no_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([], d.modified)
@@ -86,7 +99,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_2(tree2)
+ tree2 = self.get_tree_no_parents_abc_content_2(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([('a', 'a-id', 'file', True, False)], d.modified)
@@ -98,7 +112,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_3(tree2)
+ tree2 = self.get_tree_no_parents_abc_content_3(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([('b/c', 'c-id', 'file', False, True)], d.modified)
@@ -110,7 +125,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_4(tree2)
+ tree2 = self.get_tree_no_parents_abc_content_4(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([], d.modified)
@@ -122,7 +138,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_5(tree2)
+ tree2 = self.get_tree_no_parents_abc_content_5(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([], d.modified)
@@ -134,7 +151,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_6(tree2)
+ tree2 = self.get_tree_no_parents_abc_content_6(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare()
self.assertEqual([], d.added)
self.assertEqual([], d.modified)
@@ -146,7 +164,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare(specific_files=['a'])
self.assertEqual([('a', 'a-id', 'file')], d.added)
self.assertEqual([], d.modified)
@@ -158,7 +177,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare(
specific_files=['a', 'b/c'])
self.assertEqual(
@@ -174,7 +194,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
self.assertEqual(
[('b', 'b-id', 'directory'),('b/c', 'c-id', 'file')],
@@ -189,7 +210,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_5(tree2)
+ tree2 = self.get_tree_no_parents_abc_content_5(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
d = self.intertree_class(tree1, tree2).compare(want_unchanged=True)
self.assertEqual([], d.added)
self.assertEqual([], d.modified)
@@ -204,11 +226,17 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_3(tree2)
+ tree2 = self.get_tree_no_parents_abc_content_3(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+ d = self.intertree_class(tree1, tree2).compare(specific_files=['b'])
# the type of tree-3 does not matter - it is used as a lookup, not
- # a dispatch
+ # a dispatch. XXX: For dirstate it does speak to the optimisability of
+ # the lookup, in merged trees it can be fast-pathed. We probably want
+ # two tests: one as is, and one with it as a pending merge.
tree3 = self.make_branch_and_tree('3')
tree3 = self.get_tree_no_parents_abc_content_6(tree3)
+ tree3.lock_read()
+ self.addCleanup(tree3.unlock)
# tree 3 has 'e' which is 'c-id'. Tree 1 has c-id at b/c, and Tree 2
# has c-id at b/c with its exec flag toggled.
# without extra_trees, we should get no modifications from this
@@ -233,7 +261,8 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
self.assertRaises(errors.PathsNotVersionedError,
self.intertree_class(tree1, tree2).compare,
specific_files=['d'],
@@ -243,16 +272,30 @@
class TestIterChanges(TestCaseWithTwoTrees):
"""Test the comparison iterator"""
+ def do_iter_changes(self, tree1, tree2, **extra_args):
+ """Helper to run _iter_changes from tree1 to tree2.
+
+ :param tree1, tree2: The source and target trees. These will be locked
+ automatically.
+ :param **extra_args: Extra args to pass to _iter_changes. This is not
+ inspected by this test helper.
+ """
+ tree1.lock_read()
+ tree2.lock_read()
+ try:
+ return list(self.intertree_class(tree1, tree2)
+ ._iter_changes(**extra_args))
+ finally:
+ tree1.unlock()
+ tree2.unlock()
+
def test_compare_empty_trees(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_no_content(tree2)
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([], list(tree2._iter_changes(tree1)))
+ tree2 = self.get_tree_no_parents_no_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+ self.assertEqual([], self.do_iter_changes(tree1, tree2))
def added(self, tree, file_id):
entry = tree.inventory[file_id]
@@ -272,150 +315,153 @@
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
-
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
tree1.lock_read()
- self.addCleanup(tree1.unlock)
tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([self.added(tree2, 'root-id'),
- self.added(tree2, 'a-id'),
- self.added(tree2, 'b-id'),
- self.added(tree2, 'c-id'),
- self.deleted(tree1, 'empty-root-id')],
- list(tree2._iter_changes(tree1)))
+ expected_results = [
+ self.added(tree2, 'root-id'),
+ self.added(tree2, 'a-id'),
+ self.added(tree2, 'b-id'),
+ self.added(tree2, 'c-id'),
+ self.deleted(tree1, 'empty-root-id')]
+ tree1.unlock()
+ tree2.unlock()
+ self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
def test_empty_to_abc_content_a_only(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([self.added(tree2, 'a-id')],
- list(tree2._iter_changes(tree1,
- specific_file_ids=['a-id'])))
- self.assertEqual([self.deleted(tree2, 'a-id')],
- list(tree1._iter_changes(tree2,
- specific_file_ids=['a-id'])))
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+ tree1.lock_read()
+ tree2.lock_read()
+ self.assertEqual(
+ [self.added(tree2, 'a-id')],
+ self.do_iter_changes(tree1, tree2, specific_file_ids=['a-id']))
+ tree1.unlock()
+ tree2.unlock()
+
+ def test_abc_content_to_empty_to_abc_content_a_only(self):
+ tree1 = self.make_branch_and_tree('1')
+ tree2 = self.make_to_branch_and_tree('2')
+ tree1 = self.get_tree_no_parents_abc_content(tree1)
+ tree2 = self.get_tree_no_parents_no_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+ tree1.lock_read()
+ tree2.lock_read()
+ self.assertEqual(
+ [self.deleted(tree1, 'a-id')],
+ self.do_iter_changes(tree1, tree2, specific_file_ids=['a-id']))
+ tree1.unlock()
+ tree2.unlock()
def test_empty_to_abc_content_a_and_c_only(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
+ tree2 = self.get_tree_no_parents_abc_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
tree1.lock_read()
- self.addCleanup(tree1.unlock)
tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([self.added(tree2, 'a-id'),
- self.added(tree2, 'c-id')],
- list(tree2._iter_changes(tree1,
- specific_file_ids=['a-id',
- 'c-id'])))
- d = self.intertree_class(tree1, tree2).compare(
- specific_files=['a', 'b/c'])
+ expected_result = [self.added(tree2, 'a-id'), self.added(tree2, 'c-id')]
+ tree1.unlock()
+ tree2.unlock()
+ self.assertEqual(expected_result,
+ self.do_iter_changes(tree1, tree2, specific_file_ids=['a-id', 'c-id']))
- def test_abc_content(self):
+ def test_abc_content_to_empty(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
- tree1 = self.get_tree_no_parents_no_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content(tree2)
+ tree1 = self.get_tree_no_parents_abc_content(tree1)
+ tree2 = self.get_tree_no_parents_no_content(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+ tree1.lock_read()
+ tree2.lock_read()
def deleted(file_id):
- entry = tree2.inventory[file_id]
- path = tree2.id2path(file_id)
- return (file_id, path, True, (True, False),
+ entry = tree1.inventory[file_id]
+ path = tree1.id2path(file_id)
+ return (file_id, path, True, (True, False),
(entry.parent_id, None),
- (entry.name, None), (entry.kind, None),
+ (entry.name, None), (entry.kind, None),
(entry.executable, None))
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([self.added(tree1, 'empty-root-id'),
- deleted('root-id'), deleted('a-id'),
- deleted('b-id'), deleted('c-id')],
- list(tree1._iter_changes(tree2)))
+ expected_results = [self.added(tree2, 'empty-root-id'),
+ deleted('root-id'), deleted('a-id'),
+ deleted('b-id'), deleted('c-id')]
+ tree1.unlock()
+ tree2.unlock()
+ self.assertEqual(
+ expected_results,
+ self.do_iter_changes(tree1, tree2))
def test_content_modification(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_2(tree2)
- root_id = tree1.inventory.root.file_id
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([('a-id', 'a', True, (True, True),
- (root_id, root_id), ('a', 'a'),
- ('file', 'file'), (False, False))],
- list(tree2._iter_changes(tree1)))
+ 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.do_iter_changes(tree1, tree2))
def test_meta_modification(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_3(tree2)
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([('c-id', 'b/c', False, (True, True),
- ('b-id', 'b-id'), ('c', 'c'), ('file', 'file'),
- (False, True))], list(tree2._iter_changes(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'),
+ (False, True))],
+ self.do_iter_changes(tree1, tree2))
def test_file_rename(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_4(tree2)
- root_id = tree1.inventory.root.file_id
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([('a-id', 'd', False, (True, True),
+ 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))], list(tree2._iter_changes(tree1)))
+ (False, False))],
+ self.do_iter_changes(tree1, tree2))
def test_file_rename_and_modification(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_5(tree2)
- root_id = tree1.inventory.root.file_id
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([('a-id', 'd', True, (True, True),
+ 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'),
- (False, False))], list(tree2._iter_changes(tree1)))
+ (False, False))],
+ self.do_iter_changes(tree1, tree2))
def test_file_rename_and_meta_modification(self):
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_6(tree2)
- root_id = tree1.inventory.root.file_id
- tree1.lock_read()
- self.addCleanup(tree1.unlock)
- tree2.lock_read()
- self.addCleanup(tree2.unlock)
- self.assertEqual([('c-id', 'e', False, (True, True),
- ('b-id', root_id), ('c', 'e'), ('file', 'file'),
- (False, True))], list(tree2._iter_changes(tree1)))
+ 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.do_iter_changes(tree1, tree2))
def test_unchanged_with_renames_and_modifications(self):
"""want_unchanged should generate a list of unchanged entries."""
tree1 = self.make_branch_and_tree('1')
tree2 = self.make_to_branch_and_tree('2')
tree1 = self.get_tree_no_parents_abc_content(tree1)
- tree2 = self.get_to_tree_no_parents_abc_content_5(tree2)
- root_id = tree1.inventory.root.file_id
+ tree2 = self.get_tree_no_parents_abc_content_5(tree2)
+ tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
+ root_id = tree1.path2id('')
tree1.lock_read()
self.addCleanup(tree1.unlock)
tree2.lock_read()
@@ -433,5 +479,4 @@
('a-id', 'd', True, (True, True),
(root_id, root_id), ('a', 'd'), ('file', 'file'),
(False, False)), unchanged('c-id')],
- list(tree2._iter_changes(tree1,
- include_unchanged=True)))
+ self.do_iter_changes(tree1, tree2, include_unchanged=True))
=== modified file 'bzrlib/tests/test_selftest.py'
--- a/bzrlib/tests/test_selftest.py 2007-02-17 03:34:50 +0000
+++ b/bzrlib/tests/test_selftest.py 2007-02-23 05:12:06 +0000
@@ -410,24 +410,24 @@
server2 = "b"
format1 = WorkingTreeFormat2()
format2 = WorkingTreeFormat3()
- formats = [(str, format1, format2, False, True),
- (int, format2, format1, False, True)]
+ formats = [(str, format1, format2, "converter1"),
+ (int, format2, format1, "converter2")]
adapter = InterTreeTestProviderAdapter(server1, server2, formats)
suite = adapter.adapt(input_test)
tests = list(iter(suite))
self.assertEqual(2, len(tests))
self.assertEqual(tests[0].intertree_class, formats[0][0])
self.assertEqual(tests[0].workingtree_format, formats[0][1])
- self.assertEqual(tests[0].workingtree_to_test_tree, formats[0][2])
- self.assertEqual(tests[0].workingtree_format_to, formats[0][3])
- self.assertEqual(tests[0].workingtree_to_test_tree_to, formats[0][4])
+ self.assertEqual(tests[0].workingtree_format_to, formats[0][2])
+ self.assertEqual(tests[0].mutable_trees_to_test_trees, formats[0][3])
+ self.assertEqual(tests[0].workingtree_to_test_tree, return_parameter)
self.assertEqual(tests[0].transport_server, server1)
self.assertEqual(tests[0].transport_readonly_server, server2)
self.assertEqual(tests[1].intertree_class, formats[1][0])
self.assertEqual(tests[1].workingtree_format, formats[1][1])
- self.assertEqual(tests[1].workingtree_to_test_tree, formats[1][2])
- self.assertEqual(tests[1].workingtree_format_to, formats[1][3])
- self.assertEqual(tests[1].workingtree_to_test_tree_to, formats[1][4])
+ self.assertEqual(tests[1].workingtree_format_to, formats[1][2])
+ self.assertEqual(tests[1].mutable_trees_to_test_trees, formats[1][3])
+ self.assertEqual(tests[1].workingtree_to_test_tree, return_parameter)
self.assertEqual(tests[1].transport_server, server1)
self.assertEqual(tests[1].transport_readonly_server, server2)
=== modified file 'bzrlib/tests/test_workingtree_4.py'
--- a/bzrlib/tests/test_workingtree_4.py 2007-02-23 03:01:08 +0000
+++ b/bzrlib/tests/test_workingtree_4.py 2007-02-23 05:12:06 +0000
@@ -284,6 +284,19 @@
lock_and_compare_all_current_dirstate(tree, 'lock_write')
lock_and_compare_all_current_dirstate(tree, 'lock_write')
+ def test_constructing_invalid_interdirstate_raises(self):
+ tree = self.make_workingtree()
+ rev_id = tree.commit('first post')
+ rev_id2 = tree.commit('second post')
+ rev_tree = tree.branch.repository.revision_tree(rev_id)
+ # Exception is not a great thing to raise, but this test is
+ # very short, and code is used to sanity check other tests, so
+ # a full error object is YAGNI.
+ self.assertRaises(
+ Exception, workingtree_4.InterDirStateTree, rev_tree, tree)
+ self.assertRaises(
+ Exception, workingtree_4.InterDirStateTree, tree, rev_tree)
+
def test_revtree_to_revtree_not_interdirstate(self):
# we should not get a dirstate optimiser for two repository sourced
# revtrees. we can't prove a negative, so we dont do exhaustive tests
=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py 2007-02-22 15:04:35 +0000
+++ b/bzrlib/tree.py 2007-02-23 05:12:06 +0000
@@ -87,10 +87,10 @@
include_root=include_root
)
- def _iter_changes(self, from_tree, include_unchanged=False,
+ def _iter_changes(self, from_tree, include_unchanged=False,
specific_file_ids=None, pb=None):
intertree = InterTree.get(from_tree, self)
- return intertree._iter_changes(from_tree, self, include_unchanged,
+ return intertree._iter_changes(include_unchanged,
specific_file_ids, pb)
def conflicts(self):
@@ -587,28 +587,29 @@
return delta._compare_trees(self.source, self.target, want_unchanged,
specific_file_ids, include_root)
- def _iter_changes(self, from_tree, to_tree, include_unchanged,
- specific_file_ids, pb):
+ def _iter_changes(self, include_unchanged=False,
+ specific_file_ids=None, pb=None):
"""Generate an iterator of changes between trees.
A tuple is returned:
(file_id, path, changed_content, versioned, parent, name, kind,
executable)
- Path is relative to the to_tree. changed_content is True if the file's
- content has changed. This includes changes to its kind, and to
+ 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.
versioned, parent, name, kind, executable are tuples of (from, to).
If a file is missing in a tree, its kind is None.
- Iteration is done in parent-to-child order, relative to the to_tree.
+ Iteration is done in parent-to-child order, relative to the target
+ tree.
"""
to_paths = {}
- from_entries_by_dir = list(from_tree.inventory.iter_entries_by_dir(
+ from_entries_by_dir = list(self.source.inventory.iter_entries_by_dir(
specific_file_ids=specific_file_ids))
from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
- to_entries_by_dir = list(to_tree.inventory.iter_entries_by_dir(
+ to_entries_by_dir = list(self.target.inventory.iter_entries_by_dir(
specific_file_ids=specific_file_ids))
num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
entry_count = 0
@@ -624,7 +625,7 @@
from_name = from_entry.name
from_parent = from_entry.parent_id
from_kind, from_executable, from_stat = \
- from_tree._comparison_data(from_entry, from_path)
+ self.source._comparison_data(from_entry, from_path)
entry_count += 1
else:
from_versioned = False
@@ -634,21 +635,21 @@
from_executable = None
versioned = (from_versioned, True)
to_kind, to_executable, to_stat = \
- to_tree._comparison_data(to_entry, to_path)
+ self.target._comparison_data(to_entry, to_path)
kind = (from_kind, to_kind)
if kind[0] != kind[1]:
changed_content = True
elif from_kind == 'file':
- from_size = from_tree._file_size(from_entry, from_stat)
- to_size = to_tree._file_size(to_entry, to_stat)
+ from_size = self.source._file_size(from_entry, from_stat)
+ to_size = self.target._file_size(to_entry, to_stat)
if from_size != to_size:
changed_content = True
- elif (from_tree.get_file_sha1(file_id, from_path, from_stat) !=
- to_tree.get_file_sha1(file_id, to_path, to_stat)):
+ elif (self.source.get_file_sha1(file_id, from_path, from_stat) !=
+ self.target.get_file_sha1(file_id, to_path, to_stat)):
changed_content = True
elif from_kind == 'symlink':
- if (from_tree.get_symlink_target(file_id) !=
- to_tree.get_symlink_target(file_id)):
+ if (self.source.get_symlink_target(file_id) !=
+ self.target.get_symlink_target(file_id)):
changed_content = True
parent = (from_parent, to_entry.parent_id)
name = (from_name, to_entry.name)
@@ -666,7 +667,7 @@
to_path = ''
else:
if from_entry.parent_id not in to_paths:
- get_to_path(from_tree.inventory[from_entry.parent_id])
+ 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
@@ -684,7 +685,7 @@
parent = (from_entry.parent_id, None)
name = (from_entry.name, None)
from_kind, from_executable, stat_value = \
- from_tree._comparison_data(from_entry, path)
+ self.source._comparison_data(from_entry, path)
kind = (from_kind, None)
executable = (from_executable, None)
changed_content = True
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-02-23 02:50:58 +0000
+++ b/bzrlib/workingtree_4.py 2007-02-23 05:12:06 +0000
@@ -1235,15 +1235,55 @@
class InterDirStateTree(InterTree):
"""Fast path optimiser for changes_from with dirstate trees."""
+ def __init__(self, source, target):
+ super(InterDirStateTree, self).__init__(source, target)
+ if not InterDirStateTree.is_compatible(source, target):
+ raise Exception, "invalid source %r and target %r" % (source, target)
+
@staticmethod
- def revision_tree_from_workingtree(tree):
- """Create a revision tree from a working tree."""
- revid = tree.commit('save tree', allow_pointless=True)
- return tree.branch.repository.revision_tree(revid)
- _from_tree_converter = revision_tree_from_workingtree
+ def make_source_parent_tree(source, target):
+ """Change the source tree into a parent of the target."""
+ revid = source.commit('record tree')
+ target.branch.repository.fetch(source.branch.repository, revid)
+ target.set_parent_ids([revid])
+ return target.basis_tree(), target
_matching_from_tree_format = WorkingTreeFormat4()
_matching_to_tree_format = WorkingTreeFormat4()
- _to_tree_converter = staticmethod(lambda x: x)
+ _test_mutable_trees_to_test_trees = make_source_parent_tree
+
+ @needs_read_lock
+ def compare(self, want_unchanged=False, specific_files=None,
+ extra_trees=None, require_versioned=False, include_root=False):
+ """Return the changes from source to target.
+
+ :return: A TreeDelta.
+ :param specific_files: An optional list of file paths to restrict the
+ comparison to. When mapping filenames to ids, all matches in all
+ trees (including optional extra_trees) are used, and all children of
+ matched directories are included.
+ :param want_unchanged: An optional boolean requesting the inclusion of
+ unchanged entries in the result.
+ :param extra_trees: An optional list of additional trees to use when
+ mapping the contents of specific_files (paths) to file_ids.
+ :param require_versioned: An optional boolean (defaults to False). When
+ supplied and True all the 'specific_files' must be versioned, or
+ a PathsNotVersionedError will be thrown.
+ """
+ # NB: show_status depends on being able to pass in non-versioned files
+ # and report them as unknown
+ trees = (self.source,)
+ if extra_trees is not None:
+ trees = trees + tuple(extra_trees)
+ # target is usually the newer tree:
+ specific_file_ids = self.target.paths2ids(specific_files, trees,
+ require_versioned=require_versioned)
+ from bzrlib import delta
+ if specific_files and not specific_file_ids:
+ # All files are unversioned, so just return an empty delta
+ # _compare_trees would think we want a complete delta
+ return delta.TreeDelta()
+ return delta._compare_trees(self.source, self.target, want_unchanged,
+ specific_file_ids, include_root)
@staticmethod
def is_compatible(source, target):
More information about the bazaar-commits
mailing list