Rev 2683: * The ``bzrlib.pack`` interface has changed to use tuples of bytestrings in http://people.ubuntu.com/~robertc/baz2.0/pack

Robert Collins robertc at robertcollins.net
Wed Aug 8 03:57:41 BST 2007


At http://people.ubuntu.com/~robertc/baz2.0/pack

------------------------------------------------------------
revno: 2683
revision-id: robertc at robertcollins.net-20070808025722-26wvnolkzmnse7s1
parent: pqm at pqm.ubuntu.com-20070808002810-703n3mr6b6hwataj
committer: Robert Collins <robertc at robertcollins.net>
branch nick: pack
timestamp: Wed 2007-08-08 12:57:22 +1000
message:
  * The ``bzrlib.pack`` interface has changed to use tuples of bytestrings
    rather than just bytestrings, making it easier to represent multiple
    element names. As this interface was not used by any internal facilities
    since it was introduced in 0.18 no API compatibility is being preserved.
    The serialised form of these packs is identical with 0.18 when a single
    element tuple is in use. (Robert Collins)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/bundle/serializer/v4.py v10.py-20070611062757-5ggj7k18s9dej0fr-1
  bzrlib/pack.py                 container.py-20070607160755-tr8zc26q18rn0jnb-1
  bzrlib/tests/test_pack.py      test_container.py-20070607160755-tr8zc26q18rn0jnb-2
=== modified file 'NEWS'
--- a/NEWS	2007-08-07 22:59:45 +0000
+++ b/NEWS	2007-08-08 02:57:22 +0000
@@ -135,6 +135,13 @@
     * Ancient unused ``Repository.text_store`` attribute has been removed.
       (Robert Collins)
 
+    * The ``bzrlib.pack`` interface has changed to use tuples of bytestrings
+      rather than just bytestrings, making it easier to represent multiple
+      element names. As this interface was not used by any internal facilities
+      since it was introduced in 0.18 no API compatibility is being preserved.
+      The serialised form of these packs is identical with 0.18 when a single
+      element tuple is in use. (Robert Collins)
+
   INTERNALS:
 
     * merge now uses ``iter_changes`` to calculate changes, which makes room for

=== modified file 'bzrlib/bundle/serializer/v4.py'
--- a/bzrlib/bundle/serializer/v4.py	2007-07-05 00:17:17 +0000
+++ b/bzrlib/bundle/serializer/v4.py	2007-08-08 02:57:22 +0000
@@ -131,7 +131,7 @@
         """
         name = self.encode_name(repo_kind, revision_id, file_id)
         encoded_metadata = bencode.bencode(metadata)
-        self._container.add_bytes_record(encoded_metadata, [name])
+        self._container.add_bytes_record(encoded_metadata, [(name, )])
         if metadata['storage_kind'] != 'header':
             self._container.add_bytes_record(bytes, [])
 
@@ -200,7 +200,7 @@
             else:
                 _unused, bytes = iterator.next()
                 bytes = bytes(None)
-            yield (bytes, metadata) + self.decode_name(names[0])
+            yield (bytes, metadata) + self.decode_name(names[0][0])
 
 
 class BundleSerializerV4(serializer.BundleSerializer):

=== modified file 'bzrlib/pack.py'
--- a/bzrlib/pack.py	2007-08-02 03:17:46 +0000
+++ b/bzrlib/pack.py	2007-08-08 02:57:22 +0000
@@ -86,7 +86,9 @@
         """Add a Bytes record with the given names.
         
         :param bytes: The bytes to insert.
-        :param names: The names to give the inserted bytes.
+        :param names: The names to give the inserted bytes. Each name is
+            a tuple of bytestrings. The bytestrings may not contain
+            whitespace.
         :return: An offset, length tuple. The offset is the offset
             of the record within the container, and the length is the
             length of data that will need to be read to reconstitute the
@@ -100,11 +102,12 @@
         # Length
         self.write_func(str(len(bytes)) + "\n")
         # Names
-        for name in names:
+        for name_tuple in names:
             # Make sure we're writing valid names.  Note that we will leave a
             # half-written record if a name is bad!
-            _check_name(name)
-            self.write_func(name + "\n")
+            for name in name_tuple:
+                _check_name(name)
+            self.write_func('\x00'.join(name_tuple) + "\n")
         # End of headers
         self.write_func("\n")
         # Finally, the contents.
@@ -262,15 +265,16 @@
         all_names = set()
         for record_names, read_bytes in self.iter_records():
             read_bytes(None)
-            for name in record_names:
-                _check_name_encoding(name)
+            for name_tuple in record_names:
+                for name in name_tuple:
+                    _check_name_encoding(name)
                 # Check that the name is unique.  Note that Python will refuse
                 # to decode non-shortest forms of UTF-8 encoding, so there is no
                 # risk that the same unicode string has been encoded two
                 # different ways.
-                if name in all_names:
-                    raise errors.DuplicateRecordNameError(name)
-                all_names.add(name)
+                if name_tuple in all_names:
+                    raise errors.DuplicateRecordNameError(name_tuple)
+                all_names.add(name_tuple)
         excess_bytes = self.reader_func(1)
         if excess_bytes != '':
             raise errors.ContainerHasExcessDataError(excess_bytes)
@@ -300,11 +304,13 @@
         # Read the list of names.
         names = []
         while True:
-            name = self._read_line()
-            if name == '':
+            name_line = self._read_line()
+            if name_line == '':
                 break
-            _check_name(name)
-            names.append(name)
+            name_tuple = tuple(name_line.split('\x00'))
+            for name in name_tuple:
+                _check_name(name)
+            names.append(name_tuple)
 
         self._remaining_length = length
         return names, self._content_reader
@@ -328,7 +334,8 @@
         :raises ContainerError: if this record is invalid.
         """
         names, read_bytes = self.read()
-        for name in names:
-            _check_name_encoding(name)
+        for name_tuple in names:
+            for name in name_tuple:
+                _check_name_encoding(name)
         read_bytes(None)
 

=== modified file 'bzrlib/tests/test_pack.py'
--- a/bzrlib/tests/test_pack.py	2007-08-02 05:35:16 +0000
+++ b/bzrlib/tests/test_pack.py	2007-08-08 02:57:22 +0000
@@ -64,7 +64,7 @@
         output = StringIO()
         writer = pack.ContainerWriter(output.write)
         writer.begin()
-        offset, length = writer.add_bytes_record('abc', names=['name1'])
+        offset, length = writer.add_bytes_record('abc', names=[('name1', )])
         self.assertEqual((42, 13), (offset, length))
         self.assertEqual(
             'Bazaar pack format 1 (introduced in 0.18)\n'
@@ -76,11 +76,35 @@
         output = StringIO()
         writer = pack.ContainerWriter(output.write)
         writer.begin()
-        offset, length = writer.add_bytes_record('abc', names=['name1', 'name2'])
-        self.assertEqual((42, 19), (offset, length))
-        self.assertEqual(
-            'Bazaar pack format 1 (introduced in 0.18)\n'
-            'B3\nname1\nname2\n\nabc',
+        offset, length = writer.add_bytes_record('abc', names=[('name1', ), ('name2', )])
+        self.assertEqual((42, 19), (offset, length))
+        self.assertEqual(
+            'Bazaar pack format 1 (introduced in 0.18)\n'
+            'B3\nname1\nname2\n\nabc',
+            output.getvalue())
+
+    def test_add_bytes_record_two_names(self):
+        """Add a bytes record with two names."""
+        output = StringIO()
+        writer = pack.ContainerWriter(output.write)
+        writer.begin()
+        offset, length = writer.add_bytes_record('abc', names=[('name1', ), ('name2', )])
+        self.assertEqual((42, 19), (offset, length))
+        self.assertEqual(
+            'Bazaar pack format 1 (introduced in 0.18)\n'
+            'B3\nname1\nname2\n\nabc',
+            output.getvalue())
+
+    def test_add_bytes_record_two_element_name(self):
+        """Add a bytes record with a two-element name."""
+        output = StringIO()
+        writer = pack.ContainerWriter(output.write)
+        writer.begin()
+        offset, length = writer.add_bytes_record('abc', names=[('name1', 'name2')])
+        self.assertEqual((42, 19), (offset, length))
+        self.assertEqual(
+            'Bazaar pack format 1 (introduced in 0.18)\n'
+            'B3\nname1\x00name2\n\nabc',
             output.getvalue())
 
     def test_add_second_bytes_record_gets_higher_offset(self):
@@ -105,7 +129,7 @@
         writer.begin()
         self.assertRaises(
             errors.InvalidRecordError,
-            writer.add_bytes_record, 'abc', names=['bad name'])
+            writer.add_bytes_record, 'abc', names=[('bad name', )])
 
 
 class TestContainerReader(tests.TestCase):
@@ -263,7 +287,7 @@
         """
         reader = self.get_reader_for("5\nname1\n\naaaaa")
         names, get_bytes = reader.read()
-        self.assertEqual(['name1'], names)
+        self.assertEqual([('name1', )], names)
         self.assertEqual('aaaaa', get_bytes(None))
 
     def test_record_with_two_names(self):
@@ -271,7 +295,14 @@
         """
         reader = self.get_reader_for("5\nname1\nname2\n\naaaaa")
         names, get_bytes = reader.read()
-        self.assertEqual(['name1', 'name2'], names)
+        self.assertEqual([('name1', ), ('name2', )], names)
+        self.assertEqual('aaaaa', get_bytes(None))
+
+    def test_record_with_two_part_names(self):
+        """Reading a Bytes record with a two_part name reads both."""
+        reader = self.get_reader_for("5\nname1\x00name2\n\naaaaa")
+        names, get_bytes = reader.read()
+        self.assertEqual([('name1', 'name2', )], names)
         self.assertEqual('aaaaa', get_bytes(None))
 
     def test_invalid_length(self):
@@ -399,8 +430,8 @@
         writer.begin()
         memos = []
         memos.append(writer.add_bytes_record('abc', names=[]))
-        memos.append(writer.add_bytes_record('def', names=['name1']))
-        memos.append(writer.add_bytes_record('ghi', names=['name2']))
+        memos.append(writer.add_bytes_record('def', names=[('name1', )]))
+        memos.append(writer.add_bytes_record('ghi', names=[('name2', )]))
         memos.append(writer.add_bytes_record('jkl', names=[]))
         writer.end()
         transport = self.get_transport()
@@ -410,7 +441,7 @@
         result = []
         for names, reader_func in reader.iter_records():
             result.append((names, reader_func(None)))
-        self.assertEqual([([], 'abc'), (['name2'], 'ghi')], result)
+        self.assertEqual([([], 'abc'), ([('name2', )], 'ghi')], result)
 
 
 class TestReadvFile(tests.TestCaseWithTransport):



More information about the bazaar-commits mailing list