--- /dev/null
+Return-Path: <jan@iptel.org>\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 3966C431FBF\r
+ for <notmuch@notmuchmail.org>; Thu, 19 Nov 2009 03:35:07 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\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 r5UMGTB+G9l7 for <notmuch@notmuchmail.org>;\r
+ Thu, 19 Nov 2009 03:35:06 -0800 (PST)\r
+Received: from mail.iptel.org (smtp.iptel.org [213.192.59.67])\r
+ by olra.theworths.org (Postfix) with ESMTP id DEAC8431FAE\r
+ for <notmuch@notmuchmail.org>; Thu, 19 Nov 2009 03:35:05 -0800 (PST)\r
+Received: by mail.iptel.org (Postfix, from userid 103)\r
+ id B27F2370667; Thu, 19 Nov 2009 12:34:42 +0100 (CET)\r
+Received: from x61s.janakj (nat.sip-server.net [213.192.30.130])\r
+ (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\r
+ (Client did not present a certificate)\r
+ by mail.iptel.org (Postfix) with ESMTPSA id B9041370659\r
+ for <notmuch@notmuchmail.org>; Thu, 19 Nov 2009 12:34:41 +0100 (CET)\r
+Received: by x61s.janakj (Postfix, from userid 1000)\r
+ id 89305440651; Thu, 19 Nov 2009 12:34:41 +0100 (CET)\r
+From: Jan Janak <jan@ryngle.com>\r
+To: notmuch@notmuchmail.org\r
+Date: Thu, 19 Nov 2009 12:34:40 +0100\r
+Message-Id: <1258630481-5133-1-git-send-email-jan@ryngle.com>\r
+X-Mailer: git-send-email 1.6.3.3\r
+Subject: [notmuch] [PATCH 1/2] notmuch: Support for notmuch_database_get_tags\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.12\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: Thu, 19 Nov 2009 11:35:07 -0000\r
+\r
+This patch adds a new function called notmuch_database_get_tags which\r
+can be used to obtain a list of all tags defined in the database (that\r
+is, the list all tags from all messages). The function produces an\r
+alphabetically sorted list.\r
+\r
+To add support for the new function, we rip the guts off of\r
+notmuch_message_get_tags and put them in a new generic function\r
+called _notmuch_convert_tags. The generic function takes a TermIterator\r
+as argument and produces a notmuch_tags_t list of tags.\r
+\r
+Function notmuch_message_get_tags is then reimplemented to call the\r
+generic function with message->doc.termlist_begin() as argument.\r
+\r
+Similarly, we implement notmuch_message_database_tags, the function\r
+calls the generic function with db->xapian_db->allterms_begin() as\r
+argument.\r
+\r
+Finally, notmuch_database_get_tags is exported through lib/notmuch.h\r
+\r
+Signed-off-by: Jan Janak <jan@ryngle.com>\r
+---\r
+ lib/database.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++++\r
+ lib/message.cc | 38 ++++++--------------------------------\r
+ lib/notmuch.h | 4 ++++\r
+ 3 files changed, 58 insertions(+), 32 deletions(-)\r
+\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 4998fc9..b1c15c3 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -983,3 +983,51 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ \r
+ return ret;\r
+ }\r
++\r
++notmuch_tags_t *\r
++_notmuch_convert_tags (void* ctx, Xapian::TermIterator i);\r
++\r
++/* Converts tags from the format used in Xapian to a list in\r
++ notmuch_tags_t. */\r
++notmuch_tags_t *\r
++_notmuch_convert_tags (void* ctx, Xapian::TermIterator i)\r
++{\r
++ const char *prefix = _find_prefix ("tag");\r
++ notmuch_tags_t *tags;\r
++ std::string tag;\r
++\r
++ /* Currently this iteration is written with the assumption that\r
++ * "tag" has a single-character prefix. */\r
++ assert (strlen (prefix) == 1);\r
++\r
++ tags = _notmuch_tags_create (ctx);\r
++ if (unlikely (tags == NULL))\r
++ return NULL;\r
++\r
++ i.skip_to (prefix);\r
++\r
++ while (1) {\r
++ tag = *i;\r
++\r
++ if (tag.empty () || tag[0] != *prefix)\r
++ break;\r
++\r
++ _notmuch_tags_add_tag (tags, tag.c_str () + 1);\r
++\r
++ i++;\r
++ }\r
++\r
++ _notmuch_tags_prepare_iterator (tags);\r
++\r
++ return tags;\r
++}\r
++\r
++/*\r
++ * Returns a list of all tags defined in a notmuch database. The resulting\r
++ * list is sorted alphabetically.\r
++ */\r
++notmuch_tags_t *\r
++notmuch_database_get_tags (notmuch_database_t *db)\r
++{\r
++ return _notmuch_convert_tags(db, db->xapian_db->allterms_begin());\r
++}\r
+diff --git a/lib/message.cc b/lib/message.cc\r
+index 9488fb6..af23bb2 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -41,6 +41,9 @@ struct _notmuch_message {\r
+ Xapian::Document doc;\r
+ };\r
+ \r
++extern notmuch_tags_t *\r
++_notmuch_convert_tags (void* ctx, Xapian::TermIterator i);\r
++\r
+ /* "128 bits of thread-id ought to be enough for anybody" */\r
+ #define NOTMUCH_THREAD_ID_BITS 128\r
+ #define NOTMUCH_THREAD_ID_DIGITS (NOTMUCH_THREAD_ID_BITS / 4)\r
+@@ -445,43 +448,14 @@ notmuch_message_get_date (notmuch_message_t *message)\r
+ return Xapian::sortable_unserialise (value);\r
+ }\r
+ \r
++\r
+ notmuch_tags_t *\r
+ notmuch_message_get_tags (notmuch_message_t *message)\r
+ {\r
+- const char *prefix = _find_prefix ("tag");\r
+- Xapian::TermIterator i, end;\r
+- notmuch_tags_t *tags;\r
+- std::string tag;\r
+-\r
+- /* Currently this iteration is written with the assumption that\r
+- * "tag" has a single-character prefix. */\r
+- assert (strlen (prefix) == 1);\r
+-\r
+- tags = _notmuch_tags_create (message);\r
+- if (unlikely (tags == NULL))\r
+- return NULL;\r
+-\r
+- i = message->doc.termlist_begin ();\r
+- end = message->doc.termlist_end ();\r
+-\r
+- i.skip_to (prefix);\r
+-\r
+- while (1) {\r
+- tag = *i;\r
+-\r
+- if (tag.empty () || tag[0] != *prefix)\r
+- break;\r
+-\r
+- _notmuch_tags_add_tag (tags, tag.c_str () + 1);\r
+-\r
+- i++;\r
+- }\r
+-\r
+- _notmuch_tags_prepare_iterator (tags);\r
+-\r
+- return tags;\r
++ return _notmuch_convert_tags(message, message->doc.termlist_begin());\r
+ }\r
+ \r
++\r
+ void\r
+ _notmuch_message_set_date (notmuch_message_t *message,\r
+ const char *date)\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index cc713a3..1edcfd6 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -271,6 +271,10 @@ notmuch_message_t *\r
+ notmuch_database_find_message (notmuch_database_t *database,\r
+ const char *message_id);\r
+ \r
++notmuch_tags_t *\r
++notmuch_database_get_tags (notmuch_database_t *database);\r
++\r
++\r
+ /* Create a new query for 'database'.\r
+ *\r
+ * Here, 'database' should be an open database, (see\r
+-- \r
+1.6.3.3\r
+\r