PING [MERGE] Root entry has a revision id

Aaron Bentley aaron.bentley at utoronto.ca
Mon Aug 14 14:51:03 BST 2006


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I haven't heard anyone's opinion of this, and I think it's a bit too
major for me to just merge without review.

This is a blocker for the format bump.  The dependencies are

nested-trees requires unique-root-id
unique-root-id requires format-bump
format-bump requires root-has-revision

Aaron

Aaron Bentley wrote:
> Hi all,
> 
> This is another patch in the make-root-less-weird series.
> 
> This patch ensures that the root entry has a revision id in all
> RevisionTrees and BundleTrees.
> 
> Since the stored inventory doesn't always have its revision id recorded,
> this is determined when the RevisionTree or BundleTree is generated.
> 
> Updates to commit were necessary to ensure that the revision id was
> appropriately set there, as well.
> 
> The inventory change is due to the commit changes.  It
> 1. Allows inventories to be generated that don't have root entries
> 2. Allows root entries to be added the same way other entries are added.
> 
> Although commit can now call record_entry_contents on a root entry, this
> does not create a weave or knit for the root entry.  Similarly, other
> CommitBuilders may choose to ignore the root entry if appropriate.
> 
> I have tried to maintain backwards compatibility two ways:
> 1. commit should work with old CommitBuilders (e.g. the bzr-svn one)
> 2. other CommitBuilder clients (are there any?) should work with new
> CommitBuilders.
> 
> Oh, and I nuked a bare except and added some comments.
> 
> Aaron

- ------------------------------------------------------------------------

=== modified file 'bzrlib/bundle/bundle_data.py'
- --- bzrlib/bundle/bundle_data.py	2006-08-05 22:33:36 +0000
+++ bzrlib/bundle/bundle_data.py	2006-08-08 12:33:07 +0000
@@ -652,6 +652,7 @@
             inv = Inventory(root_id, self.revision_id)
         except TypeError:
             inv = Inventory(revision_id=self.revision_id)
+        inv.root.revision = self.get_last_changed(root_id)

         def add_entry(file_id):
             path = self.id2path(file_id)

=== modified file 'bzrlib/bundle/serializer/v08.py'
- --- bzrlib/bundle/serializer/v08.py	2006-08-05 22:33:36 +0000
+++ bzrlib/bundle/serializer/v08.py	2006-08-08 18:10:37 +0000
@@ -317,7 +317,7 @@
         self.from_file = iter(from_file)
         self._next_line = None

- -        self.info = BundleInfo()
+        self.info = BundleInfo08()
         # We put the actual inventory ids in the footer, so that the patch
         # is easier to read for humans.
         # Unfortunately, that means we need to read everything before we
@@ -500,3 +500,9 @@
                 # Consume the trailing \n and stop processing
                 self._next().next()
                 break
+
+
+class BundleInfo08(BundleInfo):
+    def _update_tree(self, bundle_tree, revision_id):
+        bundle_tree.note_last_changed('', revision_id)
+        BundleInfo._update_tree(self, bundle_tree, revision_id)

=== modified file 'bzrlib/commit.py'
- --- bzrlib/commit.py	2006-08-05 22:33:36 +0000
+++ bzrlib/commit.py	2006-08-08 17:43:56 +0000
@@ -308,8 +308,11 @@
                 raise PointlessCommit()

             self._emit_progress_update()
- -            # TODO: Now the new inventory is known, check for conflicts
and prompt the
- -            # user for a commit message.
+            # TODO: Now the new inventory is known, check for conflicts and
+            # prompt the user for a commit message.
+            # ADHB 2006-08-08: If this is done, populate_new_inv should
not add
+            # weave lines, because nothing should be recorded until it
is known
+            # that commit will succeed.
             self.builder.finish_inventory()
             self._emit_progress_update()
             self.rev_id = self.builder.commit(self.message)
@@ -502,10 +505,13 @@
         # in bugs like #46635.  Any reason not to use/enhance
Tree.changes_from?
         # ADHB 11-07-2006
         mutter("Selecting files for commit with filter %s",
self.specific_files)
- -        # at this point we dont copy the root entry:
         entries = self.work_inv.iter_entries()
- -        entries.next()
- -        self._emit_progress_update()
+        if not self.builder.record_root_entry:
+            warnings.warn('CommitBuilders should support recording the
root'
+                ' entry as of bzr 0.10.', DeprecationWarning, stacklevel=2)
+            self.builder.new_inventory.add(self.basis_inv.root.copy())
+            entries.next()
+            self._emit_progress_update()
         for path, new_ie in entries:
             self._emit_progress_update()
             file_id = new_ie.file_id

=== modified file 'bzrlib/inventory.py'
- --- bzrlib/inventory.py	2006-08-07 23:14:45 +0000
+++ bzrlib/inventory.py	2006-08-08 15:12:54 +0000
@@ -865,10 +865,17 @@
         # root id. Rather than generating a random one here.
         #if root_id is None:
         #    root_id = bzrlib.branch.gen_file_id('TREE_ROOT')
- -        self.root = InventoryDirectory(root_id, '', None)
+        if root_id is not None:
+            self._set_root(InventoryDirectory(root_id, '', None))
+        else:
+            self.root = None
+            self._byid = {}
         # FIXME: this isn't ever used, changing it to self.revision may
break
         # things. TODO make everything use self.revision_id
         self.revision_id = revision_id
+
+    def _set_root(self, ie):
+        self.root = ie
         self._byid = {self.root.file_id: self.root}

     def copy(self):
@@ -1046,7 +1053,12 @@
         if entry.file_id in self._byid:
             raise BzrError("inventory already contains entry with id
{%s}" % entry.file_id)

- -        if entry.parent_id == ROOT_ID or entry.parent_id is None:
+        if entry.parent_id is None:
+            assert self.root is None and len(self._byid) == 0
+            self._set_root(entry)
+            return entry
+        if entry.parent_id == ROOT_ID:
+            assert self.root is not None, self
             entry.parent_id = self.root.file_id

         try:

=== modified file 'bzrlib/repository.py'
- --- bzrlib/repository.py	2006-08-05 22:33:36 +0000
+++ bzrlib/repository.py	2006-08-08 17:52:24 +0000
@@ -20,13 +20,14 @@
 import re
 import time
 from unittest import TestSuite
+from warnings import warn

 from bzrlib import bzrdir, check, delta, gpg, errors, xml5, ui,
transactions, osutils
 from bzrlib.decorators import needs_read_lock, needs_write_lock
 from bzrlib.errors import InvalidRevisionId
 from bzrlib.graph import Graph
 from bzrlib.inter import InterObject
- -from bzrlib.inventory import Inventory
+from bzrlib.inventory import Inventory, InventoryDirectory, ROOT_ID
 from bzrlib.knit import KnitVersionedFile, KnitPlainFactory
 from bzrlib.lockable_files import LockableFiles, TransportLock
 from bzrlib.lockdir import LockDir
@@ -255,8 +256,8 @@
         :param revprops: Optional dictionary of revision properties.
         :param revision_id: Optional revision id.
         """
- -        return CommitBuilder(self, parents, config, timestamp, timezone,
- -                             committer, revprops, revision_id)
+        return NewCommitBuilder(self, parents, config, timestamp, timezone,
+                                committer, revprops, revision_id)

     def unlock(self):
         self.control_files.unlock()
@@ -443,7 +444,9 @@
         :param revision_id: The expected revision id of the inventory.
         :param xml: A serialised inventory.
         """
- -        return xml5.serializer_v5.read_inventory_from_string(xml)
+        result = xml5.serializer_v5.read_inventory_from_string(xml)
+        result.root.revision = revision_id
+        return result

     @needs_read_lock
     def get_inventory_xml(self, revision_id):
@@ -1950,6 +1953,8 @@
     This allows describing a tree to be committed without needing to
     know the internals of the format of the repository.
     """
+
+    record_root_entry = False
     def __init__(self, repository, parents, config, timestamp=None,
                  timezone=None, committer=None, revprops=None,
                  revision_id=None):
@@ -1972,7 +1977,7 @@
             assert isinstance(committer, basestring), type(committer)
             self._committer = committer

- -        self.new_inventory = Inventory()
+        self.new_inventory = Inventory(None)
         self._new_revision_id = revision_id
         self.parents = parents
         self.repository = repository
@@ -2012,6 +2017,11 @@

     def finish_inventory(self):
         """Tell the builder that the inventory is finished."""
+        if self.new_inventory.root is None:
+            warn('Root entry should be supplied to
record_entry_contents, as'
+                 ' of bzr 0.10.',
+                 DeprecationWarning, stacklevel=2)
+            self.new_inventory.add(InventoryDirectory(ROOT_ID, '', None))
         self.new_inventory.revision_id = self._new_revision_id
         self.inv_sha1 = self.repository.add_inventory(
             self._new_revision_id,
@@ -2041,6 +2051,8 @@
     def record_entry_contents(self, ie, parent_invs, path, tree):
         """Record the content of ie from tree into the commit if needed.

+        Side effect: sets ie.revision when unchanged
+
         :param ie: An inventory entry present in the commit.
         :param parent_invs: The inventories of the parent revisions of the
             commit.
@@ -2055,6 +2067,14 @@
         # which may be the sole parent if it is untouched.
         if ie.revision is not None:
             return
+
+        # In this revision format, root entries have no knit or weave
+        if ie is self.new_inventory.root:
+            if len(parent_invs):
+                ie.revision = parent_invs[0].root.revision
+            else:
+                ie.revision = None
+            return
         previous_entries = ie.find_previous_heads(
             parent_invs,
             self.repository.weave_store,
@@ -2120,6 +2140,15 @@
         versionedfile.clear_cache()


+class NewCommitBuilder(CommitBuilder):
+    """Temporary class so old CommitBuilders are detected properly
+
+    Note: CommitBuilder works whether or not root entry is recorded.
+    """
+
+    record_root_entry = True
+
+
 _unescape_map = {
     'apos':"'",
     'quot':'"',

=== modified file
'bzrlib/tests/repository_implementations/test_repository.py'
- --- bzrlib/tests/repository_implementations/test_repository.py
2006-08-05 22:33:36 +0000
+++ bzrlib/tests/repository_implementations/test_repository.py
2006-08-08 12:33:11 +0000
@@ -313,6 +313,13 @@
             self.assertEqual(revision.revision_id, revision_id)
             self.assertEqual(revision, repo.get_revision(revision_id))

+    def test_root_entry_has_revision(self):
+        tree = self.make_branch_and_tree('.')
+        tree.commit('message', rev_id='rev_id')
+        self.assertEqual(tree.basis_tree().inventory.root.revision,
'rev_id')
+        rev_tree =
tree.branch.repository.revision_tree(tree.last_revision())
+        self.assertEqual(rev_tree.inventory.root.revision, 'rev_id')
+

 class TestCaseWithComplexRepository(TestCaseWithRepository):


=== modified file 'bzrlib/tests/test_bundle.py'
- --- bzrlib/tests/test_bundle.py	2006-08-04 04:41:02 +0000
+++ bzrlib/tests/test_bundle.py	2006-08-08 13:43:53 +0000
@@ -27,7 +27,8 @@
 from bzrlib.bundle.serializer import write_bundle, read_bundle
 from bzrlib.branch import Branch
 from bzrlib.diff import internal_diff
- -from bzrlib.errors import BzrError, TestamentMismatch, NotABundle,
BadBundle
+from bzrlib.errors import (BzrError, TestamentMismatch, NotABundle,
BadBundle,
+                           NoSuchFile,)
 from bzrlib.merge import Merge3Merger
 from bzrlib.osutils import has_symlinks, sha_file
 from bzrlib.tests import (TestCaseInTempDir, TestCaseWithTransport,
@@ -411,7 +412,7 @@
             for inventory_id in old:
                 try:
                     old_file = old.get_file(inventory_id)
- -                except:
+                except NoSuchFile:
                     continue
                 if old_file is None:
                     continue
@@ -799,6 +800,14 @@
         self.assertEqual(19800, rev.timezone)
         self.assertEqual(1152544886.0, rev.timestamp)

+    def test_bundle_root_id(self):
+        self.tree1 = self.make_branch_and_tree('b1')
+        self.b1 = self.tree1.branch
+        self.tree1.commit('message', rev_id='revid1')
+        bundle = self.get_valid_bundle(None, 'revid1')
+        tree = bundle.revision_tree(self.b1.repository, 'revid1')
+        self.assertEqual(tree.inventory.root.revision, 'revid1')
+

 class MungedBundleTester(TestCaseWithTransport):


=== modified file 'bzrlib/tests/test_commit.py'
- --- bzrlib/tests/test_commit.py	2006-08-02 01:50:08 +0000
+++ bzrlib/tests/test_commit.py	2006-08-08 16:01:29 +0000
@@ -494,6 +494,7 @@
         reporter = CapturingReporter()
         this_tree.commit('do the commit', reporter=reporter)
         self.assertEqual([
+            ('change', 'unchanged', ''),
             ('change', 'unchanged', 'dirtoleave'),
             ('change', 'unchanged', 'filetoleave'),
             ('change', 'modified', 'filetomodify'),

=== modified file
'bzrlib/tests/workingtree_implementations/test_basis_inventory.py'
- --- bzrlib/tests/workingtree_implementations/test_basis_inventory.py
2006-07-28 16:05:23 +0000
+++ bzrlib/tests/workingtree_implementations/test_basis_inventory.py
2006-08-08 12:33:14 +0000
@@ -51,6 +51,7 @@

         basis_inv_txt = t.read_basis_inventory()
         basis_inv =
bzrlib.xml5.serializer_v5.read_inventory_from_string(basis_inv_txt)
+        basis_inv.root.revision = 'r2'
         self.assertEquals('r2', basis_inv.revision_id)
         store_inv = b.repository.get_inventory('r2')


=== modified file 'bzrlib/workingtree.py'
- --- bzrlib/workingtree.py	2006-08-08 00:24:38 +0000
+++ bzrlib/workingtree.py	2006-08-08 12:33:16 +0000
@@ -399,6 +399,7 @@
             try:
                 xml = self.read_basis_inventory()
                 inv =
bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
+                inv.root.revision = revision_id
             except NoSuchFile:
                 inv = None
             if inv is not None and inv.revision_id == revision_id:


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFE4H/G0F+nu1YWqI0RAn4FAJ4t+xgFzKmw61uEP9hOXbzCP335CACbBz6a
kQn+yrHKlwB6VASV+W0dVaI=
=w0Yw
-----END PGP SIGNATURE-----




More information about the bazaar mailing list