--- /dev/null
+Return-Path: <bremner@tethera.net>\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 7B4566DE0159\r
+ for <notmuch@notmuchmail.org>; Tue, 12 Jan 2016 19:10:25 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.31\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.31 tagged_above=-999 required=5 tests=[AWL=0.241, \r
+ RP_MATCHES_RCVD=-0.55, SPF_PASS=-0.001] 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 rAui08uTvCWO for <notmuch@notmuchmail.org>;\r
+ Tue, 12 Jan 2016 19:10:22 -0800 (PST)\r
+Received: from fethera.tethera.net (fethera.tethera.net [198.245.60.197])\r
+ by arlo.cworth.org (Postfix) with ESMTPS id C68216DE01D3\r
+ for <notmuch@notmuchmail.org>; Tue, 12 Jan 2016 19:10:21 -0800 (PST)\r
+Received: from remotemail by fethera.tethera.net with local (Exim 4.84)\r
+ (envelope-from <bremner@tethera.net>) id 1aJBp3-0000xw-Vb\r
+ for notmuch@notmuchmail.org; Tue, 12 Jan 2016 22:10:09 -0500\r
+Received: (nullmailer pid 23093 invoked by uid 1000);\r
+ Wed, 13 Jan 2016 03:10:18 -0000\r
+From: David Bremner <david@tethera.net>\r
+To: notmuch@notmuchmail.org\r
+Subject: second round of library config API and dump\r
+Date: Tue, 12 Jan 2016 23:10:06 -0400\r
+Message-Id: <1452654610-22864-1-git-send-email-david@tethera.net>\r
+X-Mailer: git-send-email 2.6.4\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: Wed, 13 Jan 2016 03:10:25 -0000\r
+\r
+Based on feedback on IRC from Austin and Tomi, I've simplified the API\r
+and no longer expose the database level prefix to the caller.\r
+\r
+This series does fix at least one memory ownership bug. Not a\r
+particularly subtle one, I apparently only got half way through making\r
+the current 'value' owned by the iterator.\r
+\r
+There's also a few more tests, as the API starts to settle down.\r
+\r
+Because some global renaming, the interdiff is somewhat noisy, but\r
+hopefully mostly straightforward.\r
+\r
+diff --git a/lib/Makefile.local b/lib/Makefile.local\r
+index ccc1e49..eb442d1 100644\r
+--- a/lib/Makefile.local\r
++++ b/lib/Makefile.local\r
+@@ -48,7 +48,7 @@ libnotmuch_cxx_srcs = \\r
+ $(dir)/index.cc \\r
+ $(dir)/message.cc \\r
+ $(dir)/query.cc \\r
+- $(dir)/metadata.cc \\r
++ $(dir)/config.cc \\r
+ $(dir)/thread.cc\r
+ \r
+ libnotmuch_modules := $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)\r
+diff --git a/lib/metadata.cc b/lib/config.cc\r
+similarity index 47%\r
+rename from lib/metadata.cc\r
+rename to lib/config.cc\r
+index 34b46e0..4cd9314 100644\r
+--- a/lib/metadata.cc\r
++++ b/lib/config.cc\r
+@@ -22,88 +22,36 @@\r
+ #include "notmuch-private.h"\r
+ #include "database-private.h"\r
+ \r
+-struct _notmuch_metadata {\r
++static const std::string CONFIG_PREFIX="C";\r
++\r
++struct _notmuch_config_list {\r
+ notmuch_database_t *notmuch;\r
+ Xapian::TermIterator *iterator;\r
+- notmuch_metadata_class_t mclass;\r
+ char *current_key;\r
++ char *current_val;\r
+ };\r
+ \r
+ static int\r
+-_notmuch_metadata_destroy (notmuch_metadata_t *list) {\r
++_notmuch_config_list_destroy (notmuch_config_list_t *list) {\r
+ delete list->iterator;\r
+ return 0;\r
+ }\r
+ \r
+-typedef struct prefix {\r
+- notmuch_metadata_class_t mclass;\r
+- const char *prefix;\r
+-} prefix_t;\r
+-\r
+-static prefix_t METADATA_PREFIX[] = {\r
+- {NOTMUCH_METADATA_CONFIG, "C"},\r
+-};\r
+-\r
+-#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))\r
+-\r
+-const char *\r
+-notmuch_metadata_prefix_string (notmuch_metadata_class_t mclass)\r
+-{\r
+- unsigned int i;\r
+-\r
+- for (i=0; i < ARRAY_SIZE(METADATA_PREFIX); i++) {\r
+- if (METADATA_PREFIX[0].mclass == mclass)\r
+- return METADATA_PREFIX[i].prefix;\r
+- }\r
+- return NULL;\r
+-}\r
+-\r
+-notmuch_status_t _make_key(void *ctx, notmuch_metadata_class_t mclass,\r
+- const char *in, const char **out)\r
+-{\r
+- const char *term;\r
+- const char *prefix = NULL;\r
+-\r
+- if (!out)\r
+- return NOTMUCH_STATUS_NULL_POINTER;\r
+-\r
+- prefix = notmuch_metadata_prefix_string(mclass);\r
+- if (!prefix)\r
+- return NOTMUCH_STATUS_UNSUPPORTED_OPERATION;\r
+-\r
+- term = talloc_asprintf (ctx, "%s%s",\r
+- prefix, in);\r
+- if (!term)\r
+- return NOTMUCH_STATUS_OUT_OF_MEMORY;\r
+-\r
+- *out = term;\r
+- return NOTMUCH_STATUS_SUCCESS;\r
+-}\r
+-\r
+ notmuch_status_t\r
+-notmuch_database_set_metadata (notmuch_database_t *notmuch,\r
+- notmuch_metadata_class_t mclass,\r
+- const char *key,\r
+- const char *value)\r
++notmuch_database_set_config (notmuch_database_t *notmuch,\r
++ const char *key,\r
++ const char *value)\r
+ {\r
+ notmuch_status_t status;\r
+ Xapian::WritableDatabase *db;\r
+- const char *key_term = NULL;\r
+- void *local;\r
+-\r
+- local = talloc_new (NULL);\r
+ \r
+ status = _notmuch_database_ensure_writable (notmuch);\r
+ if (status)\r
+- goto DONE;\r
+-\r
+- status = _make_key (local, mclass, key, &key_term);\r
+- if (status)\r
+- goto DONE;\r
++ return status;\r
+ \r
+ try {\r
+ db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);\r
+- db->set_metadata (key_term, value);\r
++ db->set_metadata (CONFIG_PREFIX+key, value);\r
+ } catch (const Xapian::Error &error) {\r
+ status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
+ notmuch->exception_reported = TRUE;\r
+@@ -112,33 +60,18 @@ notmuch_database_set_metadata (notmuch_database_t *notmuch,\r
+ error.get_msg().c_str());\r
+ }\r
+ }\r
+- DONE:\r
+- talloc_free (local);\r
+-\r
+- return status;\r
++ return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
+ \r
+ static notmuch_status_t\r
+ _metadata_value (notmuch_database_t *notmuch,\r
+- notmuch_metadata_class_t mclass,\r
+ const char *key,\r
+ std::string &value)\r
+ {\r
+- notmuch_status_t status;\r
+-\r
+- const char *key_term = NULL;\r
+- void *local;\r
+-\r
+- local = talloc_new (NULL);\r
+-\r
+- status = _make_key (local, mclass, key, &key_term);\r
+- if (status)\r
+- goto DONE;\r
++ notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
+ \r
+ try {\r
+-\r
+- value = notmuch->xapian_db->get_metadata (key_term);\r
+-\r
++ value = notmuch->xapian_db->get_metadata (CONFIG_PREFIX+key);\r
+ } catch (const Xapian::Error &error) {\r
+ status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
+ notmuch->exception_reported = TRUE;\r
+@@ -147,24 +80,20 @@ _metadata_value (notmuch_database_t *notmuch,\r
+ error.get_msg().c_str());\r
+ }\r
+ }\r
+-\r
+- DONE:\r
+- talloc_free (local);\r
+ return status;\r
+ }\r
+ \r
+ notmuch_status_t\r
+-notmuch_database_get_metadata (notmuch_database_t *notmuch,\r
+- notmuch_metadata_class_t mclass,\r
+- const char *key,\r
+- char **value) {\r
++notmuch_database_get_config (notmuch_database_t *notmuch,\r
++ const char *key,\r
++ char **value) {\r
+ std::string strval;\r
+ notmuch_status_t status;\r
+ \r
+ if (!value)\r
+ return NOTMUCH_STATUS_NULL_POINTER;\r
+ \r
+- status = _metadata_value (notmuch, mclass, key, strval);\r
++ status = _metadata_value (notmuch, key, strval);\r
+ if (status)\r
+ return status;\r
+ \r
+@@ -174,31 +103,28 @@ notmuch_database_get_metadata (notmuch_database_t *notmuch,\r
+ }\r
+ \r
+ notmuch_status_t\r
+-notmuch_database_get_all_metadata (notmuch_database_t *notmuch,\r
+- notmuch_metadata_class_t mclass,\r
+- notmuch_metadata_t **out)\r
++notmuch_database_get_config_list (notmuch_database_t *notmuch,\r
++ const char *prefix,\r
++ notmuch_config_list_t **out)\r
+ {\r
+- notmuch_metadata_t *list = NULL;\r
++ notmuch_config_list_t *list = NULL;\r
+ notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
+ \r
+- const char *prefix = notmuch_metadata_prefix_string (mclass);\r
+-\r
+- list = talloc (notmuch, notmuch_metadata_t);\r
++ list = talloc (notmuch, notmuch_config_list_t);\r
+ if (!list) {\r
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;\r
+ goto DONE;\r
+ }\r
+ \r
+- talloc_set_destructor(list, _notmuch_metadata_destroy);\r
++ talloc_set_destructor(list, _notmuch_config_list_destroy);\r
+ list->iterator = new Xapian::TermIterator;\r
+ list->notmuch = notmuch;\r
+- list->mclass = mclass;\r
+ list->current_key = NULL;\r
++ list->current_val = NULL;\r
+ \r
+ try {\r
+ \r
+- *list->iterator = notmuch->xapian_db->metadata_keys_begin();\r
+- list->iterator->skip_to (prefix);\r
++ *list->iterator = notmuch->xapian_db->metadata_keys_begin(CONFIG_PREFIX + (prefix ? prefix : NULL));\r
+ \r
+ } catch (const Xapian::Error &error) {\r
+ _notmuch_database_log (notmuch, "A Xapian exception occurred getting metadata iterator: %s.\n",\r
+@@ -217,49 +143,52 @@ notmuch_database_get_all_metadata (notmuch_database_t *notmuch,\r
+ }\r
+ \r
+ notmuch_bool_t\r
+-notmuch_metadata_valid (notmuch_metadata_t *metadata)\r
++notmuch_config_list_valid (notmuch_config_list_t *metadata)\r
+ {\r
+- const char *prefix = notmuch_metadata_prefix_string (metadata->mclass);\r
+ if (*(metadata->iterator) == metadata->notmuch->xapian_db->metadata_keys_end())\r
+ return FALSE;\r
+ \r
+- return (strncmp((**(metadata->iterator)).c_str (), prefix, strlen (prefix)) == 0);\r
++ return TRUE;\r
+ }\r
+ \r
+ const char *\r
+-notmuch_metadata_key (notmuch_metadata_t *metadata)\r
++notmuch_config_list_key (notmuch_config_list_t *list)\r
+ {\r
+- const char *prefix = notmuch_metadata_prefix_string (metadata->mclass);\r
++ if (list->current_key)\r
++ talloc_free (list->current_key);\r
+ \r
+- if (metadata->current_key)\r
+- talloc_free (metadata->current_key);\r
+- metadata->current_key = talloc_strdup (metadata, (**(metadata->iterator)).c_str () + strlen (prefix));\r
++ list->current_key = talloc_strdup (list, (**(list->iterator)).c_str () + CONFIG_PREFIX.length ());\r
+ \r
+- return metadata->current_key;\r
++ return list->current_key;\r
+ }\r
+ \r
+ const char *\r
+-notmuch_metadata_value (notmuch_metadata_t *metadata)\r
++notmuch_config_list_value (notmuch_config_list_t *list)\r
+ {\r
+- const char *key = notmuch_metadata_key (metadata);\r
+- char *val;\r
++ std::string strval;\r
+ notmuch_status_t status;\r
++ const char *key = notmuch_config_list_key (list);\r
+ \r
+- status=notmuch_database_get_metadata (metadata->notmuch, metadata->mclass, key, &val);\r
++ /* TODO: better error reporting?? */\r
++ status = _metadata_value (list->notmuch, key, strval);\r
+ if (status)\r
+ return NULL;\r
+ \r
+- return val;\r
++ if (list->current_val)\r
++ talloc_free(list->current_val);\r
++\r
++ list->current_val = talloc_strdup(list, strval.c_str ());\r
++ return list->current_val;\r
+ }\r
+ \r
+ void\r
+-notmuch_metadata_move_to_next (notmuch_metadata_t *metadata)\r
++notmuch_config_list_move_to_next (notmuch_config_list_t *list)\r
+ {\r
+- (*(metadata->iterator))++;\r
++ (*(list->iterator))++;\r
+ }\r
+ \r
+ void\r
+-notmuch_metadata_destroy (notmuch_metadata_t *metadata)\r
++notmuch_config_list_destroy (notmuch_config_list_t *list)\r
+ {\r
+- talloc_free (metadata);\r
++ talloc_free (list);\r
+ }\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 657a7d6..b439c88 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -197,7 +197,7 @@ typedef struct _notmuch_message notmuch_message_t;\r
+ typedef struct _notmuch_tags notmuch_tags_t;\r
+ typedef struct _notmuch_directory notmuch_directory_t;\r
+ typedef struct _notmuch_filenames notmuch_filenames_t;\r
+-typedef struct _notmuch_metadata notmuch_metadata_t;\r
++typedef struct _notmuch_config_list notmuch_config_list_t;\r
+ #endif /* __DOXYGEN__ */\r
+ \r
+ /**\r
+@@ -1830,78 +1830,69 @@ notmuch_filenames_move_to_next (notmuch_filenames_t *filenames);\r
+ void\r
+ notmuch_filenames_destroy (notmuch_filenames_t *filenames);\r
+ \r
+-/**\r
+- * metadata class\r
+- */\r
+-\r
+-typedef enum _notmuch_metadata_class {\r
+- NOTMUCH_METADATA_FIRST_CLASS = 1,\r
+- NOTMUCH_METADATA_CONFIG = 1,\r
+- NOTMUCH_METADATA_LAST_CLASS\r
+-} notmuch_metadata_class_t;\r
+ \r
+ /**\r
+- * set metadata\r
++ * set config 'key' to 'value'\r
+ *\r
+ */\r
+ notmuch_status_t\r
+-notmuch_database_set_metadata (notmuch_database_t *db, notmuch_metadata_class_t mclass, const char *key, const char *value);\r
++notmuch_database_set_config (notmuch_database_t *db, const char *key, const char *value);\r
+ \r
+ /**\r
+- * retrieve one metadata value\r
++ * retrieve config item 'key', assign to 'value'\r
++ *\r
++ * keys which have not been previously set with n_d_set_config will\r
++ * return an empty string.\r
+ *\r
+- * return value is allocated by malloc and should be freed by the caller.\r
++ * return value is allocated by malloc and should be freed by the\r
++ * caller.\r
+ */\r
+ notmuch_status_t\r
+-notmuch_database_get_metadata (notmuch_database_t *db, notmuch_metadata_class_t mclass, const char *key, char **value);\r
++notmuch_database_get_config (notmuch_database_t *db, const char *key, char **value);\r
+ \r
+ /**\r
+- * get all metadata of a given class\r
++ * Create an iterator for all config items with keys matching a given prefix\r
+ */\r
+ notmuch_status_t\r
+-notmuch_database_get_all_metadata (notmuch_database_t *db, notmuch_metadata_class_t mclass, notmuch_metadata_t **out);\r
++notmuch_database_get_config_list (notmuch_database_t *db, const char *prefix, notmuch_config_list_t **out);\r
+ \r
+ /**\r
+- * Is 'metadata' iterator valid (i.e. _key, _value, _move_to_next can be called).\r
++ * Is 'config_list' iterator valid (i.e. _key, _value, _move_to_next can be called).\r
+ */\r
+ notmuch_bool_t\r
+-notmuch_metadata_valid (notmuch_metadata_t *metadata);\r
++notmuch_config_list_valid (notmuch_config_list_t *config_list);\r
+ \r
+ /**\r
+- * return key for current metadata pair\r
++ * return key for current config pair\r
+ *\r
+ * return value is owned by the iterator, and will be destroyed by the\r
+- * next call to notmuch_metadata_key or notmuch_metadata_destroy.\r
++ * next call to notmuch_config_list_key or notmuch_config_list_destroy.\r
+ */\r
+ const char *\r
+-notmuch_metadata_key (notmuch_metadata_t *metadata);\r
++notmuch_config_list_key (notmuch_config_list_t *config_list);\r
+ \r
+ /**\r
+- * return 'value' for current metadata pair\r
++ * return 'value' for current config pair\r
+ *\r
+ * return value is owned by the iterator, and will be destroyed by the\r
+- * next call to notmuch_metadata_value\r
++ * next call to notmuch_config_list_value or notmuch config_list_destroy\r
+ */\r
+ const char *\r
+-notmuch_metadata_value (notmuch_metadata_t *metadata);\r
++notmuch_config_list_value (notmuch_config_list_t *config_list);\r
++\r
+ \r
+ /**\r
+- * move 'metadata' iterator to the next pair\r
++ * move 'config_list' iterator to the next pair\r
+ */\r
+ void\r
+-notmuch_metadata_move_to_next (notmuch_metadata_t *metadata);\r
++notmuch_config_list_move_to_next (notmuch_config_list_t *config_list);\r
+ \r
+ /**\r
+- * free any resources held by 'metadata'\r
++ * free any resources held by 'config_list'\r
+ */\r
+ void\r
+-notmuch_metadata_destroy (notmuch_metadata_t * metadata);\r
++notmuch_config_list_destroy (notmuch_config_list_t *config_list);\r
+ \r
+-/**\r
+- * convert enum to string\r
+- */\r
+-const char *\r
+-notmuch_metadata_prefix_string (notmuch_metadata_class_t mclass);\r
+ /* @} */\r
+ \r
+ NOTMUCH_END_DECLS\r
+diff --git a/notmuch-client.h b/notmuch-client.h\r
+index 8ee6e0e..2dca83c 100644\r
+--- a/notmuch-client.h\r
++++ b/notmuch-client.h\r
+@@ -445,7 +445,7 @@ typedef enum dump_formats {\r
+ \r
+ typedef enum dump_includes {\r
+ DUMP_INCLUDE_TAGS=1,\r
+- DUMP_INCLUDE_METADATA=2,\r
++ DUMP_INCLUDE_CONFIG=2,\r
+ } dump_include_t;\r
+ \r
+ int\r
+diff --git a/notmuch-dump.c b/notmuch-dump.c\r
+index a88b5d5..4909493 100644\r
+--- a/notmuch-dump.c\r
++++ b/notmuch-dump.c\r
+@@ -24,25 +24,21 @@\r
+ #include <zlib.h>\r
+ \r
+ static notmuch_status_t\r
+-database_dump_metadata(notmuch_database_t *notmuch, gzFile output)\r
++database_dump_config(notmuch_database_t *notmuch, gzFile output)\r
+ {\r
+- notmuch_metadata_class_t mclass;\r
+- notmuch_metadata_t *meta;\r
++ notmuch_config_list_t *list;\r
+ notmuch_status_t status;\r
+-\r
+- for (mclass = NOTMUCH_METADATA_FIRST_CLASS; mclass < NOTMUCH_METADATA_LAST_CLASS; mclass++) {\r
+- status = notmuch_database_get_all_metadata (notmuch, NOTMUCH_METADATA_CONFIG, &meta);\r
+- if (status)\r
+- return status;\r
+-\r
+- for (; notmuch_metadata_valid (meta); notmuch_metadata_move_to_next (meta)) {\r
+- /* FIXME hexencode key and values */\r
+- gzprintf(output, "#@ %s %s %s\n",\r
+- notmuch_metadata_prefix_string(mclass),\r
+- notmuch_metadata_key (meta), notmuch_metadata_value (meta));\r
+- }\r
+- notmuch_metadata_destroy (meta);\r
++ status = notmuch_database_get_config_list (notmuch, NULL, &list);\r
++ if (status)\r
++ return status;\r
++\r
++ for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {\r
++ /* FIXME hexencode key and values */\r
++ gzprintf(output, "#@ %s %s\n",\r
++ notmuch_config_list_key (list), notmuch_config_list_value (list));\r
+ }\r
++ notmuch_config_list_destroy (list);\r
++\r
+ return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
+ \r
+@@ -55,9 +51,9 @@ database_dump_file (notmuch_database_t *notmuch, gzFile output,\r
+ notmuch_message_t *message;\r
+ notmuch_tags_t *tags;\r
+ \r
+- if (include | DUMP_INCLUDE_METADATA) {\r
++ if (include | DUMP_INCLUDE_CONFIG) {\r
+ if (print_status_database ("notmuch dump", notmuch,\r
+- database_dump_metadata(notmuch,output)))\r
++ database_dump_config(notmuch,output)))\r
+ return EXIT_FAILURE;\r
+ }\r
+ \r
+@@ -267,7 +263,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
+ { "batch-tag", DUMP_FORMAT_BATCH_TAG },\r
+ { 0, 0 } } },\r
+ { NOTMUCH_OPT_KEYWORD_FLAGS, &include, "include", 'i',\r
+- (notmuch_keyword_t []){ { "metadata", DUMP_INCLUDE_METADATA },\r
++ (notmuch_keyword_t []){ { "metadata", DUMP_INCLUDE_CONFIG },\r
+ { "tags", DUMP_INCLUDE_TAGS} } },\r
+ { NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0 },\r
+ { NOTMUCH_OPT_BOOLEAN, &gzip_output, "gzip", 'z', 0 },\r
+@@ -282,7 +278,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
+ notmuch_process_shared_options (argv[0]);\r
+ \r
+ if (include == 0)\r
+- include = DUMP_INCLUDE_METADATA | DUMP_INCLUDE_TAGS;\r
++ include = DUMP_INCLUDE_CONFIG | DUMP_INCLUDE_TAGS;\r
+ \r
+ if (opt_index < argc) {\r
+ query_str = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);\r
+diff --git a/notmuch-new.c b/notmuch-new.c\r
+index 1f8050d..fd2ff82 100644\r
+--- a/notmuch-new.c\r
++++ b/notmuch-new.c\r
+@@ -1041,7 +1041,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])\r
+ }\r
+ \r
+ if (notmuch_database_dump (notmuch, backup_name, "",\r
+- DUMP_FORMAT_BATCH_TAG, DUMP_INCLUDE_METADATA | DUMP_INCLUDE_TAGS, TRUE)) {\r
++ DUMP_FORMAT_BATCH_TAG, DUMP_INCLUDE_CONFIG | DUMP_INCLUDE_TAGS, TRUE)) {\r
+ fprintf (stderr, "Backup failed. Aborting upgrade.");\r
+ return EXIT_FAILURE;\r
+ }\r
+diff --git a/test/T590-metadata.sh b/test/T590-libconfig.sh\r
+similarity index 35%\r
+rename from test/T590-metadata.sh\r
+rename to test/T590-libconfig.sh\r
+index 45a49be..4fe6bd1 100755\r
+--- a/test/T590-metadata.sh\r
++++ b/test/T590-libconfig.sh\r
+@@ -1,5 +1,5 @@\r
+ #!/usr/bin/env bash\r
+-test_description="metadata API"\r
++test_description="library config API"\r
+ \r
+ . ./test-lib.sh || exit 1\r
+ \r
+@@ -36,14 +36,14 @@ cat <<EOF > c_tail\r
+ }\r
+ EOF\r
+ \r
+-test_begin_subtest "notmuch_database_{set,get}_metadata"\r
++test_begin_subtest "notmuch_database_{set,get}_config"\r
+ cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}\r
+ {\r
+- RUN(notmuch_database_set_metadata (db, NOTMUCH_METADATA_CONFIG, "testkey1", "testvalue1"));\r
+- RUN(notmuch_database_set_metadata (db, NOTMUCH_METADATA_CONFIG, "testkey2", "testvalue2"));\r
+- RUN(notmuch_database_get_metadata (db, NOTMUCH_METADATA_CONFIG, "testkey1", &val));\r
++ RUN(notmuch_database_set_config (db, "testkey1", "testvalue1"));\r
++ RUN(notmuch_database_set_config (db, "testkey2", "testvalue2"));\r
++ RUN(notmuch_database_get_config (db, "testkey1", &val));\r
+ printf("testkey1 = %s\n", val);\r
+- RUN(notmuch_database_get_metadata (db, NOTMUCH_METADATA_CONFIG, "testkey2", &val));\r
++ RUN(notmuch_database_get_config (db, "testkey2", &val));\r
+ printf("testkey2 = %s\n", val);\r
+ }\r
+ EOF\r
+@@ -55,33 +55,73 @@ testkey2 = testvalue2\r
+ EOF\r
+ test_expect_equal_file EXPECTED OUTPUT\r
+ \r
+-test_begin_subtest "get all metadata in one class"\r
++\r
++test_begin_subtest "notmuch_database_get_config_list: empty list"\r
++cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}\r
++{\r
++ notmuch_config_list_t *list;\r
++ RUN(notmuch_database_get_config_list (db, "nonexistent", &list));\r
++ printf("valid = %d\n", notmuch_config_list_valid (list));\r
++ notmuch_config_list_destroy (list);\r
++}\r
++EOF\r
++cat <<'EOF' >EXPECTED\r
++== stdout ==\r
++valid = 0\r
++== stderr ==\r
++EOF\r
++test_expect_equal_file EXPECTED OUTPUT\r
++\r
++\r
++test_begin_subtest "notmuch_database_get_config_list: all pairs"\r
++cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}\r
++{\r
++ notmuch_config_list_t *list;\r
++ RUN(notmuch_database_set_config (db, "zzzafter", "afterval"));\r
++ RUN(notmuch_database_set_config (db, "aaabefore", "beforeval"));\r
++ RUN(notmuch_database_get_config_list (db, "", &list));\r
++ for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {\r
++ printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));\r
++ }\r
++ notmuch_config_list_destroy (list);\r
++}\r
++EOF\r
++cat <<'EOF' >EXPECTED\r
++== stdout ==\r
++aaabefore beforeval\r
++testkey1 testvalue1\r
++testkey2 testvalue2\r
++zzzafter afterval\r
++== stderr ==\r
++EOF\r
++test_expect_equal_file EXPECTED OUTPUT\r
++\r
++test_begin_subtest "notmuch_database_get_config_list: one prefix"\r
+ cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}\r
+ {\r
+- notmuch_metadata_t *meta;\r
+- RUN(notmuch_database_get_all_metadata (db, NOTMUCH_METADATA_CONFIG, &meta));\r
+- for (; notmuch_metadata_valid (meta); notmuch_metadata_move_to_next (meta)) {\r
+- printf("key = %s\n", notmuch_metadata_key (meta));\r
+- printf("val = %s\n", notmuch_metadata_value (meta));\r
++ notmuch_config_list_t *list;\r
++ RUN(notmuch_database_get_config_list (db, "testkey", &list));\r
++ for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {\r
++ printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));\r
+ }\r
+- notmuch_metadata_destroy (meta);\r
++ notmuch_config_list_destroy (list);\r
+ }\r
+ EOF\r
+ cat <<'EOF' >EXPECTED\r
+ == stdout ==\r
+-key = testkey1\r
+-val = testvalue1\r
+-key = testkey2\r
+-val = testvalue2\r
++testkey1 testvalue1\r
++testkey2 testvalue2\r
+ == stderr ==\r
+ EOF\r
+ test_expect_equal_file EXPECTED OUTPUT\r
+ \r
+-test_begin_subtest "dump metadata"\r
++test_begin_subtest "dump config"\r
+ notmuch dump --include=metadata >OUTPUT\r
+ cat <<'EOF' >EXPECTED\r
+-#@ C testkey1 testvalue1\r
+-#@ C testkey2 testvalue2\r
++#@ aaabefore beforeval\r
++#@ testkey1 testvalue1\r
++#@ testkey2 testvalue2\r
++#@ zzzafter afterval\r
+ EOF\r
+ test_expect_equal_file EXPECTED OUTPUT\r
+ \r