Rev 3776: Create bzrlib.repository.Repository.add_inventory_delta for adding inventories via deltas. in http://people.ubuntu.com/~robertc/baz2.0/commit-delta

Robert Collins robertc at robertcollins.net
Mon Oct 13 01:28:23 BST 2008


At http://people.ubuntu.com/~robertc/baz2.0/commit-delta

------------------------------------------------------------
revno: 3776
revision-id: robertc at robertcollins.net-20081013002817-xxxsr37afvuhbzdx
parent: pqm at pqm.ubuntu.com-20081012204951-j2dgh06nuzrak1ri
committer: Robert Collins <robertc at robertcollins.net>
branch nick: commit-delta
timestamp: Mon 2008-10-13 11:28:17 +1100
message:
  Create bzrlib.repository.Repository.add_inventory_delta for adding inventories via deltas.
added:
  bzrlib/tests/per_repository/test_add_inventory_delta.py test_add_inventory_d-20081013002626-rut81igtlqb4590z-1
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/per_repository/__init__.py __init__.py-20060131092037-9564957a7d4a841b
  bzrlib/tests/per_repository/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
=== modified file 'NEWS'
--- a/NEWS	2008-10-10 20:54:04 +0000
+++ b/NEWS	2008-10-13 00:28:17 +0000
@@ -12,6 +12,12 @@
     * ``bzr dump-btree`` is a hidden command introduced to allow dumping
       the contents of a compressed btree file.  (John Arbash Meinel)
 
+  INTERNALS:
+
+    * New method ``bzrlib.repository.Repository.add_inventory_delta``
+      allows adding an inventory via an inventory delta, which can be
+      more efficient for some repository types. (Robert Collins)
+
 
 bzr 1.8rc1 2008-10-07
 ---------------------

=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2008-09-23 02:16:55 +0000
+++ b/bzrlib/remote.py	2008-10-13 00:28:17 +0000
@@ -742,6 +742,12 @@
         self._ensure_real()
         return self._real_repository.add_inventory(revid, inv, parents)
 
+    def add_inventory_delta(self, basis_revision_id, delta, new_revision_id,
+        parents):
+        self._ensure_real()
+        return self._real_repository.add_inventory_delta(basis_revision_id,
+            delta, new_revision_id, parents)
+
     def add_revision(self, rev_id, rev, inv=None, config=None):
         self._ensure_real()
         return self._real_repository.add_revision(

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2008-10-01 05:40:45 +0000
+++ b/bzrlib/repository.py	2008-10-13 00:28:17 +0000
@@ -583,6 +583,42 @@
         return self._inventory_add_lines(revision_id, parents,
             inv_lines, check_content=False)
 
+    def add_inventory_delta(self, basis_revision_id, delta, new_revision_id,
+        parents):
+        """Add a new inventory expressed as a delta against another revision.
+        
+        :param basis_revision_id: The inventory id the delta was created
+            against.
+        :param delta: The inventory delta (see Inventory.apply_delta for
+            details).
+        :param new_revision_id: The revision id that the inventory is being
+            added for.
+        :param parents: The revision ids of the parents that revision_id is
+            known to have and are in the repository already. These are supplied
+            for repositories that depend on the inventory graph for revision
+            graph access, as well as for those that pun ancestry with delta
+            compression.
+
+        :returns: The validator(which is a sha1 digest, though what is sha'd is
+            repository format specific) of the serialized inventory.
+        """
+        if not self.is_in_write_group():
+            raise AssertionError("%r not in write group" % (self,))
+        _mod_revision.check_not_reserved_id(new_revision_id)
+        basis_tree = self.revision_tree(basis_revision_id)
+        basis_tree.lock_read()
+        try:
+            # Note that this mutates the inventory of basis_tree, which not all
+            # inventory implementations may support: A better idiom would be to
+            # return a new inventory, but as there is no revision tree cache in
+            # repository this is safe for now - RBC 20081013
+            basis_inv = basis_tree.inventory
+            basis_inv.apply_delta(delta)
+            basis_inv.revision_id = new_revision_id
+            return self.add_inventory(new_revision_id, basis_inv, parents)
+        finally:
+            basis_tree.unlock()
+
     def _inventory_add_lines(self, revision_id, parents, lines,
         check_content=True):
         """Store lines in inv_vf and return the sha1 of the inventory."""

=== modified file 'bzrlib/tests/per_repository/__init__.py'
--- a/bzrlib/tests/per_repository/__init__.py	2008-09-17 07:18:20 +0000
+++ b/bzrlib/tests/per_repository/__init__.py	2008-10-13 00:28:17 +0000
@@ -858,6 +858,7 @@
     result.addTests(basic_tests)
     prefix = 'bzrlib.tests.per_repository.'
     test_repository_modules = [
+        'test_add_inventory_delta',
         'test_add_fallback_repository',
         'test_break_lock',
         'test_check',

=== added file 'bzrlib/tests/per_repository/test_add_inventory_delta.py'
--- a/bzrlib/tests/per_repository/test_add_inventory_delta.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/per_repository/test_add_inventory_delta.py	2008-10-13 00:28:17 +0000
@@ -0,0 +1,90 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# 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 Repository.add_inventory_delta."""
+
+from bzrlib import errors, revision
+from bzrlib.tests.per_repository import TestCaseWithRepository
+
+
+class TestAddInventoryDelta(TestCaseWithRepository):
+
+    def _get_repo_in_write_group(self, path='repository'):
+        repo = self.make_repository(path)
+        repo.lock_write()
+        self.addCleanup(repo.unlock)
+        repo.start_write_group()
+        return repo
+    
+    def test_basis_missing_errors(self):
+        repo = self._get_repo_in_write_group()
+        try:
+            self.assertRaises(errors.NoSuchRevision,
+                repo.add_inventory_delta, "missing-revision", [], "new-revision",
+                ["missing-revision"])
+        finally:
+            repo.abort_write_group()
+
+    def test_not_in_write_group_errors(self):
+        repo = self.make_repository('repository')
+        repo.lock_write()
+        self.addCleanup(repo.unlock)
+        self.assertRaises(AssertionError, repo.add_inventory_delta,
+            "missing-revision", [], "new-revision", ["missing-revision"])
+
+    def make_inv_delta(self, old, new):
+        """Make an inventory delta from two inventories."""
+        old_ids = set(old._byid.iterkeys())
+        new_ids = set(new._byid.iterkeys())
+        adds = new_ids - old_ids
+        deletes = old_ids - new_ids
+        common = old_ids.intersection(new_ids)
+        delta = []
+        for file_id in deletes:
+            delta.append((old.id2path(file_id), None, file_id, None))
+        for file_id in adds:
+            delta.append((None, new.id2path(file_id), file_id, new[file_id]))
+        for file_id in common:
+            if old[file_id] != new[file_id]:
+                delta.append((old.id2path(file_id), new.id2path(file_id),
+                    file_id, new[file_id]))
+        return delta
+
+    def test_same_validator(self):
+        # Adding an inventory via delta or direct results in the same
+        # validator.
+        tree = self.make_branch_and_tree('tree')
+        revid = tree.commit("empty post")
+        revtree = tree.basis_tree()
+        revtree.lock_read()
+        self.addCleanup(revtree.unlock)
+        new_inv = revtree.inventory
+        delta = self.make_inv_delta(
+            tree.branch.repository.revision_tree(revision.NULL_REVISION).inventory,
+            new_inv)
+        repo_direct = self._get_repo_in_write_group('direct')
+        add_validator = repo_direct.add_inventory(revid, new_inv, [])
+        repo_direct.commit_write_group()
+        repo_delta = self._get_repo_in_write_group('delta')
+        try:
+            delta_validator = repo_delta.add_inventory_delta(revision.NULL_REVISION,
+                delta, revid, [])
+        except:
+            repo_delta.abort_write_group()
+            raise
+        else:
+            repo_delta.commit_write_group()
+        self.assertEqual(add_validator, delta_validator)

=== modified file 'bzrlib/tests/per_repository/test_repository.py'
--- a/bzrlib/tests/per_repository/test_repository.py	2008-09-17 07:18:20 +0000
+++ b/bzrlib/tests/per_repository/test_repository.py	2008-10-13 00:28:17 +0000
@@ -994,6 +994,8 @@
         try:
             self.assertRaises(errors.ReservedId, repo.add_inventory, 'reserved:',
                               None, None)
+            self.assertRaises(errors.ReservedId, repo.add_inventory_delta,
+                "foo", [], 'reserved:', None)
             self.assertRaises(errors.ReservedId, repo.add_revision, 'reserved:',
                               None)
         finally:




More information about the bazaar-commits mailing list