--- /dev/null
+Return-Path: <polatel@gmail.com>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 44D6F429E21\r
+ for <notmuch@notmuchmail.org>; Mon, 3 Oct 2011 09:49:37 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References"\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 1.7\r
+X-Spam-Level: *\r
+X-Spam-Status: No, score=1.7 tagged_above=-999 required=5\r
+ tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+ FREEMAIL_FROM=0.001, FREEMAIL_REPLY=2.499, RCVD_IN_DNSWL_LOW=-0.7]\r
+ autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id msIDsCPIiafs for <notmuch@notmuchmail.org>;\r
+ Mon, 3 Oct 2011 09:49:36 -0700 (PDT)\r
+Received: from mail-dy0-f53.google.com (mail-dy0-f53.google.com\r
+ [209.85.220.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id CB7ED431FB6\r
+ for <notmuch@notmuchmail.org>; Mon, 3 Oct 2011 09:49:35 -0700 (PDT)\r
+Received: by dye4 with SMTP id 4so176309dye.26\r
+ for <notmuch@notmuchmail.org>; Mon, 03 Oct 2011 09:49:33 -0700 (PDT)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;\r
+ h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references\r
+ :in-reply-to:references:organization;\r
+ bh=kSMXOME/xCGF22PVGo39cM0DkSIcWxa3XO+80rKctws=;\r
+ b=r6walyAMkxFAXucLOejWOUrvpeSdc2uF/XLiL8H7088XXgGQp0BB6R9orZCntoBO40\r
+ kZNGebetHzl3czpi1HDHu9A+bsEUFwFaoRJeaqtq9IVnycn9hmXRlf7I4yVP1ypPiMz3\r
+ BagPDt9n97bKy1X7wfIZ/inTt3STWI5OM4T2g=\r
+Received: by 10.223.45.85 with SMTP id d21mr180774faf.63.1317660572942;\r
+ Mon, 03 Oct 2011 09:49:32 -0700 (PDT)\r
+Received: from localhost ([88.236.39.101])\r
+ by mx.google.com with ESMTPS id n1sm21888425fad.20.2011.10.03.09.49.31\r
+ (version=TLSv1/SSLv3 cipher=OTHER);\r
+ Mon, 03 Oct 2011 09:49:32 -0700 (PDT)\r
+From: Ali Polatel <polatel@gmail.com>\r
+To: Notmuch Mailing List <notmuch@notmuchmail.org>\r
+Subject: [PATCH v1 1/1] lib: make find_message{,by_filename) report errors\r
+Date: Mon, 3 Oct 2011 19:49:20 +0300\r
+Message-Id:\r
+ <1218582065f35bfcc5b84dfc1fbce21fc05034a6.1317660324.git.alip@exherbo.org>\r
+X-Mailer: git-send-email 1.7.6.1\r
+In-Reply-To: <cover.1317660324.git.alip@exherbo.org>\r
+References: <cover.1317456435.git.alip@exherbo.org>\r
+ <cover.1317660324.git.alip@exherbo.org>\r
+In-Reply-To: <cover.1317660324.git.alip@exherbo.org>\r
+References: <cover.1317660324.git.alip@exherbo.org>\r
+Organization: Pink Floyd\r
+Cc: Austin Clements <amdragon@MIT.EDU>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://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: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Mon, 03 Oct 2011 16:49:37 -0000\r
+\r
+Previously, the functions notmuch_database_find_message() and\r
+notmuch_database_find_message_by_filename() functions did not properly\r
+report error condition to the library user.\r
+\r
+For more information, read the thread on the notmuch mailing list\r
+starting with my mail "id:871uv2unfd.fsf@gmail.com"\r
+\r
+Make these functions accept a pointer to 'notmuch_message_t' as argument\r
+and return notmuch_status_t which may be used to check for any error\r
+condition.\r
+\r
+restore: Modify for the new notmuch_database_find_message()\r
+new: Modify for the new notmuch_database_find_message_by_filename()\r
+---\r
+ lib/database.cc | 90 ++++++++++++++++++++++++++++++++++------------------\r
+ lib/message.cc | 6 ++--\r
+ lib/notmuch.h | 61 +++++++++++++++++++++++++----------\r
+ notmuch-new.c | 4 ++-\r
+ notmuch-restore.c | 11 ++++--\r
+ 5 files changed, 115 insertions(+), 57 deletions(-)\r
+\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 9299c8d..1705232 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -360,13 +360,17 @@ _message_id_compressed (void *ctx, const char *message_id)\r
+ return compressed;\r
+ }\r
+ \r
+-notmuch_message_t *\r
++notmuch_status_t\r
+ notmuch_database_find_message (notmuch_database_t *notmuch,\r
+- const char *message_id)\r
++ const char *message_id,\r
++ notmuch_message_t **message)\r
+ {\r
+ notmuch_private_status_t status;\r
+ unsigned int doc_id;\r
+ \r
++ if (message == NULL)\r
++ return NOTMUCH_STATUS_NULL_POINTER;\r
++\r
+ if (strlen (message_id) > NOTMUCH_MESSAGE_ID_MAX)\r
+ message_id = _message_id_compressed (notmuch, message_id);\r
+ \r
+@@ -375,14 +379,21 @@ notmuch_database_find_message (notmuch_database_t *notmuch,\r
+ message_id, &doc_id);\r
+ \r
+ if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND)\r
+- return NULL;\r
++ *message = NULL;\r
++ else {\r
++ *message = _notmuch_message_create (notmuch, notmuch, doc_id,\r
++ NULL);\r
++ if (*message == NULL)\r
++ return NOTMUCH_STATUS_OUT_OF_MEMORY;\r
++ }\r
+ \r
+- return _notmuch_message_create (notmuch, notmuch, doc_id, NULL);\r
++ return NOTMUCH_STATUS_SUCCESS;\r
+ } catch (const Xapian::Error &error) {\r
+ fprintf (stderr, "A Xapian exception occurred finding message: %s.\n",\r
+ error.get_msg().c_str());\r
+ notmuch->exception_reported = TRUE;\r
+- return NULL;\r
++ *message = NULL;\r
++ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
+ }\r
+ }\r
+ \r
+@@ -1311,7 +1322,8 @@ _get_metadata_thread_id_key (void *ctx, const char *message_id)\r
+ \r
+ /* Find the thread ID to which the message with 'message_id' belongs.\r
+ *\r
+- * Always returns a newly talloced string belonging to 'ctx'.\r
++ * Note: 'thread_id' must not be NULL!\r
++ * On success '*thread_id' is set to a newly talloced string belonging to 'ctx'.\r
+ *\r
+ * Note: If there is no message in the database with the given\r
+ * 'message_id' then a new thread_id will be allocated for this\r
+@@ -1319,25 +1331,29 @@ _get_metadata_thread_id_key (void *ctx, const char *message_id)\r
+ * thread ID can be looked up if the message is added to the database\r
+ * later).\r
+ */\r
+-static const char *\r
++static notmuch_status_t\r
+ _resolve_message_id_to_thread_id (notmuch_database_t *notmuch,\r
+ void *ctx,\r
+- const char *message_id)\r
++ const char *message_id,\r
++ const char **thread_id)\r
+ {\r
++ notmuch_status_t status;\r
+ notmuch_message_t *message;\r
+ string thread_id_string;\r
+- const char *thread_id;\r
+ char *metadata_key;\r
+ Xapian::WritableDatabase *db;\r
+ \r
+- message = notmuch_database_find_message (notmuch, message_id);\r
++ status = notmuch_database_find_message (notmuch, message_id, &message);\r
++\r
++ if (status)\r
++ return status;\r
+ \r
+ if (message) {\r
+- thread_id = talloc_steal (ctx, notmuch_message_get_thread_id (message));\r
++ *thread_id = talloc_steal (ctx, notmuch_message_get_thread_id (message));\r
+ \r
+ notmuch_message_destroy (message);\r
+ \r
+- return thread_id;\r
++ return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
+ \r
+ /* Message has not been seen yet.\r
+@@ -1351,15 +1367,15 @@ _resolve_message_id_to_thread_id (notmuch_database_t *notmuch,\r
+ thread_id_string = notmuch->xapian_db->get_metadata (metadata_key);\r
+ \r
+ if (thread_id_string.empty()) {\r
+- thread_id = _notmuch_database_generate_thread_id (notmuch);\r
+- db->set_metadata (metadata_key, thread_id);\r
++ *thread_id = talloc_strdup (ctx, _notmuch_database_generate_thread_id (notmuch));\r
++ db->set_metadata (metadata_key, *thread_id);\r
+ } else {\r
+- thread_id = thread_id_string.c_str();\r
++ *thread_id = talloc_strdup(ctx, thread_id_string.c_str());\r
+ }\r
+ \r
+ talloc_free (metadata_key);\r
+ \r
+- return talloc_strdup (ctx, thread_id);\r
++ return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
+ \r
+ static notmuch_status_t\r
+@@ -1446,9 +1462,12 @@ _notmuch_database_link_message_to_parents (notmuch_database_t *notmuch,\r
+ _notmuch_message_add_term (message, "reference",\r
+ parent_message_id);\r
+ \r
+- parent_thread_id = _resolve_message_id_to_thread_id (notmuch,\r
+- message,\r
+- parent_message_id);\r
++ ret = _resolve_message_id_to_thread_id (notmuch,\r
++ message,\r
++ parent_message_id,\r
++ &parent_thread_id);\r
++ if (ret)\r
++ goto DONE;\r
+ \r
+ if (*thread_id == NULL) {\r
+ *thread_id = talloc_strdup (message, parent_thread_id);\r
+@@ -1759,11 +1778,12 @@ notmuch_status_t\r
+ notmuch_database_remove_message (notmuch_database_t *notmuch,\r
+ const char *filename)\r
+ {\r
+- notmuch_message_t *message =\r
+- notmuch_database_find_message_by_filename (notmuch, filename);\r
+- notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
++ notmuch_status_t status;\r
++ notmuch_message_t *message;\r
+ \r
+- if (message) {\r
++ status = notmuch_database_find_message_by_filename (notmuch, filename, &message);\r
++\r
++ if (status == NOTMUCH_STATUS_SUCCESS && message) {\r
+ status = _notmuch_message_remove_filename (message, filename);\r
+ if (status == NOTMUCH_STATUS_SUCCESS)\r
+ _notmuch_message_delete (message);\r
+@@ -1774,24 +1794,27 @@ notmuch_database_remove_message (notmuch_database_t *notmuch,\r
+ return status;\r
+ }\r
+ \r
+-notmuch_message_t *\r
++notmuch_status_t\r
+ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,\r
+- const char *filename)\r
++ const char *filename,\r
++ notmuch_message_t **message)\r
+ {\r
+ void *local;\r
+ const char *prefix = _find_prefix ("file-direntry");\r
+ char *direntry, *term;\r
+ Xapian::PostingIterator i, end;\r
+- notmuch_message_t *message = NULL;\r
+ notmuch_status_t status;\r
+ \r
++ if (message == NULL)\r
++ return NOTMUCH_STATUS_NULL_POINTER;\r
++\r
+ local = talloc_new (notmuch);\r
+ \r
+ try {\r
+ status = _notmuch_database_filename_to_direntry (local, notmuch,\r
+ filename, &direntry);\r
+ if (status)\r
+- return NULL;\r
++ goto DONE;\r
+ \r
+ term = talloc_asprintf (local, "%s%s", prefix, direntry);\r
+ \r
+@@ -1800,19 +1823,24 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,\r
+ if (i != end) {\r
+ notmuch_private_status_t private_status;\r
+ \r
+- message = _notmuch_message_create (notmuch, notmuch,\r
+- *i, &private_status);\r
++ *message = _notmuch_message_create (notmuch, notmuch,\r
++ *i, &private_status);\r
++ if (*message == NULL)\r
++ status = NOTMUCH_STATUS_OUT_OF_MEMORY;\r
+ }\r
+ } catch (const Xapian::Error &error) {\r
+ fprintf (stderr, "Error: A Xapian exception occurred finding message by filename: %s\n",\r
+ error.get_msg().c_str());\r
+ notmuch->exception_reported = TRUE;\r
+- message = NULL;\r
++ status = NOTMUCH_STATUS_OUT_OF_MEMORY;\r
+ }\r
+ \r
++ DONE:\r
+ talloc_free (local);\r
+ \r
+- return message;\r
++ if (status)\r
++ *message = NULL;\r
++ return status;\r
+ }\r
+ \r
+ notmuch_string_list_t *\r
+diff --git a/lib/message.cc b/lib/message.cc\r
+index 531d304..2a85744 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -216,11 +216,11 @@ _notmuch_message_create_for_message_id (notmuch_database_t *notmuch,\r
+ unsigned int doc_id;\r
+ char *term;\r
+ \r
+- *status_ret = NOTMUCH_PRIVATE_STATUS_SUCCESS;\r
+-\r
+- message = notmuch_database_find_message (notmuch, message_id);\r
++ *status_ret = (notmuch_private_status_t) notmuch_database_find_message (notmuch, message_id, &message);\r
+ if (message)\r
+ return talloc_steal (notmuch, message);\r
++ else if (*status_ret)\r
++ return NULL;\r
+ \r
+ term = talloc_asprintf (NULL, "%s%s",\r
+ _find_prefix ("id"), message_id);\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 6d7a99f..08b4ce2 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -347,35 +347,60 @@ notmuch_database_remove_message (notmuch_database_t *database,\r
+ \r
+ /* Find a message with the given message_id.\r
+ *\r
+- * If the database contains a message with the given message_id, then\r
+- * a new notmuch_message_t object is returned. The caller should call\r
+- * notmuch_message_destroy when done with the message.\r
++ * If message with the given message_id is found then, on successful return\r
++ * (NOTMUCH_STATUS_SUCCESS) '*message' will be initialized to a message object.\r
++ * The user should call notmuch_message_destroy when done with the message.\r
+ *\r
+- * This function returns NULL in the following situations:\r
++ * On any failure or when the message is not found, this function initializes\r
++ * '*message' to NULL. This means, when NOTMUCH_STATUS_SUCCESS is returned, the\r
++ * user is supposed to check '*message' for NULL to find out whether the\r
++ * message with the given message_id was found.\r
+ *\r
+- * * No message is found with the given message_id\r
+- * * An out-of-memory situation occurs\r
+- * * A Xapian exception occurs\r
++ * Note: The argument 'message' must not be NULL!\r
++ *\r
++ * Return value:\r
++ *\r
++ * NOTMUCH_STATUS_SUCCESS: Successful return, check '*message'.\r
++ *\r
++ * NOTMUCH_STATUS_NULL_POINTER: The given 'message' argument is NULL\r
++ *\r
++ * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory, creating message object\r
++ *\r
++ * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred\r
+ */\r
+-notmuch_message_t *\r
++notmuch_status_t\r
+ notmuch_database_find_message (notmuch_database_t *database,\r
+- const char *message_id);\r
++ const char *message_id,\r
++ notmuch_message_t **message);\r
+ \r
+ /* Find a message with the given filename.\r
+ *\r
+- * If the database contains a message with the given filename, then a\r
+- * new notmuch_message_t object is returned. The caller should call \r
+- * notmuch_message_destroy when done with the message.\r
++ * If the database contains a message with the given filename then, on\r
++ * successful return (NOTMUCH_STATUS_SUCCESS) '*message' will be initialized to\r
++ * a message object. The user should call notmuch_message_destroy when done\r
++ * with the message.\r
+ *\r
+- * This function returns NULL in the following situations:\r
++ * On any failure or when the message is not found, this function initializes\r
++ * '*message' to NULL. This means, when NOTMUCH_STATUS_SUCCESS is returned, the\r
++ * user is supposed to check '*message' for NULL to find out whether the\r
++ * message with the given filename is found.\r
+ *\r
+- * * No message is found with the given filename\r
+- * * An out-of-memory situation occurs\r
+- * * A Xapian exception occurs\r
++ * Note: The argument 'message' must not be NULL!\r
++ *\r
++ * Return value:\r
++ *\r
++ * NOTMUCH_STATUS_SUCCESS: Successful return, check '*message'\r
++ *\r
++ * NOTMUCH_STATUS_NULL_POINTER: The given 'message' argument is NULL\r
++ *\r
++ * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory, creating the message object\r
++ *\r
++ * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred\r
+ */\r
+-notmuch_message_t *\r
++notmuch_status_t\r
+ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,\r
+- const char *filename);\r
++ const char *filename,\r
++ notmuch_message_t **message);\r
+ \r
+ /* Return a list of all tags found in the database.\r
+ *\r
+diff --git a/notmuch-new.c b/notmuch-new.c\r
+index e79593c..96a1e31 100644\r
+--- a/notmuch-new.c\r
++++ b/notmuch-new.c\r
+@@ -743,7 +743,9 @@ remove_filename (notmuch_database_t *notmuch,\r
+ status = notmuch_database_begin_atomic (notmuch);\r
+ if (status)\r
+ return status;\r
+- message = notmuch_database_find_message_by_filename (notmuch, path);\r
++ status = notmuch_database_find_message_by_filename (notmuch, path, &message);\r
++ if (status || message == NULL)\r
++ return status;\r
+ status = notmuch_database_remove_message (notmuch, path);\r
+ if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) {\r
+ add_files_state->renamed_messages++;\r
+diff --git a/notmuch-restore.c b/notmuch-restore.c\r
+index f095f64..e4a5355 100644\r
+--- a/notmuch-restore.c\r
++++ b/notmuch-restore.c\r
+@@ -87,10 +87,13 @@ notmuch_restore_command (unused (void *ctx), int argc, char *argv[])\r
+ file_tags = xstrndup (line + match[2].rm_so,\r
+ match[2].rm_eo - match[2].rm_so);\r
+ \r
+- message = notmuch_database_find_message (notmuch, message_id);\r
+- if (message == NULL) {\r
+- fprintf (stderr, "Warning: Cannot apply tags to missing message: %s\n",\r
+- message_id);\r
++ status = notmuch_database_find_message (notmuch, message_id, &message);\r
++ if (status || message == NULL) {\r
++ fprintf (stderr, "Warning: Cannot apply tags to %smessage: %s\n",\r
++ message ? "" : "missing ", message_id);\r
++ if (status)\r
++ fprintf (stderr, "%s\n",\r
++ notmuch_status_to_string(status));\r
+ goto NEXT_LINE;\r
+ }\r
+ \r
+-- \r
+1.7.6.1\r
+\r