From 9c9115178efdcf0f6457cc68c6ba00de6ec2df9a Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 9 Apr 2014 15:26:06 -0700 Subject: [PATCH] aiaiai: extract patches from email prior to using git-am 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 Signed-off-by: Artem Bityutskiy --- helpers/aiaiai-extract-patches | 76 ++++++++++++++++++++++++++++++++++ helpers/aiaiai-sh-functions | 2 +- 2 files changed, 77 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 0000000..fe7b7a1 --- /dev/null +++ b/helpers/aiaiai-extract-patches @@ -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 +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: diff --git a/helpers/aiaiai-sh-functions b/helpers/aiaiai-sh-functions index c17255a..799672c 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 <