]> code.delx.au - gnu-emacs-elpa/blob - admin/forward-diffs.py
Add debug option, to not send mail.
[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 <-p /path/to/packages> [-o overmaintfile] [--sendmail] [--debug]
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( "-p", dest="packagedir", default=None,
68 help="path to packages directory")
69 parser.add_option( "-s", dest="sender", default=None,
70 help="sender address for forwards")
71 parser.add_option( "--sendmail", dest="sendmail", default=False,
72 action="store_true", help="use sendmail rather than smtp")
73 parser.add_option( "--debug", dest="debug", default=False,
74 action="store_true", help="debug only, do not send mail")
75
76
77 ( opts, args ) = parser.parse_args()
78
79 if not opts.logfile:
80 parser.error('No logfile specified')
81
82 if not opts.maintfile:
83 parser.error('No maintfile specified')
84
85 if not opts.packagedir:
86 parser.error('No packagedir specified')
87
88 if not opts.sender:
89 parser.error('No sender specified')
90
91
92 if not os.path.isdir(opts.packagedir):
93 sys.stderr.write('Error reading packagedir\n')
94 sys.exit(1)
95
96
97 try:
98 lfile = open( opts.logfile, 'a' )
99 except Exception as err:
100 sys.stderr.write('Error opening logfile: %s\n' % str(err))
101 sys.exit(1)
102
103
104 try:
105 mfile = open( opts.maintfile, 'r' )
106 except Exception as err:
107 lfile.write('Error opening maintfile: %s\n' % str(err))
108 sys.exit(1)
109
110 ## Each element is package: maint1, maint2, ...
111 maints = {}
112
113 for line in mfile:
114 if re.match( '^#|^ *$', line ): continue
115 (pack, maint) = line.split()
116 maints[pack] = maint.split(',')
117
118 mfile.close()
119
120
121 if opts.overmaintfile:
122 try:
123 ofile = open( opts.overmaintfile, 'r' )
124 except Exception as err:
125 lfile.write('Error opening overmaintfile: %s\n' % str(err))
126 sys.exit(1)
127
128 for line in ofile:
129 if re.match( '^#|^ *$', line ): continue
130 (pack, maint) = line.split()
131 maints[pack] = maint.split(',')
132
133 ofile.close()
134
135
136 stdin = sys.stdin
137
138 text = stdin.read()
139
140
141 resent_via = 'GNU ELPA diff forwarder'
142
143 message = email.message_from_string( text )
144
145 (msg_name, msg_from) = email.utils.parseaddr( message['from'] )
146
147 lfile.write('\nDate: %s\n' % str(datetime.datetime.now()))
148 lfile.write('Message-ID: %s\n' % message['message-id'])
149 lfile.write('From: %s\n' % msg_from)
150
151 if resent_via == message['x-resent-via']:
152 lfile.write('Mail loop; aborting\n')
153 sys.exit(1)
154
155
156 start = False
157 packs_seen = []
158 maints_seen = []
159
160 for line in text.splitlines():
161
162 if re.match( '^modified:$', line ):
163 start = True
164 continue
165
166 if not start: continue
167
168 if re.match( '^ *$', line ): break
169
170
171 reg = re.match( '^packages/([^/]+)', line.strip() )
172 if not reg: break
173
174
175 pack = reg.group(1)
176
177 lfile.write('Package: %s\n' % pack)
178
179 if pack in packs_seen:
180 lfile.write('Already seen this package\n')
181 continue
182
183 packs_seen.append(pack)
184
185
186 if not pack in maints:
187 lfile.write('Unknown maintainer\n')
188 continue
189
190
191 for maint in maints[pack]:
192
193 lfile.write('Maint: %s\n' % maint)
194
195
196 if maint in maints_seen:
197 lfile.write('Already seen this maintainer\n')
198 continue
199
200 maints_seen.append(maint)
201
202
203 if maint == "nomail":
204 lfile.write('Not resending, no mail is requested\n')
205 continue
206
207
208 if maint == msg_from:
209 lfile.write('Not resending, since maintainer = committer\n')
210 continue
211
212
213 forward = message
214 forward.add_header('X-Resent-Via', resent_via)
215 forward.add_header('Resent-To', maint)
216 forward.add_header('Resent-From', opts.sender)
217
218 lfile.write('Resending via %s...\n' % ('sendmail'
219 if opts.sendmail else 'smtp') )
220
221
222 if debug: continue
223
224
225 if opts.sendmail:
226 s = os.popen("/usr/sbin/sendmail -i -f %s %s" %
227 (opts.sender, maint), "w")
228 s.write(forward.as_string())
229 status = s.close()
230 if status:
231 lfile.write('Sendmail exit status: %s\n' % status)
232
233 else:
234
235 try:
236 s = smtplib.SMTP('localhost')
237 except Exception as err:
238 lfile.write('Error opening smtp: %s\n' % str(err))
239 sys.exit(1)
240
241 try:
242 s.sendmail(opts.sender, maint, forward.as_string())
243 except Exception as err:
244 lfile.write('Error sending smtp: %s\n' % str(err))
245
246 s.quit()
247
248 ### forward-diffs.py ends here