[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