PatchSeries: Only pass patch description and header to git-mailinfo
authorGuido Günther <agx@sigxcpu.org>
Thu, 8 Nov 2018 10:09:10 +0000 (11:09 +0100)
committerGuido Günther <agx@sigxcpu.org>
Thu, 8 Nov 2018 10:34:46 +0000 (11:34 +0100)
There are patches around that use

Content-Transfer-Encoding: base64

but the actual patch after '---' is unencoded ascii resulting in garbage
after the patch description when imported into a patch queue.

Since we're discarding the patch part of git-mailinfo anyway don't pass
this on in the first place.

Closes: #912426
gbp/patch_series.py
tests/08_test_patch.py
tests/08_test_patch_data/base64.patch [new file with mode: 0644]

index c74a414a411bb0ed6fc9e5e344cb17cee4e5e4f4..ef373a8389354a22498de1dde81e8bd3cd2e3c56 100644 (file)
@@ -19,9 +19,9 @@
 import collections
 import os
 import re
-import subprocess
 import tempfile
 from gbp.errors import GbpError
+from gbp.git.repository import GitRepository
 
 VALID_DEP3_ENDS = re.compile(r'(?:---|\*\*\*|Index:)[ \t][^ \t]|^diff -|^---')
 
@@ -68,17 +68,38 @@ class Patch(object):
         using I{git mailinfo}
         """
         self.info = {}
+        self.long_desc = ''
+
         body = tempfile.NamedTemporaryFile(prefix='gbp_')
-        pipe = subprocess.Popen("git mailinfo -k '%s' /dev/null 2>/dev/null < '%s'" %
-                                (body.name, self.path),
-                                shell=True,
-                                stdout=subprocess.PIPE).stdout
-        for line in pipe:
-            line = line.decode()
+
+        # No patch yet, file name information only
+        if not os.path.exists(self.path):
+            return
+        # The patch description might contain UTF-8 while the actual patch is ascii.
+        # To unconfuse git-mailinfo stop at the patch separator
+        toparse = []
+        for line in open(self.path, 'rb'):
+            if line == b'---\n':
+                break
+            toparse.append(line)
+
+        out, err, ret = GitRepository.git_inout(command='mailinfo',
+                                                args=['-k', body.name, '/dev/null'],
+                                                input=b''.join(toparse),
+                                                extra_env=None,
+                                                cwd=None,
+                                                capture_stderr=True)
+        if ret != 0:
+            raise GbpError("Failed to read patch header of '%s': %s" %
+                           (self.path, err))
+
+        # Header
+        for line in out.decode().split('\n'):
             if ':' in line:
                 rfc_header, value = line.split(" ", 1)
                 header = rfc_header[:-1].lower()
                 self.info[header] = value.strip()
+        # Body
         try:
             self.long_desc = "".join([l.decode("utf-8", "backslashreplace") for l in body])
         except (IOError, UnicodeDecodeError) as msg:
index c0f3e5cefd39d7d1ee5f3db025ebccdd44e684a2..1567f018693f05e33616f3a1eaa8c0c2b3ed6793 100644 (file)
@@ -102,3 +102,27 @@ usbip_common.c has the same problem.
 Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
 """,
                          p.long_desc)
+
+
+class TestBase64Patch(unittest.TestCase):
+    data_dir = os.path.splitext(__file__)[0] + '_data'
+
+    def test_parse(self):
+        """Get patch information from git mailimport with base64 body but plain text patch"""
+        patchfile = os.path.join(self.data_dir, "base64.patch")
+        self.assertTrue(os.path.exists(patchfile))
+        p = Dep3Patch(patchfile)
+        self.assertEqual("Sort files in archive (reproducible builds)", p.subject)
+        self.assertEqual("Nick Leverton", p.author)
+        self.assertEqual("nick@leverton.org", p.email)
+        self.assertEqual("""\
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: base64
+
+Sort files when using mergelib to create libnullmailer.a, to get
+reproducible build
+
+Author: Alexis Bienvenüe <pado@passoire.fr>
+""",
+                         p.long_desc)
diff --git a/tests/08_test_patch_data/base64.patch b/tests/08_test_patch_data/base64.patch
new file mode 100644 (file)
index 0000000..c267be8
--- /dev/null
@@ -0,0 +1,25 @@
+From: Nick Leverton <nick@leverton.org>
+Date: Tue, 11 Jul 2017 22:25:43 -0300
+Subject: Sort files in archive (reproducible builds)
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: base64
+
+U29ydCBmaWxlcyB3aGVuIHVzaW5nIG1lcmdlbGliIHRvIGNyZWF0ZSBsaWJudWxsbWFpbGVyLmEs
+IHRvIGdldApyZXByb2R1Y2libGUgYnVpbGQKCkF1dGhvcjogQWxleGlzIEJpZW52ZW7DvGUgPHBh
+ZG9AcGFzc29pcmUuZnI+Cg==
+---
+ lib/mergelib.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/mergelib.sh b/lib/mergelib.sh
+index f9b7a94..4e71079 100644
+--- a/lib/mergelib.sh
++++ b/lib/mergelib.sh
+@@ -12,5 +12,5 @@ for input in "$@"; do
+       "${AR:-ar}" x ../../"$input"
+       cd ..
+ done
+-"${AR:-ar}" rc ../"$archive" */*
++"${AR:-ar}" rc ../"$archive" `LC_ALL=C ls */*`
+ "${RANLIB:-ranlib}" ../"$archive"