[PATCH aiaiai 6/7] aiaiai: extract patches from email prior to using git-am

Jacob Keller jacob.e.keller at intel.com
Fri Apr 4 15:06:51 PDT 2014

Some patch authors submit patches directly attached via git-format-patch
output as an attachment. Sometimes they include both the patch and the
inline diff. This is problematic because it causes aiaiai to fail to
apply the patch, due to git being confused about the attached patch.
This patch modifies how aiaiai reads the commits, using a python script
which is capable of extracting the patches from the mbox (including
attachments) before calling git-am.

This helps aiaiai more easily handle this weird patch case, and still
works great for regular patch submissions. In addition, turn on 3-way
merge of git-am, so that duplicate patches will be properly ignored (as
in the case with inlined and attached patches)

Signed-off-by: Jacob Keller <jacob.e.keller at intel.com>
 helpers/aiaiai-extract-patches | 54 ++++++++++++++++++++++++++++++++++++++++++
 helpers/aiaiai-sh-functions    |  2 +-
 2 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100755 helpers/aiaiai-extract-patches

diff --git a/helpers/aiaiai-extract-patches b/helpers/aiaiai-extract-patches
new file mode 100755
index 000000000000..7aeab0d89376
--- /dev/null
+++ b/helpers/aiaiai-extract-patches
@@ -0,0 +1,54 @@
+# Copyright 2014 Intel Corporation
+# Author: Jacob Keller
+# License: GPLv2
+import argparse
+import email
+import string
+import sys
+headers_to_copy = ['From', 'Date', 'Subject', 'To']
+Extract git patches out of an email message, including if the patch is embedded
+in the email as an attachment from git-format-patch. %(prog)s only works on a
+single email message at a time, so another program for splitting mbox files
+such as formail is suggested.
+parser = argparse.ArgumentParser(description=description)
+group = parser.add_mutually_exclusive_group()
+group.add_argument('--discard-inline', dest='inline', action='store_false', help='discard inlined segment, keeping only git-format-patch attachments')
+group.add_argument('--discard-attachments', dest='attachments', action='store_false', help='discard any git-format-patch attachments, keeping only inlined email')
+args = parser.parse_args()
+# Now, grab standard input and parse it as an email message
+msg = email.message_from_file(sys.stdin)
+patches = []
+if msg.is_multipart():
+    segments = msg.get_payload()
+    for segment in segments[:]:
+        if segment.get_payload().startswith(">From "):
+            segments.remove(segment)
+            patches.append(email.message_from_string(segment.get_payload()[1:]))
+inline = email.message.Message()
+inline.set_unixfrom( msg.get_unixfrom() )
+for header in headers_to_copy:
+    inline[header] = msg[header]
+if msg.is_multipart():
+    inline.set_payload( ''.join( [x.get_payload() for x in msg.get_payload() ] ) )
+    inline.set_payload( msg.get_payload() )
+if args.inline:
+    print inline.as_string(unixfrom=True)
+if args.attachments:
+    for patch in patches:
+        print patch.as_string(unixfrom=True)
diff --git a/helpers/aiaiai-sh-functions b/helpers/aiaiai-sh-functions
index c17255aa2809..799672c00017 100644
--- a/helpers/aiaiai-sh-functions
+++ b/helpers/aiaiai-sh-functions
@@ -175,7 +175,7 @@ apply_patch()
 	cmt="$(git rev-parse "HEAD^{commit}")"
-	am="$(git am 2>&1)" || {
+	am="$(formail -s aiaiai-extract-patches | git am --3way 2>&1)" || {
 		cat <<EOF
 Failed to apply patch(es) with git am on top of:
 $(git log -1 --oneline "$cmt")

More information about the aiaiai mailing list