Rev 2448: Implement upgrade for working trees. in http://bazaar.launchpad.net/~bzr/bzr/dirstate

Robert Collins robertc at robertcollins.net
Tue Mar 6 00:26:34 GMT 2007


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

------------------------------------------------------------
revno: 2448
revision-id: robertc at robertcollins.net-20070306002528-zkvfpjt0dwzwz85l
parent: john at arbash-meinel.com-20070305212803-wowsk4ytx1x836tv
parent: robertc at robertcollins.net-20070305091133-bjk279of5h029hpg
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate.dogfood
timestamp: Tue 2007-03-06 11:25:28 +1100
message:
  Implement upgrade for working trees.
modified:
  bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
  bzrlib/tests/test_bzrdir.py    test_bzrdir.py-20060131065654-deba40eef51cf220
  bzrlib/tests/test_upgrade.py   test_upgrade.py-20051004040251-555fe1d2bae1bc71
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
    ------------------------------------------------------------
    revno: 2446.1.1
    merged: robertc at robertcollins.net-20070305091133-bjk279of5h029hpg
    parent: mbp at sourcefrog.net-20070305064521-2ewp1qiqp3ils4ff
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: dirstate.dogfood
    timestamp: Mon 2007-03-05 20:11:33 +1100
    message:
      Implement upgrade for working trees.
=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py	2007-03-02 09:44:41 +0000
+++ b/bzrlib/bzrdir.py	2007-03-05 09:11:33 +0000
@@ -49,6 +49,8 @@
     urlutils,
     xml4,
     xml5,
+    workingtree,
+    workingtree_4,
     )
 from bzrlib.osutils import (
     safe_unicode,
@@ -1058,11 +1060,17 @@
         try:
             if not isinstance(self.open_branch()._format,
                               format.get_branch_format().__class__):
-                # the repository needs an upgrade.
-                return True
-        except errors.NotBranchError:
-            pass
-        # currently there are no other possible conversions for meta1 formats.
+                # the branch needs an upgrade.
+                return True
+        except errors.NotBranchError:
+            pass
+        try:
+            if not isinstance(self.open_workingtree()._format,
+                              format.workingtree_format.__class__):
+                # the workingtree needs an upgrade.
+                return True
+        except errors.NotBranchError:
+            pass
         return False
 
     def open_branch(self, unsupported=False):
@@ -2063,6 +2071,8 @@
         except errors.NotBranchError:
             pass
         else:
+            # TODO: conversions of Branch and Tree should be done by
+            # InterXFormat lookups
             # Avoid circular imports
             from bzrlib import branch as _mod_branch
             if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
@@ -2070,6 +2080,17 @@
                 _mod_branch.BzrBranchFormat6):
                 branch_converter = _mod_branch.Converter5to6()
                 branch_converter.convert(branch)
+        try:
+            tree = self.bzrdir.open_workingtree()
+        except errors.NotBranchError:
+            pass
+        else:
+            # TODO: conversions of Branch and Tree should be done by
+            # InterXFormat lookups
+            if (isinstance(tree, workingtree.WorkingTree3) and
+                isinstance(self.target_format.workingtree_format,
+                    workingtree_4.WorkingTreeFormat4)):
+                workingtree_4.Converter3to4().convert(tree)
         return to_convert
 
 
@@ -2221,12 +2242,15 @@
     deprecated=True)
 format_registry.register_metadir('knit',
     'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
-    'Format using knits.  Recommended.',
-    branch_format='bzrlib.branch.BzrBranchFormat5')
+    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
+    branch_format='bzrlib.branch.BzrBranchFormat5',
+    tree_format='bzrlib.workingtree_4.WorkingTreeFormat3')
 format_registry.set_default('knit')
 format_registry.register_metadir('metaweave',
     'bzrlib.repofmt.weaverepo.RepositoryFormat7',
     'Transitional format in 0.8.  Slower than knit.',
+    branch_format='bzrlib.branch.BzrBranchFormat5',
+    tree_format='bzrlib.workingtree_4.WorkingTreeFormat3',
     deprecated=True)
 format_registry.register_metadir('experimental-knit2',
     'bzrlib.repofmt.knitrepo.RepositoryFormatKnit2',
@@ -2247,3 +2271,18 @@
     branch_format='bzrlib.branch.BzrBranchFormat6',
     tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
     )
+format_registry.register_metadir('dirstate',
+    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
+    help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
+        'above when accessed over the network.',
+    branch_format='bzrlib.branch.BzrBranchFormat5',
+    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
+    )
+format_registry.register_metadir('dirstate-with-subtree',
+    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
+    help='New in 0.15: Fast local operations and improved scaling for '
+        'network operations. Additionally adds support for versioning nested '
+        'bzr branches. Incompatible with bzr < 0.15.',
+    branch_format='bzrlib.branch.BzrBranchFormat6',
+    tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
+    )

=== modified file 'bzrlib/tests/test_bzrdir.py'
--- a/bzrlib/tests/test_bzrdir.py	2007-03-05 04:55:34 +0000
+++ b/bzrlib/tests/test_bzrdir.py	2007-03-05 09:11:33 +0000
@@ -555,7 +555,19 @@
         self.assertNotEqual(otherdir2, mydir)
         self.assertFalse(otherdir2 == mydir)
 
-        
+    def test_needs_conversion_different_working_tree(self):
+        # meta1dirs need an conversion if any element is not the default.
+        old_format = bzrdir.BzrDirFormat.get_default_format()
+        # test with 
+        new_default = bzrdir.format_registry.make_bzrdir('dirstate')
+        bzrdir.BzrDirFormat._set_default_format(new_default)
+        try:
+            tree = self.make_branch_and_tree('tree', format='knit')
+            self.assertTrue(tree.bzrdir.needs_format_conversion())
+        finally:
+            bzrdir.BzrDirFormat._set_default_format(old_format)
+
+
 class TestFormat5(TestCaseWithTransport):
     """Tests specific to the version 5 bzrdir format."""
 

=== modified file 'bzrlib/tests/test_upgrade.py'
--- a/bzrlib/tests/test_upgrade.py	2007-02-09 22:59:51 +0000
+++ b/bzrlib/tests/test_upgrade.py	2007-03-05 09:11:33 +0000
@@ -31,17 +31,17 @@
     bzrdir,
     progress,
     repository,
+    workingtree,
+    workingtree_4,
     )
 import bzrlib.branch
 from bzrlib.branch import Branch
-from bzrlib.revision import is_ancestor
-from bzrlib.tests import TestCase, TestCaseInTempDir
+from bzrlib.tests import TestCaseWithTransport
 from bzrlib.transport import get_transport
 from bzrlib.upgrade import upgrade
-import bzrlib.workingtree as workingtree
-
-
-class TestUpgrade(TestCaseInTempDir):
+
+
+class TestUpgrade(TestCaseWithTransport):
     
     def test_build_tree(self):
         """Test tree-building test helper"""
@@ -184,6 +184,63 @@
         branch2 = self.make_branch('branch2', format='knit')
         converter = branch2.bzrdir._format.get_converter(target)
         converter.convert(branch2.bzrdir, progress.DummyProgress())
+        branch2 = _mod_branch.Branch.open(self.get_url('branch'))
+        self.assertIs(branch2.__class__, _mod_branch.BzrBranch6)
+
+    def test_convert_knit_dirstate_empty(self):
+        # test that asking for an upgrade from knit to dirstate works.
+        tree = self.make_branch_and_tree('tree', format='knit')
+        target = bzrdir.format_registry.make_bzrdir('dirstate')
+        converter = tree.bzrdir._format.get_converter(target)
+        converter.convert(tree.bzrdir, progress.DummyProgress())
+        new_tree = workingtree.WorkingTree.open('tree')
+        self.assertIs(new_tree.__class__, workingtree_4.WorkingTree4)
+        self.assertEqual(None, new_tree.last_revision())
+
+    def test_convert_knit_dirstate_content(self):
+        # smoke test for dirstate conversion: we call dirstate primitives,
+        # and its there that the core logic is tested.
+        tree = self.make_branch_and_tree('tree', format='knit')
+        self.build_tree(['tree/file'])
+        tree.add(['file'], ['file-id'])
+        target = bzrdir.format_registry.make_bzrdir('dirstate')
+        converter = tree.bzrdir._format.get_converter(target)
+        converter.convert(tree.bzrdir, progress.DummyProgress())
+        new_tree = workingtree.WorkingTree.open('tree')
+        self.assertIs(new_tree.__class__, workingtree_4.WorkingTree4)
+        self.assertEqual(None, new_tree.last_revision())
+
+    def test_convert_knit_one_parent_dirstate(self):
+        # test that asking for an upgrade from knit to dirstate works.
+        tree = self.make_branch_and_tree('tree', format='knit')
+        rev_id = tree.commit('first post')
+        target = bzrdir.format_registry.make_bzrdir('dirstate')
+        converter = tree.bzrdir._format.get_converter(target)
+        converter.convert(tree.bzrdir, progress.DummyProgress())
+        new_tree = workingtree.WorkingTree.open('tree')
+        self.assertIs(new_tree.__class__, workingtree_4.WorkingTree4)
+        self.assertEqual(rev_id, new_tree.last_revision())
+        for path in ['basis-inventory-cache', 'inventory', 'last-revision',
+            'pending-merges', 'stat-cache']:
+            self.failIfExists('tree/.bzr/checkout/' + path)
+
+    def test_convert_knit_merges_dirstate(self):
+        tree = self.make_branch_and_tree('tree', format='knit')
+        rev_id = tree.commit('first post')
+        merge_tree = tree.bzrdir.sprout('tree2').open_workingtree()
+        rev_id2 = tree.commit('second post')
+        rev_id3 = merge_tree.commit('second merge post')
+        tree.merge_from_branch(merge_tree.branch)
+        target = bzrdir.format_registry.make_bzrdir('dirstate')
+        converter = tree.bzrdir._format.get_converter(target)
+        converter.convert(tree.bzrdir, progress.DummyProgress())
+        new_tree = workingtree.WorkingTree.open('tree')
+        self.assertIs(new_tree.__class__, workingtree_4.WorkingTree4)
+        self.assertEqual(rev_id2, new_tree.last_revision())
+        self.assertEqual([rev_id2, rev_id3], new_tree.get_parent_ids())
+        for path in ['basis-inventory-cache', 'inventory', 'last-revision',
+            'pending-merges', 'stat-cache']:
+            self.failIfExists('tree/.bzr/checkout/' + path)
 
 
 _upgrade1_template = \

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-03-05 21:28:03 +0000
+++ b/bzrlib/workingtree_4.py	2007-03-06 00:25:28 +0000
@@ -2169,3 +2169,42 @@
         return True
 
 InterTree.register_optimiser(InterDirStateTree)
+
+
+class Converter3to4(object):
+    """Perform an in-place upgrade of format 3 to format 4 trees."""
+
+    def __init__(self):
+        self.target_format = WorkingTreeFormat4()
+
+    def convert(self, tree):
+        # lock the control files not the tree, so that we dont get tree
+        # on-unlock behaviours, and so that noone else diddles with the 
+        # tree during upgrade.
+        tree._control_files.lock_write()
+        try:
+            self.create_dirstate_data(tree)
+            self.update_format(tree)
+            self.remove_xml_files(tree)
+        finally:
+            tree._control_files.unlock()
+
+    def create_dirstate_data(self, tree):
+        """Create the dirstate based data for tree."""
+        local_path = tree.bzrdir.get_workingtree_transport(None
+            ).local_abspath('dirstate')
+        state = dirstate.DirState.from_tree(tree, local_path)
+        state.save()
+        state.unlock()
+
+    def remove_xml_files(self, tree):
+        """Remove the oldformat 3 data."""
+        transport = tree.bzrdir.get_workingtree_transport(None)
+        for path in ['basis-inventory-cache', 'inventory', 'last-revision',
+            'pending-merges', 'stat-cache']:
+            transport.delete(path)
+
+    def update_format(self, tree):
+        """Change the format marker."""
+        tree._control_files.put_utf8('format',
+            self.target_format.get_format_string())



More information about the bazaar-commits mailing list