Rev 2896: (robertc) Fold KnitRepositry3 into KnitRepository and move xml serialisation logic from it into the serializer classes. (Robert Collins) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Oct 9 01:18:34 BST 2007


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 2896
revision-id: pqm at pqm.ubuntu.com-20071009001832-kl9ak6vzgz6d4fpy
parent: pqm at pqm.ubuntu.com-20071008081200-04a0byt5lo5tyft9
parent: robertc at robertcollins.net-20071008232701-sns4ku33wvaxr2y0
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2007-10-09 01:18:32 +0100
message:
  (robertc) Fold KnitRepositry3 into KnitRepository and move xml serialisation logic from it into the serializer classes. (Robert Collins)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/repofmt/knitrepo.py     knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/test_xml.py       test_xml.py-20050905091053-80b45588931a9b35
  bzrlib/tests/workingtree_implementations/test_parents.py test_set_parents.py-20060807231740-yicmnlci1mj8smu1-1
  bzrlib/xml4.py                 xml4.py-20050916091259-db5ab55e7e6ca324
  bzrlib/xml5.py                 xml5.py-20050907032657-aac8f960815b66b1
  bzrlib/xml6.py                 xml6.py-20060823042456-dbaaq4atrche7xy5-1
  bzrlib/xml_serializer.py       xml.py-20050309040759-57d51586fdec365d
    ------------------------------------------------------------
    revno: 2889.1.3
    merged: robertc at robertcollins.net-20071008232701-sns4ku33wvaxr2y0
    parent: robertc at robertcollins.net-20071008232014-8ztf3wevtj9xjikj
    parent: pqm at pqm.ubuntu.com-20071008081200-04a0byt5lo5tyft9
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: integration
    timestamp: Tue 2007-10-09 09:27:01 +1000
    message:
      Merge bzr.dev.
    ------------------------------------------------------------
    revno: 2889.1.2
    merged: robertc at robertcollins.net-20071008232014-8ztf3wevtj9xjikj
    parent: robertc at robertcollins.net-20071005024137-kn7brcu07nu8cwl1
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: knit-repo
    timestamp: Tue 2007-10-09 09:20:14 +1000
    message:
      Review feedback.
    ------------------------------------------------------------
    revno: 2889.1.1
    merged: robertc at robertcollins.net-20071005024137-kn7brcu07nu8cwl1
    parent: pqm at pqm.ubuntu.com-20071004223314-qpih4e2os3o2627a
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: knit-repo
    timestamp: Fri 2007-10-05 12:41:37 +1000
    message:
      * The class ``bzrlib.repofmt.knitrepo.KnitRepository3`` has been folded into
        ``KnitRepository`` by parameters to the constructor. (Robert Collins)
      * ``bzrlib.xml_serializer.Serializer`` is now responsible for checking that
        mandatory attributes are present on serialisation and deserialisation.
        This fixes some holes in API usage and allows better separation between
        physical storage and object serialisation. (Robert Collins)
=== modified file 'NEWS'
--- a/NEWS	2007-10-08 02:26:21 +0000
+++ b/NEWS	2007-10-08 23:27:01 +0000
@@ -155,6 +155,9 @@
      class that needs it.
      (Martin Pool)
 
+   * The class ``bzrlib.repofmt.knitrepo.KnitRepository3`` has been folded into
+     ``KnitRepository`` by parameters to the constructor. (Robert Collins)
+
    * The ``VersionedFile`` interface now allows content checks to be bypassed
      by supplying check_content=False.  This saves nearly 30% of the minimum
      cost to store a version of a file. (Robert Collins)
@@ -176,6 +179,11 @@
      put by the method call, to allow avoiding stat-after-write or
      housekeeping in callers. (Robert Collins)
 
+   * ``bzrlib.xml_serializer.Serializer`` is now responsible for checking that
+     mandatory attributes are present on serialisation and deserialisation.
+     This fixes some holes in API usage and allows better separation between
+     physical storage and object serialisation. (Robert Collins)
+
    * New class ``bzrlib.errors.InternalBzrError`` which is just a convenient
      shorthand for deriving from BzrError and setting internal_error = True.
      (Robert Collins)

=== modified file 'bzrlib/repofmt/knitrepo.py'
--- a/bzrlib/repofmt/knitrepo.py	2007-10-08 07:29:57 +0000
+++ b/bzrlib/repofmt/knitrepo.py	2007-10-08 23:27:01 +0000
@@ -37,6 +37,7 @@
 
 from bzrlib.decorators import needs_read_lock, needs_write_lock
 from bzrlib.repository import (
+    CommitBuilder,
     MetaDirRepository,
     MetaDirRepositoryFormat,
     RepositoryFormat,
@@ -76,7 +77,19 @@
 class KnitRepository(MetaDirRepository):
     """Knit format repository."""
 
-    _serializer = xml5.serializer_v5
+    # These attributes are inherited from the Repository base class. Setting
+    # them to None ensures that if the constructor is changed to not initialize
+    # them, or a subclass fails to call the constructor, that an error will
+    # occur rather than the system working but generating incorrect data.
+    _commit_builder_class = None
+    _serializer = None
+
+    def __init__(self, _format, a_bzrdir, control_files, _revision_store,
+        control_store, text_store, _commit_builder_class, _serializer):
+        MetaDirRepository.__init__(self, _format, a_bzrdir, control_files,
+            _revision_store, control_store, text_store)
+        self._commit_builder_class = _commit_builder_class
+        self._serializer = _serializer
 
     def _warn_if_deprecated(self):
         # This class isn't deprecated
@@ -228,38 +241,6 @@
         return _KnitParentsProvider(self._get_revision_vf())
 
 
-class KnitRepository3(KnitRepository):
-
-    # knit3 repositories need a RootCommitBuilder
-    _commit_builder_class = RootCommitBuilder
-
-    def __init__(self, _format, a_bzrdir, control_files, _revision_store,
-                 control_store, text_store):
-        KnitRepository.__init__(self, _format, a_bzrdir, control_files,
-                              _revision_store, control_store, text_store)
-        self._serializer = xml7.serializer_v7
-
-    def deserialise_inventory(self, revision_id, xml):
-        """Transform the xml into an inventory object. 
-
-        :param revision_id: The expected revision id of the inventory.
-        :param xml: A serialised inventory.
-        """
-        result = self._serializer.read_inventory_from_string(xml)
-        assert result.root.revision is not None
-        return result
-
-    def serialise_inventory(self, inv):
-        """Transform the inventory object into XML text.
-
-        :param revision_id: The expected revision id of the inventory.
-        :param xml: A serialised inventory.
-        """
-        assert inv.revision_id is not None
-        assert inv.root.revision is not None
-        return KnitRepository.serialise_inventory(self, inv)
-
-
 class RepositoryFormatKnit(MetaDirRepositoryFormat):
     """Bzr repository knit format (generalized). 
 
@@ -277,6 +258,13 @@
     # Set this attribute in derived classes to control the repository class
     # created by open and initialize.
     repository_class = None
+    # Set this attribute in derived classes to control the
+    # _commit_builder_class that the repository objects will have passed to
+    # their constructor.
+    _commit_builder_class = None
+    # Set this attribute in derived clases to control the _serializer that the
+    # repository objects will have passed to their constructor.
+    _serializer = xml5.serializer_v5
 
     def _get_control_store(self, repo_transport, control_files):
         """Return the control store for this repository."""
@@ -368,7 +356,9 @@
                               control_files=control_files,
                               _revision_store=_revision_store,
                               control_store=control_store,
-                              text_store=text_store)
+                              text_store=text_store,
+                              _commit_builder_class=self._commit_builder_class,
+                              _serializer=self._serializer)
 
 
 class RepositoryFormatKnit1(RepositoryFormatKnit):
@@ -388,6 +378,8 @@
     """
 
     repository_class = KnitRepository
+    _commit_builder_class = CommitBuilder
+    _serializer = xml5.serializer_v5
 
     def __ne__(self, other):
         return self.__class__ is not other.__class__
@@ -420,9 +412,11 @@
      - support for recording tree-references
     """
 
-    repository_class = KnitRepository3
+    repository_class = KnitRepository
+    _commit_builder_class = RootCommitBuilder
     rich_root_data = True
     supports_tree_reference = True
+    _serializer = xml7.serializer_v7
 
     def _get_matching_bzrdir(self):
         return bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2007-10-08 07:29:57 +0000
+++ b/bzrlib/repository.py	2007-10-08 23:27:01 +0000
@@ -1182,9 +1182,7 @@
         :param revision_id: The expected revision id of the inventory.
         :param xml: A serialised inventory.
         """
-        result = self._serializer.read_inventory_from_string(xml)
-        result.root.revision = revision_id
-        return result
+        return self._serializer.read_inventory_from_string(xml, revision_id)
 
     def serialise_inventory(self, inv):
         return self._serializer.write_inventory_to_string(inv)
@@ -1645,8 +1643,7 @@
 
 
 class RepositoryFormatRegistry(registry.Registry):
-    """Registry of RepositoryFormats.
-    """
+    """Registry of RepositoryFormats."""
 
     def get(self, format_string):
         r = registry.Registry.get(self, format_string)
@@ -1675,6 +1672,11 @@
        children.
      * an open routine which returns a Repository instance.
 
+    There is one and only one Format subclass for each on-disk format. But
+    there can be one Repository subclass that is used for several different
+    formats. The _format attribute on a Repository instance can be used to
+    determine the disk format.
+
     Formats are placed in an dict by their format string for reference 
     during opening. These should be subclasses of RepositoryFormat
     for consistency.

=== modified file 'bzrlib/tests/test_xml.py'
--- a/bzrlib/tests/test_xml.py	2007-09-13 22:41:38 +0000
+++ b/bzrlib/tests/test_xml.py	2007-10-05 02:41:37 +0000
@@ -178,6 +178,7 @@
 
 class TestSerializer(TestCase):
     """Test XML serialization"""
+
     def test_canned_inventory(self):
         """Test unpacked a canned inventory v4 file."""
         inp = StringIO(_working_inventory_v4)
@@ -388,7 +389,7 @@
         fid_bar1 = u'b\xe5r-01'.encode('utf8')
         fid_sub = u's\xb5bdir-01'.encode('utf8')
         fid_bar2 = u'b\xe5r-02'.encode('utf8')
-        expected = [(u'', fid_root, None, None),
+        expected = [(u'', fid_root, None, rev_id_2),
                     (u'b\xe5r', fid_bar1, fid_root, rev_id_1),
                     (u's\xb5bdir', fid_sub, fid_root, rev_id_1),
                     (u's\xb5bdir/b\xe5r', fid_bar2, fid_sub, rev_id_2),

=== modified file 'bzrlib/tests/workingtree_implementations/test_parents.py'
--- a/bzrlib/tests/workingtree_implementations/test_parents.py	2007-10-03 02:10:09 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_parents.py	2007-10-05 02:41:37 +0000
@@ -340,6 +340,9 @@
 
     def assertTransitionFromBasisToShape(self, basis_shape, basis_revid,
         new_shape, new_revid, extra_parent=None):
+        # set the inventory revision ids.
+        basis_shape.revision_id = basis_revid
+        new_shape.revision_id = new_revid
         delta = self.make_inv_delta(basis_shape, new_shape)
         tree = self.make_branch_and_tree('tree')
         # the shapes need to be in the tree's repository to be able to set them

=== modified file 'bzrlib/xml4.py'
--- a/bzrlib/xml4.py	2007-09-13 22:41:38 +0000
+++ b/bzrlib/xml4.py	2007-10-05 02:41:37 +0000
@@ -58,8 +58,10 @@
         return e
 
 
-    def _unpack_inventory(self, elt):
+    def _unpack_inventory(self, elt, revision_id=None):
         """Construct from XML Element
+
+        :param revision_id: Ignored parameter used by xml5.
         """
         assert elt.tag == 'inventory'
         root_id = elt.get('file_id') or ROOT_ID

=== modified file 'bzrlib/xml5.py'
--- a/bzrlib/xml5.py	2007-09-13 22:41:38 +0000
+++ b/bzrlib/xml5.py	2007-10-05 02:41:37 +0000
@@ -154,6 +154,15 @@
     supported_kinds = set(['file', 'directory', 'symlink'])
     format_num = '5'
 
+    def _check_revisions(self, inv):
+        """Extension point for subclasses to check during serialisation.
+
+        By default no checking is done.
+
+        :param inv: An inventory about to be serialised, to be checked.
+        :raises: AssertionError if an error has occured.
+        """
+
     def write_inventory_to_lines(self, inv):
         """Return a list of lines with the encoded inventory."""
         return self.write_inventory(inv, None)
@@ -179,6 +188,7 @@
         :return: The inventory as a list of lines.
         """
         _ensure_utf8_re()
+        self._check_revisions(inv)
         output = []
         append = output.append
         self._append_inventory_root(append, inv)
@@ -326,7 +336,7 @@
             prop_elt.tail = '\n'
         top_elt.tail = '\n'
 
-    def _unpack_inventory(self, elt):
+    def _unpack_inventory(self, elt, revision_id):
         """Construct from XML Element
         """
         assert elt.tag == 'inventory'
@@ -347,6 +357,8 @@
             if ie.parent_id is None:
                 ie.parent_id = root_id
             inv.add(ie)
+        if revision_id is not None:
+            inv.root.revision = revision_id
         return inv
 
     def _unpack_entry(self, elt):

=== modified file 'bzrlib/xml6.py'
--- a/bzrlib/xml6.py	2007-09-13 22:41:38 +0000
+++ b/bzrlib/xml6.py	2007-10-05 02:41:37 +0000
@@ -18,6 +18,7 @@
 
 
 class Serializer_v6(xml5.Serializer_v5):
+    """This serialiser adds rich roots."""
 
     format_num = '6'
     root_id = None
@@ -37,7 +38,18 @@
             xml5._encode_and_escape(inv.root.name),
             xml5._encode_and_escape(inv.root.revision)))
 
-    def _unpack_inventory(self, elt):
+    def _check_revisions(self, inv):
+        """Extension point for subclasses to check during serialisation.
+
+        By default no checking is done.
+
+        :param inv: An inventory about to be serialised, to be checked.
+        :raises: AssertionError if an error has occured.
+        """
+        assert inv.revision_id is not None
+        assert inv.root.revision is not None
+
+    def _unpack_inventory(self, elt, revision_id=None):
         """Construct from XML Element"""
         if elt.tag != 'inventory':
             raise errors.UnexpectedInventoryFormat('Root tag is %r' % elt.tag)
@@ -52,6 +64,7 @@
         for e in elt:
             ie = self._unpack_entry(e)
             inv.add(ie)
+        assert inv.root.revision is not None
         return inv
 
 

=== modified file 'bzrlib/xml_serializer.py'
--- a/bzrlib/xml_serializer.py	2007-09-13 22:41:38 +0000
+++ b/bzrlib/xml_serializer.py	2007-10-05 02:41:37 +0000
@@ -59,15 +59,23 @@
     def write_inventory_to_string(self, inv):
         raise NotImplementedError(self.write_inventory_to_string)
 
-    def read_inventory_from_string(self, xml_string):
+    def read_inventory_from_string(self, xml_string, revision_id=None):
+        """Read xml_string into an inventory object.
+
+        :param xml_string: The xml to read.
+        :param revision_id: If not-None, the expected revision id of the
+            inventory. Some serialisers use this to set the results' root
+            revision.
+        """
         try:
-            return self._unpack_inventory(fromstring(xml_string))
+            return self._unpack_inventory(fromstring(xml_string), revision_id)
         except ParseError, e:
             raise errors.UnexpectedInventoryFormat(e)
 
-    def read_inventory(self, f):
+    def read_inventory(self, f, revision_id=None):
         try:
-            return self._unpack_inventory(self._read_element(f))
+            return self._unpack_inventory(self._read_element(f),
+                revision_id=None)
         except ParseError, e:
             raise errors.UnexpectedInventoryFormat(e)
 




More information about the bazaar-commits mailing list