From 48df8095d4e50a3c98a14939ed046f2e100615f7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 28 Nov 2022 07:59:26 +0200 Subject: Add patch-save.py script Signed-off-by: Laurent Pinchart --- patch-save.py | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100755 patch-save.py diff --git a/patch-save.py b/patch-save.py new file mode 100755 index 0000000..1c0516f --- /dev/null +++ b/patch-save.py @@ -0,0 +1,90 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022 Laurent Pinchart +# +# Author: Laurent Pinchart +# +# Patch save script for mutt that handles mailman From header mangling. +# +# To install, copy the script to ~/.mutt/, and add the following lines to your +# .muttrc to bind to ctrl-h. +# +# set pipe_split=yes +# macro index \Ch "unset wait_key +# set pipe_decode +# ~/.mutt/patch-save.py +# unset pipe_decode +# set wait_key" "output git patches" +# + +import email +import pathlib +import re +import sys + + +def sanitize(s): + out = '' + + for c in s: + if c in '[]': + continue + + if c in "'": + c = '.' + elif c in '/:': + c = '-' + elif c in '*()" \t\n\r': + c = '_' + + out += c + + return out + + +def main(argv): + + # Parse the message from stdin as binary, as we can't assume any particular + # encoding. + msg = email.message_from_binary_file(sys.stdin.buffer) + + # mailman can mangle the From header to work around DMARC rejection rules. + # It then formats From as "Name via mailing-list " and + # stores the original sender in the Reply-to header. Restore the original + # author in the From header to please git-am. + from_header = msg.get('From') + reply_to = msg.get('Reply-to') + if reply_to and ' via ' in from_header: + msg.replace_header('From', reply_to) + + subject = msg.get('Subject') + if not subject: + return 1 + + # The subject can be an str instance or an email.header.Header instance. + # Convert it to str in all cases. + subject = str(subject) + + # Strip everything before the [PATCH] or [RESEND] tag. + match = re.search(r'\[(PATCH|RESEND) [^]]*\].*', subject) + if match: + subject = match.group(0) + + # Sanitize the subject. + subject = sanitize(subject) + + subject = subject.replace('..', '.') + subject = subject.replace('-_', '_') + subject = subject.replace('__', '_') + + subject = subject.strip() + subject = subject.rstrip('.') + + file_name = pathlib.Path.home() / '.maildir' / 'patches' / (subject + '.patch') + open(file_name, 'wb').write(bytes(msg)) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) -- cgit v1.2.3