Rev 2473: Make the nested tree commit smoke test be more rigourous. in http://bazaar.launchpad.net/~bzr/bzr/dirstate

Robert Collins robertc at robertcollins.net
Tue Mar 6 10:30:31 GMT 2007


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

------------------------------------------------------------
revno: 2473
revision-id: robertc at robertcollins.net-20070306102901-y25mgksdvocjmib8
parent: mbp at sourcefrog.net-20070306102233-xr93c99y5y7pod64
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate.dogfood
timestamp: Tue 2007-03-06 21:29:01 +1100
message:
  Make the nested tree commit smoke test be more rigourous.
modified:
  BRANCH.TODO                    BRANCH.TODO-20060103052123-79ac4969351c03a9
  bzrlib/commit.py               commit.py-20050511101309-79ec1a0168e0e825
  bzrlib/mutabletree.py          mutabletree.py-20060906023413-4wlkalbdpsxi2r4y-2
  bzrlib/tests/test_commit.py    test_commit.py-20050914060732-279f057f8c295434
  bzrlib/tests/workingtree_implementations/test_commit.py test_commit.py-20060421013633-1610ec2331c8190f
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'BRANCH.TODO'
--- a/BRANCH.TODO	2007-03-06 03:57:57 +0000
+++ b/BRANCH.TODO	2007-03-06 10:29:01 +0000
@@ -3,6 +3,10 @@
 # 
 #
 
+nested commits:
+message_callback : call it many times?
+specific files : adjust them as we walk deep into the trees.
+
 get_reference_revision should not take an InventoryEntry
 
 notice subtrees based on whether they actually have a control directory, not

=== modified file 'bzrlib/commit.py'
--- a/bzrlib/commit.py	2007-02-22 05:51:57 +0000
+++ b/bzrlib/commit.py	2007-03-06 10:29:01 +0000
@@ -173,7 +173,8 @@
                local=False,
                reporter=None,
                config=None,
-               message_callback=None):
+               message_callback=None,
+               recursive='down'):
         """Commit working copy as a new revision.
 
         branch -- the deprecated branch to commit to. New callers should pass in 
@@ -200,6 +201,8 @@
 
         revprops -- Properties for new revision
         :param local: Perform a local only commit.
+        :param recursive: If set to 'down', commit in any subtrees that have
+            pending changes of any sort during this commit.
         """
         mutter('preparing to commit')
 
@@ -233,6 +236,16 @@
         self.rev_id = None
         self.specific_files = specific_files
         self.allow_pointless = allow_pointless
+        self.recursive = recursive
+        self.revprops = revprops
+        self.message_callback = message_callback
+        self.timestamp = timestamp
+        self.timezone = timezone
+        self.committer = committer
+        self.specific_files = specific_files
+        self.strict = strict
+        self.verbose = verbose
+        self.local = local
 
         if reporter is None and self.reporter is None:
             self.reporter = NullCommitReporter()
@@ -282,7 +295,9 @@
             if specific_files is not None:
                 # Ensure specified files are versioned
                 # (We don't actually need the ids here)
-                tree.find_ids_across_trees(specific_files, 
+                # XXX: Dont we have filter_unversioned to do this more
+                # cheaply?
+                tree.find_ids_across_trees(specific_files,
                                            [self.basis_tree, self.work_tree])
             # one to finish, one for rev and inventory, and one for each
             # inventory entry, and the same for the new inventory.
@@ -297,7 +312,7 @@
                 raise NotImplementedError('selected-file commit of merges is not supported yet: files %r',
                         self.specific_files)
             
-            self.builder = self.branch.get_commit_builder(self.parents, 
+            self.builder = self.branch.get_commit_builder(self.parents,
                 self.config, timestamp, timezone, committer, revprops, rev_id)
             
             self._remove_deleted()
@@ -593,6 +608,31 @@
             file_id = new_ie.file_id
             try:
                 kind = self.work_tree.kind(file_id)
+                if kind == 'tree-reference' and self.recursive == 'down':
+                    # nested tree: commit in it
+                    sub_tree = WorkingTree.open(self.work_tree.abspath(path))
+                    # FIXME: be more comprehensive here:
+                    # this works when both trees are in --trees repository,
+                    # but when both are bound to a different repository,
+                    # it fails; a better way of approaching this is to 
+                    # finally implement the explicit-caches approach design
+                    # a while back - RBC 20070306.
+                    if (sub_tree.branch.repository.bzrdir.root_transport.base
+                        ==
+                        self.work_tree.branch.repository.bzrdir.root_transport.base):
+                        sub_tree.branch.repository = \
+                            self.work_tree.branch.repository
+                    try:
+                        sub_tree.commit(message=None, revprops=self.revprops,
+                            recursive=self.recursive,
+                            message_callback=self.message_callback,
+                            timestamp=self.timestamp, timezone=self.timezone,
+                            committer=self.committer,
+                            allow_pointless=self.allow_pointless,
+                            strict=self.strict, verbose=self.verbose,
+                            local=self.local, reporter=self.reporter)
+                    except errors.PointlessCommit:
+                        pass
                 if kind != new_ie.kind:
                     new_ie = inventory.make_entry(kind, new_ie.name,
                                                   new_ie.parent_id, file_id)

=== modified file 'bzrlib/mutabletree.py'
--- a/bzrlib/mutabletree.py	2007-03-01 10:14:03 +0000
+++ b/bzrlib/mutabletree.py	2007-03-06 10:29:01 +0000
@@ -142,14 +142,8 @@
         raise NotImplementedError(self._add)
 
     @needs_write_lock
-    def commit(self, message=None, revprops=None, recursive='down', *args,
+    def commit(self, message=None, revprops=None, *args,
                **kwargs):
-        if recursive == 'down':
-            for tree in self.iter_nested_trees():
-                try:
-                    tree.commit(message, revprops, recursive, *args, **kwargs)
-                except errors.PointlessCommit:
-                    pass
         # avoid circular imports
         from bzrlib import commit
         if revprops is None:

=== modified file 'bzrlib/tests/test_commit.py'
--- a/bzrlib/tests/test_commit.py	2007-03-06 00:28:36 +0000
+++ b/bzrlib/tests/test_commit.py	2007-03-06 10:29:01 +0000
@@ -679,20 +679,3 @@
         repository.add_inventory = raise_
         self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
         self.assertFalse(cb.called)
-
-    def test_nested_commit(self):
-        """Commit in multiply-nested trees"""
-        tree = self.make_branch_and_tree('.',
-            format='dirstate-with-subtree')
-        subtree = self.make_branch_and_tree('subtree',
-            format='dirstate-with-subtree')
-        subsubtree = self.make_branch_and_tree('subtree/subtree',
-            format='dirstate-with-subtree')
-        subtree.add_reference(subsubtree)
-        tree.add_reference(subtree)
-        tree.commit('added reference', allow_pointless=False)
-        self.assertIs(subsubtree.last_revision(), None,
-                      'subsubtree was committed')
-        self.assertIsNot(subtree.last_revision(), None,
-                         'subtree was not committed')
-

=== modified file 'bzrlib/tests/workingtree_implementations/test_commit.py'
--- a/bzrlib/tests/workingtree_implementations/test_commit.py	2006-09-27 16:16:10 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_commit.py	2007-03-06 10:29:01 +0000
@@ -210,6 +210,45 @@
         wt.rename_one('name1', 'name2')
         wt.commit('third')
         wt.path2id('name1-id')
+
+    def test_nested_commit(self):
+        """Commit in multiply-nested trees"""
+        tree = self.make_branch_and_tree('.')
+        if not tree.supports_tree_reference():
+            # inapplicable test.
+            return
+        subtree = self.make_branch_and_tree('subtree')
+        subsubtree = self.make_branch_and_tree('subtree/subtree')
+        subtree.add(['subtree'])
+        tree.add(['subtree'])
+        # use allow_pointless=False to ensure that the deepest tree, which
+        # has no commits made to it, does not get a pointless commit.
+        rev_id = tree.commit('added reference', allow_pointless=False)
+        tree.lock_read()
+        self.addCleanup(tree.unlock)
+        # the deepest subtree has not changed, so no commit should take place.
+        self.assertEqual(None, subsubtree.last_revision())
+        # the intermediate tree should have committed a pointer to the current
+        # subtree revision.
+        sub_basis = subtree.basis_tree()
+        sub_basis.lock_read()
+        self.addCleanup(sub_basis.unlock)
+        self.assertEqual(subsubtree.last_revision(),
+            sub_basis.get_reference_revision(
+                sub_basis.inventory[sub_basis.path2id('subtree')]))
+        # the intermediate tree has changed, so should have had a commit
+        # take place.
+        self.assertNotEqual(None, subtree.last_revision())
+        # the outer tree should have committed a pointer to the current
+        # subtree revision.
+        basis = tree.basis_tree()
+        basis.lock_read()
+        self.addCleanup(basis.unlock)
+        self.assertEqual(subtree.last_revision(),
+            basis.get_reference_revision(
+                basis.inventory[basis.path2id('subtree')]))
+        # the outer tree must have have changed too.
+        self.assertNotEqual(None, rev_id)
         
 
 class TestCommitProgress(TestCaseWithWorkingTree):

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-03-06 09:17:08 +0000
+++ b/bzrlib/workingtree_4.py	2007-03-06 10:29:01 +0000
@@ -353,7 +353,7 @@
                     # add this entry to the parent map.
                     parent_ies[(dirname + '/' + name).strip('/')] = inv_entry
                 elif kind == 'tree-reference':
-                    inv_entry.reference_revision = link_or_sha1
+                    inv_entry.reference_revision = link_or_sha1 or None
                 else:
                     assert 'unknown kind'
                 # These checks cost us around 40ms on a 55k entry tree
@@ -1357,7 +1357,7 @@
                     inv_entry.text_size = size
                     inv_entry.symlink_target = utf8_decode(fingerprint)[0]
                 elif kind == 'tree-reference':
-                    inv_entry.reference_revision = fingerprint
+                    inv_entry.reference_revision = fingerprint or None
                 else:
                     raise AssertionError("cannot convert entry %r into an InventoryEntry"
                             % entry)
@@ -1403,6 +1403,9 @@
     def get_file_text(self, file_id):
         return ''.join(self.get_file_lines(file_id))
 
+    def get_reference_revision(self, entry, path=None):
+        return entry.reference_revision
+
     def get_symlink_target(self, file_id):
         entry = self._get_entry(file_id=file_id)
         parent_index = self._get_parent_index()



More information about the bazaar-commits mailing list