Rev 2376: split out the WorkingTreeFormat4 tests into a separate test file in http://bazaar.launchpad.net/%7Ebzr/bzr/dirstate

John Arbash Meinel john at arbash-meinel.com
Fri Feb 23 03:02:18 GMT 2007


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

------------------------------------------------------------
revno: 2376
revision-id: john at arbash-meinel.com-20070223030108-da1z3sofjti2xulz
parent: john at arbash-meinel.com-20070223025058-dw62sga95cx45hvg
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate
timestamp: Thu 2007-02-22 21:01:08 -0600
message:
  split out the WorkingTreeFormat4 tests into a separate test file
  and clean up the imports of both files.
added:
  bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
modified:
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
  bzrlib/tests/test_workingtree.py testworkingtree.py-20051004024258-b88d0fe8f101d468
  bzrlib/tests/workingtree_implementations/test_workingtree.py test_workingtree.py-20060203003124-817757d3e31444fb
-------------- next part --------------
=== added file 'bzrlib/tests/test_workingtree_4.py'
--- a/bzrlib/tests/test_workingtree_4.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/test_workingtree_4.py	2007-02-23 03:01:08 +0000
@@ -0,0 +1,407 @@
+# Copyright (C) 2005, 2006 Canonical Ltd
+# Authors:  Robert Collins <robert.collins at canonical.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Tests for WorkingTreeFormat4"""
+
+from bzrlib import (
+    bzrdir,
+    dirstate,
+    errors,
+    workingtree_4,
+    )
+from bzrlib.lockdir import LockDir
+from bzrlib.tests import TestCaseWithTransport, TestSkipped
+from bzrlib.tree import InterTree
+
+
+class TestWorkingTreeFormat4(TestCaseWithTransport):
+    """Tests specific to WorkingTreeFormat4."""
+
+    def test_disk_layout(self):
+        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
+        control.create_repository()
+        control.create_branch()
+        tree = workingtree_4.WorkingTreeFormat4().initialize(control)
+        # we want:
+        # format 'Bazaar Working Tree format 4'
+        # stat-cache = ??
+        t = control.get_workingtree_transport(None)
+        self.assertEqualDiff('Bazaar Working Tree format 4\n',
+                             t.get('format').read())
+        self.assertEqualDiff('### bzr hashcache v5\n',
+                             t.get('stat-cache').read())
+        self.assertFalse(t.has('inventory.basis'))
+        # no last-revision file means 'None' or 'NULLREVISION'
+        self.assertFalse(t.has('last-revision'))
+        # TODO RBC 20060210 do a commit, check the inventory.basis is created 
+        # correctly and last-revision file becomes present.
+        # manually make a dirstate toc check the format is as desired.
+        state = dirstate.DirState.on_file(t.local_abspath('dirstate'))
+        state.lock_read()
+        try:
+            self.assertEqual([], state.get_parent_ids())
+        finally:
+            state.unlock()
+
+    def test_uses_lockdir(self):
+        """WorkingTreeFormat4 uses its own LockDir:
+            
+            - lock is a directory
+            - when the WorkingTree is locked, LockDir can see that
+        """
+        # this test could be factored into a subclass of tests common to both
+        # format 3 and 4, but for now its not much of an issue as there is only one in common.
+        t = self.get_transport()
+        tree = self.make_workingtree()
+        self.assertIsDirectory('.bzr', t)
+        self.assertIsDirectory('.bzr/checkout', t)
+        self.assertIsDirectory('.bzr/checkout/lock', t)
+        our_lock = LockDir(t, '.bzr/checkout/lock')
+        self.assertEquals(our_lock.peek(), None)
+        tree.lock_write()
+        self.assertTrue(our_lock.peek())
+        tree.unlock()
+        self.assertEquals(our_lock.peek(), None)
+
+    def make_workingtree(self, relpath=''):
+        url = self.get_url(relpath)
+        if relpath:
+            self.build_tree([relpath + '/'])
+        dir = bzrdir.BzrDirMetaFormat1().initialize(url)
+        repo = dir.create_repository()
+        branch = dir.create_branch()
+        try:
+            return workingtree_4.WorkingTreeFormat4().initialize(dir)
+        except errors.NotLocalUrl:
+            raise TestSkipped('Not a local URL')
+
+    # TODO: test that dirstate also stores & retrieves the parent list of 
+    # workingtree-parent revisions, including when they have multiple parents.
+    # (in other words, the case when we're constructing a merge of 
+    # revisions which are themselves merges.)
+
+    # The simplest case is that the the workingtree's primary 
+    # parent tree can be retrieved.  This is required for all WorkingTrees, 
+    # and covered by the generic tests.
+
+    def test_dirstate_stores_all_parent_inventories(self):
+        tree = self.make_workingtree()
+
+        # We're going to build in tree a working tree 
+        # with three parent trees, with some files in common.  
+    
+        # We really don't want to do commit or merge in the new dirstate-based
+        # tree, because that might not work yet.  So instead we build
+        # revisions elsewhere and pull them across, doing by hand part of the
+        # work that merge would do.
+
+        subtree = self.make_branch_and_tree('subdir')
+        # writelock the tree so its repository doesn't get readlocked by
+        # the revision tree locks. This works around the bug where we dont
+        # permit lock upgrading.
+        subtree.lock_write()
+        self.addCleanup(subtree.unlock)
+        self.build_tree(['subdir/file-a',])
+        subtree.add(['file-a'], ['id-a'])
+        rev1 = subtree.commit('commit in subdir')
+
+        subtree2 = subtree.bzrdir.sprout('subdir2').open_workingtree()
+        self.build_tree(['subdir2/file-b'])
+        subtree2.add(['file-b'], ['id-b'])
+        rev2 = subtree2.commit('commit in subdir2')
+
+        subtree.flush()
+        subtree.merge_from_branch(subtree2.branch)
+        rev3 = subtree.commit('merge from subdir2')
+
+        repo = tree.branch.repository
+        repo.fetch(subtree.branch.repository, rev3)
+        # will also pull the others...
+
+        # create repository based revision trees
+        rev1_revtree = subtree.branch.repository.revision_tree(rev1)
+        rev2_revtree = subtree2.branch.repository.revision_tree(rev2)
+        rev3_revtree = subtree.branch.repository.revision_tree(rev3)
+        # tree doesn't contain a text merge yet but we'll just
+        # set the parents as if a merge had taken place. 
+        # this should cause the tree data to be folded into the 
+        # dirstate.
+        tree.set_parent_trees([
+            (rev1, rev1_revtree),
+            (rev2, rev2_revtree),
+            (rev3, rev3_revtree), ])
+
+        # create tree-sourced revision trees
+        rev1_tree = tree.revision_tree(rev1)
+        rev1_tree.lock_read()
+        self.addCleanup(rev1_tree.unlock)
+        rev2_tree = tree.revision_tree(rev2)
+        rev2_tree.lock_read()
+        self.addCleanup(rev2_tree.unlock)
+        rev3_tree = tree.revision_tree(rev3)
+        rev3_tree.lock_read()
+        self.addCleanup(rev3_tree.unlock)
+
+        # now we should be able to get them back out
+        self.assertTreesEqual(rev1_revtree, rev1_tree)
+        self.assertTreesEqual(rev2_revtree, rev2_tree)
+        self.assertTreesEqual(rev3_revtree, rev3_tree)
+
+    def test_dirstate_doesnt_read_parents_from_repo_when_setting(self):
+        """Setting parent trees on a dirstate working tree takes
+        the trees it's given and doesn't need to read them from the 
+        repository.
+        """
+        tree = self.make_workingtree()
+
+        subtree = self.make_branch_and_tree('subdir')
+        rev1 = subtree.commit('commit in subdir')
+        rev1_tree = subtree.basis_tree()
+        rev1_tree.lock_read()
+        self.addCleanup(rev1_tree.unlock)
+
+        tree.branch.pull(subtree.branch)
+
+        # break the repository's legs to make sure it only uses the trees
+        # it's given; any calls to forbidden methods will raise an 
+        # AssertionError
+        repo = tree.branch.repository
+        repo.get_revision = self.fail
+        repo.get_inventory = self.fail
+        repo.get_inventory_xml = self.fail
+        # try to set the parent trees.
+        tree.set_parent_trees([(rev1, rev1_tree)])
+
+    def test_dirstate_doesnt_read_from_repo_when_returning_cache_tree(self):
+        """Getting parent trees from a dirstate tree does not read from the 
+        repos inventory store. This is an important part of the dirstate
+        performance optimisation work.
+        """
+        tree = self.make_workingtree()
+
+        subtree = self.make_branch_and_tree('subdir')
+        # writelock the tree so its repository doesn't get readlocked by
+        # the revision tree locks. This works around the bug where we dont
+        # permit lock upgrading.
+        subtree.lock_write()
+        self.addCleanup(subtree.unlock)
+        rev1 = subtree.commit('commit in subdir')
+        rev1_tree = subtree.basis_tree()
+        rev1_tree.lock_read()
+        rev1_tree.inventory
+        self.addCleanup(rev1_tree.unlock)
+        rev2 = subtree.commit('second commit in subdir', allow_pointless=True)
+        rev2_tree = subtree.basis_tree()
+        rev2_tree.lock_read()
+        rev2_tree.inventory
+        self.addCleanup(rev2_tree.unlock)
+
+        tree.branch.pull(subtree.branch)
+
+        # break the repository's legs to make sure it only uses the trees
+        # it's given; any calls to forbidden methods will raise an 
+        # AssertionError
+        repo = tree.branch.repository
+        # dont uncomment this: the revision object must be accessed to 
+        # answer 'get_parent_ids' for the revision tree- dirstate does not 
+        # cache the parents of a parent tree at this point.
+        #repo.get_revision = self.fail
+        repo.get_inventory = self.fail
+        repo.get_inventory_xml = self.fail
+        # set the parent trees.
+        tree.set_parent_trees([(rev1, rev1_tree), (rev2, rev2_tree)])
+        # read the first tree
+        result_rev1_tree = tree.revision_tree(rev1)
+        # read the second
+        result_rev2_tree = tree.revision_tree(rev2)
+        # compare - there should be no differences between the handed and 
+        # returned trees
+        self.assertTreesEqual(rev1_tree, result_rev1_tree)
+        self.assertTreesEqual(rev2_tree, result_rev2_tree)
+
+    def test_dirstate_doesnt_cache_non_parent_trees(self):
+        """Getting parent trees from a dirstate tree does not read from the 
+        repos inventory store. This is an important part of the dirstate
+        performance optimisation work.
+        """
+        tree = self.make_workingtree()
+
+        # make a tree that we can try for, which is able to be returned but
+        # must not be
+        subtree = self.make_branch_and_tree('subdir')
+        rev1 = subtree.commit('commit in subdir')
+        tree.branch.pull(subtree.branch)
+        # check it fails
+        self.assertRaises(errors.NoSuchRevision, tree.revision_tree, rev1)
+
+    def test_no_dirstate_outside_lock(self):
+        # temporary test until the code is mature enough to test from outside.
+        """Getting a dirstate object fails if there is no lock."""
+        def lock_and_call_current_dirstate(tree, lock_method):
+            getattr(tree, lock_method)()
+            tree.current_dirstate()
+            tree.unlock()
+        tree = self.make_workingtree()
+        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
+        lock_and_call_current_dirstate(tree, 'lock_read')
+        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
+        lock_and_call_current_dirstate(tree, 'lock_write')
+        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
+        lock_and_call_current_dirstate(tree, 'lock_tree_write')
+        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
+
+    def test_new_dirstate_on_new_lock(self):
+        # until we have detection for when a dirstate can be reused, we
+        # want to reparse dirstate on every new lock.
+        known_dirstates = set()
+        def lock_and_compare_all_current_dirstate(tree, lock_method):
+            getattr(tree, lock_method)()
+            state = tree.current_dirstate()
+            self.assertFalse(state in known_dirstates)
+            known_dirstates.add(state)
+            tree.unlock()
+        tree = self.make_workingtree()
+        # lock twice with each type to prevent silly per-lock-type bugs.
+        # each lock and compare looks for a unique state object.
+        lock_and_compare_all_current_dirstate(tree, 'lock_read')
+        lock_and_compare_all_current_dirstate(tree, 'lock_read')
+        lock_and_compare_all_current_dirstate(tree, 'lock_tree_write')
+        lock_and_compare_all_current_dirstate(tree, 'lock_tree_write')
+        lock_and_compare_all_current_dirstate(tree, 'lock_write')
+        lock_and_compare_all_current_dirstate(tree, 'lock_write')
+
+    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
+        # of all formats; though that could be written in the future it doesn't
+        # seem well worth it.
+        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)
+        rev_tree2 = tree.branch.repository.revision_tree(rev_id2)
+        optimiser = InterTree.get(rev_tree, rev_tree2)
+        self.assertIsInstance(optimiser, InterTree)
+        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
+        optimiser = InterTree.get(rev_tree2, rev_tree)
+        self.assertIsInstance(optimiser, InterTree)
+        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
+
+    def test_revtree_not_in_dirstate_to_dirstate_not_interdirstate(self):
+        # we should not get a dirstate optimiser when the revision id for of
+        # the source is not in the dirstate of the target.
+        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)
+        tree.lock_read()
+        optimiser = InterTree.get(rev_tree, tree)
+        self.assertIsInstance(optimiser, InterTree)
+        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
+        optimiser = InterTree.get(tree, rev_tree)
+        self.assertIsInstance(optimiser, InterTree)
+        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
+        tree.unlock()
+
+    def test_empty_basis_to_dirstate_tree(self):
+        # we should get a InterDirStateTree for doing
+        # 'changes_from' from the first basis dirstate revision tree to a
+        # WorkingTree4.
+        tree = self.make_workingtree()
+        tree.lock_read()
+        basis_tree = tree.basis_tree()
+        basis_tree.lock_read()
+        optimiser = InterTree.get(basis_tree, tree)
+        tree.unlock()
+        basis_tree.unlock()
+        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
+
+    def test_nonempty_basis_to_dirstate_tree(self):
+        # we should get a InterDirStateTree for doing
+        # 'changes_from' from a non-null basis dirstate revision tree to a
+        # WorkingTree4.
+        tree = self.make_workingtree()
+        tree.commit('first post')
+        tree.lock_read()
+        basis_tree = tree.basis_tree()
+        basis_tree.lock_read()
+        optimiser = InterTree.get(basis_tree, tree)
+        tree.unlock()
+        basis_tree.unlock()
+        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
+
+    def test_empty_basis_revtree_to_dirstate_tree(self):
+        # we should get a InterDirStateTree for doing
+        # 'changes_from' from an empty repository based rev tree to a
+        # WorkingTree4.
+        tree = self.make_workingtree()
+        tree.lock_read()
+        basis_tree = tree.branch.repository.revision_tree(tree.last_revision())
+        basis_tree.lock_read()
+        optimiser = InterTree.get(basis_tree, tree)
+        tree.unlock()
+        basis_tree.unlock()
+        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
+
+    def test_nonempty_basis_revtree_to_dirstate_tree(self):
+        # we should get a InterDirStateTree for doing
+        # 'changes_from' from a non-null repository based rev tree to a
+        # WorkingTree4.
+        tree = self.make_workingtree()
+        tree.commit('first post')
+        tree.lock_read()
+        basis_tree = tree.branch.repository.revision_tree(tree.last_revision())
+        basis_tree.lock_read()
+        optimiser = InterTree.get(basis_tree, tree)
+        tree.unlock()
+        basis_tree.unlock()
+        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
+
+    def test_tree_to_basis_in_other_tree(self):
+        # we should get a InterDirStateTree when
+        # the source revid is in the dirstate object of the target and
+        # the dirstates are different. This is largely covered by testing
+        # with repository revtrees, so is just for extra confidence.
+        tree = self.make_workingtree('a')
+        tree.commit('first post')
+        tree2 = self.make_workingtree('b')
+        tree2.pull(tree.branch)
+        basis_tree = tree.basis_tree()
+        tree2.lock_read()
+        basis_tree.lock_read()
+        optimiser = InterTree.get(basis_tree, tree2)
+        tree2.unlock()
+        basis_tree.unlock()
+        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
+
+    def test_merged_revtree_to_tree(self):
+        # we should get a InterDirStateTree when
+        # the source tree is a merged tree present in the dirstate of target.
+        tree = self.make_workingtree('a')
+        tree.commit('first post')
+        tree.commit('tree 1 commit 2')
+        tree2 = self.make_workingtree('b')
+        tree2.pull(tree.branch)
+        tree2.commit('tree 2 commit 2')
+        tree.merge_from_branch(tree2.branch)
+        second_parent_tree = tree.revision_tree(tree.get_parent_ids()[1])
+        second_parent_tree.lock_read()
+        tree.lock_read()
+        optimiser = InterTree.get(second_parent_tree, tree)
+        tree.unlock()
+        second_parent_tree.unlock()
+        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2007-02-17 03:34:50 +0000
+++ b/bzrlib/tests/__init__.py	2007-02-23 03:01:08 +0000
@@ -1856,6 +1856,7 @@
                    'bzrlib.tests.test_weave',
                    'bzrlib.tests.test_whitebox',
                    'bzrlib.tests.test_workingtree',
+                   'bzrlib.tests.test_workingtree_4',
                    'bzrlib.tests.test_wsgi',
                    'bzrlib.tests.test_xml',
                    ]

=== modified file 'bzrlib/tests/test_workingtree.py'
--- a/bzrlib/tests/test_workingtree.py	2007-02-23 02:50:58 +0000
+++ b/bzrlib/tests/test_workingtree.py	2007-02-23 03:01:08 +0000
@@ -18,28 +18,27 @@
 from cStringIO import StringIO
 import os
 
-from bzrlib import dirstate, ignores
-import bzrlib
+from bzrlib import (
+    bzrdir,
+    conflicts,
+    errors,
+    workingtree,
+    )
 from bzrlib.branch import Branch
-from bzrlib import bzrdir, conflicts, errors, workingtree, workingtree_4
 from bzrlib.bzrdir import BzrDir
-from bzrlib.errors import NotBranchError, NotVersionedError
 from bzrlib.lockdir import LockDir
 from bzrlib.mutabletree import needs_tree_write_lock
-from bzrlib.osutils import pathjoin, getcwd, has_symlinks
 from bzrlib.symbol_versioning import zero_thirteen
 from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
-from bzrlib.trace import mutter
 from bzrlib.transport import get_transport
-from bzrlib.tree import InterTree
 from bzrlib.workingtree import (
     TreeEntry,
     TreeDirectory,
     TreeFile,
     TreeLink,
-    WorkingTree,
     )
 
+
 class TestTreeDirectory(TestCaseWithTransport):
 
     def test_kind_character(self):
@@ -227,391 +226,12 @@
         self.assertEqual([], tree.get_parent_ids())
 
 
-class TestWorkingTreeFormat4(TestCaseWithTransport):
-    """Tests specific to WorkingTreeFormat4."""
-
-    def test_disk_layout(self):
-        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
-        control.create_repository()
-        control.create_branch()
-        tree = workingtree_4.WorkingTreeFormat4().initialize(control)
-        # we want:
-        # format 'Bazaar Working Tree format 4'
-        # stat-cache = ??
-        t = control.get_workingtree_transport(None)
-        self.assertEqualDiff('Bazaar Working Tree format 4\n',
-                             t.get('format').read())
-        self.assertEqualDiff('### bzr hashcache v5\n',
-                             t.get('stat-cache').read())
-        self.assertFalse(t.has('inventory.basis'))
-        # no last-revision file means 'None' or 'NULLREVISION'
-        self.assertFalse(t.has('last-revision'))
-        # TODO RBC 20060210 do a commit, check the inventory.basis is created 
-        # correctly and last-revision file becomes present.
-        # manually make a dirstate toc check the format is as desired.
-        state = dirstate.DirState.on_file(t.local_abspath('dirstate'))
-        state.lock_read()
-        try:
-            self.assertEqual([], state.get_parent_ids())
-        finally:
-            state.unlock()
-
-    def test_uses_lockdir(self):
-        """WorkingTreeFormat4 uses its own LockDir:
-            
-            - lock is a directory
-            - when the WorkingTree is locked, LockDir can see that
-        """
-        # this test could be factored into a subclass of tests common to both
-        # format 3 and 4, but for now its not much of an issue as there is only one in common.
-        t = self.get_transport()
-        tree = self.make_workingtree()
-        self.assertIsDirectory('.bzr', t)
-        self.assertIsDirectory('.bzr/checkout', t)
-        self.assertIsDirectory('.bzr/checkout/lock', t)
-        our_lock = LockDir(t, '.bzr/checkout/lock')
-        self.assertEquals(our_lock.peek(), None)
-        tree.lock_write()
-        self.assertTrue(our_lock.peek())
-        tree.unlock()
-        self.assertEquals(our_lock.peek(), None)
-
-    def make_workingtree(self, relpath=''):
-        url = self.get_url(relpath)
-        if relpath:
-            self.build_tree([relpath + '/'])
-        dir = bzrdir.BzrDirMetaFormat1().initialize(url)
-        repo = dir.create_repository()
-        branch = dir.create_branch()
-        try:
-            return workingtree_4.WorkingTreeFormat4().initialize(dir)
-        except errors.NotLocalUrl:
-            raise TestSkipped('Not a local URL')
-
-    # TODO: test that dirstate also stores & retrieves the parent list of 
-    # workingtree-parent revisions, including when they have multiple parents.
-    # (in other words, the case when we're constructing a merge of 
-    # revisions which are themselves merges.)
-
-    # The simplest case is that the the workingtree's primary 
-    # parent tree can be retrieved.  This is required for all WorkingTrees, 
-    # and covered by the generic tests.
-
-    def test_dirstate_stores_all_parent_inventories(self):
-        tree = self.make_workingtree()
-
-        # We're going to build in tree a working tree 
-        # with three parent trees, with some files in common.  
-    
-        # We really don't want to do commit or merge in the new dirstate-based
-        # tree, because that might not work yet.  So instead we build
-        # revisions elsewhere and pull them across, doing by hand part of the
-        # work that merge would do.
-
-        subtree = self.make_branch_and_tree('subdir')
-        # writelock the tree so its repository doesn't get readlocked by
-        # the revision tree locks. This works around the bug where we dont
-        # permit lock upgrading.
-        subtree.lock_write()
-        self.addCleanup(subtree.unlock)
-        self.build_tree(['subdir/file-a',])
-        subtree.add(['file-a'], ['id-a'])
-        rev1 = subtree.commit('commit in subdir')
-
-        subtree2 = subtree.bzrdir.sprout('subdir2').open_workingtree()
-        self.build_tree(['subdir2/file-b'])
-        subtree2.add(['file-b'], ['id-b'])
-        rev2 = subtree2.commit('commit in subdir2')
-
-        subtree.flush()
-        subtree.merge_from_branch(subtree2.branch)
-        rev3 = subtree.commit('merge from subdir2')
-
-        repo = tree.branch.repository
-        repo.fetch(subtree.branch.repository, rev3)
-        # will also pull the others...
-
-        # create repository based revision trees
-        rev1_revtree = subtree.branch.repository.revision_tree(rev1)
-        rev2_revtree = subtree2.branch.repository.revision_tree(rev2)
-        rev3_revtree = subtree.branch.repository.revision_tree(rev3)
-        # tree doesn't contain a text merge yet but we'll just
-        # set the parents as if a merge had taken place. 
-        # this should cause the tree data to be folded into the 
-        # dirstate.
-        tree.set_parent_trees([
-            (rev1, rev1_revtree),
-            (rev2, rev2_revtree),
-            (rev3, rev3_revtree), ])
-
-        # create tree-sourced revision trees
-        rev1_tree = tree.revision_tree(rev1)
-        rev1_tree.lock_read()
-        self.addCleanup(rev1_tree.unlock)
-        rev2_tree = tree.revision_tree(rev2)
-        rev2_tree.lock_read()
-        self.addCleanup(rev2_tree.unlock)
-        rev3_tree = tree.revision_tree(rev3)
-        rev3_tree.lock_read()
-        self.addCleanup(rev3_tree.unlock)
-
-        # now we should be able to get them back out
-        self.assertTreesEqual(rev1_revtree, rev1_tree)
-        self.assertTreesEqual(rev2_revtree, rev2_tree)
-        self.assertTreesEqual(rev3_revtree, rev3_tree)
-
-    def test_dirstate_doesnt_read_parents_from_repo_when_setting(self):
-        """Setting parent trees on a dirstate working tree takes
-        the trees it's given and doesn't need to read them from the 
-        repository.
-        """
-        tree = self.make_workingtree()
-
-        subtree = self.make_branch_and_tree('subdir')
-        rev1 = subtree.commit('commit in subdir')
-        rev1_tree = subtree.basis_tree()
-        rev1_tree.lock_read()
-        self.addCleanup(rev1_tree.unlock)
-
-        tree.branch.pull(subtree.branch)
-
-        # break the repository's legs to make sure it only uses the trees
-        # it's given; any calls to forbidden methods will raise an 
-        # AssertionError
-        repo = tree.branch.repository
-        repo.get_revision = self.fail
-        repo.get_inventory = self.fail
-        repo.get_inventory_xml = self.fail
-        # try to set the parent trees.
-        tree.set_parent_trees([(rev1, rev1_tree)])
-
-    def test_dirstate_doesnt_read_from_repo_when_returning_cache_tree(self):
-        """Getting parent trees from a dirstate tree does not read from the 
-        repos inventory store. This is an important part of the dirstate
-        performance optimisation work.
-        """
-        tree = self.make_workingtree()
-
-        subtree = self.make_branch_and_tree('subdir')
-        # writelock the tree so its repository doesn't get readlocked by
-        # the revision tree locks. This works around the bug where we dont
-        # permit lock upgrading.
-        subtree.lock_write()
-        self.addCleanup(subtree.unlock)
-        rev1 = subtree.commit('commit in subdir')
-        rev1_tree = subtree.basis_tree()
-        rev1_tree.lock_read()
-        rev1_tree.inventory
-        self.addCleanup(rev1_tree.unlock)
-        rev2 = subtree.commit('second commit in subdir', allow_pointless=True)
-        rev2_tree = subtree.basis_tree()
-        rev2_tree.lock_read()
-        rev2_tree.inventory
-        self.addCleanup(rev2_tree.unlock)
-
-        tree.branch.pull(subtree.branch)
-
-        # break the repository's legs to make sure it only uses the trees
-        # it's given; any calls to forbidden methods will raise an 
-        # AssertionError
-        repo = tree.branch.repository
-        # dont uncomment this: the revision object must be accessed to 
-        # answer 'get_parent_ids' for the revision tree- dirstate does not 
-        # cache the parents of a parent tree at this point.
-        #repo.get_revision = self.fail
-        repo.get_inventory = self.fail
-        repo.get_inventory_xml = self.fail
-        # set the parent trees.
-        tree.set_parent_trees([(rev1, rev1_tree), (rev2, rev2_tree)])
-        # read the first tree
-        result_rev1_tree = tree.revision_tree(rev1)
-        # read the second
-        result_rev2_tree = tree.revision_tree(rev2)
-        # compare - there should be no differences between the handed and 
-        # returned trees
-        self.assertTreesEqual(rev1_tree, result_rev1_tree)
-        self.assertTreesEqual(rev2_tree, result_rev2_tree)
-
-    def test_dirstate_doesnt_cache_non_parent_trees(self):
-        """Getting parent trees from a dirstate tree does not read from the 
-        repos inventory store. This is an important part of the dirstate
-        performance optimisation work.
-        """
-        tree = self.make_workingtree()
-
-        # make a tree that we can try for, which is able to be returned but
-        # must not be
-        subtree = self.make_branch_and_tree('subdir')
-        rev1 = subtree.commit('commit in subdir')
-        tree.branch.pull(subtree.branch)
-        # check it fails
-        self.assertRaises(errors.NoSuchRevision, tree.revision_tree, rev1)
-
-    def test_no_dirstate_outside_lock(self):
-        # temporary test until the code is mature enough to test from outside.
-        """Getting a dirstate object fails if there is no lock."""
-        def lock_and_call_current_dirstate(tree, lock_method):
-            getattr(tree, lock_method)()
-            tree.current_dirstate()
-            tree.unlock()
-        tree = self.make_workingtree()
-        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
-        lock_and_call_current_dirstate(tree, 'lock_read')
-        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
-        lock_and_call_current_dirstate(tree, 'lock_write')
-        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
-        lock_and_call_current_dirstate(tree, 'lock_tree_write')
-        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
-
-    def test_new_dirstate_on_new_lock(self):
-        # until we have detection for when a dirstate can be reused, we
-        # want to reparse dirstate on every new lock.
-        known_dirstates = set()
-        def lock_and_compare_all_current_dirstate(tree, lock_method):
-            getattr(tree, lock_method)()
-            state = tree.current_dirstate()
-            self.assertFalse(state in known_dirstates)
-            known_dirstates.add(state)
-            tree.unlock()
-        tree = self.make_workingtree()
-        # lock twice with each type to prevent silly per-lock-type bugs.
-        # each lock and compare looks for a unique state object.
-        lock_and_compare_all_current_dirstate(tree, 'lock_read')
-        lock_and_compare_all_current_dirstate(tree, 'lock_read')
-        lock_and_compare_all_current_dirstate(tree, 'lock_tree_write')
-        lock_and_compare_all_current_dirstate(tree, 'lock_tree_write')
-        lock_and_compare_all_current_dirstate(tree, 'lock_write')
-        lock_and_compare_all_current_dirstate(tree, 'lock_write')
-
-    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
-        # of all formats; though that could be written in the future it doesn't
-        # seem well worth it.
-        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)
-        rev_tree2 = tree.branch.repository.revision_tree(rev_id2)
-        optimiser = InterTree.get(rev_tree, rev_tree2)
-        self.assertIsInstance(optimiser, InterTree)
-        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
-        optimiser = InterTree.get(rev_tree2, rev_tree)
-        self.assertIsInstance(optimiser, InterTree)
-        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
-
-    def test_revtree_not_in_dirstate_to_dirstate_not_interdirstate(self):
-        # we should not get a dirstate optimiser when the revision id for of
-        # the source is not in the dirstate of the target.
-        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)
-        tree.lock_read()
-        optimiser = InterTree.get(rev_tree, tree)
-        self.assertIsInstance(optimiser, InterTree)
-        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
-        optimiser = InterTree.get(tree, rev_tree)
-        self.assertIsInstance(optimiser, InterTree)
-        self.assertFalse(isinstance(optimiser, workingtree_4.InterDirStateTree))
-        tree.unlock()
-
-    def test_empty_basis_to_dirstate_tree(self):
-        # we should get a InterDirStateTree for doing
-        # 'changes_from' from the first basis dirstate revision tree to a
-        # WorkingTree4.
-        tree = self.make_workingtree()
-        tree.lock_read()
-        basis_tree = tree.basis_tree()
-        basis_tree.lock_read()
-        optimiser = InterTree.get(basis_tree, tree)
-        tree.unlock()
-        basis_tree.unlock()
-        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
-
-    def test_nonempty_basis_to_dirstate_tree(self):
-        # we should get a InterDirStateTree for doing
-        # 'changes_from' from a non-null basis dirstate revision tree to a
-        # WorkingTree4.
-        tree = self.make_workingtree()
-        tree.commit('first post')
-        tree.lock_read()
-        basis_tree = tree.basis_tree()
-        basis_tree.lock_read()
-        optimiser = InterTree.get(basis_tree, tree)
-        tree.unlock()
-        basis_tree.unlock()
-        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
-
-    def test_empty_basis_revtree_to_dirstate_tree(self):
-        # we should get a InterDirStateTree for doing
-        # 'changes_from' from an empty repository based rev tree to a
-        # WorkingTree4.
-        tree = self.make_workingtree()
-        tree.lock_read()
-        basis_tree = tree.branch.repository.revision_tree(tree.last_revision())
-        basis_tree.lock_read()
-        optimiser = InterTree.get(basis_tree, tree)
-        tree.unlock()
-        basis_tree.unlock()
-        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
-
-    def test_nonempty_basis_revtree_to_dirstate_tree(self):
-        # we should get a InterDirStateTree for doing
-        # 'changes_from' from a non-null repository based rev tree to a
-        # WorkingTree4.
-        tree = self.make_workingtree()
-        tree.commit('first post')
-        tree.lock_read()
-        basis_tree = tree.branch.repository.revision_tree(tree.last_revision())
-        basis_tree.lock_read()
-        optimiser = InterTree.get(basis_tree, tree)
-        tree.unlock()
-        basis_tree.unlock()
-        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
-
-    def test_tree_to_basis_in_other_tree(self):
-        # we should get a InterDirStateTree when
-        # the source revid is in the dirstate object of the target and
-        # the dirstates are different. This is largely covered by testing
-        # with repository revtrees, so is just for extra confidence.
-        tree = self.make_workingtree('a')
-        tree.commit('first post')
-        tree2 = self.make_workingtree('b')
-        tree2.pull(tree.branch)
-        basis_tree = tree.basis_tree()
-        tree2.lock_read()
-        basis_tree.lock_read()
-        optimiser = InterTree.get(basis_tree, tree2)
-        tree2.unlock()
-        basis_tree.unlock()
-        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
-
-    def test_merged_revtree_to_tree(self):
-        # we should get a InterDirStateTree when
-        # the source tree is a merged tree present in the dirstate of target.
-        tree = self.make_workingtree('a')
-        tree.commit('first post')
-        tree.commit('tree 1 commit 2')
-        tree2 = self.make_workingtree('b')
-        tree2.pull(tree.branch)
-        tree2.commit('tree 2 commit 2')
-        tree.merge_from_branch(tree2.branch)
-        second_parent_tree = tree.revision_tree(tree.get_parent_ids()[1])
-        second_parent_tree.lock_read()
-        tree.lock_read()
-        optimiser = InterTree.get(second_parent_tree, tree)
-        tree.unlock()
-        second_parent_tree.unlock()
-        self.assertIsInstance(optimiser, workingtree_4.InterDirStateTree)
-
-
 class TestFormat2WorkingTree(TestCaseWithTransport):
     """Tests that are specific to format 2 trees."""
 
     def create_format2_tree(self, url):
         return self.make_branch_and_tree(
-            url, format=bzrlib.bzrdir.BzrDirFormat6())
+            url, format=bzrdir.BzrDirFormat6())
 
     def test_conflicts(self):
         # test backwards compatability

=== modified file 'bzrlib/tests/workingtree_implementations/test_workingtree.py'
--- a/bzrlib/tests/workingtree_implementations/test_workingtree.py	2007-02-23 02:24:10 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_workingtree.py	2007-02-23 03:01:08 +0000
@@ -594,6 +594,7 @@
         # XXX: jam 20070222 currently DirStateRevisionTree fail if you change the
         #      WorkingTree underneath them before they are accessed. So
         #      instead, let's go back to the repository for now.
+        # base = tree.basis_tree()
         base = tree.branch.repository.revision_tree(tree.last_revision())
         bzrdir.BzrDir.open("mine").sprout("other")
         file('other/bloo', 'wb').write('two')



More information about the bazaar-commits mailing list