{"thread":{"id":"21779","subject":"[StGit RFC PATCH 0/6] add support for git send-email","startedAt":"2009-11-28T19:50:11Z","lastAt":"2009-12-01T07:38:19Z","messageCount":18,"participants":["Alex Chiang","Karl Wiberg"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"128641","messageId":"20091128194056.949.88791.stgit@bob.kio","threadId":"21779","inReplyTo":null,"subject":"[StGit RFC PATCH 0/6] add support for git send-email","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-28T19:50:11Z","receivedAt":"2009-11-28T19:50:11Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"Hi Catalin,\n\nThis series starts down the path of eventually converting stg mail to\nsimply become a wrapper around git send-email.\n\nThe first 4 patches do some refactoring of internal APIs to set us up\nfor the money patch 5/6 which actually adds the call to git send-email.\n\nPatch 6/6 shows a hint of the future, where we can start leveraging\nsome of the features in git send-email for our own purposes. With it,\nyou can now use mail aliases as supported by git send-email.\n\nstg mail still has some nice features over git send-email, such\nas the -v command line parameter and --prefix. Maybe at some point\nin the future, we can migrate those features into git send-email and\ncontinue thinning out stg mail.\n\nBut I wanted to get some feedback first to make sure I'm going in the\nright direction before going too much further.\n\nDisclaimer: I'm not really a python coder. Particularly, patch 5/6\nis ugly in how we look at the various stg mail options. I'm sure there's\nlots of room for improvement.\n\nThis mail was sent with:\n\t./stg mail -a --git --auto -e \n\n[Karl, sorry about the earlier accidental mail. That was a testing mishap.]\n\nThanks,\n/ac\n\n---\n\nAlex Chiang (6):\n      stg mail: Refactor __send_message and friends\n      stg mail: reorder __build_[message|cover] parameters\n      stg mail: make __send_message do more\n      stg mail: factor out __update_header\n      stg mail: add basic support for git send-email\n      stg mail: don't parse To/Cc/Bcc in --git mode\n\n\n stgit/commands/mail.py |  205 ++++++++++++++++++++++++++++--------------------\n 1 files changed, 121 insertions(+), 84 deletions(-)\n"},{"id":"128642","messageId":"20091128195016.949.17089.stgit@bob.kio","threadId":"21779","inReplyTo":"20091128194056.949.88791.stgit@bob.kio","subject":"[PATCH 1/6] stg mail: Refactor __send_message and friends","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-28T19:50:16Z","receivedAt":"2009-11-28T19:50:16Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"Instead of passing all the various smtp* args to __send_message\nindividually, let's just pass the options list instead.\n\nThe main motivation is for future patches. The end goal is to\nthin out stg mail's implementation and make it a minimal wrapper\naround git send-email. By passing the options list to __send_message\nwe prepare to pass options directly to git send-email.\n\nAs a bonus, this change results in a cleaner internal API.\n\nFinally, it also pushes the smtp logic where it belongs, viz. into\n__send_message_smtp, instead of cluttering up the main body of\nmail.func().\n\nCc: Karl Wiberg <kha@treskal.com>\nSigned-off-by: Alex Chiang <achiang@hp.com>\n---\n\n stgit/commands/mail.py |   43 +++++++++++++++++++------------------------\n 1 files changed, 19 insertions(+), 24 deletions(-)\n\ndiff --git a/stgit/commands/mail.py b/stgit/commands/mail.py\nindex abd42e4..3978f5e 100644\n--- a/stgit/commands/mail.py\n+++ b/stgit/commands/mail.py\n@@ -190,10 +190,20 @@ def __send_message_sendmail(sendmail, msg):\n     cmd = sendmail.split()\n     Run(*cmd).raw_input(msg).discard_output()\n \n-def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg,\n-                        smtpuser, smtppassword, use_tls):\n+def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg, options):\n     \"\"\"Send the message using the given SMTP server\n     \"\"\"\n+    smtppassword = options.smtp_password or config.get('stgit.smtppassword')\n+    smtpuser = options.smtp_user or config.get('stgit.smtpuser')\n+    smtpusetls = options.smtp_tls or config.get('stgit.smtptls') == 'yes'\n+\n+    if (smtppassword and not smtpuser):\n+        raise CmdException, 'SMTP password supplied, username needed'\n+    if (smtpusetls and not smtpuser):\n+        raise CmdException, 'SMTP over TLS requested, username needed'\n+    if (smtpuser and not smtppassword):\n+        smtppassword = getpass.getpass(\"Please enter SMTP password: \")\n+\n     try:\n         s = smtplib.SMTP(smtpserver)\n     except Exception, err:\n@@ -203,7 +213,7 @@ def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg,\n     try:\n         if smtpuser and smtppassword:\n             s.ehlo()\n-            if use_tls:\n+            if smtpusetls:\n                 if not hasattr(socket, 'ssl'):\n                     raise CmdException,  \"cannot use TLS - no SSL support in Python\"\n                 s.starttls()\n@@ -218,17 +228,17 @@ def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg,\n \n     s.quit()\n \n-def __send_message(smtpserver, from_addr, to_addr_list, msg,\n-                   smtpuser, smtppassword, use_tls):\n+def __send_message(from_addr, to_addr_list, msg, options):\n     \"\"\"Message sending dispatcher.\n     \"\"\"\n+    smtpserver = options.smtp_server or config.get('stgit.smtpserver')\n+\n     if smtpserver.startswith('/'):\n         # Use the sendmail tool\n         __send_message_sendmail(smtpserver, msg)\n     else:\n         # Use the SMTP server (we have host and port information)\n-        __send_message_smtp(smtpserver, from_addr, to_addr_list, msg,\n-                            smtpuser, smtppassword, use_tls)\n+        __send_message_smtp(smtpserver, from_addr, to_addr_list, msg, options)\n \n def __build_address_headers(msg, options, extra_cc = []):\n     \"\"\"Build the address headers and check existing headers in the\n@@ -543,8 +553,6 @@ def func(parser, options, args):\n     \"\"\"Send the patches by e-mail using the patchmail.tmpl file as\n     a template\n     \"\"\"\n-    smtpserver = options.smtp_server or config.get('stgit.smtpserver')\n-\n     applied = crt_series.get_applied()\n \n     if options.all:\n@@ -564,17 +572,6 @@ def func(parser, options, args):\n             raise CmdException, 'Cannot send empty patch \"%s\"' % p\n     out.done()\n \n-    smtppassword = options.smtp_password or config.get('stgit.smtppassword')\n-    smtpuser = options.smtp_user or config.get('stgit.smtpuser')\n-    smtpusetls = options.smtp_tls or config.get('stgit.smtptls') == 'yes'\n-\n-    if (smtppassword and not smtpuser):\n-        raise CmdException, 'SMTP password supplied, username needed'\n-    if (smtpusetls and not smtpuser):\n-        raise CmdException, 'SMTP over TLS requested, username needed'\n-    if (smtpuser and not smtppassword):\n-        smtppassword = getpass.getpass(\"Please enter SMTP password: \")\n-\n     total_nr = len(patches)\n     if total_nr == 0:\n         raise CmdException, 'No patches to send'\n@@ -616,8 +613,7 @@ def func(parser, options, args):\n             out.stdout_raw(msg_string + '\\n')\n         else:\n             out.start('Sending the cover message')\n-            __send_message(smtpserver, from_addr, to_addr_list, msg_string,\n-                           smtpuser, smtppassword, smtpusetls)\n+            __send_message(from_addr, to_addr_list, msg_string, options)\n             time.sleep(sleep)\n             out.done()\n \n@@ -648,8 +644,7 @@ def func(parser, options, args):\n             out.stdout_raw(msg_string + '\\n')\n         else:\n             out.start('Sending patch \"%s\"' % p)\n-            __send_message(smtpserver, from_addr, to_addr_list, msg_string,\n-                           smtpuser, smtppassword, smtpusetls)\n+            __send_message(from_addr, to_addr_list, msg_string, options)\n             # give recipients a chance of receiving related patches in the\n             # correct order.\n             if patch_nr < total_nr:\n"},{"id":"128643","messageId":"20091128195021.949.83804.stgit@bob.kio","threadId":"21779","inReplyTo":"20091128194056.949.88791.stgit@bob.kio","subject":"[PATCH 2/6] stg mail: reorder __build_[message|cover] parameters","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-28T19:50:21Z","receivedAt":"2009-11-28T19:50:21Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"Reorder the argument lists for both __build_cover and __build_message.\n\nThis change will aid readability of a subsequent refactoring patch.\n\nCc: Karl Wiberg <kha@treskal.com>\nSigned-off-by: Alex Chiang <achiang@hp.com>\n---\n\n stgit/commands/mail.py |   10 +++++-----\n 1 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/stgit/commands/mail.py b/stgit/commands/mail.py\nindex 3978f5e..b6fc3d9 100644\n--- a/stgit/commands/mail.py\n+++ b/stgit/commands/mail.py\n@@ -370,7 +370,7 @@ def __edit_message(msg):\n \n     return msg\n \n-def __build_cover(tmpl, patches, msg_id, options):\n+def __build_cover(tmpl, msg_id, options, patches):\n     \"\"\"Build the cover message (series description) to be sent via SMTP\n     \"\"\"\n     sender = __get_sender()\n@@ -439,7 +439,7 @@ def __build_cover(tmpl, patches, msg_id, options):\n \n     return msg\n \n-def __build_message(tmpl, patch, patch_nr, total_nr, msg_id, ref_id, options):\n+def __build_message(tmpl, msg_id, options, patch, patch_nr, total_nr, ref_id):\n     \"\"\"Build the message to be sent via SMTP\n     \"\"\"\n     p = crt_series.get_patch(patch)\n@@ -600,7 +600,7 @@ def func(parser, options, args):\n                 raise CmdException, 'No cover message template file found'\n \n         msg_id = email.Utils.make_msgid('stgit')\n-        msg = __build_cover(tmpl, patches, msg_id, options)\n+        msg = __build_cover(tmpl, msg_id, options, patches)\n         from_addr, to_addr_list = __parse_addresses(msg)\n \n         msg_string = msg.as_string(options.mbox)\n@@ -630,8 +630,8 @@ def func(parser, options, args):\n \n     for (p, patch_nr) in zip(patches, range(1, total_nr + 1)):\n         msg_id = email.Utils.make_msgid('stgit')\n-        msg = __build_message(tmpl, p, patch_nr, total_nr, msg_id, ref_id,\n-                              options)\n+        msg = __build_message(tmpl, msg_id, options, p, patch_nr, total_nr,\n+                              ref_id)\n         from_addr, to_addr_list = __parse_addresses(msg)\n \n         msg_string = msg.as_string(options.mbox)\n"},{"id":"128645","messageId":"20091128195026.949.1772.stgit@bob.kio","threadId":"21779","inReplyTo":"20091128194056.949.88791.stgit@bob.kio","subject":"[PATCH 3/6] stg mail: make __send_message do more","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-28T19:50:27Z","receivedAt":"2009-11-28T19:50:27Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"Factor out the common code required to send either a cover mail\nor patch, and implement it in __send_message.\n\nWRY? DRY.\n\nCc: Karl Wiberg <kha@treskal.com>\nSigned-off-by: Alex Chiang <achiang@hp.com>\n---\n\n stgit/commands/mail.py |   61 ++++++++++++++++++++----------------------------\n 1 files changed, 26 insertions(+), 35 deletions(-)\n\ndiff --git a/stgit/commands/mail.py b/stgit/commands/mail.py\nindex b6fc3d9..fe5742e 100644\n--- a/stgit/commands/mail.py\n+++ b/stgit/commands/mail.py\n@@ -228,17 +228,37 @@ def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg, options):\n \n     s.quit()\n \n-def __send_message(from_addr, to_addr_list, msg, options):\n+def __send_message(tmpl, options, *args):\n     \"\"\"Message sending dispatcher.\n     \"\"\"\n-    smtpserver = options.smtp_server or config.get('stgit.smtpserver')\n+    msg_id = email.Utils.make_msgid('stgit')\n+    build = { 1: __build_cover, 4: __build_message }\n+    msg = build[len(args)](tmpl, msg_id, options, *args)\n+\n+    from_addr, to_addrs = __parse_addresses(msg)\n+    msg_str = msg.as_string(options.mbox)\n+    if options.mbox:\n+        out.stdout_raw(msg_str + '\\n')\n+        return msg_id\n+\n+    outstr = { 1: 'the cover message', 4: 'patch \"%s\"' % args[0] }\n+    out.start('Sending ' + outstr[len(args)])\n \n+    smtpserver = options.smtp_server or config.get('stgit.smtpserver')\n     if smtpserver.startswith('/'):\n         # Use the sendmail tool\n-        __send_message_sendmail(smtpserver, msg)\n+        __send_message_sendmail(smtpserver, msg_str)\n     else:\n         # Use the SMTP server (we have host and port information)\n-        __send_message_smtp(smtpserver, from_addr, to_addr_list, msg, options)\n+        __send_message_smtp(smtpserver, from_addr, to_addrs, msg_str, options)\n+\n+    # give recipients a chance of receiving related patches in correct order\n+    #                                       patch_nr < total_nr\n+    if len(args) == 1 or (len(args) == 4 and args[1] < args[2]):\n+        sleep = options.sleep or config.getint('stgit.smtpdelay')\n+        time.sleep(sleep)\n+    out.done()\n+    return msg_id\n \n def __build_address_headers(msg, options, extra_cc = []):\n     \"\"\"Build the address headers and check existing headers in the\n@@ -584,7 +604,6 @@ def func(parser, options, args):\n     else:\n         ref_id = None\n \n-    sleep = options.sleep or config.getint('stgit.smtpdelay')\n \n     # send the cover message (if any)\n     if options.cover or options.edit_cover:\n@@ -599,24 +618,12 @@ def func(parser, options, args):\n             if not tmpl:\n                 raise CmdException, 'No cover message template file found'\n \n-        msg_id = email.Utils.make_msgid('stgit')\n-        msg = __build_cover(tmpl, msg_id, options, patches)\n-        from_addr, to_addr_list = __parse_addresses(msg)\n-\n-        msg_string = msg.as_string(options.mbox)\n+        msg_id = __send_message(tmpl, options, patches)\n \n         # subsequent e-mails are seen as replies to the first one\n         if not options.noreply:\n             ref_id = msg_id\n \n-        if options.mbox:\n-            out.stdout_raw(msg_string + '\\n')\n-        else:\n-            out.start('Sending the cover message')\n-            __send_message(from_addr, to_addr_list, msg_string, options)\n-            time.sleep(sleep)\n-            out.done()\n-\n     # send the patches\n     if options.template:\n         tmpl = file(options.template).read()\n@@ -629,24 +636,8 @@ def func(parser, options, args):\n             raise CmdException, 'No e-mail template file found'\n \n     for (p, patch_nr) in zip(patches, range(1, total_nr + 1)):\n-        msg_id = email.Utils.make_msgid('stgit')\n-        msg = __build_message(tmpl, msg_id, options, p, patch_nr, total_nr,\n-                              ref_id)\n-        from_addr, to_addr_list = __parse_addresses(msg)\n-\n-        msg_string = msg.as_string(options.mbox)\n+        msg_id = __send_message(tmpl, options, p, patch_nr, total_nr, ref_id)\n \n         # subsequent e-mails are seen as replies to the first one\n         if not options.noreply and not options.unrelated and not ref_id:\n             ref_id = msg_id\n-\n-        if options.mbox:\n-            out.stdout_raw(msg_string + '\\n')\n-        else:\n-            out.start('Sending patch \"%s\"' % p)\n-            __send_message(from_addr, to_addr_list, msg_string, options)\n-            # give recipients a chance of receiving related patches in the\n-            # correct order.\n-            if patch_nr < total_nr:\n-                time.sleep(sleep)\n-            out.done()\n"},{"id":"128644","messageId":"20091128195032.949.31684.stgit@bob.kio","threadId":"21779","inReplyTo":"20091128194056.949.88791.stgit@bob.kio","subject":"[PATCH 4/6] stg mail: factor out __update_header","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-28T19:50:32Z","receivedAt":"2009-11-28T19:50:32Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"Factor __update_header out of __build_address_headers.\n\nHeaders like Reply-To, Mail-Reply-To, and Mail-Followup-To are now\nhandled in __build_extra_headers.\n\nWe make this change because in the future, we do not want to call\n__build_address_headers if using git send-email but we will always\nwant to call __build_extra_headers.\n\nCc: Karl Wiberg <kha@treskal.com>\nSigned-off-by: Alex Chiang <achiang@hp.com>\n---\n\n stgit/commands/mail.py |   48 +++++++++++++++++++++++++-----------------------\n 1 files changed, 25 insertions(+), 23 deletions(-)\n\ndiff --git a/stgit/commands/mail.py b/stgit/commands/mail.py\nindex fe5742e..7f811e8 100644\n--- a/stgit/commands/mail.py\n+++ b/stgit/commands/mail.py\n@@ -260,25 +260,25 @@ def __send_message(tmpl, options, *args):\n     out.done()\n     return msg_id\n \n-def __build_address_headers(msg, options, extra_cc = []):\n-    \"\"\"Build the address headers and check existing headers in the\n-    template.\n-    \"\"\"\n+def __update_header(msg, header, addr = '', ignore = ()):\n     def __addr_pairs(msg, header, extra):\n         pairs = email.Utils.getaddresses(msg.get_all(header, []) + extra)\n         # remove pairs without an address and resolve the aliases\n         return [address_or_alias(p) for p in pairs if p[1]]\n \n-    def __update_header(header, addr = '', ignore = ()):\n-        addr_pairs = __addr_pairs(msg, header, [addr])\n-        del msg[header]\n-        # remove the duplicates and filter the addresses\n-        addr_dict = dict((addr, email.Utils.formataddr((name, addr)))\n-                         for name, addr in addr_pairs if addr not in ignore)\n-        if addr_dict:\n-            msg[header] = ', '.join(addr_dict.itervalues())\n-        return set(addr_dict.iterkeys())\n+    addr_pairs = __addr_pairs(msg, header, [addr])\n+    del msg[header]\n+    # remove the duplicates and filter the addresses\n+    addr_dict = dict((addr, email.Utils.formataddr((name, addr)))\n+                     for name, addr in addr_pairs if addr not in ignore)\n+    if addr_dict:\n+        msg[header] = ', '.join(addr_dict.itervalues())\n+    return set(addr_dict.iterkeys())\n \n+def __build_address_headers(msg, options, extra_cc = []):\n+    \"\"\"Build the address headers and check existing headers in the\n+    template.\n+    \"\"\"\n     to_addr = ''\n     cc_addr = ''\n     extra_cc_addr = ''\n@@ -298,18 +298,14 @@ def __build_address_headers(msg, options, extra_cc = []):\n         bcc_addr = autobcc\n \n     # if an address is on a header, ignore it from the rest\n-    to_set = __update_header('To', to_addr)\n-    cc_set = __update_header('Cc', cc_addr, to_set)\n-    bcc_set = __update_header('Bcc', bcc_addr, to_set.union(cc_set))\n+    to_set = __update_header(msg, 'To', to_addr)\n+    cc_set = __update_header(msg, 'Cc', cc_addr, to_set)\n+    bcc_set = __update_header(msg, 'Bcc', bcc_addr, to_set.union(cc_set))\n \n     # --auto generated addresses, don't include the sender\n-    from_set = __update_header('From')\n-    __update_header('Cc', extra_cc_addr, to_set.union(bcc_set).union(from_set))\n-\n-    # update other address headers\n-    __update_header('Reply-To')\n-    __update_header('Mail-Reply-To')\n-    __update_header('Mail-Followup-To')\n+    from_set = __update_header(msg, 'From')\n+    __update_header(msg, 'Cc', extra_cc_addr,\n+                    to_set.union(bcc_set).union(from_set))\n \n def __get_signers_list(msg):\n     \"\"\"Return the address list generated from signed-off-by and\n@@ -347,6 +343,12 @@ def __build_extra_headers(msg, msg_id, ref_id = None):\n         msg['References'] = ref_id\n     msg['User-Agent'] = 'StGit/%s' % version.version\n \n+    # update other address headers\n+    __update_header(msg, 'Reply-To')\n+    __update_header(msg, 'Mail-Reply-To')\n+    __update_header(msg, 'Mail-Followup-To')\n+\n+\n def __encode_message(msg):\n     # 7 or 8 bit encoding\n     charset = email.Charset.Charset('utf-8')\n"},{"id":"128646","messageId":"20091128195037.949.63611.stgit@bob.kio","threadId":"21779","inReplyTo":"20091128194056.949.88791.stgit@bob.kio","subject":"[PATCH 5/6] stg mail: add basic support for git send-email","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-28T19:50:37Z","receivedAt":"2009-11-28T19:50:37Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"This is the first step in turning stg mail into a wrapper for\ngit send-email. It requires passing the --git option to stg mail\nfor now.\n\nOnly a few basic options are supported for now, namely To/Cc/Bcc.\n\ngit send-email options used:\n  --suppress-cc=self\tprevent further information prompts\n  --quiet\t\treduce git send-email output\n\nCc: Karl Wiberg <kha@treskal.com>\nSigned-off-by: Alex Chiang <achiang@hp.com>\n---\n\n stgit/commands/mail.py |   60 +++++++++++++++++++++++++++++++++++++++++++++---\n 1 files changed, 56 insertions(+), 4 deletions(-)\n\ndiff --git a/stgit/commands/mail.py b/stgit/commands/mail.py\nindex 7f811e8..81ec77e 100644\n--- a/stgit/commands/mail.py\n+++ b/stgit/commands/mail.py\n@@ -140,7 +140,9 @@ options = [\n     opt('-b', '--branch', args = [argparse.stg_branches],\n         short = 'Use BRANCH instead of the default branch'),\n     opt('-m', '--mbox', action = 'store_true',\n-        short = 'Generate an mbox file instead of sending')\n+        short = 'Generate an mbox file instead of sending'),\n+    opt('--git', action = 'store_true',\n+        short = 'Use git send-email (EXPERIMENTAL)')\n     ] + argparse.diff_opts_option()\n \n directory = DirectoryHasRepository(log = False)\n@@ -228,6 +230,52 @@ def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg, options):\n \n     s.quit()\n \n+def __send_message_git(msg, options):\n+    \"\"\"Send the message using git send-email\n+    \"\"\"\n+    from subprocess import call\n+    from tempfile import mkstemp\n+\n+    cmd = [\"git\", \"send-email\", \"--from=%s\" % msg['From']]\n+    cmd.append(\"--quiet\")\n+    cmd.append(\"--suppress-cc=self\")\n+\n+    # XXX: yuck, there's gotta be a more pythonic way. Ideally we'd like\n+    # to use the git_opts dictionary as our mapping between stg mail and\n+    # git send-email; extract k, v pairs from git_opts, and use those\n+    # to iterate across options somehow.\n+    git_opts = { 'to': '--to=', 'cc': '--cc=', 'bcc': '--bcc=' }\n+    if options.to:\n+        for a in options.to:\n+            cmd.append(\"--to=%s\" % a)\n+    if options.cc:\n+        for a in options.cc:\n+            cmd.append(\"--cc=%s\" % a)\n+    if options.bcc:\n+        for a in options.bcc:\n+            cmd.append(\"--bcc=%s\" % a)\n+    if not options.auto:\n+        cmd.append(\"--suppress-cc=body\")\n+\n+    # XXX: hack for now so that we don't duplicate To/Cc/Bcc headers\n+    # in the mail, as git send-email inserts those for us.\n+    del msg['To']\n+    del msg['Cc']\n+    del msg['Bcc']\n+\n+    (fd, path) = mkstemp()\n+    os.write(fd, msg.as_string(options.mbox))\n+    os.close(fd)\n+\n+    try:\n+        cmd.append(path)\n+        call(cmd)\n+    except Exception, err:\n+        os.unlink(path)\n+        raise CmdException, str(err)\n+\n+    os.unlink(path)\n+\n def __send_message(tmpl, options, *args):\n     \"\"\"Message sending dispatcher.\n     \"\"\"\n@@ -242,10 +290,13 @@ def __send_message(tmpl, options, *args):\n         return msg_id\n \n     outstr = { 1: 'the cover message', 4: 'patch \"%s\"' % args[0] }\n-    out.start('Sending ' + outstr[len(args)])\n+    if not options.git:\n+        out.start('Sending ' + outstr[len(args)])\n \n     smtpserver = options.smtp_server or config.get('stgit.smtpserver')\n-    if smtpserver.startswith('/'):\n+    if options.git:\n+        __send_message_git(msg, options)\n+    elif smtpserver.startswith('/'):\n         # Use the sendmail tool\n         __send_message_sendmail(smtpserver, msg_str)\n     else:\n@@ -257,7 +308,8 @@ def __send_message(tmpl, options, *args):\n     if len(args) == 1 or (len(args) == 4 and args[1] < args[2]):\n         sleep = options.sleep or config.getint('stgit.smtpdelay')\n         time.sleep(sleep)\n-    out.done()\n+    if not options.git:\n+        out.done()\n     return msg_id\n \n def __update_header(msg, header, addr = '', ignore = ()):\n"},{"id":"128647","messageId":"20091128195042.949.99025.stgit@bob.kio","threadId":"21779","inReplyTo":"20091128194056.949.88791.stgit@bob.kio","subject":"[PATCH 6/6] stg mail: don't parse To/Cc/Bcc in --git mode","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-28T19:50:43Z","receivedAt":"2009-11-28T19:50:43Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"When using stg mail in --git mode, do not parse command-line To/Cc/Bcc\naddresses.\n\nInstead, we pass them directly to git send-email.\n\nThis allows us to leverage git send-email's support for email aliases.\n\nCc: Karl Wiberg <kha@treskal.com>\nSigned-off-by: Alex Chiang <achiang@hp.com>\n---\n\n stgit/commands/mail.py |   15 ++++++---------\n 1 files changed, 6 insertions(+), 9 deletions(-)\n\ndiff --git a/stgit/commands/mail.py b/stgit/commands/mail.py\nindex 81ec77e..c01e14b 100644\n--- a/stgit/commands/mail.py\n+++ b/stgit/commands/mail.py\n@@ -257,12 +257,6 @@ def __send_message_git(msg, options):\n     if not options.auto:\n         cmd.append(\"--suppress-cc=body\")\n \n-    # XXX: hack for now so that we don't duplicate To/Cc/Bcc headers\n-    # in the mail, as git send-email inserts those for us.\n-    del msg['To']\n-    del msg['Cc']\n-    del msg['Bcc']\n-\n     (fd, path) = mkstemp()\n     os.write(fd, msg.as_string(options.mbox))\n     os.close(fd)\n@@ -283,7 +277,8 @@ def __send_message(tmpl, options, *args):\n     build = { 1: __build_cover, 4: __build_message }\n     msg = build[len(args)](tmpl, msg_id, options, *args)\n \n-    from_addr, to_addrs = __parse_addresses(msg)\n+    if not options.git:\n+        from_addr, to_addrs = __parse_addresses(msg)\n     msg_str = msg.as_string(options.mbox)\n     if options.mbox:\n         out.stdout_raw(msg_str + '\\n')\n@@ -507,7 +502,8 @@ def __build_cover(tmpl, msg_id, options, patches):\n     except Exception, ex:\n         raise CmdException, 'template parsing error: %s' % str(ex)\n \n-    __build_address_headers(msg, options)\n+    if not options.git:\n+        __build_address_headers(msg, options)\n     __build_extra_headers(msg, msg_id, options.refid)\n     __encode_message(msg)\n \n@@ -617,7 +613,8 @@ def __build_message(tmpl, msg_id, options, patch, patch_nr, total_nr, ref_id):\n     else:\n         extra_cc = []\n \n-    __build_address_headers(msg, options, extra_cc)\n+    if not options.git:\n+        __build_address_headers(msg, options, extra_cc)\n     __build_extra_headers(msg, msg_id, ref_id)\n     __encode_message(msg)\n \n"},{"id":"128673","messageId":"4B123B48.4050405@treskal.com","threadId":"21779","inReplyTo":"20091128195016.949.17089.stgit@bob.kio","subject":"Re: [PATCH 1/6] stg mail: Refactor __send_message and friends","fromName":"Karl Wiberg","fromEmail":"kha@treskal.com","sentAt":"2009-11-29T09:13:44Z","receivedAt":"2009-11-29T09:13:44Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"Alex Chiang wrote:\n\n> Instead of passing all the various smtp* args to __send_message\n> individually, let's just pass the options list instead.\n\nLooks good.\n\n> +    if (smtppassword and not smtpuser):\n> +        raise CmdException, 'SMTP password supplied, username needed'\n> +    if (smtpusetls and not smtpuser):\n> +        raise CmdException, 'SMTP over TLS requested, username needed'\n\nPython style nit: Use \"raise Exception('message')\" in new code. (And\nyes, I know you just moved these lines around.)\n\n-- \nKarl Wiberg, kha@treskal.com\n    subrabbit.wordpress.com\n    www.treskal.com/kalle\n"},{"id":"128706","messageId":"b8197bcb0911291323l35cb3624td3cbc393bf4513b3@mail.gmail.com","threadId":"21779","inReplyTo":"20091128195026.949.1772.stgit@bob.kio","subject":"Re: [PATCH 3/6] stg mail: make __send_message do more","fromName":"Karl Wiberg","fromEmail":"kha@treskal.com","sentAt":"2009-11-29T21:23:00Z","receivedAt":"2009-11-29T21:23:00Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On Sat, Nov 28, 2009 at 8:50 PM, Alex Chiang <achiang@hp.com> wrote:\n\n> Factor out the common code required to send either a cover mail\n> or patch, and implement it in __send_message.\n\nNice code size reduction.\n\n> +    msg_id = email.Utils.make_msgid('stgit')\n> +    build = { 1: __build_cover, 4: __build_message }\n> +    msg = build[len(args)](tmpl, msg_id, options, *args)\n> +\n> +    from_addr, to_addrs = __parse_addresses(msg)\n> +    msg_str = msg.as_string(options.mbox)\n> +    if options.mbox:\n> +        out.stdout_raw(msg_str + '\\n')\n> +        return msg_id\n> +\n> +    outstr = { 1: 'the cover message', 4: 'patch \"%s\"' % args[0] }\n> +    out.start('Sending ' + outstr[len(args)])\n\nYou could consolidate the two dictionaries like this, to avoid making\nthe same choice twice and make the code more pleasant to read:\n\n  (build, outstr) = { 1: (__build_cover, 'the cover message'), 4:\n(__build_message, 'patch \"%s\"' % args[0]) }\n\n> +    # give recipients a chance of receiving related patches in correct order\n> +    #                                       patch_nr < total_nr\n> +    if len(args) == 1 or (len(args) == 4 and args[1] < args[2]):\n> +        sleep = options.sleep or config.getint('stgit.smtpdelay')\n> +        time.sleep(sleep)\n\nHmm. I must say I find all the args[x] a bit hard to read. I'd prefer\nsymbolic names.\n\n-- \nKarl Wiberg, kha@treskal.com\n   subrabbit.wordpress.com\n   www.treskal.com/kalle\n"},{"id":"128707","messageId":"b8197bcb0911291354m674d3698m929a1d542a59ed9f@mail.gmail.com","threadId":"21779","inReplyTo":"20091128195037.949.63611.stgit@bob.kio","subject":"Re: [PATCH 5/6] stg mail: add basic support for git send-email","fromName":"Karl Wiberg","fromEmail":"kha@treskal.com","sentAt":"2009-11-29T21:54:25Z","receivedAt":"2009-11-29T21:54:25Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On Sat, Nov 28, 2009 at 8:50 PM, Alex Chiang <achiang@hp.com> wrote:\n\n> +    # XXX: yuck, there's gotta be a more pythonic way. Ideally we'd like\n> +    # to use the git_opts dictionary as our mapping between stg mail and\n> +    # git send-email; extract k, v pairs from git_opts, and use those\n> +    # to iterate across options somehow.\n> +    git_opts = { 'to': '--to=', 'cc': '--cc=', 'bcc': '--bcc=' }\n> +    if options.to:\n> +        for a in options.to:\n> +            cmd.append(\"--to=%s\" % a)\n> +    if options.cc:\n> +        for a in options.cc:\n> +            cmd.append(\"--cc=%s\" % a)\n> +    if options.bcc:\n> +        for a in options.bcc:\n> +            cmd.append(\"--bcc=%s\" % a)\n> +    if not options.auto:\n> +        cmd.append(\"--suppress-cc=body\")\n\nLike this?\n\nfor x in ['to', 'cc', 'bcc']:\n    if getattr(options, x):\n        cmd.extend('--%s=%s' % (x, a) for a in getattr(options, x))\n\n> +    (fd, path) = mkstemp()\n> +    os.write(fd, msg.as_string(options.mbox))\n> +    os.close(fd)\n> +\n> +    try:\n> +        cmd.append(path)\n> +        call(cmd)\n> +    except Exception, err:\n> +        os.unlink(path)\n> +        raise CmdException, str(err)\n> +\n> +    os.unlink(path)\n\nTo avoid having to remember to call unlink in all paths, you can write\n\ntry:\n    try:\n        cmd.append(path)\n        call(cmd)\n    except Exception, e:\n        raise CmdException(str(e))\nfinally:\n    os.unlink(path)\n\n(The combined try...except...finally statement didn't appear until\npython 2.5, but we'd like to stay compatible with 2.4.)\n\n-- \nKarl Wiberg, kha@treskal.com\n   subrabbit.wordpress.com\n   www.treskal.com/kalle\n"},{"id":"128708","messageId":"b8197bcb0911291405i6f052216q8717c34063320592@mail.gmail.com","threadId":"21779","inReplyTo":"20091128194056.949.88791.stgit@bob.kio","subject":"Re: [StGit RFC PATCH 0/6] add support for git send-email","fromName":"Karl Wiberg","fromEmail":"kha@treskal.com","sentAt":"2009-11-29T22:05:07Z","receivedAt":"2009-11-29T22:05:07Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On Sat, Nov 28, 2009 at 8:50 PM, Alex Chiang <achiang@hp.com> wrote:\n\n> stg mail still has some nice features over git send-email, such\n> as the -v command line parameter and --prefix. Maybe at some point\n> in the future, we can migrate those features into git send-email and\n> continue thinning out stg mail.\n\nYes. But note that we tend to be conservative and not require a\ntoo-new git, so a patch adding such a dependency would have to wait a\nwhile. (I'm currently carrying two such patches in my experimental\nbranch.)\n\n> But I wanted to get some feedback first to make sure I'm going in the\n> right direction before going too much further.\n\nI've read the patches, and it looks about right from where I stand.\n\nDid you remember to run the regression tests? It's very helpful when\nreviewing to know that the regression suite passes at every point in\nthe series.\n\n-- \nKarl Wiberg, kha@treskal.com\n   subrabbit.wordpress.com\n   www.treskal.com/kalle\n"},{"id":"128817","messageId":"20091130235825.GJ12733@ldl.fc.hp.com","threadId":"21779","inReplyTo":"4B123B48.4050405@treskal.com","subject":"Re: [PATCH 1/6] stg mail: Refactor __send_message and friends","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-30T23:58:25Z","receivedAt":"2009-11-30T23:58:25Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"* Karl Wiberg <kha@treskal.com>:\n> Alex Chiang wrote:\n>\n>> +    if (smtppassword and not smtpuser):\n>> +        raise CmdException, 'SMTP password supplied, username needed'\n>> +    if (smtpusetls and not smtpuser):\n>> +        raise CmdException, 'SMTP over TLS requested, username needed'\n>\n> Python style nit: Use \"raise Exception('message')\" in new code. (And\n> yes, I know you just moved these lines around.)\n\nChanged, thanks.\n"},{"id":"128818","messageId":"20091130235935.GK12733@ldl.fc.hp.com","threadId":"21779","inReplyTo":"b8197bcb0911291323l35cb3624td3cbc393bf4513b3@mail.gmail.com","subject":"Re: [PATCH 3/6] stg mail: make __send_message do more","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-11-30T23:59:35Z","receivedAt":"2009-11-30T23:59:35Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"* Karl Wiberg <kha@treskal.com>:\n> On Sat, Nov 28, 2009 at 8:50 PM, Alex Chiang <achiang@hp.com> wrote:\n> \n> > Factor out the common code required to send either a cover mail\n> > or patch, and implement it in __send_message.\n> \n> Nice code size reduction.\n\nThanks.\n\n> > +    msg_id = email.Utils.make_msgid('stgit')\n> > +    build = { 1: __build_cover, 4: __build_message }\n> > +    msg = build[len(args)](tmpl, msg_id, options, *args)\n> > +\n> > +    from_addr, to_addrs = __parse_addresses(msg)\n> > +    msg_str = msg.as_string(options.mbox)\n> > +    if options.mbox:\n> > +        out.stdout_raw(msg_str + '\\n')\n> > +        return msg_id\n> > +\n> > +    outstr = { 1: 'the cover message', 4: 'patch \"%s\"' % args[0] }\n> > +    out.start('Sending ' + outstr[len(args)])\n> \n> You could consolidate the two dictionaries like this, to avoid making\n> the same choice twice and make the code more pleasant to read:\n> \n>   (build, outstr) = { 1: (__build_cover, 'the cover message'), 4:\n> (__build_message, 'patch \"%s\"' % args[0]) }\n\nHm, I don't think that's valid. I ended up doing something like\nthis:\n\n    d = { 'cover': (__build_cover, 'the cover message'),\n          'patch': (__build_message, 'patch \"%s\"' % args[0]) }\n    \n    (build, outstr) = d[type]\n\n> > +    # give recipients a chance of receiving related patches in correct order\n> > +    #                                       patch_nr < total_nr\n> > +    if len(args) == 1 or (len(args) == 4 and args[1] < args[2]):\n> > +        sleep = options.sleep or config.getint('stgit.smtpdelay')\n> > +        time.sleep(sleep)\n> \n> Hmm. I must say I find all the args[x] a bit hard to read. I'd prefer\n> symbolic names.\n\nOk, I changed this up.\n\nThanks for the review.\n/ac\n"},{"id":"128819","messageId":"20091201000048.GL12733@ldl.fc.hp.com","threadId":"21779","inReplyTo":"b8197bcb0911291354m674d3698m929a1d542a59ed9f@mail.gmail.com","subject":"Re: [PATCH 5/6] stg mail: add basic support for git send-email","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-12-01T00:00:48Z","receivedAt":"2009-12-01T00:00:48Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"* Karl Wiberg <kha@treskal.com>:\n> On Sat, Nov 28, 2009 at 8:50 PM, Alex Chiang <achiang@hp.com> wrote:\n> \n> > +    # XXX: yuck, there's gotta be a more pythonic way. Ideally we'd like\n> > +    # to use the git_opts dictionary as our mapping between stg mail and\n> > +    # git send-email; extract k, v pairs from git_opts, and use those\n> > +    # to iterate across options somehow.\n> > +    git_opts = { 'to': '--to=', 'cc': '--cc=', 'bcc': '--bcc=' }\n> > +    if options.to:\n> > +        for a in options.to:\n> > +            cmd.append(\"--to=%s\" % a)\n> > +    if options.cc:\n> > +        for a in options.cc:\n> > +            cmd.append(\"--cc=%s\" % a)\n> > +    if options.bcc:\n> > +        for a in options.bcc:\n> > +            cmd.append(\"--bcc=%s\" % a)\n> > +    if not options.auto:\n> > +        cmd.append(\"--suppress-cc=body\")\n> \n> Like this?\n> \n> for x in ['to', 'cc', 'bcc']:\n>     if getattr(options, x):\n>         cmd.extend('--%s=%s' % (x, a) for a in getattr(options, x))\n\nYeah, that looks nice. Re-implemented with your suggestion.\n\n> > +    (fd, path) = mkstemp()\n> > +    os.write(fd, msg.as_string(options.mbox))\n> > +    os.close(fd)\n> > +\n> > +    try:\n> > +        cmd.append(path)\n> > +        call(cmd)\n> > +    except Exception, err:\n> > +        os.unlink(path)\n> > +        raise CmdException, str(err)\n> > +\n> > +    os.unlink(path)\n> \n> To avoid having to remember to call unlink in all paths, you can write\n> \n> try:\n>     try:\n>         cmd.append(path)\n>         call(cmd)\n>     except Exception, e:\n>         raise CmdException(str(e))\n> finally:\n>     os.unlink(path)\n> \n> (The combined try...except...finally statement didn't appear until\n> python 2.5, but we'd like to stay compatible with 2.4.)\n\nThis statement confuses me a bit. The way I read it, I shouldn't\nuse your suggestion due to compat reasons?\n\nThanks,\n/ac\n"},{"id":"128820","messageId":"20091201000258.GM12733@ldl.fc.hp.com","threadId":"21779","inReplyTo":"b8197bcb0911291405i6f052216q8717c34063320592@mail.gmail.com","subject":"Re: [StGit RFC PATCH 0/6] add support for git send-email","fromName":"Alex Chiang","fromEmail":"achiang@hp.com","sentAt":"2009-12-01T00:02:58Z","receivedAt":"2009-12-01T00:02:58Z","isPatch":true,"sender":{"key":"achiang@hp.com","avatar":null},"body":"* Karl Wiberg <kha@treskal.com>:\n> On Sat, Nov 28, 2009 at 8:50 PM, Alex Chiang <achiang@hp.com> wrote:\n> \n> > stg mail still has some nice features over git send-email, such\n> > as the -v command line parameter and --prefix. Maybe at some point\n> > in the future, we can migrate those features into git send-email and\n> > continue thinning out stg mail.\n> \n> Yes. But note that we tend to be conservative and not require a\n> too-new git, so a patch adding such a dependency would have to wait a\n> while. (I'm currently carrying two such patches in my experimental\n> branch.)\n\nUnderstood. For now, of course, all the changes that I'm\nproposing should work with bog-standard, oldish git, since I\ndon't think the git send-email interface has changed in a while.\n\n> > But I wanted to get some feedback first to make sure I'm going in the\n> > right direction before going too much further.\n> \n> I've read the patches, and it looks about right from where I stand.\n\nThank you very much for the review.\n\n> Did you remember to run the regression tests? It's very helpful when\n> reviewing to know that the regression suite passes at every point in\n> the series.\n\nGood idea. I've been running t/t1900-mail.sh at each stage since\nmy changes seem rather localized to sending mail.\n\nShould I be running the entire suite?\n\n/ac\n"},{"id":"128836","messageId":"b8197bcb0911302326w2fcda7dfi520159b25ecd18d0@mail.gmail.com","threadId":"21779","inReplyTo":"20091130235935.GK12733@ldl.fc.hp.com","subject":"Re: [PATCH 3/6] stg mail: make __send_message do more","fromName":"Karl Wiberg","fromEmail":"kha@treskal.com","sentAt":"2009-12-01T07:26:50Z","receivedAt":"2009-12-01T07:26:50Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On Tue, Dec 1, 2009 at 12:59 AM, Alex Chiang <achiang@hp.com> wrote:\n\n> * Karl Wiberg <kha@treskal.com>:\n>\n> > You could consolidate the two dictionaries like this, to avoid\n> > making the same choice twice and make the code more pleasant to\n> > read:\n> >\n> > (build, outstr) = { 1: (__build_cover, 'the cover message'), 4: (__build_message, 'patch \"%s\"' % args[0]) }\n>\n> Hm, I don't think that's valid. I ended up doing something like\n> this:\n>\n> d = { 'cover': (__build_cover, 'the cover message'), 'patch': (__build_message, 'patch \"%s\"' % args[0]) }\n> (build, outstr) = d[type]\n\nDuh. That's what I get for posting untested code. It should be\n\n(build, outstr) = { 1: (__build_cover, 'the cover message'), 4:\n(__build_message, 'patch \"%s\"' % args[0]) }[len(args)]\n\nThat is, we create a dictionary only to immediately use it once,\nwithout ever explicitly storing a reference to it.\n\n-- \nKarl Wiberg, kha@treskal.com\n   subrabbit.wordpress.com\n   www.treskal.com/kalle\n"},{"id":"128837","messageId":"b8197bcb0911302333v36d38ae3n86417911249fe9b0@mail.gmail.com","threadId":"21779","inReplyTo":"20091201000048.GL12733@ldl.fc.hp.com","subject":"Re: [PATCH 5/6] stg mail: add basic support for git send-email","fromName":"Karl Wiberg","fromEmail":"kha@treskal.com","sentAt":"2009-12-01T07:33:19Z","receivedAt":"2009-12-01T07:33:19Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On Tue, Dec 1, 2009 at 1:00 AM, Alex Chiang <achiang@hp.com> wrote:\n\n> * Karl Wiberg <kha@treskal.com>:\n>\n> > try:\n> >     try:\n> >         cmd.append(path)\n> >         call(cmd)\n> >     except Exception, e:\n> >         raise CmdException(str(e))\n> > finally:\n> >     os.unlink(path)\n> >\n> > (The combined try...except...finally statement didn't appear until\n> > python 2.5, but we'd like to stay compatible with 2.4.)\n>\n> This statement confuses me a bit. The way I read it, I shouldn't use\n> your suggestion due to compat reasons?\n\nOh. No, the \"combined\" statement would look like this:\n\ntry:\n    cmd.append(path)\n    call(cmd)\nexcept Exception, e:\n    raise CmdException(str(e))\nfinally:\n    os.unlink(path)\n\nIt works exactly like the nested try...finally and try...except\nstatement above, but results in less indentation---and would thus be\npreferred, if not for the 2.4 compatibility issue.\n\n-- \nKarl Wiberg, kha@treskal.com\n   subrabbit.wordpress.com\n   www.treskal.com/kalle\n"},{"id":"128840","messageId":"b8197bcb0911302338x39f06c1du2023d76c9f094121@mail.gmail.com","threadId":"21779","inReplyTo":"20091201000258.GM12733@ldl.fc.hp.com","subject":"Re: [StGit RFC PATCH 0/6] add support for git send-email","fromName":"Karl Wiberg","fromEmail":"kha@treskal.com","sentAt":"2009-12-01T07:38:19Z","receivedAt":"2009-12-01T07:38:19Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On Tue, Dec 1, 2009 at 1:02 AM, Alex Chiang <achiang@hp.com> wrote:\n\n> * Karl Wiberg <kha@treskal.com>:\n>\n>> Did you remember to run the regression tests? It's very helpful when\n>> reviewing to know that the regression suite passes at every point in\n>> the series.\n>\n> Good idea. I've been running t/t1900-mail.sh at each stage\n\nPerfect.\n\n> since my changes seem rather localized to sending mail.\n>\n> Should I be running the entire suite?\n\nJust running that single test should be sufficient in this case; as\nyou say, the changes are rather well contained.\n\nRunning the whole suite takes a few minutes, so it might be worth\ndoing once in a while.\n\n-- \nKarl Wiberg, kha@treskal.com\n   subrabbit.wordpress.com\n   www.treskal.com/kalle\n"}]}