blob: a9b9a3c3dc3187b2b3848565b2e26fddfd7cce46 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2022 Laurent Pinchart
#
# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
#
# 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 "<enter-command>unset wait_key<enter>
# <enter-command>set pipe_decode<enter>
# <tag-prefix><pipe-entry>~/.mutt/patch-save.py<enter>
# <enter-command>unset pipe_decode<enter>
# <enter-command>set wait_key<enter>" "output git patches"
#
import email
import email.parser
import email.policy
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.
parser = email.parser.BytesParser(policy=email.policy.default)
msg = parser.parse(sys.stdin.buffer)
# mailman can mangle the From header to work around DMARC rejection rules.
# It then formats From as "Name via mailing-list <mailing-list@domain>" 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))
|