Implement 'done' feature.
authorJelmer Vernooij <jelmer@samba.org>
Tue, 28 Feb 2012 11:49:37 +0000 (12:49 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Tue, 28 Feb 2012 11:49:37 +0000 (12:49 +0100)
NEWS
fastimport/errors.py
fastimport/parser.py
fastimport/tests/test_parser.py

diff --git a/NEWS b/NEWS
index 38b4ab48506de8bca1055787b0dbdd5aefd0ae43..f3a810a1b3d6f2bbd903dd711876cbfee1227255 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+0.9.1  UNRELEASED
+
+ * Update FSF address in headers. (Dan Callaghan, #868800)
+
+ * Support 'done' feature. (Jelmer Vernooij, #942563)
+
 0.9.0  2011-01-30
 
  Initial release.
index 068af6fe2f4f154dd809801862b45fd2990f2e60..afb78bc3c9d2d6fb4efdd0be67dd0c0d5f6c5164 100644 (file)
@@ -165,6 +165,15 @@ class InvalidTimezone(ParsingError):
             self.reason = ''
 
 
+class PrematureEndOfStream(ParsingError):
+    """Raised when the 'done' feature was specified but missing."""
+
+    _fmt = (_LOCATION_FMT + "Stream end before 'done' command")
+
+    def __init__(self, lineno):
+        ParsingError.__init__(self, lineno)
+
+
 class UnknownDateFormat(ImportError):
     """Raised when an unknown date format is given."""
 
index 7612ac07018ee73fd3f540b7b00a89ac24459cb0..ca8e294a7594814dd49351967f1648f17c8727d7 100644 (file)
@@ -272,6 +272,7 @@ class ImportParser(LineBasedParser):
         self.user_mapper = user_mapper
         # We auto-detect the date format when a date is first encountered
         self.date_parser = None
+        self.features = {}
 
     def warning(self, msg):
         sys.stderr.write("warning line %d: %s\n" % (self.lineno, msg))
@@ -281,6 +282,8 @@ class ImportParser(LineBasedParser):
         while True:
             line = self.next_line()
             if line is None:
+                if 'done' in self.features:
+                    raise errors.PrematureEndOfStream(self.lineno)
                 break
             elif len(line) == 0 or line.startswith('#'):
                 continue
@@ -387,6 +390,7 @@ class ImportParser(LineBasedParser):
             value = self._path(parts[1])
         else:
             value = None
+        self.features[name] = value
         return commands.FeatureCommand(name, value, lineno=self.lineno)
 
     def _parse_file_modify(self, info):
index 06270a82e8c419c80a1a1d60f662ae2f3fbe92c2..4bf11c7cd044a6ec58ba5c4a25b1fb5983f7609e 100644 (file)
@@ -259,6 +259,32 @@ class TestImportParser(testtools.TestCase):
         self.assertEqual('Donald', cmd.more_authors[1][0])
         self.assertEqual('donald@duck.org', cmd.more_authors[1][1])
 
+    def test_done_feature_missing_done(self):
+        s = StringIO.StringIO("""feature done
+""")
+        p = parser.ImportParser(s)
+        cmds = p.iter_commands()
+        self.assertEquals("feature", cmds.next().name)
+        self.assertRaises(errors.PrematureEndOfStream, cmds.next)
+
+    def test_done_with_feature(self):
+        s = StringIO.StringIO("""feature done
+done
+more data
+""")
+        p = parser.ImportParser(s)
+        cmds = p.iter_commands()
+        self.assertEquals("feature", cmds.next().name)
+        self.assertRaises(StopIteration, cmds.next)
+
+    def test_done_without_feature(self):
+        s = StringIO.StringIO("""done
+more data
+""")
+        p = parser.ImportParser(s)
+        cmds = p.iter_commands()
+        self.assertEquals([], list(cmds))
+
 
 class TestStringParsing(testtools.TestCase):