Rev 5057: (mbp, for toshio) handle noise at the start of patches in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Feb 25 06:51:33 GMT 2010


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

------------------------------------------------------------
revno: 5057 [merge]
revision-id: pqm at pqm.ubuntu.com-20100225065131-kk37qbxhedr2oyzy
parent: pqm at pqm.ubuntu.com-20100224101714-wy0vr6ldlrq7fdk7
parent: mbp at sourcefrog.net-20100225061727-4sd9lt0qmdc6087t
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2010-02-25 06:51:31 +0000
message:
  (mbp, for toshio) handle noise at the start of patches
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/patches.py              patches.py-20050727183609-378c1cc5972ce908
  bzrlib/tests/test_patches.py   test_patches.py-20051231203844-f4974d20f6aea09c
=== modified file 'NEWS'
--- a/NEWS	2010-02-23 07:43:11 +0000
+++ b/NEWS	2010-02-25 06:17:27 +0000
@@ -73,6 +73,11 @@
 * ``bzr remove-tree`` can now remove multiple working trees.
   (Jared Hance, Andrew Bennetts, #253137)
 
+* ``bzr upgrade`` now names backup directory as ``backup.bzr.~N~`` instead
+  of ``backup.bzr``. This directory is ignored by bzr commands such as
+  ``add``.
+  (Parth Malwankar, #335033, #300001)
+
 * Network transfer amounts and rates are now displayed in SI units according
   to the Ubuntu Units Policy <https://wiki.ubuntu.com/UnitsPolicy>.
   (Gordon Tyler, #514399)
@@ -81,10 +86,8 @@
   prevents ``bzr status --short`` from crashing when those files are
   present.  (John Arbash Meinel, #303275)
 
-* ``bzr upgrade`` now names backup directory as ``backup.bzr.~N~`` instead
-  of ``backup.bzr``. This directory is ignored by bzr commands such as
-  ``add``.
-  (Parth Malwankar, #335033, #300001)
+* Tolerate patches with leading noise in ``bzr-handle-patch``.
+  (Toshio Kuratomi, Martin Pool, #502076)
 
 API Changes
 ***********

=== modified file 'bzrlib/patches.py'
--- a/bzrlib/patches.py	2010-02-17 17:11:16 +0000
+++ b/bzrlib/patches.py	2010-02-25 06:17:27 +0000
@@ -250,7 +250,13 @@
         return shift
 
 
-def iter_hunks(iter_lines):
+def iter_hunks(iter_lines, allow_dirty=False):
+    '''
+    :arg iter_lines: iterable of lines to parse for hunks
+    :kwarg allow_dirty: If True, when we encounter something that is not
+        a hunk header when we're looking for one, assume the rest of the lines
+        are not part of the patch (comments or other junk).  Default False
+    '''
     hunk = None
     for line in iter_lines:
         if line == "\n":
@@ -260,7 +266,15 @@
             continue
         if hunk is not None:
             yield hunk
-        hunk = hunk_from_header(line)
+        try:
+            hunk = hunk_from_header(line)
+        except MalformedHunkHeader:
+            if allow_dirty:
+                # If the line isn't a hunk header, then we've reached the end
+                # of this patch and there's "junk" at the end.  Ignore the
+                # rest of this patch.
+                return
+            raise
         orig_size = 0
         mod_size = 0
         while orig_size < hunk.orig_range or mod_size < hunk.mod_range:
@@ -339,7 +353,12 @@
                     pos += 1
 
 
-def parse_patch(iter_lines):
+def parse_patch(iter_lines, allow_dirty=False):
+    '''
+    :arg iter_lines: iterable of lines to parse
+    :kwarg allow_dirty: If True, allow the patch to have trailing junk.
+        Default False
+    '''
     iter_lines = iter_lines_handle_nl(iter_lines)
     try:
         (orig_name, mod_name) = get_patch_names(iter_lines)
@@ -347,15 +366,29 @@
         return BinaryPatch(e.orig_name, e.mod_name)
     else:
         patch = Patch(orig_name, mod_name)
-        for hunk in iter_hunks(iter_lines):
+        for hunk in iter_hunks(iter_lines, allow_dirty):
             patch.hunks.append(hunk)
         return patch
 
 
-def iter_file_patch(iter_lines):
+def iter_file_patch(iter_lines, allow_dirty=False):
+    '''
+    :arg iter_lines: iterable of lines to parse for patches
+    :kwarg allow_dirty: If True, allow comments and other non-patch text
+        before the first patch.  Note that the algorithm here can only find
+        such text before any patches have been found.  Comments after the
+        first patch are stripped away in iter_hunks() if it is also passed
+        allow_dirty=True.  Default False.
+    '''
+    ### FIXME: Docstring is not quite true.  We allow certain comments no
+    # matter what, If they startwith '===', '***', or '#' Someone should
+    # reexamine this logic and decide if we should include those in
+    # allow_dirty or restrict those to only being before the patch is found
+    # (as allow_dirty does).
     regex = re.compile(binary_files_re)
     saved_lines = []
     orig_range = 0
+    beginning = True
     for line in iter_lines:
         if line.startswith('=== ') or line.startswith('*** '):
             continue
@@ -365,7 +398,12 @@
             if line.startswith('-') or line.startswith(' '):
                 orig_range -= 1
         elif line.startswith('--- ') or regex.match(line):
-            if len(saved_lines) > 0:
+            if allow_dirty and beginning:
+                # Patches can have "junk" at the beginning
+                # Stripping junk from the end of patches is handled when we
+                # parse the patch
+                beginning = False
+            elif len(saved_lines) > 0:
                 yield saved_lines
             saved_lines = []
         elif line.startswith('@@'):
@@ -397,8 +435,15 @@
         yield last_line
 
 
-def parse_patches(iter_lines):
-    return [parse_patch(f.__iter__()) for f in iter_file_patch(iter_lines)]
+def parse_patches(iter_lines, allow_dirty=False):
+    '''
+    :arg iter_lines: iterable of lines to parse for patches
+    :kwarg allow_dirty: If True, allow text that's not part of the patch at
+        selected places.  This includes comments before and after a patch
+        for instance.  Default False.
+    '''
+    return [parse_patch(f.__iter__(), allow_dirty) for f in
+                        iter_file_patch(iter_lines, allow_dirty)]
 
 
 def difference_index(atext, btext):

=== modified file 'bzrlib/tests/test_patches.py'
--- a/bzrlib/tests/test_patches.py	2010-02-17 17:11:16 +0000
+++ b/bzrlib/tests/test_patches.py	2010-02-25 06:17:27 +0000
@@ -1,5 +1,4 @@
 # Copyright (C) 2005-2010 Aaron Bentley, Canonical Ltd
-# <aaron.bentley at utoronto.ca>
 #
 # 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
@@ -55,6 +54,14 @@
         finally:
             datafile.close()
 
+    def test_parse_patches_leading_noise(self):
+        # https://bugs.edge.launchpad.net/bzr/+bug/502076
+        # https://code.edge.launchpad.net/~toshio/bzr/allow-dirty-patches/+merge/18854
+        lines = ["diff -pruN commands.py",
+            "--- orig/commands.py",
+            "+++ mod/dommands.py"]
+        bits = parse_patches(iter(lines), allow_dirty=True)
+
     def testValidPatchHeader(self):
         """Parse a valid patch header"""
         lines = "--- orig/commands.py\n+++ mod/dommands.py\n".split('\n')




More information about the bazaar-commits mailing list