[MERGE] Container format version 2

Andrew Bennetts andrew at canonical.com
Tue Jul 17 06:46:12 BST 2007


Andrew Bennetts wrote:
> This primarily updates the container format to allow whitespace in record names.
[...]

Argh, ":wq<enter>y" is too ingrained in my muscle memory!  (I use vim and mutt)

Here's the merge directive I forgot to attach.  At some point I'll teach mutt to
complain if I try to send a [MERGE] email with no attachment...

-Andrew.

-------------- next part --------------
# Bazaar merge directive format 1
# revision_id: andrew.bennetts at canonical.com-20070717044423-\
#   cetp5spep142xsr4
# target_branch: http://bazaar-vcs.org/bzr/bzr.dev
# testament_sha1: 6ddb5bed4f84527c5bae21b7837d876f03a9a087
# timestamp: 2007-07-17 15:27:30 +1000
# source_branch: http://people.ubuntu.com/~andrew/bzr/container-format
# 
# Bazaar revision bundle v0.9
#
# message:
#   Updates to "pack" format:
#     * rename pack.py to container.py, to avoid confusion with the new "bzr pack"
#       command.
#     * bump format version.  The only change is that all whitespace apart from 
#       '\n' is now allowed in record names, because it appears that file IDs can
#       contain whitespace (even though bzr itself won't generate them, bzrlib will
#       accept them).
#     * format 1 is simply orphaned, no effort has been made to read the old format
#       as to the best of my knowledge it isn't used yet.  (Similarly there's no
#       backwards compatibility for the module rename)  I'll change this if someone
#       needs it.
#   
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Tue 2007-07-17 14:44:23.928999901 +1000

=== renamed file bzrlib/pack.py // bzrlib/container.py
--- bzrlib/pack.py
+++ bzrlib/container.py
@@ -24,22 +24,18 @@
 from bzrlib import errors
 
 
-FORMAT_ONE = "Bazaar pack format 1 (introduced in 0.18)"
-
-
-_whitespace_re = re.compile('[\t\n\x0b\x0c\r ]')
+FORMAT_TWO = "Bazaar pack format 2 (introduced in 0.19)"
 
 
 def _check_name(name):
     """Do some basic checking of 'name'.
     
-    At the moment, this just checks that there are no whitespace characters in a
-    name.
+    At the moment, this just makes sure there's no newline in name.
 
     :raises InvalidRecordError: if name is not valid.
     :seealso: _check_name_encoding
     """
-    if _whitespace_re.search(name) is not None:
+    if '\n' in name:
         raise errors.InvalidRecordError("%r is not a valid name." % (name,))
 
 
@@ -70,7 +66,7 @@
 
     def begin(self):
         """Begin writing a container."""
-        self.write_func(FORMAT_ONE + "\n")
+        self.write_func(FORMAT_TWO + "\n")
 
     def end(self):
         """Finish writing a container."""
@@ -182,7 +178,7 @@
 
     def _read_format(self):
         format = self._read_line()
-        if format != FORMAT_ONE:
+        if format != FORMAT_TWO:
             raise errors.UnknownContainerFormatError(format)
 
     def validate(self):

=== renamed file bzrlib/tests/test_pack.py // bzrlib/tests/test_container.py
--- bzrlib/tests/test_pack.py
+++ bzrlib/tests/test_container.py
@@ -14,12 +14,12 @@
 # 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 bzrlib.pack."""
+"""Tests for bzrlib.container."""
 
 
 from cStringIO import StringIO
 
-from bzrlib import pack, errors, tests
+from bzrlib import container, errors, tests
 
 
 class TestContainerWriter(tests.TestCase):
@@ -30,53 +30,53 @@
         This uses None as the output stream to show that the constructor doesn't
         try to use the output stream.
         """
-        writer = pack.ContainerWriter(None)
+        writer = container.ContainerWriter(None)
 
     def test_begin(self):
         """The begin() method writes the container format marker line."""
         output = StringIO()
-        writer = pack.ContainerWriter(output.write)
+        writer = container.ContainerWriter(output.write)
         writer.begin()
-        self.assertEqual('Bazaar pack format 1 (introduced in 0.18)\n',
+        self.assertEqual('Bazaar pack format 2 (introduced in 0.19)\n',
                          output.getvalue())
 
     def test_end(self):
         """The end() method writes an End Marker record."""
         output = StringIO()
-        writer = pack.ContainerWriter(output.write)
+        writer = container.ContainerWriter(output.write)
         writer.begin()
         writer.end()
-        self.assertEqual('Bazaar pack format 1 (introduced in 0.18)\nE',
+        self.assertEqual('Bazaar pack format 2 (introduced in 0.19)\nE',
                          output.getvalue())
 
     def test_add_bytes_record_no_name(self):
         """Add a bytes record with no name."""
         output = StringIO()
-        writer = pack.ContainerWriter(output.write)
+        writer = container.ContainerWriter(output.write)
         writer.begin()
         writer.add_bytes_record('abc', names=[])
-        self.assertEqual('Bazaar pack format 1 (introduced in 0.18)\nB3\n\nabc',
+        self.assertEqual('Bazaar pack format 2 (introduced in 0.19)\nB3\n\nabc',
                          output.getvalue())
 
     def test_add_bytes_record_one_name(self):
         """Add a bytes record with one name."""
         output = StringIO()
-        writer = pack.ContainerWriter(output.write)
+        writer = container.ContainerWriter(output.write)
         writer.begin()
         writer.add_bytes_record('abc', names=['name1'])
         self.assertEqual(
-            'Bazaar pack format 1 (introduced in 0.18)\n'
+            'Bazaar pack format 2 (introduced in 0.19)\n'
             'B3\nname1\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 = container.ContainerWriter(output.write)
         writer.begin()
         writer.add_bytes_record('abc', names=['name1', 'name2'])
         self.assertEqual(
-            'Bazaar pack format 1 (introduced in 0.18)\n'
+            'Bazaar pack format 2 (introduced in 0.19)\n'
             'B3\nname1\nname2\n\nabc',
             output.getvalue())
 
@@ -85,18 +85,18 @@
         InvalidRecordError.
         """
         output = StringIO()
-        writer = pack.ContainerWriter(output.write)
+        writer = container.ContainerWriter(output.write)
         writer.begin()
         self.assertRaises(
             errors.InvalidRecordError,
-            writer.add_bytes_record, 'abc', names=['bad name'])
+            writer.add_bytes_record, 'abc', names=['name with \n char'])
 
 
 class TestContainerReader(tests.TestCase):
 
     def get_reader_for(self, bytes):
         stream = StringIO(bytes)
-        reader = pack.ContainerReader(stream)
+        reader = container.ContainerReader(stream)
         return reader
 
     def test_construct(self):
@@ -105,12 +105,12 @@
         This uses None as the output stream to show that the constructor doesn't
         try to use the input stream.
         """
-        reader = pack.ContainerReader(None)
+        reader = container.ContainerReader(None)
 
     def test_empty_container(self):
         """Read an empty container."""
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\nE")
+            "Bazaar pack format 2 (introduced in 0.19)\nE")
         self.assertEqual([], list(reader.iter_records()))
 
     def test_unknown_format(self):
@@ -124,7 +124,7 @@
         UnexpectedEndOfContainerError to be raised.
         """
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\n")
+            "Bazaar pack format 2 (introduced in 0.19)\n")
         iterator = reader.iter_records()
         self.assertRaises(
             errors.UnexpectedEndOfContainerError, iterator.next)
@@ -132,7 +132,7 @@
     def test_unknown_record_type(self):
         """Unknown record types cause UnknownRecordTypeError to be raised."""
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\nX")
+            "Bazaar pack format 2 (introduced in 0.19)\nX")
         iterator = reader.iter_records()
         self.assertRaises(
             errors.UnknownRecordTypeError, iterator.next)
@@ -145,7 +145,7 @@
         ContainerReader's integration with BytesRecordReader is working.
         """
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\nB5\n\naaaaaE")
+            "Bazaar pack format 2 (introduced in 0.19)\nB5\n\naaaaaE")
         expected_records = [([], 'aaaaa')]
         self.assertEqual(
             expected_records,
@@ -154,7 +154,7 @@
 
     def test_validate_empty_container(self):
         """validate does not raise an error for a container with no records."""
-        reader = self.get_reader_for("Bazaar pack format 1 (introduced in 0.18)\nE")
+        reader = self.get_reader_for("Bazaar pack format 2 (introduced in 0.19)\nE")
         # No exception raised
         reader.validate()
 
@@ -162,7 +162,7 @@
         """validate does not raise an error for a container with a valid record.
         """
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\nB3\nname\n\nabcE")
+            "Bazaar pack format 2 (introduced in 0.19)\nB3\nname\n\nabcE")
         # No exception raised
         reader.validate()
 
@@ -172,7 +172,7 @@
         It may raise either UnexpectedEndOfContainerError or
         UnknownContainerFormatError, depending on exactly what the string is.
         """
-        inputs = ["", "x", "Bazaar pack format 1 (introduced in 0.18)", "bad\n"]
+        inputs = ["", "x", "Bazaar pack format 2 (introduced in 0.19)", "bad\n"]
         for input in inputs:
             reader = self.get_reader_for(input)
             self.assertRaises(
@@ -185,7 +185,7 @@
         types.
         """
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\nX")
+            "Bazaar pack format 2 (introduced in 0.19)\nX")
         self.assertRaises(errors.UnknownRecordTypeError, reader.validate)
 
     def test_validate_data_after_end_marker(self):
@@ -193,7 +193,7 @@
         after the end of the container.
         """
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\nEcrud")
+            "Bazaar pack format 2 (introduced in 0.19)\nEcrud")
         self.assertRaises(
             errors.ContainerHasExcessDataError, reader.validate)
 
@@ -202,7 +202,7 @@
         container marker, even if the container up to this point has been valid.
         """
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\n")
+            "Bazaar pack format 2 (introduced in 0.19)\n")
         self.assertRaises(
             errors.UnexpectedEndOfContainerError, reader.validate)
 
@@ -211,7 +211,7 @@
         multiple times in the container.
         """
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\n"
+            "Bazaar pack format 2 (introduced in 0.19)\n"
             "B0\nname\n\n"
             "B0\nname\n\n"
             "E")
@@ -220,7 +220,7 @@
     def test_validate_undecodeable_name(self):
         """Names that aren't valid UTF-8 cause validate to fail."""
         reader = self.get_reader_for(
-            "Bazaar pack format 1 (introduced in 0.18)\nB0\n\xcc\n\nE")
+            "Bazaar pack format 2 (introduced in 0.19)\nB0\n\xcc\n\nE")
         self.assertRaises(errors.InvalidRecordError, reader.validate)
         
 
@@ -229,7 +229,7 @@
 
     def get_reader_for(self, bytes):
         stream = StringIO(bytes)
-        reader = pack.BytesRecordReader(stream)
+        reader = container.BytesRecordReader(stream)
         return reader
 
     def test_record_with_no_name(self):
@@ -306,25 +306,6 @@
         reader = self.get_reader_for("123\nname")
         self.assertRaises(errors.UnexpectedEndOfContainerError, reader.read)
 
-    def test_read_invalid_name_whitespace(self):
-        """Names must have no whitespace."""
-        # A name with a space.
-        reader = self.get_reader_for("0\nbad name\n\n")
-        self.assertRaises(errors.InvalidRecordError, reader.read)
-
-        # A name with a tab.
-        reader = self.get_reader_for("0\nbad\tname\n\n")
-        self.assertRaises(errors.InvalidRecordError, reader.read)
-
-        # A name with a vertical tab.
-        reader = self.get_reader_for("0\nbad\vname\n\n")
-        self.assertRaises(errors.InvalidRecordError, reader.read)
-
-    def test_validate_whitespace_in_name(self):
-        """Names must have no whitespace."""
-        reader = self.get_reader_for("0\nbad name\n\n")
-        self.assertRaises(errors.InvalidRecordError, reader.validate)
-
     def test_validate_interrupted_prelude(self):
         """EOF during reading a record's prelude causes validate to fail."""
         reader = self.get_reader_for("")

=== modified file bzrlib/tests/__init__.py
--- bzrlib/tests/__init__.py
+++ bzrlib/tests/__init__.py
@@ -2260,7 +2260,7 @@
                    'bzrlib.tests.test_commit_merge',
                    'bzrlib.tests.test_config',
                    'bzrlib.tests.test_conflicts',
-                   'bzrlib.tests.test_pack',
+                   'bzrlib.tests.test_container',
                    'bzrlib.tests.test_counted_lock',
                    'bzrlib.tests.test_decorators',
                    'bzrlib.tests.test_delta',

=== modified directory  // last-changed:andrew.bennetts at canonical.com-200707170
... 44423-cetp5spep142xsr4
# revision id: andrew.bennetts at canonical.com-20070717044423-cetp5spep142xsr4
# sha1: 6ddb5bed4f84527c5bae21b7837d876f03a9a087
# inventory sha1: 0d2ce96fbef2f0a80a0e65e46940aa919be6f4ec
# parent ids:
#   pqm at pqm.ubuntu.com-20070716205413-42lqws7bkld2gbju
# base id: pqm at pqm.ubuntu.com-20070716205413-42lqws7bkld2gbju
# properties:
#   branch-nick: container-format



More information about the bazaar mailing list