]> www.infradead.org Git - users/dedekind/aiaiai.git/commitdiff
aiaiai: extract patches from email prior to using git-am
authorJacob Keller <jacob.e.keller@intel.com>
Wed, 9 Apr 2014 22:26:06 +0000 (15:26 -0700)
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Fri, 25 Apr 2014 22:37:45 +0000 (15:37 -0700)
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@intel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
helpers/aiaiai-extract-patches [new file with mode: 0755]
helpers/aiaiai-sh-functions

diff --git a/helpers/aiaiai-extract-patches b/helpers/aiaiai-extract-patches
new file mode 100755 (executable)
index 0000000..fe7b7a1
--- /dev/null
@@ -0,0 +1,76 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+
+"""
+Extract attached patches from MIME messaged passed to standard input. Will
+output an mbox where each message contains a single patch. Assumes attachments
+will begin with '>From' to indicate they are a seperate email to be extracted.
+
+Copyright 2014 Intel Corporation
+Author: Jacob Keller <jacob.e.keller@intel.com>
+License: GPLv2
+"""
+
+import argparse
+import email
+import sys
+
+def main():
+    """Extract attached patches from stdin as a MIME email."""
+    headers_to_copy = ["From", "Date", "Subject", "To"]
+
+    description = """\
+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()]))
+    else:
+        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)
+
+if __name__ == "__main__":
+    sys.exit(main())
+
+# vim: ts=4 et sw=4 sts=4 ai sta:
index c17255aa2809f4b59da86ac0de78d595270abab0..799672c00017e0267a570cd0da99474b31460ca1 100644 (file)
@@ -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")