--- /dev/null
+Return-Path: <sagi@rtsn.nl>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id E36236DE0C4A\r
+ for <notmuch@notmuchmail.org>; Sun, 7 Feb 2016 13:14:02 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.303\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.303 tagged_above=-999 required=5 tests=[AWL=0.249,\r
+ RP_MATCHES_RCVD=-0.55, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001]\r
+ autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id cO64LdXF3QyV for <notmuch@notmuchmail.org>;\r
+ Sun, 7 Feb 2016 13:14:00 -0800 (PST)\r
+Received: from kardo2.rtsn.nl (rtsn.nl [37.97.129.244])\r
+ by arlo.cworth.org (Postfix) with ESMTPS id 76F016DE0B27\r
+ for <notmuch@notmuchmail.org>; Sun, 7 Feb 2016 13:14:00 -0800 (PST)\r
+Received: by kardo2.rtsn.nl (Postfix, from userid 1000)\r
+ id 02EBA1FF571; Sun, 7 Feb 2016 22:13:40 +0100 (CET)\r
+Content-Type: text/plain; charset="utf-8"\r
+MIME-Version: 1.0\r
+Content-Transfer-Encoding: quoted-printable\r
+From: Maarten Aertsen <sagi-notmuch@rtsn.nl>\r
+User-Agent: alot/0.3.6\r
+To: "Notmuch Mail" <notmuch@notmuchmail.org>\r
+References: <20160124154800.19103.24730@kardo2.rtsn.nl>\r
+ <87a8nsz8bd.fsf@zancas.localnet>\r
+In-Reply-To: <87a8nsz8bd.fsf@zancas.localnet>\r
+Message-ID: <20160207211340.15609.92485@kardo2.rtsn.nl>\r
+Subject: [PATCH] cli: avoid non-zero exits in notmuch insert --keep\r
+Date: Sun, 07 Feb 2016 22:13:40 +0100\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sun, 07 Feb 2016 21:14:03 -0000\r
+\r
+Re-ordered code that touches the database to try and deliver e-mail to\r
+at least try to deliver to the Maildir (which, with --keep should return\r
+success).\r
+\r
+In the case of any failure, we now return EX_TEMPFAIL (a sendmail\r
+convention, defined in sysexits.h) to signal to the LDA that it should\r
+retry later. This prevents a direct reject or bounce of e-mail.\r
+---\r
+ notmuch-client.h | 1 +\r
+ notmuch-insert.c | 42 +++++++++++++++++++++++-------------------\r
+ notmuch.c | 17 +++++++++++++----\r
+ 3 files changed, 37 insertions(+), 23 deletions(-)\r
+\r
+diff --git a/notmuch-client.h b/notmuch-client.h\r
+index 18e6c60..e3d6a46 100644\r
+--- a/notmuch-client.h\r
++++ b/notmuch-client.h\r
+@@ -466,6 +466,7 @@ print_status_query (const char *loc,\r
+ =\r
+\r
+ extern char *notmuch_requested_db_uuid;\r
+ extern const notmuch_opt_desc_t notmuch_shared_options [];\r
++notmuch_bool_t notmuch_has_unmatched_db_uuid (notmuch_database_t *notmuch);\r
+ void notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch);\r
+ =\r
+\r
+ void notmuch_process_shared_options (const char* subcommand_name);\r
+diff --git a/notmuch-insert.c b/notmuch-insert.c\r
+index 5205c17..35b6779 100644\r
+--- a/notmuch-insert.c\r
++++ b/notmuch-insert.c\r
+@@ -28,6 +28,8 @@\r
+ #include <sys/stat.h>\r
+ #include <fcntl.h>\r
+ =\r
+\r
++#include <sysexits.h>\r
++\r
+ static volatile sig_atomic_t interrupted;\r
+ =\r
+\r
+ static void\r
+@@ -532,31 +534,33 @@ notmuch_insert_command (notmuch_config_t *config, int=\r
+ argc, char *argv[])\r
+ action.sa_flags =3D 0;\r
+ sigaction (SIGINT, &action, NULL);\r
+ =\r
+\r
+- if (notmuch_database_open (notmuch_config_get_database_path (config),\r
+- NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))\r
+- return EXIT_FAILURE;\r
+-\r
+- notmuch_exit_if_unmatched_db_uuid (notmuch);\r
+-\r
+ /* Write the message to the Maildir new directory. */\r
+ newpath =3D maildir_write_new (config, STDIN_FILENO, maildir);\r
+ if (! newpath) {\r
+- notmuch_database_destroy (notmuch);\r
+ return EXIT_FAILURE;\r
+ }\r
+ =\r
+\r
+- /* Index the message. */\r
+- status =3D add_file (notmuch, newpath, tag_ops, synchronize_flags, kee=\r
+p);\r
+-\r
+- /* Commit changes. */\r
+- close_status =3D notmuch_database_destroy (notmuch);\r
+- if (close_status) {\r
+- /* Hold on to the first error, if any. */\r
+- if (! status)\r
+- status =3D close_status;\r
+- fprintf (stderr, "%s: failed to commit database changes: %s\n",\r
+- keep ? "Warning" : "Error",\r
+- notmuch_status_to_string (close_status));\r
++ status =3D notmuch_database_open (notmuch_config_get_database_path (co=\r
+nfig),\r
++ NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much);\r
++ if (! status) {\r
++ /* with keep, send EX_TEMPFAIL per sysexits.h to invite the caller to\r
++ * retry at some later point and avoid permanent failure */\r
++ if (notmuch_has_unmatched_db_uuid(notmuch))\r
++ exit (keep ? EX_TEMPFAIL : EXIT_FAILURE);\r
++\r
++ /* Index the message. */\r
++ status =3D add_file (notmuch, newpath, tag_ops, synchronize_flags,=\r
+ keep);\r
++\r
++ /* Commit changes. */\r
++ close_status =3D notmuch_database_destroy (notmuch);\r
++ if (close_status) {\r
++ /* Hold on to the first error, if any. */\r
++ if (! status)\r
++ status =3D close_status;\r
++ fprintf (stderr, "%s: failed to commit database changes: %s\n",\r
++ keep ? "Warning" : "Error",\r
++ notmuch_status_to_string (close_status));\r
++ }\r
+ }\r
+ =\r
+\r
+ if (status) {\r
+diff --git a/notmuch.c b/notmuch.c\r
+index ce6c575..783bb2a 100644\r
+--- a/notmuch.c\r
++++ b/notmuch.c\r
+@@ -220,20 +220,29 @@ be supported in the future.\n", notmuch_format_versio=\r
+n);\r
+ }\r
+ }\r
+ =\r
+\r
+-void\r
+-notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch)\r
++notmuch_bool_t\r
++notmuch_has_unmatched_db_uuid (notmuch_database_t *notmuch)\r
+ {\r
+ const char *uuid =3D NULL;\r
+ =\r
+\r
+ if (!notmuch_requested_db_uuid)\r
+- return;\r
++ return FALSE;\r
+ IGNORE_RESULT (notmuch_database_get_revision (notmuch, &uuid));\r
+ =\r
+\r
+ if (strcmp (notmuch_requested_db_uuid, uuid) !=3D 0){\r
+ fprintf (stderr, "Error: requested database revision %s does not match %s=\r
+\n",\r
+ notmuch_requested_db_uuid, uuid);\r
+- exit (1);\r
++ return TRUE;\r
+ }\r
++\r
++ return FALSE;\r
++}\r
++\r
++void\r
++notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch)\r
++{\r
++ if (notmuch_has_unmatched_db_uuid(notmuch))\r
++ exit (1);\r
+ }\r
+ =\r
+\r
+ static void\r
+-- =\r
+\r
+2.7.0\r