--- /dev/null
+Return-Path: <bremner@tesseract.cs.unb.ca>\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 9B56A429E39\r
+ for <notmuch@notmuchmail.org>; Tue, 30 Dec 2014 12:30:35 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\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 AzKQ8rufYTG5 for <notmuch@notmuchmail.org>;\r
+ Tue, 30 Dec 2014 12:30:27 -0800 (PST)\r
+Received: from yantan.tethera.net (yantan.tethera.net [199.188.72.155])\r
+ (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id CAA1C431FD9\r
+ for <notmuch@notmuchmail.org>; Tue, 30 Dec 2014 12:30:23 -0800 (PST)\r
+Received: from remotemail by yantan.tethera.net with local (Exim 4.80)\r
+ (envelope-from <bremner@tesseract.cs.unb.ca>)\r
+ id 1Y63Qq-0000zW-CL; Tue, 30 Dec 2014 16:30:20 -0400\r
+Received: (nullmailer pid 10599 invoked by uid 1000); Tue, 30 Dec 2014\r
+ 20:29:44 -0000\r
+From: David Bremner <david@tethera.net>\r
+To: notmuch@notmuchmail.org\r
+Subject: [Patch v2 5/5] lib: add status return to\r
+ notmuch_query_count_{message,threads}\r
+Date: Tue, 30 Dec 2014 21:29:40 +0100\r
+Message-Id: <1419971380-10307-6-git-send-email-david@tethera.net>\r
+X-Mailer: git-send-email 2.1.3\r
+In-Reply-To: <1419971380-10307-1-git-send-email-david@tethera.net>\r
+References: <1419971380-10307-1-git-send-email-david@tethera.net>\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: Tue, 30 Dec 2014 20:30:35 -0000\r
+\r
+We follow many other notmuch_ functions by having a status return and\r
+an output parameter. I decided not to add compatibility wrappers but\r
+just to break the API because the old API seems worth encouraging\r
+people to move away from. This change is large than might otherwise be desirable because it updates the CLI, the python bindings and the ruby bindings (but not the go bindings).\r
+---\r
+ bindings/python/notmuch/globals.py | 4 ++--\r
+ bindings/python/notmuch/query.py | 18 +++++++++++++-----\r
+ bindings/ruby/query.c | 26 ++++++++++++++++----------\r
+ lib/Makefile.local | 4 ++--\r
+ lib/database.cc | 8 +++++++-\r
+ lib/notmuch.h | 26 +++++++++++++++++++-------\r
+ lib/query.cc | 24 +++++++++++++-----------\r
+ notmuch-count.c | 14 ++++++++++++--\r
+ notmuch-reply.c | 8 +++++++-\r
+ notmuch-search.c | 14 ++++++++++++--\r
+ notmuch-show.c | 8 +++++++-\r
+ 11 files changed, 110 insertions(+), 44 deletions(-)\r
+\r
+diff --git a/bindings/python/notmuch/globals.py b/bindings/python/notmuch/globals.py\r
+index 24b25d3..85aab39 100644\r
+--- a/bindings/python/notmuch/globals.py\r
++++ b/bindings/python/notmuch/globals.py\r
+@@ -24,9 +24,9 @@ from ctypes import CDLL, Structure, POINTER\r
+ try:\r
+ from os import uname\r
+ if uname()[0] == 'Darwin':\r
+- nmlib = CDLL("libnotmuch.4.dylib")\r
++ nmlib = CDLL("libnotmuch.5.dylib")\r
+ else:\r
+- nmlib = CDLL("libnotmuch.so.4")\r
++ nmlib = CDLL("libnotmuch.so.5")\r
+ except:\r
+ raise ImportError("Could not find shared 'notmuch' library.")\r
+ \r
+diff --git a/bindings/python/notmuch/query.py b/bindings/python/notmuch/query.py\r
+index 94773ac..96fc1cd 100644\r
+--- a/bindings/python/notmuch/query.py\r
++++ b/bindings/python/notmuch/query.py\r
+@@ -17,7 +17,7 @@ along with notmuch. If not, see <http://www.gnu.org/licenses/>.\r
+ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>\r
+ """\r
+ \r
+-from ctypes import c_char_p, c_uint\r
++from ctypes import c_char_p, c_uint, POINTER, byref\r
+ from .globals import (\r
+ nmlib,\r
+ Enum,\r
+@@ -179,7 +179,7 @@ class Query(object):\r
+ return Messages(msgs_p, self)\r
+ \r
+ _count_messages = nmlib.notmuch_query_count_messages\r
+- _count_messages.argtypes = [NotmuchQueryP]\r
++ _count_messages.argtypes = [NotmuchQueryP, POINTER(c_uint)]\r
+ _count_messages.restype = c_uint\r
+ \r
+ def count_messages(self):\r
+@@ -191,10 +191,14 @@ class Query(object):\r
+ :rtype: int\r
+ '''\r
+ self._assert_query_is_initialized()\r
+- return Query._count_messages(self._query)\r
++ count = c_uint(0)\r
++ status = Query._count_messages(self._query, byref(count))\r
++ if status != 0:\r
++ raise NotmuchError(status)\r
++ return count.value\r
+ \r
+ _count_threads = nmlib.notmuch_query_count_threads\r
+- _count_threads.argtypes = [NotmuchQueryP]\r
++ _count_threads.argtypes = [NotmuchQueryP, POINTER(c_uint)]\r
+ _count_threads.restype = c_uint\r
+ \r
+ def count_threads(self):\r
+@@ -210,7 +214,11 @@ class Query(object):\r
+ :rtype: int\r
+ '''\r
+ self._assert_query_is_initialized()\r
+- return Query._count_threads(self._query)\r
++ count = c_uint(0)\r
++ status = Query._count_threads(self._query, byref(count))\r
++ if status != 0:\r
++ raise NotmuchError(status)\r
++ return count.value\r
+ \r
+ _destroy = nmlib.notmuch_query_destroy\r
+ _destroy.argtypes = [NotmuchQueryP]\r
+diff --git a/bindings/ruby/query.c b/bindings/ruby/query.c\r
+index a7dacba..d39b6bc 100644\r
+--- a/bindings/ruby/query.c\r
++++ b/bindings/ruby/query.c\r
+@@ -173,14 +173,17 @@ VALUE\r
+ notmuch_rb_query_count_messages (VALUE self)\r
+ {\r
+ notmuch_query_t *query;\r
++ notmuch_status_t status;\r
++ unsigned count;\r
+ \r
+ Data_Get_Notmuch_Query (self, query);\r
+ \r
+- /* Xapian exceptions are not handled properly.\r
+- * (function may return 0 after printing a message)\r
+- * Thus there is nothing we can do here...\r
+- */\r
+- return UINT2NUM(notmuch_query_count_messages(query));\r
++ status = notmuch_query_count_messages(query, &count);\r
++\r
++ if (status)\r
++ notmuch_rb_status_raise (status);\r
++ else\r
++ return UINT2NUM(count);\r
+ }\r
+ \r
+ /*\r
+@@ -192,12 +195,15 @@ VALUE\r
+ notmuch_rb_query_count_threads (VALUE self)\r
+ {\r
+ notmuch_query_t *query;\r
++ notmuch_status_t status;\r
++ unsigned count;\r
+ \r
+ Data_Get_Notmuch_Query (self, query);\r
+ \r
+- /* Xapian exceptions are not handled properly.\r
+- * (function may return 0 after printing a message)\r
+- * Thus there is nothing we can do here...\r
+- */\r
+- return UINT2NUM(notmuch_query_count_threads(query));\r
++ status = notmuch_query_count_threads(query, &count);\r
++ if (status)\r
++ notmuch_rb_status_raise (status);\r
++ else\r
++ return UINT2NUM(count);\r
++\r
+ }\r
+diff --git a/lib/Makefile.local b/lib/Makefile.local\r
+index 4120390..4bf8116 100644\r
+--- a/lib/Makefile.local\r
++++ b/lib/Makefile.local\r
+@@ -5,13 +5,13 @@\r
+ # the library interface, (such as the deletion of an API or a major\r
+ # semantic change that breaks formerly functioning code).\r
+ #\r
+-LIBNOTMUCH_VERSION_MAJOR = 4\r
++LIBNOTMUCH_VERSION_MAJOR = 5\r
+ \r
+ # The minor version of the library interface. This should be incremented at\r
+ # the time of release for any additions to the library interface,\r
+ # (and when it is incremented, the release version of the library should\r
+ # be reset to 0).\r
+-LIBNOTMUCH_VERSION_MINOR = 1\r
++LIBNOTMUCH_VERSION_MINOR = 0\r
+ \r
+ # The release version the library interface. This should be incremented at\r
+ # the time of release if there have been no changes to the interface, (but\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 3601f9d..b7fbc63 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -1268,7 +1268,13 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,\r
+ if (new_features &\r
+ (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_BOOL_FOLDER)) {\r
+ notmuch_query_t *query = notmuch_query_create (notmuch, "");\r
+- total += notmuch_query_count_messages (query);\r
++ unsigned msg_count;\r
++\r
++ status = notmuch_query_count_messages (query, &msg_count);\r
++ if (status)\r
++ goto DONE;\r
++\r
++ total += msg_count;\r
+ notmuch_query_destroy (query);\r
+ }\r
+ if (new_features & NOTMUCH_FEATURE_DIRECTORY_DOCS) {\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 220839b..37bf0bd 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -898,11 +898,15 @@ notmuch_threads_destroy (notmuch_threads_t *threads);\r
+ * This function performs a search and returns Xapian's best\r
+ * guess as to number of matching messages.\r
+ *\r
+- * If a Xapian exception occurs, this function may return 0 (after\r
+- * printing a message).\r
++ * Return value:\r
++ *\r
++ * NOTMUCH_STATUS_SUCCESS: query complete successfully.\r
++ *\r
++ * NOTMUCH_STATUS_XAPIAN_EXCEPTION: a Xapian exception occured. The\r
++ * value of *count is not defined.\r
+ */\r
+-unsigned\r
+-notmuch_query_count_messages (notmuch_query_t *query);\r
++notmuch_status_t\r
++notmuch_query_count_messages (notmuch_query_t *query, unsigned *count);\r
+ \r
+ /**\r
+ * Return the number of threads matching a search.\r
+@@ -914,10 +918,18 @@ notmuch_query_count_messages (notmuch_query_t *query);\r
+ * Note that this is a significantly heavier operation than\r
+ * notmuch_query_count_messages().\r
+ *\r
+- * If an error occurs, this function may return 0.\r
++ * Return value:\r
++ *\r
++ * NOTMUCH_STATUS_OUT_OF_MEMORY: Memory allocation failed. The value\r
++ * of *count is not defined\r
++\r
++ * NOTMUCH_STATUS_SUCCESS: query complete successfully.\r
++ *\r
++ * NOTMUCH_STATUS_XAPIAN_EXCEPTION: a Xapian exception occured. The\r
++ * value of *count is not defined.\r
+ */\r
+-unsigned\r
+-notmuch_query_count_threads (notmuch_query_t *query);\r
++notmuch_status_t\r
++notmuch_query_count_threads (notmuch_query_t *query, unsigned *count);\r
+ \r
+ /**\r
+ * Get the thread ID of 'thread'.\r
+diff --git a/lib/query.cc b/lib/query.cc\r
+index 60ff8bd..10ecf2e 100644\r
+--- a/lib/query.cc\r
++++ b/lib/query.cc\r
+@@ -508,8 +508,8 @@ notmuch_threads_destroy (notmuch_threads_t *threads)\r
+ talloc_free (threads);\r
+ }\r
+ \r
+-unsigned\r
+-notmuch_query_count_messages (notmuch_query_t *query)\r
++notmuch_status_t\r
++notmuch_query_count_messages (notmuch_query_t *query, unsigned *count_out)\r
+ {\r
+ notmuch_database_t *notmuch = query->notmuch;\r
+ const char *query_string = query->query_string;\r
+@@ -565,30 +565,32 @@ notmuch_query_count_messages (notmuch_query_t *query)\r
+ fprintf (stderr, "A Xapian exception occurred: %s\n",\r
+ error.get_msg().c_str());\r
+ fprintf (stderr, "Query string was: %s\n", query->query_string);\r
++ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
+ }\r
+ \r
+- return count;\r
++ *count_out=count;\r
++ return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
+ \r
+-unsigned\r
+-notmuch_query_count_threads (notmuch_query_t *query)\r
++notmuch_status_t\r
++notmuch_query_count_threads (notmuch_query_t *query, unsigned *count)\r
+ {\r
+ notmuch_messages_t *messages;\r
+ GHashTable *hash;\r
+- unsigned int count;\r
+ notmuch_sort_t sort;\r
++ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
+ \r
+ sort = query->sort;\r
+ query->sort = NOTMUCH_SORT_UNSORTED;\r
+ messages = notmuch_query_search_messages (query);\r
+ query->sort = sort;\r
+ if (messages == NULL)\r
+- return 0;\r
++ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
+ \r
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);\r
+ if (hash == NULL) {\r
+ talloc_free (messages);\r
+- return 0;\r
++ return NOTMUCH_STATUS_OUT_OF_MEMORY;\r
+ }\r
+ \r
+ while (notmuch_messages_valid (messages)) {\r
+@@ -597,7 +599,7 @@ notmuch_query_count_threads (notmuch_query_t *query)\r
+ char *thread_id_copy = talloc_strdup (messages, thread_id);\r
+ if (unlikely (thread_id_copy == NULL)) {\r
+ notmuch_message_destroy (message);\r
+- count = 0;\r
++ ret = NOTMUCH_STATUS_OUT_OF_MEMORY;\r
+ goto DONE;\r
+ }\r
+ g_hash_table_insert (hash, thread_id_copy, NULL);\r
+@@ -605,11 +607,11 @@ notmuch_query_count_threads (notmuch_query_t *query)\r
+ notmuch_messages_move_to_next (messages);\r
+ }\r
+ \r
+- count = g_hash_table_size (hash);\r
++ *count = g_hash_table_size (hash);\r
+ \r
+ DONE:\r
+ g_hash_table_unref (hash);\r
+ talloc_free (messages);\r
+ \r
+- return count;\r
++ return ret;\r
+ }\r
+diff --git a/notmuch-count.c b/notmuch-count.c\r
+index 6058f7c..7e3c1b7 100644\r
+--- a/notmuch-count.c\r
++++ b/notmuch-count.c\r
+@@ -71,6 +71,8 @@ print_count (notmuch_database_t *notmuch, const char *query_str,\r
+ {\r
+ notmuch_query_t *query;\r
+ size_t i;\r
++ unsigned count;\r
++ notmuch_status_t status;\r
+ \r
+ query = notmuch_query_create (notmuch, query_str);\r
+ if (query == NULL) {\r
+@@ -83,10 +85,18 @@ print_count (notmuch_database_t *notmuch, const char *query_str,\r
+ \r
+ switch (output) {\r
+ case OUTPUT_MESSAGES:\r
+- printf ("%u\n", notmuch_query_count_messages (query));\r
++ if ((status = notmuch_query_count_messages (query, &count))) {\r
++ fprintf (stderr, "Error: %s\n", notmuch_status_to_string (status));\r
++ return 1;\r
++ }\r
++ printf ("%u\n", count);\r
+ break;\r
+ case OUTPUT_THREADS:\r
+- printf ("%u\n", notmuch_query_count_threads (query));\r
++ if ((status = notmuch_query_count_threads (query, &count))) {\r
++ fprintf (stderr, "Error: %s\n", notmuch_status_to_string (status));\r
++ return 1;\r
++ }\r
++ printf ("%u\n", count);\r
+ break;\r
+ case OUTPUT_FILES:\r
+ printf ("%u\n", count_files (query));\r
+diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+index 7c1c809..c5f1b92 100644\r
+--- a/notmuch-reply.c\r
++++ b/notmuch-reply.c\r
+@@ -650,8 +650,14 @@ notmuch_reply_format_sprinter(void *ctx,\r
+ notmuch_messages_t *messages;\r
+ notmuch_message_t *message;\r
+ mime_node_t *node;\r
++ unsigned count;\r
++ notmuch_status_t status;\r
+ \r
+- if (notmuch_query_count_messages (query) != 1) {\r
++ if ((status = notmuch_query_count_messages (query, &count))) {\r
++ fprintf (stderr, "Error: %s.\n", notmuch_status_to_string (status));\r
++ return 1;\r
++ }\r
++ if (count != 1) {\r
+ fprintf (stderr, "Error: search term did not match precisely one message.\n");\r
+ return 1;\r
+ }\r
+diff --git a/notmuch-search.c b/notmuch-search.c\r
+index 14b9f01..cadfc0c 100644\r
+--- a/notmuch-search.c\r
++++ b/notmuch-search.c\r
+@@ -113,7 +113,14 @@ do_search_threads (search_context_t *ctx)\r
+ int i;\r
+ \r
+ if (ctx->offset < 0) {\r
+- ctx->offset += notmuch_query_count_threads (ctx->query);\r
++ unsigned count;\r
++ notmuch_status_t status;\r
++ if ((status = notmuch_query_count_threads (ctx->query, &count))) {\r
++ fprintf (stderr, "Error: %s\n", notmuch_status_to_string (status));\r
++ return 1;\r
++ }\r
++\r
++ ctx->offset += count;\r
+ if (ctx->offset < 0)\r
+ ctx->offset = 0;\r
+ }\r
+@@ -414,7 +421,10 @@ do_search_messages (search_context_t *ctx)\r
+ int i;\r
+ \r
+ if (ctx->offset < 0) {\r
+- ctx->offset += notmuch_query_count_messages (ctx->query);\r
++ unsigned count;\r
++ if (notmuch_query_count_messages (ctx->query, &count))\r
++ return 1;\r
++ ctx->offset += count;\r
+ if (ctx->offset < 0)\r
+ ctx->offset = 0;\r
+ }\r
+diff --git a/notmuch-show.c b/notmuch-show.c\r
+index d416fbd..16835a3 100644\r
+--- a/notmuch-show.c\r
++++ b/notmuch-show.c\r
+@@ -982,8 +982,14 @@ do_show_single (void *ctx,\r
+ {\r
+ notmuch_messages_t *messages;\r
+ notmuch_message_t *message;\r
++ unsigned count;\r
++ notmuch_status_t status;\r
++ if ((status = notmuch_query_count_messages (query, &count))) {\r
++ fprintf (stderr, "Error: %s\n", notmuch_status_to_string (status));\r
++ return 1;\r
++ }\r
+ \r
+- if (notmuch_query_count_messages (query) != 1) {\r
++ if (count != 1) {\r
+ fprintf (stderr, "Error: search term did not match precisely one message.\n");\r
+ return 1;\r
+ }\r
+-- \r
+2.1.3\r
+\r