[PATCH 3 of 4] patchbomb: let diffstat prompt only once with complete summary
Christian Ebert
blacktrash at gmx.net
Wed Sep 8 02:03:56 CDT 2010
# HG changeset patch
# User Christian Ebert <blacktrash at gmx.net>
# Date 1283929208 -7200
# Node ID dfe41fdb339d125f73954d8d43f792152656697d
# Parent 724564c8adb259b88c2f369d08ce967b3a8b3d86
patchbomb: let diffstat prompt only once with complete summary
This changes the behaviour of --diffstat.
Before the user was asked for confirmation of each patch with its
description and diffstat, and a final summary.
Now there is only one prompt right before sending with a final
summary which does not include the patch descriptions, but the
message details and the diffstats:
Final summary:
From: sender
To: recipient(s)
Cc: if present or empty
Bcc: if present or empty
Reply-To: if present or empty
Subject: [patch 0 of x [flags]] intro (if present)
a | 28 ++++++++++++++++++++++++++++
b | 15 +++++++++++++++
Subject: [patch 1 of x [flags]] subject
a | 28 ++++++++++++++++++++++++++++
[ ... ]
are you sure you want to send (yn)?
diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -22,9 +22,9 @@
and References headers, so they will show up as a sequence in threaded
mail and news readers, and in mail archives.
-With the -d/--diffstat option, you will be prompted for each changeset
-with a diffstat summary and the changeset summary, so you can be sure
-you are sending the right changes.
+With the -d/--diffstat option, you will be presented with a final
+summary of all messages and asked for confirmation before the messages
+are sent.
To configure other defaults, add a section like this to your hgrc
file::
@@ -94,27 +94,18 @@
return default
ui.warn(_('Please enter a valid value.\n'))
-def cdiffstat(ui, summary, patchlines):
- s = patch.diffstat(patchlines)
- if summary:
- ui.write(summary, '\n')
- ui.write(s, '\n')
- if ui.promptchoice(_('does the diffstat above look okay (yn)?'),
- (_('&Yes'), _('&No'))):
- raise util.Abort(_('diffstat rejected'))
- return s
-
def introneeded(opts, number):
'''is an introductory message required?'''
return number > 1 or opts.get('intro') or opts.get('desc')
-def makepatch(ui, repo, patch, opts, _charsets, idx, total, patchname=None):
+def makepatch(ui, repo, patchlines, opts, _charsets, idx, total,
+ patchname=None):
desc = []
node = None
body = ''
- for line in patch:
+ for line in patchlines:
if line.startswith('#'):
if line.startswith('# Node ID'):
node = line.split()[-1]
@@ -132,21 +123,22 @@
body += '\n\n\n'
if opts.get('plain'):
- while patch and patch[0].startswith('# '):
- patch.pop(0)
- if patch:
- patch.pop(0)
- while patch and not patch[0].strip():
- patch.pop(0)
+ while patchlines and patchlines[0].startswith('# '):
+ patchlines.pop(0)
+ if patchlines:
+ patchlines.pop(0)
+ while patchlines and not patchlines[0].strip():
+ patchlines.pop(0)
+ ds = patch.diffstat(patchlines)
if opts.get('diffstat'):
- body += cdiffstat(ui, '\n'.join(desc), patch) + '\n\n'
+ body += ds + '\n\n'
if opts.get('attach') or opts.get('inline'):
msg = email.MIMEMultipart.MIMEMultipart()
if body:
msg.attach(mail.mimeencode(ui, body, _charsets, opts.get('test')))
- p = mail.mimetextpatch('\n'.join(patch), 'x-patch', opts.get('test'))
+ p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
binnode = bin(node)
# if node is mq patch, it will have the patch file's name as a tag
if not patchname:
@@ -165,7 +157,7 @@
p['Content-Disposition'] = disposition + '; filename=' + patchname
msg.attach(p)
else:
- body += '\n'.join(patch)
+ body += '\n'.join(patchlines)
msg = mail.mimetextpatch(body, display=opts.get('test'))
flag = ' '.join(opts.get('flag'))
@@ -180,7 +172,7 @@
subj = '[PATCH %0*d of %d%s] %s' % (tlen, idx, total, flag, subj)
msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
msg['X-Mercurial-Node'] = node
- return msg, subj
+ return msg, subj, ds
def patchbomb(ui, repo, *revs, **opts):
'''send changesets by email
@@ -350,17 +342,16 @@
prompt(ui, 'Subject: ', rest=subj))
body = ''
- if opts.get('diffstat'):
- d = cdiffstat(ui, _('Final summary:\n'), jumbo)
- if d:
- body = '\n' + d
+ ds = patch.diffstat(jumbo)
+ if ds and opts.get('diffstat'):
+ body = '\n' + ds
body = getdescription(body, sender)
msg = mail.mimeencode(ui, body, _charsets, opts.get('test'))
msg['Subject'] = mail.headencode(ui, subj, _charsets,
opts.get('test'))
- msgs.insert(0, (msg, subj))
+ msgs.insert(0, (msg, subj, ds))
return msgs
def getbundlemsgs(bundle):
@@ -379,7 +370,7 @@
email.Encoders.encode_base64(datapart)
msg.attach(datapart)
msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
- return [(msg, subj)]
+ return [(msg, subj, None)]
sender = (opts.get('from') or ui.config('email', 'from') or
ui.config('patchbomb', 'from') or
@@ -392,9 +383,17 @@
else:
msgs = getpatchmsgs(list(getpatches(revs)))
+ showaddrs = []
+
def getaddrs(opt, prpt=None, default=None):
addrs = opts.get(opt.replace('-', '_'))
+ if opt != 'reply-to':
+ showaddr = '%s:' % opt.capitalize()
+ else:
+ showaddr = 'Reply-To:'
+
if addrs:
+ showaddrs.append('%s %s' % (showaddr, ', '.join(addrs)))
return mail.addrlistencode(ui, addrs, _charsets,
opts.get('test'))
@@ -402,6 +401,10 @@
if not addrs and prpt:
addrs = prompt(ui, prpt, default)
+ if addrs:
+ showaddr = '%s %s' % (showaddr, addrs)
+ showaddrs.append(showaddr)
+
return mail.addrlistencode(ui, [addrs], _charsets, opts.get('test'))
to = getaddrs('to', 'To')
@@ -409,6 +412,20 @@
bcc = getaddrs('bcc')
replyto = getaddrs('reply-to')
+ if opts.get('diffstat'):
+ ui.write(_('\nFinal summary:\n\n'))
+ ui.write('From: %s\n' % sender)
+ for addr in showaddrs:
+ ui.write('%s\n' % addr)
+ for m, subj, ds in msgs:
+ ui.write('Subject: %s\n' % subj)
+ if ds:
+ ui.write(ds)
+ ui.write('\n')
+ if ui.promptchoice(_('are you sure you want to send (yn)?'),
+ (_('&Yes'), _('&No'))):
+ raise util.Abort(_('patchbomb canceled'))
+
ui.write('\n')
parent = opts.get('in_reply_to') or None
@@ -424,7 +441,7 @@
sender_addr = email.Utils.parseaddr(sender)[1]
sender = mail.addressencode(ui, sender, _charsets, opts.get('test'))
sendmail = None
- for m, subj in msgs:
+ for m, subj, ds in msgs:
try:
m['Message-Id'] = genmsgid(m['X-Mercurial-Node'])
except TypeError:
diff --git a/tests/test-patchbomb.t b/tests/test-patchbomb.t
--- a/tests/test-patchbomb.t
+++ b/tests/test-patchbomb.t
@@ -332,12 +332,19 @@
> fixheaders
This patch series consists of 1 patches.
- c
+ Final summary:
+
+ From: quux
+ To: foo
+ Cc: bar
+ Bcc:
+ Reply-To:
+ Subject: [PATCH] test
c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
- does the diffstat above look okay (yn)? y
+ are you sure you want to send (yn)? y
Displaying [PATCH] test ...
Content-Type: text/plain; charset="us-ascii"
@@ -375,28 +382,29 @@
> -r 0:1 | fixheaders
This patch series consists of 2 patches.
- a
+ Write the introductory message for the patch series.
+
+
+ Final summary:
+
+ From: quux
+ To: foo
+ Cc: bar
+ Bcc:
+ Reply-To:
+ Subject: [PATCH 0 of 2] test
+ a | 1 +
+ b | 1 +
+ 2 files changed, 2 insertions(+), 0 deletions(-)
+ Subject: [PATCH 1 of 2] a
a | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
-
- does the diffstat above look okay (yn)? y
- b
-
+ Subject: [PATCH 2 of 2] b
b | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
- does the diffstat above look okay (yn)? y
- Final summary:
-
- a | 1 +
- b | 1 +
- 2 files changed, 2 insertions(+), 0 deletions(-)
-
- does the diffstat above look okay (yn)? y
-
- Write the introductory message for the patch series.
-
+ are you sure you want to send (yn)? y
Displaying [PATCH 0 of 2] test ...
Content-Type: text/plain; charset="us-ascii"
More information about the Mercurial-devel
mailing list