diff options
-rwxr-xr-x | scripts/rfr | 119 |
1 files changed, 113 insertions, 6 deletions
diff --git a/scripts/rfr b/scripts/rfr index d5d776ee..0d54d572 100755 --- a/scripts/rfr +++ b/scripts/rfr | |||
@@ -5,9 +5,14 @@ | |||
5 | 5 | ||
6 | import os | 6 | import os |
7 | import re | 7 | import re |
8 | import sys | ||
8 | import json | 9 | import json |
9 | import argparse | 10 | import argparse |
11 | import tempfile | ||
10 | import subprocess | 12 | import subprocess |
13 | import smtplib | ||
14 | |||
15 | from email.mime.text import MIMEText | ||
11 | 16 | ||
12 | VERSION = '1.0.0' | 17 | VERSION = '1.0.0' |
13 | 18 | ||
@@ -50,6 +55,14 @@ Otherwise it's treated as a git commit ID. | |||
50 | help='print the program version') | 55 | help='print the program version') |
51 | parser.add_argument('-m', '--msg', action='store', default=None, | 56 | parser.add_argument('-m', '--msg', action='store', default=None, |
52 | help='Custom message to add to the RFR email') | 57 | help='Custom message to add to the RFR email') |
58 | parser.add_argument('-N', '--no-msg', action='store_true', default=False, | ||
59 | help='Force no message in output.') | ||
60 | parser.add_argument('-e', '--email', action='store_true', default=False, | ||
61 | help='Use direct email to post the RFR.') | ||
62 | parser.add_argument('-s', '--subject', action='store', default=None, | ||
63 | help='Specify the email\'s subject.') | ||
64 | parser.add_argument('-R', '--sender', action='store', default=None, | ||
65 | help='Specify a special from: email address.') | ||
53 | 66 | ||
54 | # Positionals: the gerrit URLs. | 67 | # Positionals: the gerrit URLs. |
55 | parser.add_argument('commits', metavar='Commit-IDs', | 68 | parser.add_argument('commits', metavar='Commit-IDs', |
@@ -148,15 +161,39 @@ def git_sha1_from_commit(commit_ish): | |||
148 | 161 | ||
149 | return stdout_data.decode('utf-8') | 162 | return stdout_data.decode('utf-8') |
150 | 163 | ||
164 | def get_user_message(start_msg): | ||
165 | """ | ||
166 | Get a user message from the user. This is done with the default text | ||
167 | editor. | ||
168 | """ | ||
169 | |||
170 | editor = os.environ.get('EDITOR', 'vim') | ||
171 | |||
172 | with tempfile.NamedTemporaryFile(suffix=".tmp") as filp: | ||
173 | filp.write(start_msg) | ||
174 | filp.flush() | ||
175 | |||
176 | edit_cmd = editor + ' ' + filp.name | ||
177 | |||
178 | try: | ||
179 | subprocess.call(edit_cmd.split()) | ||
180 | except: | ||
181 | print('Failed to run editor: `%s\'' % edit_cmd) | ||
182 | return None | ||
183 | |||
184 | filp.seek(0) | ||
185 | return filp.read() | ||
186 | |||
151 | def indent_lines(text, ind): | 187 | def indent_lines(text, ind): |
152 | """ | 188 | """ |
153 | Prepend each new line in the passed text with ind. | 189 | Prepend each new line in the passed text with ind. |
154 | """ | 190 | """ |
155 | return ''.join(ind + l + '\n' for l in text.splitlines()) | 191 | return ''.join(ind + l + '\n' for l in text.splitlines()) |
156 | 192 | ||
157 | def display_commits(commits_info, extra_message): | 193 | def format_commits(commits_info, extra_message): |
158 | """ | 194 | """ |
159 | Takes a list of the commit info objects to print. | 195 | Takes a list of the commit info objects and returns a string with the |
196 | text to print. This can either be directly printed or emailed. | ||
160 | """ | 197 | """ |
161 | 198 | ||
162 | whole_template = """ | 199 | whole_template = """ |
@@ -193,9 +230,62 @@ Thanks! | |||
193 | cmtmsg=indent_lines( | 230 | cmtmsg=indent_lines( |
194 | c['commitMessage'], ' ')) | 231 | c['commitMessage'], ' ')) |
195 | 232 | ||
196 | print(whole_template.format(cmt_descriptions=cmt_descriptions, | 233 | return whole_template.format(cmt_descriptions=cmt_descriptions, |
197 | extra_message=extra_message, | 234 | extra_message=extra_message, |
198 | cmt_verbose=cmt_verbose)) | 235 | cmt_verbose=cmt_verbose) |
236 | |||
237 | def display_commits(commits_info, extra_message): | ||
238 | """ | ||
239 | Print the list of commits to the directly to the terminal. | ||
240 | """ | ||
241 | |||
242 | print(format_commits(commits_info, extra_message)) | ||
243 | |||
244 | def email_commits(commits_info, sender, subject, args): | ||
245 | """ | ||
246 | Directly email commits to the nvgpu-core mailing list for review! | ||
247 | """ | ||
248 | |||
249 | to_addr = 'SW-Mobile-nvgpu-core <SW-Mobile-nvgpu-core@exchange.nvidia.com>' | ||
250 | |||
251 | if args.no_msg: | ||
252 | args.msg = None | ||
253 | |||
254 | body = format_commits(commits_info, args.msg) | ||
255 | |||
256 | # Most people like to write a little description of their patch series | ||
257 | # in the email body. This aims to take care of that. | ||
258 | # | ||
259 | # If arg_parser.msg is set then we can just use that. If there's no | ||
260 | # args.msg field then we will try to fire up a text editor and let the | ||
261 | # user write something we will copy into the email the same way as | ||
262 | # args.msg. This makes it easier to a write paragraph - passing that much | ||
263 | # text on the CLI is annoying! | ||
264 | # | ||
265 | # However, if the user decides no message is a must then they can use | ||
266 | # the '--no-msg' argument to supress this message. This arg will also | ||
267 | # supress a message supplied with '--msg'. | ||
268 | |||
269 | if not args.msg and not args.no_msg: | ||
270 | text = get_user_message(body) | ||
271 | |||
272 | if not text or text.strip() == '': | ||
273 | print 'Empty user message: aborting!' | ||
274 | return | ||
275 | |||
276 | msg = MIMEText(text) | ||
277 | else: | ||
278 | msg = MIMEText(body) | ||
279 | |||
280 | msg['To'] = to_addr | ||
281 | msg['From'] = sender | ||
282 | msg['Subject'] = subject | ||
283 | |||
284 | s = smtplib.SMTP('mail.nvidia.com') | ||
285 | s.sendmail(sender, | ||
286 | [to_addr], | ||
287 | msg.as_string()) | ||
288 | s.quit() | ||
199 | 289 | ||
200 | def main(): | 290 | def main(): |
201 | """ | 291 | """ |
@@ -228,7 +318,24 @@ def main(): | |||
228 | else: | 318 | else: |
229 | print('Warning: \'%s\' doesn\'t appear to be a commit!' % cmt) | 319 | print('Warning: \'%s\' doesn\'t appear to be a commit!' % cmt) |
230 | 320 | ||
231 | display_commits(commits_info, arg_parser.msg) | 321 | if arg_parser.email: |
322 | # If no subject was specified then use the first commit subject as | ||
323 | # the subject. | ||
324 | subject = arg_parser.subject | ||
325 | if not subject: | ||
326 | subject = '[RFR] %s' % commits_info[0]['subject'] | ||
327 | |||
328 | # If no specified sender then use the name from the environment as | ||
329 | # the sender (plus @nvidia.com). This arg is primarily useful for | ||
330 | # people who do not have a username for the Linux machine that matches | ||
331 | # their SSO ID. | ||
332 | sender = arg_parser.sender | ||
333 | if not sender: | ||
334 | sender = '%s@nvidia.com' % user | ||
335 | |||
336 | email_commits(commits_info, sender, subject, arg_parser) | ||
337 | else: | ||
338 | display_commits(commits_info, arg_parser.msg) | ||
232 | 339 | ||
233 | if __name__ == '__main__': | 340 | if __name__ == '__main__': |
234 | main() | 341 | main() |