]> code.delx.au - gnu-emacs-elpa/blob - admin/forward-diffs.py
Add optional override file to override maintainers.
[gnu-emacs-elpa] / admin / forward-diffs.py
1 #!/usr/bin/python
2 ### forward-diffs.py --- forward emacs-elpa-diffs mails to maintainers
3
4 ## Copyright (C) 2012 Free Software Foundation, Inc.
5
6 ## Author: Glenn Morris <rgm@gnu.org>
7
8 ## This program is free software; you can redistribute it and/or modify
9 ## it under the terms of the GNU General Public License as published by
10 ## the Free Software Foundation, either version 3 of the License, or
11 ## (at your option) any later version.
12
13 ## This program is distributed in the hope that it will be useful,
14 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ## GNU General Public License for more details.
17
18 ## You should have received a copy of the GNU General Public License
19 ## along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 ### Commentary:
22
23 ## Forward emails from the emacs-elpa-diffs mailing list to the
24 ## maintainer(s) of the modified files.
25
26 ## Example usage from procmail (all arguments are compulsory):
27
28 ## :0c
29 ## * ^TO_emacs-elpa-diffs@gnu\.org
30 ## | forward-diffs.py -m maintfile -l logfile -s sender
31
32 ## where
33
34 ## sender = your email address
35 ## logfile = file to write log to (you might want to rotate/compress/examine it)
36 ## maintfile = file listing packages and their maintainers, with format:
37 ##
38 ## package1 email1
39 ## package2 email2,email3
40 ##
41 ## Use "nomail" for the email field to not send a mail.
42 ##
43 ## overmaintfile = like maintfile, but takes precedence over it.
44
45 ### Code:
46
47 import optparse
48 import sys
49 import re
50 import email
51 import smtplib
52 import datetime
53 import os
54
55 usage="""usage: %prog <-m maintfile> <-l logfile> <-s sender>
56 [-o overmaintfile] [--sendmail]
57 Take a GNU ELPA diff on stdin, and forward it to the maintainer(s)."""
58
59 parser = optparse.OptionParser()
60 parser.set_usage ( usage )
61 parser.add_option( "-m", dest="maintfile", default=None,
62 help="file listing packages and maintainers")
63 parser.add_option( "-l", dest="logfile", default=None,
64 help="file to append output to")
65 parser.add_option( "-o", dest="overmaintfile", default=None,
66 help="override file listing packages and maintainers")
67 parser.add_option( "-s", dest="sender", default=None,
68 help="sender address for forwards")
69 parser.add_option( "--sendmail", dest="sendmail", default=False,
70 action="store_true", help="use sendmail rather than smtp")
71
72 ( opts, args ) = parser.parse_args()
73
74 if not opts.logfile:
75 parser.error('No logfile specified')
76
77 if not opts.maintfile:
78 parser.error('No maintfile specified')
79
80 if not opts.sender:
81 parser.error('No sender specified')
82
83
84 try:
85 lfile = open( opts.logfile, 'a' )
86 except Exception as err:
87 sys.stderr.write('Error opening logfile: %s\n' % str(err))
88 sys.exit(1)
89
90
91 try:
92 mfile = open( opts.maintfile, 'r' )
93 except Exception as err:
94 lfile.write('Error opening maintfile: %s\n' % str(err))
95 sys.exit(1)
96
97 ## Each element is package: maint1, maint2, ...
98 maints = {}
99
100 for line in mfile:
101 if re.match( '^#|^ *$', line ): continue
102 (pack, maint) = line.split()
103 maints[pack] = maint.split(',')
104
105 mfile.close()
106
107
108 if opts.overmaintfile:
109 try:
110 ofile = open( opts.overmaintfile, 'r' )
111 except Exception as err:
112 lfile.write('Error opening overmaintfile: %s\n' % str(err))
113 sys.exit(1)
114
115 for line in ofile:
116 if re.match( '^#|^ *$', line ): continue
117 (pack, maint) = line.split()
118 maints[pack] = maint.split(',')
119
120 ofile.close()
121
122
123 stdin = sys.stdin
124
125 text = stdin.read()
126
127
128 resent_via = 'GNU ELPA diff forwarder'
129
130 message = email.message_from_string( text )
131
132 (msg_name, msg_from) = email.utils.parseaddr( message['from'] )
133
134 lfile.write('\nDate: %s\n' % str(datetime.datetime.now()))
135 lfile.write('Message-ID: %s\n' % message['message-id'])
136 lfile.write('From: %s\n' % msg_from)
137
138 if resent_via == message['x-resent-via']:
139 lfile.write('Mail loop; aborting\n')
140 sys.exit(1)
141
142
143 start = False
144 packs_seen = []
145 maints_seen = []
146
147 for line in text.splitlines():
148
149 if re.match( '^modified:$', line ):
150 start = True
151 continue
152
153 if not start: continue
154
155 if re.match( '^ *$', line ): break
156
157
158 reg = re.match( '^packages/([^/]+)', line.strip() )
159 if not reg: break
160
161
162 pack = reg.group(1)
163
164 lfile.write('Package: %s\n' % pack)
165
166 if pack in packs_seen:
167 lfile.write('Already seen this package\n')
168 continue
169
170 packs_seen.append(pack)
171
172
173 if not pack in maints:
174 lfile.write('Unknown maintainer\n')
175 continue
176
177
178 for maint in maints[pack]:
179
180 lfile.write('Maint: %s\n' % maint)
181
182
183 if maint in maints_seen:
184 lfile.write('Already seen this maintainer\n')
185 continue
186
187 maints_seen.append(maint)
188
189
190 if maint == "nomail":
191 lfile.write('Not resending, no mail is requested\n')
192 continue
193
194
195 if maint == msg_from:
196 lfile.write('Not resending, since maintainer = committer\n')
197 continue
198
199
200 forward = message
201 forward.add_header('X-Resent-Via', resent_via)
202 forward.add_header('Resent-To', maint)
203 forward.add_header('Resent-From', opts.sender)
204
205 lfile.write('Resending via %s...\n' % ('sendmail'
206 if opts.sendmail else 'smtp') )
207
208
209 if opts.sendmail:
210 s = os.popen("/usr/sbin/sendmail -i -f %s %s" %
211 (opts.sender, maint), "w")
212 s.write(forward.as_string())
213 status = s.close()
214 if status:
215 lfile.write('Sendmail exit status: %s\n' % status)
216
217 else:
218
219 try:
220 s = smtplib.SMTP('localhost')
221 except Exception as err:
222 lfile.write('Error opening smtp: %s\n' % str(err))
223 sys.exit(1)
224
225 try:
226 s.sendmail(opts.sender, maint, forward.as_string())
227 except Exception as err:
228 lfile.write('Error sending smtp: %s\n' % str(err))
229
230 s.quit()
231
232 ### forward-diffs.py ends here