#!/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))