Created
August 20, 2014 10:39
-
-
Save fritschy/b73fb2231505e283b062 to your computer and use it in GitHub Desktop.
Submit patches using git send-email/format-patch that are compatible with an msft exchange/outlook receiver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Marcus Fritzsch, July 2014 | |
import os.path | |
import sys | |
import glob | |
from tempfile import mkdtemp | |
from email.parser import Parser | |
from email.generator import Generator | |
from subprocess import check_output | |
try: | |
from cStringIO import StringIO | |
except: | |
from io import StringIO | |
# Ready patches from git for submission in a outlook-on-receiver-side | |
# friendly format. That is; attach the patches including all it's headers, | |
# just like if you manually created a lot of email in outlook and | |
# attached a patch to each of them. | |
parser = Parser() | |
commit = sys.argv[-1] | |
patchdir = "patches" | |
# where the emails will be | |
tmpdir = mkdtemp() | |
# where the patches will be | |
patchdir = os.path.join(tmpdir, patchdir) | |
os.mkdir(patchdir) | |
def spawn(cmd): | |
return check_output(cmd.replace(' ', ' ').split(' ')) | |
def rewrite_email(name): | |
basename = os.path.basename(name) | |
# do not rewrite cover letter | |
if basename == "0000-cover-letter.patch": | |
return | |
with open(name, "r") as mf: | |
m = parser.parse(mf) | |
parts = list(m.walk()) | |
# assert the files are in our expected layout! | |
assert len(parts) == 3 | |
# set the email payload to be just the email body of the original mail | |
m.set_payload([parts[1]]) | |
# read patch and attach | |
attach = os.path.join(patchdir, basename) | |
with open(attach, "r") as f: | |
fs = f.read() | |
# make attachment | |
amail = None | |
with open(attach, "r") as ff: | |
amail = parser.parse(ff) | |
amail.add_header('Content-Disposition', 'attachment', filename=basename) | |
amail.add_header('Content-Type', 'text/x-patch') | |
# also, set the attachment to be it whole payload, this is needed | |
# as we need the headers to be present in the attachment too, this | |
# this is the actual cause we had to hack up this piece of near | |
# future technology! | |
amail.set_payload(fs) | |
m.attach(amail) | |
# Actually rewrite the email. | |
with open(name, "w") as f: | |
io = StringIO() | |
g = Generator(io, mangle_from_=False, maxheaderlen=60) | |
g.flatten(m) | |
f.write(io.getvalue()) | |
def check_patches(patches): | |
# assert that we have a cover-letter for submission! | |
assert patches[0].endswith("0000-cover-letter.patch") | |
# assert that we only have .patch files in the list! | |
assert all(x.endswith(".patch") for x in patches) | |
# assert that no filename contains a ' ' | |
assert all(not (' ' in x or '\t' in x) for x in patches) | |
def main(): | |
# extra args for format-patch, also be aware that this is passed to system() | |
# unchecked | |
xargs = " ".join(sys.argv[1:-1]) | |
# XXX: allow cover-letter to be specified on command line, | |
# take care of cover-letter (or all xargs?) to the second | |
# format-patch call. | |
# Create emails for submission | |
patches = spawn("git format-patch --thread --signoff --attach --cover-letter -o %s %s %s" % (tmpdir, xargs, commit)) | |
patches = list(filter(lambda x: len(x) > 0, bytes(patches).decode().split("\n"))) | |
check_patches(patches) | |
# Create patches for attachment | |
spawn("git format-patch --signoff --cover-letter -o %s %s" % (patchdir, commit)) | |
for name in patches: | |
rewrite_email(name) | |
os.system("git send-email --annotate --suppress-cc=all %s %s" % (xargs, " ".join(patches))) | |
for x in patches: | |
os.unlink(os.path.join(patchdir, os.path.basename(x))) | |
os.unlink(x) | |
os.rmdir(patchdir) | |
os.rmdir(tmpdir) | |
__name__ == '__main__' and main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment