[PATCH 4 of 4] Added new send extension

John Goerzen jgoerzen at complete.org
Wed Mar 21 22:59:09 CDT 2007


# HG changeset patch
# User John Goerzen <jgoerzen at complete.org>
# Date 1174535734 18000
# Node ID d67c403f1dc44ec91537a6de32562a9b2e03c8ca
# Parent  cf386be05926f5d4ce3bef3eca71c8fe2af5a53f
Added new send extension

diff --git a/hgext/send.py b/hgext/send.py
new file mode 100644
--- /dev/null
+++ b/hgext/send.py
@@ -0,0 +1,125 @@
+# Command to send Mercurial changesets as a bundle.
+#
+# The subject line defaults to being based off the first patch
+#
+# To enable this extension:
+#
+#  [extensions]
+#  hgext.send =
+#
+# To configure other defaults, add a section like this to your hgrc
+# file:
+#
+#   [email]
+#   from = My Name <my at email>
+#   to = recipient1, recipient2, ...
+#   cc = cc1, cc2, ...
+#   bcc = bcc1, bcc2, ...
+
+import os, errno, tempfile, os.path
+import email.MIMEMultipart, email.MIMEText, email.MIMEBase
+import email.Utils, email.Encoders
+from mercurial import cmdutil, commands, hg, mail, ui, patch, util
+from mercurial.node import *
+from mercurial.i18n import _
+
+def send(ui, repo, dest=None, **opts):
+    """Send changesets as a bundle attached to an email.
+    
+    By default, determines what changesets are missing in the destination
+    repository, generates a bundle, and attaches it to an email.  Useful
+    for submitting changes projects that prefer bundles.
+
+    This is quick and easy, and preserves all changeset contents,
+    including permissions, copy/rename information, merges,
+    and revision history.
+    
+    --base, -r, or an explicit destination may be given and have the 
+    same meaning as for hg bundle."""
+    def prompt(prompt, default = None, rest = ':', empty_ok = False):
+        if default is not None:
+            prompt += ' [%s]' % default
+        prompt += rest
+        if empty_ok or default is not None:
+            pat = None
+        else:
+            pat = "."
+
+        r = ui.prompt(prompt, pat, default)
+        if not r:
+            return default
+        return r
+
+    tmpdir = tempfile.mkdtemp(prefix='hg-send-')
+    tmpfn = os.path.join(tmpdir, "bundle")
+    try:
+        commands.bundle(ui, repo, tmpfn, dest, **opts)
+        sender = (opts['from'] or ui.config('email', 'from') or
+                  ui.config('patchbomb', 'from') or
+                  prompt('From', ui.username()))
+        def getaddrs(opt, prpt, default = None):
+            addrs = opts[opt] or (ui.config('email', opt) or
+                                  ui.config('send', opt) or
+                                  prompt(prpt, default = default)).split(',')
+            return [a.strip() for a in addrs if a.strip()]
+        to = getaddrs('to', 'To')
+        cc = getaddrs('cc', 'Cc', '')
+
+        start_time = util.makedate()
+
+        bcc = opts['bcc'] or (ui.config('email', 'bcc') or
+                              ui.config('send', 'bcc') or '').split(',')
+        bcc = [a.strip() for a in bcc if a.strip()]
+        subj = opts['subject'] or \
+                prompt('Subject:', default='A patch for your repository')
+        ui.write(_('\nWrite the introductory message for the changset bundle.\n\n'))
+        body = ui.edit('', sender)
+
+        msg = email.MIMEMultipart.MIMEMultipart()
+        if body:
+            msg.attach(email.MIMEText.MIMEText(body, 'plain'))
+        datapart = email.MIMEBase.MIMEBase('application', 'x-mercurial-bundle')
+        datapart.set_payload(open(tmpfn).read())
+        email.Encoders.encode_base64(datapart)
+        msg.attach(datapart)
+        msg['Subject'] = subj
+        msg['Date'] = util.datestr(date=start_time,
+                format="%a, %d %b %Y %H:%M:%S", timezone=True)
+        msg['Message-Id'] = mail.genmsgid('hg-send')
+        msg['From'] = sender
+        msg['To'] = ', '.join(to)
+        if cc:
+            msg['Cc'] = ', '.join(cc)
+        ui.status('Sending ', subj, ' ...\n')
+        mail.connect(ui).sendmail(sender, to + bcc + cc, msg.as_string(0))
+        
+    finally:
+        try:
+            os.unlink(tmpfn)
+        except:
+            pass
+        os.rmdir(tmpdir)
+
+def bundleopts():
+    bundleopts = commands.table['bundle'][1]
+    # -f is used here already
+    localargs = map(lambda x: x[0], localopts)
+    def convopt(this):
+        if this[0] in localargs:
+            return ('',) + this[1:]
+        else:
+            return this
+    return(map(convopt, bundleopts))
+
+localopts = [('', 'bcc', [], 'email addresses of blind copy recipients'),
+      ('c', 'cc', [], 'email addresses of copy recipients'),
+      ('f', 'from', '', 'email address of sender'),
+      ('s', 'subject', '', 'subject of message'),
+      ('t', 'to', [], 'email addresses of recipients')]
+
+cmdtable = {
+    'send':
+    (send,
+     localopts + bundleopts(),
+     "hg send [OPTION]... [-r REV]... [--base REV]... [DEST]")
+    }


More information about the Mercurial-devel mailing list