##// END OF EJS Templates
patchbomb: let diffstat prompt only once with complete summary...
Christian Ebert -
r12200:aebb39d4 default
parent child Browse files
Show More
@@ -22,9 +22,9 b' Each message refers to the first in the '
22 and References headers, so they will show up as a sequence in threaded
22 and References headers, so they will show up as a sequence in threaded
23 mail and news readers, and in mail archives.
23 mail and news readers, and in mail archives.
24
24
25 With the -d/--diffstat option, you will be prompted for each changeset
25 With the -d/--diffstat option, you will be presented with a final
26 with a diffstat summary and the changeset summary, so you can be sure
26 summary of all messages and asked for confirmation before the messages
27 you are sending the right changes.
27 are sent.
28
28
29 To configure other defaults, add a section like this to your hgrc
29 To configure other defaults, add a section like this to your hgrc
30 file::
30 file::
@@ -94,16 +94,6 b' def prompt(ui, prompt, default=None, res'
94 return default
94 return default
95 ui.warn(_('Please enter a valid value.\n'))
95 ui.warn(_('Please enter a valid value.\n'))
96
96
97 def cdiffstat(ui, summary, patchlines):
98 s = patch.diffstat(patchlines)
99 if summary:
100 ui.write(summary, '\n')
101 ui.write(s, '\n')
102 if ui.promptchoice(_('does the diffstat above look okay (yn)?'),
103 (_('&Yes'), _('&No'))):
104 raise util.Abort(_('diffstat rejected'))
105 return s
106
107 def introneeded(opts, number):
97 def introneeded(opts, number):
108 '''is an introductory message required?'''
98 '''is an introductory message required?'''
109 return number > 1 or opts.get('intro') or opts.get('desc')
99 return number > 1 or opts.get('intro') or opts.get('desc')
@@ -140,8 +130,9 b' def makepatch(ui, repo, patchlines, opts'
140 while patchlines and not patchlines[0].strip():
130 while patchlines and not patchlines[0].strip():
141 patchlines.pop(0)
131 patchlines.pop(0)
142
132
133 ds = patch.diffstat(patchlines)
143 if opts.get('diffstat'):
134 if opts.get('diffstat'):
144 body += cdiffstat(ui, '\n'.join(desc), patchlines) + '\n\n'
135 body += ds + '\n\n'
145
136
146 if opts.get('attach') or opts.get('inline'):
137 if opts.get('attach') or opts.get('inline'):
147 msg = email.MIMEMultipart.MIMEMultipart()
138 msg = email.MIMEMultipart.MIMEMultipart()
@@ -181,7 +172,7 b' def makepatch(ui, repo, patchlines, opts'
181 subj = '[PATCH %0*d of %d%s] %s' % (tlen, idx, total, flag, subj)
172 subj = '[PATCH %0*d of %d%s] %s' % (tlen, idx, total, flag, subj)
182 msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
173 msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
183 msg['X-Mercurial-Node'] = node
174 msg['X-Mercurial-Node'] = node
184 return msg, subj
175 return msg, subj, ds
185
176
186 def patchbomb(ui, repo, *revs, **opts):
177 def patchbomb(ui, repo, *revs, **opts):
187 '''send changesets by email
178 '''send changesets by email
@@ -351,17 +342,16 b' def patchbomb(ui, repo, *revs, **opts):'
351 prompt(ui, 'Subject: ', rest=subj))
342 prompt(ui, 'Subject: ', rest=subj))
352
343
353 body = ''
344 body = ''
354 if opts.get('diffstat'):
345 ds = patch.diffstat(jumbo)
355 d = cdiffstat(ui, _('Final summary:\n'), jumbo)
346 if ds and opts.get('diffstat'):
356 if d:
347 body = '\n' + ds
357 body = '\n' + d
358
348
359 body = getdescription(body, sender)
349 body = getdescription(body, sender)
360 msg = mail.mimeencode(ui, body, _charsets, opts.get('test'))
350 msg = mail.mimeencode(ui, body, _charsets, opts.get('test'))
361 msg['Subject'] = mail.headencode(ui, subj, _charsets,
351 msg['Subject'] = mail.headencode(ui, subj, _charsets,
362 opts.get('test'))
352 opts.get('test'))
363
353
364 msgs.insert(0, (msg, subj))
354 msgs.insert(0, (msg, subj, ds))
365 return msgs
355 return msgs
366
356
367 def getbundlemsgs(bundle):
357 def getbundlemsgs(bundle):
@@ -380,7 +370,7 b' def patchbomb(ui, repo, *revs, **opts):'
380 email.Encoders.encode_base64(datapart)
370 email.Encoders.encode_base64(datapart)
381 msg.attach(datapart)
371 msg.attach(datapart)
382 msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
372 msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
383 return [(msg, subj)]
373 return [(msg, subj, None)]
384
374
385 sender = (opts.get('from') or ui.config('email', 'from') or
375 sender = (opts.get('from') or ui.config('email', 'from') or
386 ui.config('patchbomb', 'from') or
376 ui.config('patchbomb', 'from') or
@@ -393,9 +383,17 b' def patchbomb(ui, repo, *revs, **opts):'
393 else:
383 else:
394 msgs = getpatchmsgs(list(getpatches(revs)))
384 msgs = getpatchmsgs(list(getpatches(revs)))
395
385
386 showaddrs = []
387
396 def getaddrs(opt, prpt=None, default=None):
388 def getaddrs(opt, prpt=None, default=None):
397 addrs = opts.get(opt.replace('-', '_'))
389 addrs = opts.get(opt.replace('-', '_'))
390 if opt != 'reply-to':
391 showaddr = '%s:' % opt.capitalize()
392 else:
393 showaddr = 'Reply-To:'
394
398 if addrs:
395 if addrs:
396 showaddrs.append('%s %s' % (showaddr, ', '.join(addrs)))
399 return mail.addrlistencode(ui, addrs, _charsets,
397 return mail.addrlistencode(ui, addrs, _charsets,
400 opts.get('test'))
398 opts.get('test'))
401
399
@@ -403,6 +401,10 b' def patchbomb(ui, repo, *revs, **opts):'
403 if not addrs and prpt:
401 if not addrs and prpt:
404 addrs = prompt(ui, prpt, default)
402 addrs = prompt(ui, prpt, default)
405
403
404 if addrs:
405 showaddr = '%s %s' % (showaddr, addrs)
406 showaddrs.append(showaddr)
407
406 return mail.addrlistencode(ui, [addrs], _charsets, opts.get('test'))
408 return mail.addrlistencode(ui, [addrs], _charsets, opts.get('test'))
407
409
408 to = getaddrs('to', 'To')
410 to = getaddrs('to', 'To')
@@ -410,6 +412,20 b' def patchbomb(ui, repo, *revs, **opts):'
410 bcc = getaddrs('bcc')
412 bcc = getaddrs('bcc')
411 replyto = getaddrs('reply-to')
413 replyto = getaddrs('reply-to')
412
414
415 if opts.get('diffstat'):
416 ui.write(_('\nFinal summary:\n\n'))
417 ui.write('From: %s\n' % sender)
418 for addr in showaddrs:
419 ui.write('%s\n' % addr)
420 for m, subj, ds in msgs:
421 ui.write('Subject: %s\n' % subj)
422 if ds:
423 ui.write(ds)
424 ui.write('\n')
425 if ui.promptchoice(_('are you sure you want to send (yn)?'),
426 (_('&Yes'), _('&No'))):
427 raise util.Abort(_('patchbomb canceled'))
428
413 ui.write('\n')
429 ui.write('\n')
414
430
415 parent = opts.get('in_reply_to') or None
431 parent = opts.get('in_reply_to') or None
@@ -425,7 +441,7 b' def patchbomb(ui, repo, *revs, **opts):'
425 sender_addr = email.Utils.parseaddr(sender)[1]
441 sender_addr = email.Utils.parseaddr(sender)[1]
426 sender = mail.addressencode(ui, sender, _charsets, opts.get('test'))
442 sender = mail.addressencode(ui, sender, _charsets, opts.get('test'))
427 sendmail = None
443 sendmail = None
428 for m, subj in msgs:
444 for m, subj, ds in msgs:
429 try:
445 try:
430 m['Message-Id'] = genmsgid(m['X-Mercurial-Node'])
446 m['Message-Id'] = genmsgid(m['X-Mercurial-Node'])
431 except TypeError:
447 except TypeError:
@@ -332,12 +332,17 b' test diffstat for single patch:'
332 > fixheaders
332 > fixheaders
333 This patch series consists of 1 patches.
333 This patch series consists of 1 patches.
334
334
335 c
335
336 Final summary:
336
337
338 From: quux
339 To: foo
340 Cc: bar
341 Subject: [PATCH] test
337 c | 1 +
342 c | 1 +
338 1 files changed, 1 insertions(+), 0 deletions(-)
343 1 files changed, 1 insertions(+), 0 deletions(-)
339
344
340 does the diffstat above look okay (yn)? y
345 are you sure you want to send (yn)? y
341
346
342 Displaying [PATCH] test ...
347 Displaying [PATCH] test ...
343 Content-Type: text/plain; charset="us-ascii"
348 Content-Type: text/plain; charset="us-ascii"
@@ -375,28 +380,27 b' test diffstat for multiple patches:'
375 > -r 0:1 | fixheaders
380 > -r 0:1 | fixheaders
376 This patch series consists of 2 patches.
381 This patch series consists of 2 patches.
377
382
378 a
383
384 Write the introductory message for the patch series.
385
386
387 Final summary:
379
388
389 From: quux
390 To: foo
391 Cc: bar
392 Subject: [PATCH 0 of 2] test
393 a | 1 +
394 b | 1 +
395 2 files changed, 2 insertions(+), 0 deletions(-)
396 Subject: [PATCH 1 of 2] a
380 a | 1 +
397 a | 1 +
381 1 files changed, 1 insertions(+), 0 deletions(-)
398 1 files changed, 1 insertions(+), 0 deletions(-)
382
399 Subject: [PATCH 2 of 2] b
383 does the diffstat above look okay (yn)? y
384 b
385
386 b | 1 +
400 b | 1 +
387 1 files changed, 1 insertions(+), 0 deletions(-)
401 1 files changed, 1 insertions(+), 0 deletions(-)
388
402
389 does the diffstat above look okay (yn)? y
403 are you sure you want to send (yn)? y
390 Final summary:
391
392 a | 1 +
393 b | 1 +
394 2 files changed, 2 insertions(+), 0 deletions(-)
395
396 does the diffstat above look okay (yn)? y
397
398 Write the introductory message for the patch series.
399
400
404
401 Displaying [PATCH 0 of 2] test ...
405 Displaying [PATCH 0 of 2] test ...
402 Content-Type: text/plain; charset="us-ascii"
406 Content-Type: text/plain; charset="us-ascii"
General Comments 0
You need to be logged in to leave comments. Login now