unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* v2 convert remaining CLI to new configuration
@ 2021-04-07  1:55 David Bremner
  2021-04-07  1:55 ` [PATCH 01/28] lib/open: fix leaks calling _trial_open David Bremner
                   ` (28 more replies)
  0 siblings, 29 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch

This obsoletes [1] and [2].

I've been using it for a month, I think it's probably ready to
apply to master. Since the last posted version the only difference (other than
incorporating [2]) is that I changed the call to access to test the
config file not to check for write access.

[1]: id:20210304130139.4046183-1-david@tethera.net
[2]: id:20210327122028.526710-1-david@tethera.net

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/28] lib/open: fix leaks calling _trial_open
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 02/28] lib: add missing status strings David Bremner
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

_trial_open can't know if the PATH_ERROR return value will cause the
error message to be returned from the library, so it's up the caller
to clean up if not.
---
 lib/open.cc | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/open.cc b/lib/open.cc
index 8f572b0b..dc191d64 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -280,6 +280,9 @@ _notmuch_choose_xapian_path (void *ctx, const char *database_path,
     if (status != NOTMUCH_STATUS_PATH_ERROR)
 	goto DONE;
 
+    if (*message_ptr)
+	free (*message_ptr);
+
     notmuch_path = talloc_asprintf (ctx, "%s/.notmuch", database_path);
     status = _db_dir_exists (notmuch_path, message_ptr);
     if (status)
@@ -648,6 +651,9 @@ notmuch_database_create_with_config (const char *database_path,
 	goto DONE;
     }
 
+    if (message)
+	free (message);
+
     status = _finish_open (notmuch,
 			   profile,
 			   NOTMUCH_DATABASE_MODE_READ_WRITE,
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 02/28] lib: add missing status strings
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
  2021-04-07  1:55 ` [PATCH 01/28] lib/open: fix leaks calling _trial_open David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 03/28] test: convert random-corpus to use n_d_open_with_config David Bremner
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

---
 lib/database.cc | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/database.cc b/lib/database.cc
index 9743c1ca..d2ccdd58 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -293,12 +293,20 @@ notmuch_status_to_string (notmuch_status_t status)
 	return "Operation requires a database upgrade";
     case NOTMUCH_STATUS_PATH_ERROR:
 	return "Path supplied is illegal for this function";
+    case NOTMUCH_STATUS_IGNORED:
+	return "Argument was ignored";
+    case NOTMUCH_STATUS_ILLEGAL_ARGUMENT:
+	return "Illegal argument for function";
     case NOTMUCH_STATUS_MALFORMED_CRYPTO_PROTOCOL:
 	return "Crypto protocol missing, malformed, or unintelligible";
     case NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION:
 	return "Crypto engine initialization failure";
     case NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL:
 	return "Unknown crypto protocol";
+    case NOTMUCH_STATUS_NO_CONFIG:
+	return "No configuration file found";
+    case NOTMUCH_STATUS_DATABASE_EXISTS:
+	return "Database exists, not recreated";
     default:
     case NOTMUCH_STATUS_LAST_STATUS:
 	return "Unknown error status value";
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 03/28] test: convert random-corpus to use n_d_open_with_config
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
  2021-04-07  1:55 ` [PATCH 01/28] lib/open: fix leaks calling _trial_open David Bremner
  2021-04-07  1:55 ` [PATCH 02/28] lib: add missing status strings David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 04/28] lib/open: pull _load_key_file out of _choose_database_path David Bremner
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Remove one more usage of notmuch_config_get_database_path
---
 test/random-corpus.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/test/random-corpus.c b/test/random-corpus.c
index d0354e35..7cde22c5 100644
--- a/test/random-corpus.c
+++ b/test/random-corpus.c
@@ -141,7 +141,6 @@ main (int argc, char **argv)
     void *ctx = talloc_new (NULL);
 
     const char *config_path = NULL;
-    notmuch_config_t *config;
     notmuch_database_t *notmuch;
 
     int num_messages = 500;
@@ -179,12 +178,12 @@ main (int argc, char **argv)
 	exit (1);
     }
 
-    config = notmuch_config_open (ctx, config_path, false);
-    if (config == NULL)
-	return 1;
-
-    if (notmuch_database_open (notmuch_config_get_database_path (config),
-			       NOTMUCH_DATABASE_MODE_READ_WRITE, &notmuch))
+    if (notmuch_database_open_with_config (NULL,
+					   NOTMUCH_DATABASE_MODE_READ_WRITE,
+					   config_path,
+					   NULL,
+					   &notmuch,
+					   NULL))
 	return 1;
 
     srandom (seed);
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 04/28] lib/open: pull _load_key_file out of _choose_database_path
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (2 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 03/28] test: convert random-corpus to use n_d_open_with_config David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 05/28] lib: provide notmuch_database_load_config David Bremner
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Although this increases code duplication, it also increases
flexibility in handling various combinations of missing config file
and missing database.
---
 lib/open.cc | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index dc191d64..9bb313da 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -183,27 +183,18 @@ _db_dir_exists (const char *database_path, char **message)
 
 static notmuch_status_t
 _choose_database_path (void *ctx,
-		       const char *config_path,
 		       const char *profile,
-		       GKeyFile **key_file,
+		       GKeyFile *key_file,
 		       const char **database_path,
 		       bool *split,
 		       char **message)
 {
-    notmuch_status_t status;
-
-    status = _load_key_file (config_path, profile, key_file);
-    if (status) {
-	*message = strdup ("Error: cannot load config file.\n");
-	return status;
-    }
-
     if (! *database_path) {
 	*database_path = getenv ("NOTMUCH_DATABASE");
     }
 
-    if (! *database_path && *key_file) {
-	char *path = g_key_file_get_value (*key_file, "database", "path", NULL);
+    if (! *database_path && key_file) {
+	char *path = g_key_file_get_value (key_file, "database", "path", NULL);
 	if (path) {
 	    *database_path = talloc_strdup (ctx, path);
 	    g_free (path);
@@ -500,8 +491,14 @@ notmuch_database_open_with_config (const char *database_path,
 	goto DONE;
     }
 
-    if ((status = _choose_database_path (local, config_path, profile,
-					 &key_file, &database_path, &split,
+    status = _load_key_file (config_path, profile, &key_file);
+    if (status) {
+	message = strdup ("Error: cannot load config file.\n");
+	goto DONE;
+    }
+
+    if ((status = _choose_database_path (local, profile, key_file,
+					 &database_path, &split,
 					 &message)))
 	goto DONE;
 
@@ -591,11 +588,14 @@ notmuch_database_create_with_config (const char *database_path,
 	goto DONE;
     }
 
-    _init_libs ();
+    status = _load_key_file (config_path, profile, &key_file);
+    if (status) {
+	message = strdup ("Error: cannot load config file.\n");
+	goto DONE;
+    }
 
-    if ((status = _choose_database_path (local, config_path, profile,
-					 &key_file, &database_path, &split,
-					 &message)))
+    if ((status = _choose_database_path (local, profile, key_file,
+					 &database_path, &split, &message)))
 	goto DONE;
 
     status = _db_dir_exists (database_path, &message);
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 05/28] lib: provide notmuch_database_load_config
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (3 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 04/28] lib/open: pull _load_key_file out of _choose_database_path David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 06/28] lib/config: add notmuch_config_get_values_string David Bremner
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This is mainly targetted at notmuch-config.c, or similar applications
that don't necessarily need both a configuration file and a database
to exist.
---
 lib/notmuch.h          |  27 ++++++
 lib/open.cc            |  96 ++++++++++++++++++++++
 test/T590-libconfig.sh | 182 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 302 insertions(+), 3 deletions(-)

diff --git a/lib/notmuch.h b/lib/notmuch.h
index f9efd79e..da556e50 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -442,6 +442,33 @@ notmuch_database_open_with_config (const char *database_path,
 				   const char *profile,
 				   notmuch_database_t **database,
 				   char **error_message);
+
+
+/**
+ * Loads configuration from config file, database, and/or defaults
+ *
+ * For description of arguments, @see notmuch_database_open_with_config
+ *
+ * @retval NOTMUCH_STATUS_SUCCESS: Successfully loaded (some) configuration.
+ *
+ * @retval NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory.
+ *
+ * @retval NOTMUCH_STATUS_FILE_ERROR: An error occurred trying to open the
+ *	database or config file (such as permission denied, or file not found,
+ *	etc.)
+ *
+ * @retval NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred.
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ */
+
+notmuch_status_t
+notmuch_database_load_config (const char *database_path,
+			      const char *config_path,
+			      const char *profile,
+			      notmuch_database_t **database,
+			      char **error_message);
+
 /**
  * Create a new notmuch database located at 'database_path', using
  * configuration in 'config_path'.
diff --git a/lib/open.cc b/lib/open.cc
index 9bb313da..6c3ef46f 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -738,3 +738,99 @@ notmuch_database_reopen (notmuch_database_t *notmuch,
     notmuch->open = true;
     return NOTMUCH_STATUS_SUCCESS;
 }
+
+notmuch_status_t
+_maybe_load_config_from_database (notmuch_database_t *notmuch,
+				  GKeyFile *key_file,
+				  const char *database_path,
+				  const char *profile)
+{
+    char *message; /* ignored */
+
+    if (_db_dir_exists (database_path, &message))
+	return NOTMUCH_STATUS_SUCCESS;
+
+    _set_database_path (notmuch, database_path);
+
+    if (_notmuch_choose_xapian_path (notmuch, database_path, &notmuch->xapian_path, &message))
+	return NOTMUCH_STATUS_SUCCESS;
+
+    (void) _finish_open (notmuch, profile, NOTMUCH_DATABASE_MODE_READ_ONLY, key_file, &message);
+
+    return NOTMUCH_STATUS_SUCCESS;
+}
+
+notmuch_status_t
+notmuch_database_load_config (const char *database_path,
+			      const char *config_path,
+			      const char *profile,
+			      notmuch_database_t **database,
+			      char **status_string)
+{
+    notmuch_status_t status = NOTMUCH_STATUS_SUCCESS, warning = NOTMUCH_STATUS_SUCCESS;
+    void *local = talloc_new (NULL);
+    notmuch_database_t *notmuch = NULL;
+    char *message = NULL;
+    GKeyFile *key_file = NULL;
+    bool split = false;
+
+    _init_libs ();
+
+    notmuch = _alloc_notmuch ();
+    if (! notmuch) {
+	status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+	goto DONE;
+    }
+
+    status = _load_key_file (config_path, profile, &key_file);
+    switch (status) {
+    case NOTMUCH_STATUS_SUCCESS:
+    case NOTMUCH_STATUS_NO_CONFIG:
+	warning = status;
+	break;
+    default:
+	message = strdup ("Error: cannot load config file.\n");
+	goto DONE;
+    }
+
+    status = _choose_database_path (local, profile, key_file,
+				    &database_path, &split, &message);
+    switch (status) {
+    /* weirdly NULL_POINTER is what is returned if we fail to find
+     * a database */
+    case NOTMUCH_STATUS_NULL_POINTER:
+    case NOTMUCH_STATUS_SUCCESS:
+	break;
+    default:
+	goto DONE;
+    }
+
+    if (database_path) {
+	status = _maybe_load_config_from_database (notmuch, key_file, database_path, profile);
+	if (status)
+	    goto DONE;
+    }
+
+    if (key_file) {
+	status = _notmuch_config_load_from_file (notmuch, key_file);
+	if (status)
+	    goto DONE;
+    }
+    status = _notmuch_config_load_defaults (notmuch);
+    if (status)
+	goto DONE;
+
+  DONE:
+    talloc_free (local);
+
+    if (status_string)
+	*status_string = message;
+
+    if (database)
+	*database = notmuch;
+
+    if (status)
+	return status;
+    else
+	return warning;
+}
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 310668a9..dc9964cf 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -538,7 +538,7 @@ cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
    printf("test.key2 = %s\n", val);
 }
 EOF
-NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
+export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
 unset NOTMUCH_DATABASE
 cat <<'EOF' >EXPECTED
 == stdout ==
@@ -549,7 +549,7 @@ EOF
 test_expect_equal_file EXPECTED OUTPUT
 
 test_begin_subtest "NOTMUCH_DATABASE overrides config"
-old_path=$(notmuch config get database.path)
+cp notmuch-config notmuch-config.bak
 notmuch config set database.path /nonexistent
 export NOTMUCH_DATABASE=${MAIL_DIR}
 cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
@@ -568,8 +568,184 @@ test.key1 = testvalue1
 test.key2 = testvalue2
 == stderr ==
 EOF
-notmuch config set database.path "${old_path}"
+cp notmuch-config.bak notmuch-config
+test_expect_equal_file EXPECTED OUTPUT
+
+cat <<EOF > c_head2
+#include <string.h>
+#include <stdlib.h>
+#include <notmuch-test.h>
+
+int main (int argc, char** argv)
+{
+   notmuch_database_t *db;
+   char *val;
+   notmuch_status_t stat;
+   char *msg = NULL;
+
+   for (int i = 1; i < argc; i++)
+      if (strcmp (argv[i], "%NULL%") == 0) argv[i] = NULL;
+
+   stat = notmuch_database_load_config (argv[1],
+                                        argv[2],
+                                        argv[3],
+                                        &db,
+                                        &msg);
+   if (stat != NOTMUCH_STATUS_SUCCESS  && stat != NOTMUCH_STATUS_NO_CONFIG) {
+     fprintf (stderr, "error opening database\n%d: %s\n%s\n", stat,
+	      notmuch_status_to_string (stat), msg ? msg : "");
+     exit (1);
+   }
+EOF
+
+
+test_begin_subtest "notmuch_database_get_config (ndlc)"
+echo NOTMUCH_CONFIG=$NOTMUCH_CONFIG
+echo NOTMUCH_PROFILE=$NOTMUCH_PROFILE
+echo HOME=$HOME
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
+{
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = testvalue1
+test.key2 = testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+
+test_begin_subtest "notmuch_database_get_config_list: all pairs (ndlc)"
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+   notmuch_config_list_t *list;
+   EXPECT0(notmuch_database_get_config_list (db, "", &list));
+   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
+      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
+   }
+   notmuch_config_list_destroy (list);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+aaabefore beforeval
+key with spaces value, with, spaces!
+test.key1 testvalue1
+test.key2 testvalue2
+zzzafter afterval
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "notmuch_database_get_config_list: one prefix (ndlc)"
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+   notmuch_config_list_t *list;
+   EXPECT0(notmuch_database_get_config_list (db, "test.key", &list));
+   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
+      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
+   }
+   notmuch_config_list_destroy (list);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 testvalue1
+test.key2 testvalue2
+== stderr ==
+EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+test_begin_subtest "list by keys (ndlc)"
+notmuch config set search.exclude_tags "foo;bar;fub"
+notmuch config set new.ignore "sekrit_junk"
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
+{
+    notmuch_config_key_t key;
+    for (key = NOTMUCH_CONFIG_FIRST;
+	 key < NOTMUCH_CONFIG_LAST;
+	 key = (notmuch_config_key_t)(key + 1)) {
+	const char *val = notmuch_config_get (db, key);
+        printf("%s\n", val ? val : "NULL" );
+    }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+MAIL_DIR
+MAIL_DIR
+MAIL_DIR/.notmuch/hooks
+MAIL_DIR/.notmuch/backups
+foo;bar;fub
+unread;inbox;
+sekrit_junk
+true
+test_suite@notmuchmail.org
+test_suite_other@notmuchmail.org;test_suite@otherdomain.org
+Notmuch Test Suite
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "load default values (ndlc, nonexistent config)"
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} /nonexistent %NULL%
+{
+    notmuch_config_key_t key;
+    for (key = NOTMUCH_CONFIG_FIRST;
+	 key < NOTMUCH_CONFIG_LAST;
+	 key = (notmuch_config_key_t)(key + 1)) {
+	const char *val = notmuch_config_get (db, key);
+	printf("%s\n", val ? val : "NULL" );
+    }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+MAIL_DIR
+MAIL_DIR
+MAIL_DIR/.notmuch/hooks
+MAIL_DIR/.notmuch/backups
+
+inbox;unread
+NULL
+true
+NULL
+NULL
+NULL
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+backup_database
+test_begin_subtest "override config from \${HOME}/.notmuch-config (ndlc)"
+ovconfig=${HOME}/.notmuch-config
+cp ${NOTMUCH_CONFIG} ${ovconfig}
+old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
+unset NOTMUCH_CONFIG
+notmuch --config=${ovconfig} config set test.key1 overridden-home
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
+{
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+}
+EOF
+rm -f ${ovconfig}
+NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = overridden-home
+test.key2 = testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
 
 test_done
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 06/28] lib/config: add notmuch_config_get_values_string
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (4 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 05/28] lib: provide notmuch_database_load_config David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 07/28] lib/config: add config_pairs iterators David Bremner
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This is to support the less common (at least in the notmuch codebase)
case of accessing a ;-delimited list config value with an arbitrary
string key.
---
 lib/config.cc          | 14 ++++++++++----
 lib/notmuch.h          | 17 ++++++++++++++++-
 test/T590-libconfig.sh | 23 +++++++++++++++++++++++
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 8bd3c35a..24418f98 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -261,13 +261,19 @@ _notmuch_config_load_from_database (notmuch_database_t *notmuch)
 notmuch_config_values_t *
 notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key)
 {
-    notmuch_config_values_t *values = NULL;
-    bool ok = false;
-
     const char *key_str = _notmuch_config_key_to_string (key);
 
     if (! key_str)
-	goto DONE;
+	return NULL;
+
+    return notmuch_config_get_values_string (notmuch, key_str);
+}
+
+notmuch_config_values_t *
+notmuch_config_get_values_string (notmuch_database_t *notmuch, const char *key_str)
+{
+    notmuch_config_values_t *values = NULL;
+    bool ok = false;
 
     values = talloc (notmuch, notmuch_config_values_t);
     if (unlikely (! values))
diff --git a/lib/notmuch.h b/lib/notmuch.h
index da556e50..dd3d06a1 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -2494,7 +2494,6 @@ notmuch_config_list_move_to_next (notmuch_config_list_t *config_list);
 void
 notmuch_config_list_destroy (notmuch_config_list_t *config_list);
 
-
 /**
  * Configuration keys known to libnotmuch
  */
@@ -2565,6 +2564,22 @@ notmuch_config_set (notmuch_database_t *notmuch, notmuch_config_key_t key, const
 notmuch_config_values_t *
 notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key);
 
+/**
+ * Returns an iterator for a ';'-delimited list of configuration values
+ *
+ * These values reflect all configuration information given at the
+ * time the database was opened.
+ *
+ * @param[in] notmuch database
+ * @param[in] key configuration key
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ *
+ * @retval NULL in case of error.
+ */
+notmuch_config_values_t *
+notmuch_config_get_values_string (notmuch_database_t *notmuch, const char *key);
+
 /**
  * Is the given 'config_values' iterator pointing at a valid element.
  *
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index dc9964cf..edbba6c4 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -255,6 +255,29 @@ EOF
 test_expect_equal_file EXPECTED OUTPUT
 restore_database
 
+test_begin_subtest "notmuch_config_get_values_string"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+    notmuch_config_values_t *values;
+    EXPECT0(notmuch_database_set_config (db, "test.list", "x;y;z"));
+    for (values = notmuch_config_get_values_string (db, "test.list");
+	 notmuch_config_values_valid (values);
+	 notmuch_config_values_move_to_next (values))
+    {
+	  puts (notmuch_config_values_get (values));
+    }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+x
+y
+z
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
 test_begin_subtest "notmuch_config_get_values (restart)"
 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
 {
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 07/28] lib/config: add config_pairs iterators
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (5 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 06/28] lib/config: add notmuch_config_get_values_string David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 08/28] lib/config: set defaults for user full name David Bremner
                   ` (21 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

The layer of shims here seems a bit wasteful compared to just calling
the corresponding string map functions directly, but it allows control
over the API (calling with notmuch_database_t *) and flexibility for
future changes.
---
 lib/config.cc          | 45 +++++++++++++++++++++++++
 lib/notmuch.h          | 75 ++++++++++++++++++++++++++++++++++++++++++
 test/T590-libconfig.sh | 54 ++++++++++++++++++++++++++++++
 3 files changed, 174 insertions(+)

diff --git a/lib/config.cc b/lib/config.cc
index 24418f98..ab45ae7b 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -38,6 +38,10 @@ struct _notmuch_config_values {
     void *children; /* talloc_context */
 };
 
+struct _notmuch_config_pairs {
+    notmuch_string_map_iterator_t *iter;
+};
+
 static const char *_notmuch_config_key_to_string (notmuch_config_key_t key);
 
 static int
@@ -339,6 +343,47 @@ notmuch_config_values_destroy (notmuch_config_values_t *values)
     talloc_free (values);
 }
 
+notmuch_config_pairs_t *
+notmuch_config_get_pairs (notmuch_database_t *notmuch,
+			  const char *prefix)
+{
+    notmuch_config_pairs_t *pairs = talloc (notmuch, notmuch_config_pairs_t);
+
+    pairs->iter = _notmuch_string_map_iterator_create (notmuch->config, prefix, false);
+    return pairs;
+}
+
+notmuch_bool_t
+notmuch_config_pairs_valid (notmuch_config_pairs_t *pairs)
+{
+    return _notmuch_string_map_iterator_valid (pairs->iter);
+}
+
+void
+notmuch_config_pairs_move_to_next (notmuch_config_pairs_t *pairs)
+{
+    _notmuch_string_map_iterator_move_to_next (pairs->iter);
+}
+
+const char *
+notmuch_config_pairs_key (notmuch_config_pairs_t *pairs)
+{
+    return _notmuch_string_map_iterator_key (pairs->iter);
+}
+
+const char *
+notmuch_config_pairs_value (notmuch_config_pairs_t *pairs)
+{
+    return _notmuch_string_map_iterator_value (pairs->iter);
+}
+
+void
+notmuch_config_pairs_destroy (notmuch_config_pairs_t *pairs)
+{
+    _notmuch_string_map_iterator_destroy (pairs->iter);
+    talloc_free (pairs);
+}
+
 notmuch_status_t
 _notmuch_config_load_from_file (notmuch_database_t *notmuch,
 				GKeyFile *file)
diff --git a/lib/notmuch.h b/lib/notmuch.h
index dd3d06a1..2a013be0 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -245,6 +245,7 @@ typedef struct _notmuch_directory notmuch_directory_t;
 typedef struct _notmuch_filenames notmuch_filenames_t;
 typedef struct _notmuch_config_list notmuch_config_list_t;
 typedef struct _notmuch_config_values notmuch_config_values_t;
+typedef struct _notmuch_config_pairs notmuch_config_pairs_t;
 typedef struct _notmuch_indexopts notmuch_indexopts_t;
 #endif /* __DOXYGEN__ */
 
@@ -2639,6 +2640,80 @@ notmuch_config_values_start (notmuch_config_values_t *values);
 void
 notmuch_config_values_destroy (notmuch_config_values_t *values);
 
+
+/**
+ * Returns an iterator for a (key, value) configuration pairs
+ *
+ * @param[in] notmuch database
+ * @param[in] prefix prefix for keys. Pass "" for all keys.
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ *
+ * @retval NULL in case of error.
+ */
+notmuch_config_pairs_t *
+notmuch_config_get_pairs (notmuch_database_t *notmuch,
+			  const char *prefix);
+
+/**
+ * Is the given 'config_pairs' iterator pointing at a valid element.
+ *
+ * @param[in] pairs iterator
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ *
+ * @retval FALSE if passed a NULL pointer, or the iterator is exhausted.
+ *
+ */
+notmuch_bool_t
+notmuch_config_pairs_valid (notmuch_config_pairs_t *pairs);
+
+/**
+ * Move the 'config_pairs' iterator to the next element
+ *
+ * @param[in,out] pairs iterator
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ *
+ */
+void
+notmuch_config_pairs_move_to_next (notmuch_config_pairs_t *pairs);
+
+/**
+ * Get the current key from the 'config_pairs' iterator
+ *
+ * @param[in] pairs iterator
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ *
+ * @retval a string with the same lifetime as the iterator
+ */
+const char *
+notmuch_config_pairs_key (notmuch_config_pairs_t *pairs);
+
+/**
+ * Get the current value from the 'config_pairs' iterator
+ *
+ * @param[in] pairs iterator
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ *
+ * @retval a string with the same lifetime as the iterator
+ */
+const char *
+notmuch_config_pairs_value (notmuch_config_pairs_t *pairs);
+
+/**
+ * Destroy a config_pairs iterator, along with any associated
+ * resources.
+ *
+ * @param[in,out] pairs iterator
+ *
+ * @since libnotmuch 5.4 (notmuch 0.32)
+ */
+void
+notmuch_config_pairs_destroy (notmuch_config_pairs_t *pairs);
+
 /**
  * get a configuration value from an open database as Boolean
  *
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index edbba6c4..49cc382a 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -770,5 +770,59 @@ EOF
 test_expect_equal_file EXPECTED OUTPUT
 restore_database
 
+test_begin_subtest "notmuch_config_get_pairs: prefix (ndlc)"
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+   notmuch_config_pairs_t *list;
+   for (list =  notmuch_config_get_pairs (db, "user.");
+        notmuch_config_pairs_valid (list);
+        notmuch_config_pairs_move_to_next (list)) {
+     printf("%s %s\n", notmuch_config_pairs_key (list), notmuch_config_pairs_value(list));
+   }
+   notmuch_config_pairs_destroy (list);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+user.name Notmuch Test Suite
+user.other_email test_suite_other@notmuchmail.org;test_suite@otherdomain.org
+user.primary_email test_suite@notmuchmail.org
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "notmuch_config_get_pairs: all pairs (ndlc)"
+cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+   notmuch_config_pairs_t *list;
+   for (list =  notmuch_config_get_pairs (db, "");
+        notmuch_config_pairs_valid (list);
+        notmuch_config_pairs_move_to_next (list)) {
+     printf("%s %s\n", notmuch_config_pairs_key (list), notmuch_config_pairs_value(list));
+   }
+   notmuch_config_pairs_destroy (list);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+aaabefore beforeval
+database.backup_dir MAIL_DIR/.notmuch/backups
+database.hook_dir MAIL_DIR/.notmuch/hooks
+database.mail_root MAIL_DIR
+database.path MAIL_DIR
+key with spaces value, with, spaces!
+maildir.synchronize_flags true
+new.ignore sekrit_junk
+new.tags unread;inbox;
+search.exclude_tags foo;bar;fub
+test.key1 testvalue1
+test.key2 testvalue2
+user.name Notmuch Test Suite
+user.other_email test_suite_other@notmuchmail.org;test_suite@otherdomain.org
+user.primary_email test_suite@notmuchmail.org
+zzzafter afterval
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
 
 test_done
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 08/28] lib/config: set defaults for user full name
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (6 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 07/28] lib/config: add config_pairs iterators David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 09/28] lib/config: set default for primary user email David Bremner
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This just copies code from from the CLI into the library. New test
infrastructure is needed because apparently we have never tested this
code path.
---
 lib/config.cc          | 48 +++++++++++++++++++++++++++++++++++++++++-
 test/T590-libconfig.sh | 13 ++++++++----
 test/test-lib.sh       |  7 ++++++
 3 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index ab45ae7b..38416632 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -22,6 +22,8 @@
 #include "notmuch-private.h"
 #include "database-private.h"
 
+#include <pwd.h>
+
 static const std::string CONFIG_PREFIX = "C";
 
 struct _notmuch_config_list {
@@ -451,6 +453,41 @@ notmuch_config_get_bool (notmuch_database_t *notmuch, notmuch_config_key_t key,
     return NOTMUCH_STATUS_SUCCESS;
 }
 
+static const char *
+_get_name_from_passwd_file (void *ctx)
+{
+    long pw_buf_size;
+    char *pw_buf;
+    struct passwd passwd, *ignored;
+    const char *name;
+    int e;
+
+    pw_buf_size = sysconf (_SC_GETPW_R_SIZE_MAX);
+    if (pw_buf_size == -1) pw_buf_size = 64;
+    pw_buf = (char *) talloc_size (ctx, pw_buf_size);
+
+    while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
+			    pw_buf_size, &ignored)) == ERANGE) {
+	pw_buf_size = pw_buf_size * 2;
+	pw_buf = (char *) talloc_zero_size (ctx, pw_buf_size);
+    }
+
+    if (e == 0) {
+	char *comma = strchr (passwd.pw_gecos, ',');
+	if (comma)
+	    name = talloc_strndup (ctx, passwd.pw_gecos,
+				   comma - passwd.pw_gecos);
+	else
+	    name = talloc_strdup (ctx, passwd.pw_gecos);
+    } else {
+	name = talloc_strdup (ctx, "");
+    }
+
+    talloc_free (pw_buf);
+
+    return name;
+}
+
 static const char *
 _notmuch_config_key_to_string (notmuch_config_key_t key)
 {
@@ -486,6 +523,7 @@ static const char *
 _notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key)
 {
     char *path;
+    const char *name;
 
     switch (key) {
     case NOTMUCH_CONFIG_DATABASE_PATH:
@@ -505,10 +543,18 @@ _notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key)
 	return "inbox;unread";
     case NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS:
 	return "true";
+    case NOTMUCH_CONFIG_USER_NAME:
+	name = getenv ("NAME");
+	if (name)
+	    name = talloc_strdup (notmuch, name);
+	else
+	    name = _get_name_from_passwd_file (notmuch);
+
+	return name;
+	break;
     case NOTMUCH_CONFIG_HOOK_DIR:
     case NOTMUCH_CONFIG_BACKUP_DIR:
     case NOTMUCH_CONFIG_NEW_IGNORE:
-    case NOTMUCH_CONFIG_USER_NAME:
     case NOTMUCH_CONFIG_PRIMARY_EMAIL:
     case NOTMUCH_CONFIG_OTHER_EMAIL:
 	return NULL;
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 49cc382a..2c6e726c 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -384,6 +384,9 @@ cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} '' %NULL%
     }
 }
 EOF
+
+notmuch_passwd_sanitize < OUTPUT > OUTPUT.clean
+
 cat <<'EOF' >EXPECTED
 == stdout ==
 MAIL_DIR
@@ -396,11 +399,11 @@ NULL
 true
 NULL
 NULL
-NULL
+USER_FULL_NAME
 == stderr ==
 EOF
 unset MAILDIR
-test_expect_equal_file EXPECTED OUTPUT
+test_expect_equal_file EXPECTED OUTPUT.clean
 
 backup_database
 test_begin_subtest "override config from \${NOTMUCH_CONFIG}"
@@ -727,6 +730,8 @@ cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} /nonexistent %NULL%
     }
 }
 EOF
+
+notmuch_passwd_sanitize < OUTPUT > OUTPUT.clean
 cat <<'EOF' >EXPECTED
 == stdout ==
 MAIL_DIR
@@ -739,10 +744,10 @@ NULL
 true
 NULL
 NULL
-NULL
+USER_FULL_NAME
 == stderr ==
 EOF
-test_expect_equal_file EXPECTED OUTPUT
+test_expect_equal_file EXPECTED OUTPUT.clean
 
 backup_database
 test_begin_subtest "override config from \${HOME}/.notmuch-config (ndlc)"
diff --git a/test/test-lib.sh b/test/test-lib.sh
index fc176af8..fa2e401e 100644
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -694,6 +694,13 @@ notmuch_built_with_sanitize ()
     sed 's/^built_with[.]\(.*\)=.*$/built_with.\1=something/'
 }
 
+notmuch_passwd_sanitize ()
+{
+    local user=$(id -un)
+    local full_name=$(getent passwd $user | cut -d: -f 5 | cut -d, -f1)
+    sed "s/$full_name/USER_FULL_NAME/"
+}
+
 notmuch_config_sanitize ()
 {
     notmuch_dir_sanitize | notmuch_built_with_sanitize
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 09/28] lib/config: set default for primary user email
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (7 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 08/28] lib/config: set defaults for user full name David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 10/28] lib/open: canonicalize relative path read from config file David Bremner
                   ` (19 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This is mainly copying code from the CLI into the lib. The CLI copy
will be deleted in a later commit.
---
 lib/config.cc          | 70 +++++++++++++++++++++++++++++++++++++++---
 test/T590-libconfig.sh |  7 ++---
 test/test-lib.sh       |  6 +++-
 3 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 38416632..36f242f2 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -23,6 +23,7 @@
 #include "database-private.h"
 
 #include <pwd.h>
+#include <netdb.h>
 
 static const std::string CONFIG_PREFIX = "C";
 
@@ -488,6 +489,63 @@ _get_name_from_passwd_file (void *ctx)
     return name;
 }
 
+static char *
+_get_username_from_passwd_file (void *ctx)
+{
+    long pw_buf_size;
+    char *pw_buf;
+    struct passwd passwd, *ignored;
+    char *name;
+    int e;
+
+    pw_buf_size = sysconf (_SC_GETPW_R_SIZE_MAX);
+    if (pw_buf_size == -1) pw_buf_size = 64;
+    pw_buf = (char *) talloc_zero_size (ctx, pw_buf_size);
+
+    while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
+			    pw_buf_size, &ignored)) == ERANGE) {
+	pw_buf_size = pw_buf_size * 2;
+	pw_buf = (char *) talloc_zero_size (ctx, pw_buf_size);
+    }
+
+    if (e == 0)
+	name = talloc_strdup (ctx, passwd.pw_name);
+    else
+	name = talloc_strdup (ctx, "");
+
+    talloc_free (pw_buf);
+
+    return name;
+}
+
+static const char *
+_get_email_from_passwd_file (void *ctx)
+{
+
+    char hostname[256];
+    struct hostent *hostent;
+    const char *domainname;
+    char *email;
+
+    char *username = _get_username_from_passwd_file (ctx);
+
+    gethostname (hostname, 256);
+    hostname[255] = '\0';
+
+    hostent = gethostbyname (hostname);
+    if (hostent && (domainname = strchr (hostent->h_name, '.')))
+	domainname += 1;
+    else
+	domainname = "(none)";
+
+    email = talloc_asprintf (ctx, "%s@%s.%s",
+			     username, hostname, domainname);
+
+    talloc_free (username);
+    talloc_free (email);
+    return email;
+}
+
 static const char *
 _notmuch_config_key_to_string (notmuch_config_key_t key)
 {
@@ -523,7 +581,7 @@ static const char *
 _notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key)
 {
     char *path;
-    const char *name;
+    const char *name, *email;
 
     switch (key) {
     case NOTMUCH_CONFIG_DATABASE_PATH:
@@ -549,13 +607,17 @@ _notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key)
 	    name = talloc_strdup (notmuch, name);
 	else
 	    name = _get_name_from_passwd_file (notmuch);
-
 	return name;
-	break;
+    case NOTMUCH_CONFIG_PRIMARY_EMAIL:
+	email = getenv ("EMAIL");
+	if (email)
+	    email = talloc_strdup (notmuch, email);
+	else
+	    email = _get_email_from_passwd_file (notmuch);
+	return email;
     case NOTMUCH_CONFIG_HOOK_DIR:
     case NOTMUCH_CONFIG_BACKUP_DIR:
     case NOTMUCH_CONFIG_NEW_IGNORE:
-    case NOTMUCH_CONFIG_PRIMARY_EMAIL:
     case NOTMUCH_CONFIG_OTHER_EMAIL:
 	return NULL;
     default:
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 2c6e726c..292778d5 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -397,7 +397,7 @@ MAIL_DIR/.notmuch/backups
 inbox;unread
 NULL
 true
-NULL
+USERNAME@FQDN
 NULL
 USER_FULL_NAME
 == stderr ==
@@ -626,9 +626,6 @@ EOF
 
 
 test_begin_subtest "notmuch_database_get_config (ndlc)"
-echo NOTMUCH_CONFIG=$NOTMUCH_CONFIG
-echo NOTMUCH_PROFILE=$NOTMUCH_PROFILE
-echo HOME=$HOME
 cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
 {
    EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
@@ -742,7 +739,7 @@ MAIL_DIR/.notmuch/backups
 inbox;unread
 NULL
 true
-NULL
+USERNAME@FQDN
 NULL
 USER_FULL_NAME
 == stderr ==
diff --git a/test/test-lib.sh b/test/test-lib.sh
index fa2e401e..1f438042 100644
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -107,6 +107,9 @@ unset GREP_OPTIONS
 # For emacsclient
 unset ALTERNATE_EDITOR
 
+# for reproducibility
+unset EMAIL
+
 add_gnupg_home ()
 {
     [ -e "${GNUPGHOME}/gpg.conf" ] && return
@@ -697,8 +700,9 @@ notmuch_built_with_sanitize ()
 notmuch_passwd_sanitize ()
 {
     local user=$(id -un)
+    local fqdn=$(hostname -f)
     local full_name=$(getent passwd $user | cut -d: -f 5 | cut -d, -f1)
-    sed "s/$full_name/USER_FULL_NAME/"
+    sed -e "s/$user/USERNAME/" -e "s/$fqdn/FQDN/" -e "s/$full_name/USER_FULL_NAME/"
 }
 
 notmuch_config_sanitize ()
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 10/28] lib/open: canonicalize relative path read from config file
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (8 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 09/28] lib/config: set default for primary user email David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 11/28] CLI: load merged config at top level David Bremner
                   ` (18 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This matches functionality in the the CLI function
notmuch_config_get_database_path, which was previously used in the CLI
code for all calls to open a database.
---
 lib/open.cc | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index 6c3ef46f..d0493950 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -196,11 +196,13 @@ _choose_database_path (void *ctx,
     if (! *database_path && key_file) {
 	char *path = g_key_file_get_value (key_file, "database", "path", NULL);
 	if (path) {
-	    *database_path = talloc_strdup (ctx, path);
+	    if (path[0] == '/')
+		*database_path = talloc_strdup (ctx, path);
+	    else
+		*database_path = talloc_asprintf (ctx, "%s/%s", getenv ("HOME"), path);
 	    g_free (path);
 	}
     }
-
     if (! *database_path) {
 	*database_path = _xdg_dir (ctx, "XDG_DATA_HOME", ".local/share", profile);
 	*split = true;
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 11/28] CLI: load merged config at top level
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (9 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 10/28] lib/open: canonicalize relative path read from config file David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 12/28] CLI/config: use merged config for "config get" David Bremner
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This paves the way for the conversion of the remaining subcommands to
the new configuration framework.
---
 notmuch-client.h |  1 +
 notmuch.c        | 29 ++++++++++++++++++++++++++---
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index 70458629..b560e3ed 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -272,6 +272,7 @@ typedef enum {
     NOTMUCH_COMMAND_DATABASE_EARLY	= 1 << 2,
     NOTMUCH_COMMAND_DATABASE_WRITE	= 1 << 3,
     NOTMUCH_COMMAND_DATABASE_CREATE	= 1 << 4,
+    NOTMUCH_COMMAND_CONFIG_LOAD		= 1 << 5,
 } notmuch_command_mode_t;
 
 notmuch_config_t *
diff --git a/notmuch.c b/notmuch.c
index f2bf9c24..742544c2 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -175,7 +175,7 @@ static command_t commands[] = {
     { "reindex", notmuch_reindex_command, NOTMUCH_COMMAND_DATABASE_EARLY |
       NOTMUCH_COMMAND_DATABASE_WRITE,
       "Re-index all messages matching the search terms." },
-    { "config", notmuch_config_command, NOTMUCH_COMMAND_CONFIG_OPEN,
+    { "config", notmuch_config_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_LOAD,
       "Get or set settings in the notmuch configuration file." },
 #if WITH_EMACS
     { "emacs-mua", NULL, 0,
@@ -471,7 +471,7 @@ main (int argc, char *argv[])
     notmuch_config_t *config = NULL;
     notmuch_database_t *notmuch = NULL;
     int opt_index;
-    int ret;
+    int ret = EXIT_SUCCESS;
 
     notmuch_opt_desc_t options[] = {
 	{ .opt_string = &config_file_name, .name = "config" },
@@ -559,7 +559,30 @@ main (int argc, char *argv[])
 		return EXIT_FAILURE;
 	    }
 	}
-    } else {
+    }
+
+    if (command->mode & NOTMUCH_COMMAND_CONFIG_LOAD) {
+	char *status_string = NULL;
+	notmuch_status_t status;
+	status = notmuch_database_load_config (NULL,
+					       config_file_name,
+					       NULL,
+					       &notmuch,
+					       &status_string);
+	if (status) {
+	    if (status_string) {
+		fputs (status_string, stderr);
+		free (status_string);
+	    }
+
+	    if (status == NOTMUCH_STATUS_NO_CONFIG)
+		fputs ("Try running 'notmuch setup' to create a configuration.", stderr);
+	    goto DONE;
+	}
+
+    }
+
+    if (command->mode & NOTMUCH_COMMAND_CONFIG_OPEN) {
 	config = notmuch_config_open (local, config_file_name, command->mode);
 	if (! config) {
 	    ret = EXIT_FAILURE;
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 12/28] CLI/config: use merged config for "config get"
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (10 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 11/28] CLI: load merged config at top level David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 13/28] test/setup: check file output instead of notmuch config list David Bremner
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This commit starts the conversion of notmuch-config.c
functionality (as opposed to just interface) to the new config
framework.

The change to T030-config is because of the move of the
canonicalization database paths from the notmuch_config_t accessor to
the internal function _choose_database_path.
---
 notmuch-config.c    | 91 +++++----------------------------------------
 test/T030-config.sh | 31 ++++++++++++---
 2 files changed, 36 insertions(+), 86 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index e1a583e6..50008f78 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -864,89 +864,18 @@ _config_key_info (const char *item)
     return NULL;
 }
 
-static bool
-_stored_in_db (const char *item)
-{
-    config_key_info_t *info;
-
-    info = _config_key_info (item);
-
-    return (info && info->in_db);
-}
-
 static int
-_print_db_config (notmuch_config_t *config, const char *name)
+notmuch_config_command_get (notmuch_database_t *notmuch, char *item)
 {
-    notmuch_database_t *notmuch;
-    char *val;
-
-    if (notmuch_database_open (notmuch_config_get_database_path (config),
-			       NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch))
-	return EXIT_FAILURE;
-
-    /* XXX Handle UUID mismatch? */
-
-    if (print_status_database ("notmuch config", notmuch,
-			       notmuch_database_get_config (notmuch, name, &val)))
-	return EXIT_FAILURE;
-
-    puts (val);
+    notmuch_config_values_t *list;
 
-    return EXIT_SUCCESS;
-}
-
-static int
-notmuch_config_command_get (notmuch_config_t *config, char *item)
-{
-    if (strcmp (item, "database.path") == 0) {
-	printf ("%s\n", notmuch_config_get_database_path (config));
-    } else if (strcmp (item, "user.name") == 0) {
-	printf ("%s\n", notmuch_config_get_user_name (config));
-    } else if (strcmp (item, "user.primary_email") == 0) {
-	printf ("%s\n", notmuch_config_get_user_primary_email (config));
-    } else if (strcmp (item, "user.other_email") == 0) {
-	const char **other_email;
-	size_t i, length;
-
-	other_email = notmuch_config_get_user_other_email (config, &length);
-	for (i = 0; i < length; i++)
-	    printf ("%s\n", other_email[i]);
-    } else if (strcmp (item, "new.tags") == 0) {
-	const char **tags;
-	size_t i, length;
-
-	tags = notmuch_config_get_new_tags (config, &length);
-	for (i = 0; i < length; i++)
-	    printf ("%s\n", tags[i]);
-    } else if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
-	printf ("%s\n",
-		notmuch_built_with (item + strlen (BUILT_WITH_PREFIX)) ? "true" : "false");
-    } else if (_stored_in_db (item)) {
-	return _print_db_config (config, item);
-    } else {
-	char **value;
-	size_t i, length;
-	char *group, *key;
-
-	if (_item_split (item, &group, &key))
-	    return 1;
-
-	value = g_key_file_get_string_list (config->key_file,
-					    group, key,
-					    &length, NULL);
-	if (value == NULL) {
-	    fprintf (stderr, "Unknown configuration item: %s.%s\n",
-		     group, key);
-	    return 1;
-	}
-
-	for (i = 0; i < length; i++)
-	    printf ("%s\n", value[i]);
-
-	g_strfreev (value);
+    for (list = notmuch_config_get_values_string (notmuch, item);
+	 notmuch_config_values_valid (list);
+	 notmuch_config_values_move_to_next (list)) {
+	const char *val = notmuch_config_values_get (list);
+	puts (val);
     }
-
-    return 0;
+    return EXIT_SUCCESS;
 }
 
 static int
@@ -1107,7 +1036,7 @@ notmuch_config_command_list (notmuch_config_t *config)
 }
 
 int
-notmuch_config_command (notmuch_config_t *config, unused(notmuch_database_t *notmuch),
+notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
 			int argc, char *argv[])
 {
     int ret;
@@ -1136,7 +1065,7 @@ notmuch_config_command (notmuch_config_t *config, unused(notmuch_database_t *not
 		     "one argument.\n");
 	    return EXIT_FAILURE;
 	}
-	ret = notmuch_config_command_get (config, argv[1]);
+	ret = notmuch_config_command_get (notmuch, argv[1]);
     } else if (strcmp (argv[0], "set") == 0) {
 	if (argc < 2) {
 	    fprintf (stderr, "Error: notmuch config set requires at least "
diff --git a/test/T030-config.sh b/test/T030-config.sh
index 6610bf8e..ba29cbac 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -7,9 +7,12 @@ test_begin_subtest "Get string value"
 test_expect_equal "$(notmuch config get user.name)" "Notmuch Test Suite"
 
 test_begin_subtest "Get list value"
-test_expect_equal "$(notmuch config get new.tags)" "\
+cat <<EOF > EXPECTED
+inbox
 unread
-inbox"
+EOF
+notmuch config get new.tags | sort > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
 
 test_begin_subtest "Set string value"
 notmuch config set foo.string "this is a string value"
@@ -96,14 +99,32 @@ test_expect_equal "$(notmuch --config=alt-config-link config get user.name)" \
 test_begin_subtest "Writing config file through symlink follows symlink"
 test_expect_equal "$(readlink alt-config-link)" "alt-config"
 
+test_begin_subtest "Round trip arbitrary key"
+key=g${RANDOM}.m${RANDOM}
+value=${RANDOM}
+notmuch config set ${key} ${value}
+output=$(notmuch config get ${key})
+test_expect_equal "${output}" "${value}"
+
+test_begin_subtest "Clear arbitrary key"
+notmuch config set ${key}
+output=$(notmuch config get ${key})
+test_expect_equal "${output}" ""
+
+db_path=${HOME}/database-path
+
 test_begin_subtest "Absolute database path returned"
 notmuch config set database.path ${HOME}/Maildir
 test_expect_equal "$(notmuch config get database.path)" \
 		  "${HOME}/Maildir"
 
-test_begin_subtest "Relative database path properly expanded"
+ln -s `pwd`/mail home/Maildir
+add_email_corpus
+test_begin_subtest "Relative database path expanded in open"
 notmuch config set database.path Maildir
-test_expect_equal "$(notmuch config get database.path)" \
-		  "${HOME}/Maildir"
+path=$(notmuch config get database.path)
+count=$(notmuch count '*')
+test_expect_equal "${path} ${count}" \
+		  "Maildir 52"
 
 test_done
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 13/28] test/setup: check file output instead of notmuch config list
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (11 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 12/28] CLI/config: use merged config for "config get" David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 14/28] CLI/setup: switch to new configuration framework David Bremner
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This allows verification of comments added to new / updated config
file.
---
 test/T040-setup.sh                            | 17 +---
 .../config-with-comments                      | 88 +++++++++++++++++++
 2 files changed, 91 insertions(+), 14 deletions(-)
 create mode 100644 test/setup.expected-output/config-with-comments

diff --git a/test/T040-setup.sh b/test/T040-setup.sh
index 5eb281d7..daeca3e4 100755
--- a/test/T040-setup.sh
+++ b/test/T040-setup.sh
@@ -10,7 +10,7 @@ Error: cannot load config file.
 Try running 'notmuch setup' to create a configuration."
 
 test_begin_subtest "Create a new config interactively"
-notmuch --config=new-notmuch-config > /dev/null <<EOF
+notmuch --config=new-notmuch-config > log.${test_count} <<EOF
 Test Suite
 test.suite@example.com
 another.suite@example.com
@@ -20,19 +20,8 @@ foo bar
 baz
 EOF
 
-output=$(notmuch --config=new-notmuch-config config list | notmuch_built_with_sanitize)
-test_expect_equal "$output" "\
-database.path=/path/to/maildir
-user.name=Test Suite
-user.primary_email=test.suite@example.com
-user.other_email=another.suite@example.com;
-new.tags=foo;bar;
-new.ignore=
-search.exclude_tags=baz;
-maildir.synchronize_flags=true
-built_with.compact=something
-built_with.field_processor=something
-built_with.retry_lock=something"
+expected_dir=$NOTMUCH_SRCDIR/test/setup.expected-output
+test_expect_equal_file ${expected_dir}/config-with-comments new-notmuch-config
 
 test_begin_subtest "notmuch with a config but without a database suggests notmuch new"
 notmuch 2>&1 | notmuch_dir_sanitize > OUTPUT
diff --git a/test/setup.expected-output/config-with-comments b/test/setup.expected-output/config-with-comments
new file mode 100644
index 00000000..d9f796f2
--- /dev/null
+++ b/test/setup.expected-output/config-with-comments
@@ -0,0 +1,88 @@
+# .notmuch-config - Configuration file for the notmuch mail system
+#
+# For more information about notmuch, see https://notmuchmail.org
+
+# Database configuration
+#
+# The only value supported here is 'path' which should be the top-level
+# directory where your mail currently exists and to where mail will be
+# delivered in the future. Files should be individual email messages.
+# Notmuch will store its database within a sub-directory of the path
+# configured here named ".notmuch".
+#
+[database]
+path=/path/to/maildir
+
+# User configuration
+#
+# Here is where you can let notmuch know how you would like to be
+# addressed. Valid settings are
+#
+#	name		Your full name.
+#	primary_email	Your primary email address.
+#	other_email	A list (separated by ';') of other email addresses
+#			at which you receive email.
+#
+# Notmuch will use the various email addresses configured here when
+# formatting replies. It will avoid including your own addresses in the
+# recipient list of replies, and will set the From address based on the
+# address to which the original email was addressed.
+#
+[user]
+name=Test Suite
+primary_email=test.suite@example.com
+other_email=another.suite@example.com;
+
+# Configuration for "notmuch new"
+#
+# The following options are supported here:
+#
+#	tags	A list (separated by ';') of the tags that will be
+#		added to all messages incorporated by "notmuch new".
+#
+#	ignore	A list (separated by ';') of file and directory names
+#		that will not be searched for messages by "notmuch new".
+#
+#		NOTE: *Every* file/directory that goes by one of those
+#		names will be ignored, independent of its depth/location
+#		in the mail store.
+#
+[new]
+tags=foo;bar;
+ignore=
+
+# Search configuration
+#
+# The following option is supported here:
+#
+#	exclude_tags
+#		A ;-separated list of tags that will be excluded from
+#		search results by default.  Using an excluded tag in a
+#		query will override that exclusion.
+#
+[search]
+exclude_tags=baz;
+
+# Maildir compatibility configuration
+#
+# The following option is supported here:
+#
+#	synchronize_flags      Valid values are true and false.
+#
+#	If true, then the following maildir flags (in message filenames)
+#	will be synchronized with the corresponding notmuch tags:
+#
+#		Flag	Tag
+#		----	-------
+#		D	draft
+#		F	flagged
+#		P	passed
+#		R	replied
+#		S	unread (added when 'S' flag is not present)
+#
+#	The "notmuch new" command will notice flag changes in filenames
+#	and update tags, while the "notmuch tag" and "notmuch restore"
+#	commands will notice tag changes and update flags in filenames
+#
+[maildir]
+synchronize_flags=true
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 14/28] CLI/setup: switch to new configuration framework
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (12 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 13/28] test/setup: check file output instead of notmuch config list David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 15/28] CLI/config: switch "notmuch config list" to merged config David Bremner
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Most of the changes are the elimination of notmuch_config_t accessor
use. We also migrate some of the diagnostics to the top level where we
are opening the files in question.
---
 notmuch-setup.c | 51 +++++++++++++++++++++++--------------------------
 notmuch.c       | 21 ++++++++++++--------
 2 files changed, 37 insertions(+), 35 deletions(-)

diff --git a/notmuch-setup.c b/notmuch-setup.c
index 67214470..e9b81be8 100644
--- a/notmuch-setup.c
+++ b/notmuch-setup.c
@@ -88,14 +88,17 @@ welcome_message_post_setup (void)
 }
 
 static void
-print_tag_list (const char **tags, size_t tags_len)
+print_tag_list (notmuch_config_values_t *tags)
 {
-    unsigned int i;
+    bool first = false;
 
-    for (i = 0; i < tags_len; i++) {
-	if (i != 0)
+    for (;
+	 notmuch_config_values_valid (tags);
+	 notmuch_config_values_move_to_next (tags)) {
+	if (! first)
 	    printf (" ");
-	printf ("%s", tags[i]);
+	first = false;
+	printf ("%s", notmuch_config_values_get (tags));
     }
 }
 
@@ -122,19 +125,13 @@ parse_tag_list (void *ctx, char *response)
 
 int
 notmuch_setup_command (notmuch_config_t *config,
-		       unused(notmuch_database_t *notmuch),
+		       notmuch_database_t *notmuch,
 		       int argc, char *argv[])
 {
     char *response = NULL;
     size_t response_size = 0;
-    const char **old_other_emails;
-    size_t old_other_emails_len;
     GPtrArray *other_emails;
-    unsigned int i;
-    const char **new_tags;
-    size_t new_tags_len;
-    const char **search_exclude_tags;
-    size_t search_exclude_tags_len;
+    notmuch_config_values_t *new_tags, *search_exclude_tags, *emails;
 
 #define prompt(format, ...)                                     \
     do {                                                        \
@@ -157,26 +154,27 @@ notmuch_setup_command (notmuch_config_t *config,
     if (notmuch_config_is_new (config))
 	welcome_message_pre_setup ();
 
-    prompt ("Your full name [%s]: ", notmuch_config_get_user_name (config));
+    prompt ("Your full name [%s]: ", notmuch_config_get (notmuch, NOTMUCH_CONFIG_USER_NAME));
     if (strlen (response))
 	notmuch_config_set_user_name (config, response);
 
     prompt ("Your primary email address [%s]: ",
-	    notmuch_config_get_user_primary_email (config));
+	    notmuch_config_get (notmuch, NOTMUCH_CONFIG_PRIMARY_EMAIL));
     if (strlen (response))
 	notmuch_config_set_user_primary_email (config, response);
 
     other_emails = g_ptr_array_new ();
 
-    old_other_emails = notmuch_config_get_user_other_email (config,
-							    &old_other_emails_len);
-    for (i = 0; i < old_other_emails_len; i++) {
-	prompt ("Additional email address [%s]: ", old_other_emails[i]);
+    for (emails = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_OTHER_EMAIL);
+	 notmuch_config_values_valid (emails);
+	 notmuch_config_values_move_to_next (emails)) {
+	const char *email = notmuch_config_values_get (emails);
+
+	prompt ("Additional email address [%s]: ", email);
 	if (strlen (response))
 	    g_ptr_array_add (other_emails, talloc_strdup (config, response));
 	else
-	    g_ptr_array_add (other_emails, talloc_strdup (config,
-							  old_other_emails[i]));
+	    g_ptr_array_add (other_emails, talloc_strdup (config, email));
     }
 
     do {
@@ -192,7 +190,7 @@ notmuch_setup_command (notmuch_config_t *config,
     g_ptr_array_free (other_emails, true);
 
     prompt ("Top-level directory of your email archive [%s]: ",
-	    notmuch_config_get_database_path (config));
+	    notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH));
     if (strlen (response)) {
 	const char *absolute_path;
 
@@ -200,10 +198,10 @@ notmuch_setup_command (notmuch_config_t *config,
 	notmuch_config_set_database_path (config, absolute_path);
     }
 
-    new_tags = notmuch_config_get_new_tags (config, &new_tags_len);
+    new_tags = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_NEW_TAGS);
 
     printf ("Tags to apply to all new messages (separated by spaces) [");
-    print_tag_list (new_tags, new_tags_len);
+    print_tag_list (new_tags);
     prompt ("]: ");
 
     if (strlen (response)) {
@@ -215,11 +213,10 @@ notmuch_setup_command (notmuch_config_t *config,
 	g_ptr_array_free (tags, true);
     }
 
-
-    search_exclude_tags = notmuch_config_get_search_exclude_tags (config, &search_exclude_tags_len);
+    search_exclude_tags = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_EXCLUDE_TAGS);
 
     printf ("Tags to exclude when searching messages (separated by spaces) [");
-    print_tag_list (search_exclude_tags, search_exclude_tags_len);
+    print_tag_list (search_exclude_tags);
     prompt ("]: ");
 
     if (strlen (response)) {
diff --git a/notmuch.c b/notmuch.c
index 742544c2..0f387b00 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -141,9 +141,11 @@ notmuch_process_shared_indexing_options (notmuch_database_t *notmuch)
 
 
 static command_t commands[] = {
-    { NULL, notmuch_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_CREATE,
+    { NULL, notmuch_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_CREATE
+      | NOTMUCH_COMMAND_CONFIG_LOAD,
       "Notmuch main command." },
-    { "setup", notmuch_setup_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_CREATE,
+    { "setup", notmuch_setup_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_CREATE
+      | NOTMUCH_COMMAND_CONFIG_LOAD,
       "Interactively set up notmuch for first use." },
     { "new", notmuch_new_command,
       NOTMUCH_COMMAND_DATABASE_EARLY | NOTMUCH_COMMAND_DATABASE_WRITE |
@@ -375,7 +377,7 @@ notmuch_help_command (unused (notmuch_config_t *config), unused(notmuch_database
  */
 static int
 notmuch_command (notmuch_config_t *config,
-		 unused(notmuch_database_t *notmuch),
+		 notmuch_database_t *notmuch,
 		 unused(int argc), unused(char **argv))
 {
     char *db_path;
@@ -385,7 +387,7 @@ notmuch_command (notmuch_config_t *config,
      * notmuch_setup_command which will give a nice welcome message,
      * and interactively guide the user through the configuration. */
     if (notmuch_config_is_new (config))
-	return notmuch_setup_command (config, NULL, 0, NULL);
+	return notmuch_setup_command (config, notmuch, 0, NULL);
 
     /* Notmuch is already configured, but is there a database? */
     db_path = talloc_asprintf (config, "%s/%s",
@@ -569,14 +571,17 @@ main (int argc, char *argv[])
 					       NULL,
 					       &notmuch,
 					       &status_string);
-	if (status) {
+
+	if (status == NOTMUCH_STATUS_NO_CONFIG && ! (command->mode & NOTMUCH_COMMAND_CONFIG_CREATE)) {
+	    fputs ("Try running 'notmuch setup' to create a configuration.", stderr);
+	    goto DONE;
+	}
+
+	if (status && (status != NOTMUCH_STATUS_NO_CONFIG)) {
 	    if (status_string) {
 		fputs (status_string, stderr);
 		free (status_string);
 	    }
-
-	    if (status == NOTMUCH_STATUS_NO_CONFIG)
-		fputs ("Try running 'notmuch setup' to create a configuration.", stderr);
 	    goto DONE;
 	}
 
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 15/28] CLI/config: switch "notmuch config list" to merged config
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (13 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 14/28] CLI/setup: switch to new configuration framework David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 16/28] CLI/config: migrate notmuch_config_open to new config David Bremner
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Use the database opened at the top level rather than opening another
notmuch_database_t.

Test output changes because keys are now listed in alphabetical order,
and because a missing database is no longer an error.
---
 notmuch-config.c    | 69 ++++++++-------------------------------------
 test/T030-config.sh | 27 ++++++++----------
 2 files changed, 23 insertions(+), 73 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index 50008f78..ae315cb7 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -972,69 +972,22 @@ _notmuch_config_list_built_with ()
 }
 
 static int
-_list_db_config (notmuch_config_t *config)
+notmuch_config_command_list (notmuch_database_t *notmuch)
 {
-    notmuch_database_t *notmuch;
-    notmuch_config_list_t *list;
-
-    if (notmuch_database_open (notmuch_config_get_database_path (config),
-			       NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch))
-	return EXIT_FAILURE;
+    notmuch_config_pairs_t *list;
 
-    /* XXX Handle UUID mismatch? */
-
-
-    if (print_status_database ("notmuch config", notmuch,
-			       notmuch_database_get_config_list (notmuch, "", &list)))
-	return EXIT_FAILURE;
-
-    for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
-	printf ("%s=%s\n", notmuch_config_list_key (list), notmuch_config_list_value (list));
+    _notmuch_config_list_built_with ();
+    for (list = notmuch_config_get_pairs (notmuch, "");
+	 notmuch_config_pairs_valid (list);
+	 notmuch_config_pairs_move_to_next (list)) {
+	const char *value = notmuch_config_pairs_value (list);
+	if (value)
+	    printf ("%s=%s\n", notmuch_config_pairs_key (list), value);
     }
-    notmuch_config_list_destroy (list);
-
+    notmuch_config_pairs_destroy (list);
     return EXIT_SUCCESS;
 }
 
-static int
-notmuch_config_command_list (notmuch_config_t *config)
-{
-    char **groups;
-    size_t g, groups_length;
-
-    groups = g_key_file_get_groups (config->key_file, &groups_length);
-    if (groups == NULL)
-	return 1;
-
-    for (g = 0; g < groups_length; g++) {
-	char **keys;
-	size_t k, keys_length;
-
-	keys = g_key_file_get_keys (config->key_file,
-				    groups[g], &keys_length, NULL);
-	if (keys == NULL)
-	    continue;
-
-	for (k = 0; k < keys_length; k++) {
-	    char *value;
-
-	    value = g_key_file_get_string (config->key_file,
-					   groups[g], keys[k], NULL);
-	    if (value != NULL) {
-		printf ("%s.%s=%s\n", groups[g], keys[k], value);
-		free (value);
-	    }
-	}
-
-	g_strfreev (keys);
-    }
-
-    g_strfreev (groups);
-
-    _notmuch_config_list_built_with ();
-    return _list_db_config (config);
-}
-
 int
 notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
 			int argc, char *argv[])
@@ -1074,7 +1027,7 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
 	}
 	ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
     } else if (strcmp (argv[0], "list") == 0) {
-	ret = notmuch_config_command_list (config);
+	ret = notmuch_config_command_list (notmuch);
     } else {
 	fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
 		 argv[0]);
diff --git a/test/T030-config.sh b/test/T030-config.sh
index ba29cbac..ffbd7681 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -46,25 +46,22 @@ notmuch config set foo.nonexistent
 test_expect_equal "$(notmuch config get foo.nonexistent)" ""
 
 test_begin_subtest "List all items"
-notmuch config list > STDOUT 2> STDERR
-printf "%s\n====\n%s\n" "$(< STDOUT)" "$(< STDERR)" | notmuch_config_sanitize > OUTPUT
-
+notmuch config list 2>&1 | notmuch_config_sanitize > OUTPUT
 cat <<EOF > EXPECTED
-database.path=MAIL_DIR
-user.name=Notmuch Test Suite
-user.primary_email=test_suite@notmuchmail.org
-user.other_email=test_suite_other@notmuchmail.org;test_suite@otherdomain.org
-new.tags=unread;inbox;
-new.ignore=
-search.exclude_tags=
-maildir.synchronize_flags=true
-foo.string=this is another string value
-foo.list=this;is another;list value;
 built_with.compact=something
 built_with.field_processor=something
 built_with.retry_lock=something
-====
-Error: Cannot open database at MAIL_DIR/.notmuch: No such file or directory.
+database.mail_root=MAIL_DIR
+database.path=MAIL_DIR
+foo.list=this;is another;list value;
+foo.string=this is another string value
+maildir.synchronize_flags=true
+new.ignore=
+new.tags=unread;inbox;
+search.exclude_tags=
+user.name=Notmuch Test Suite
+user.other_email=test_suite_other@notmuchmail.org;test_suite@otherdomain.org
+user.primary_email=test_suite@notmuchmail.org
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 16/28] CLI/config: migrate notmuch_config_open to new config
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (14 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 15/28] CLI/config: switch "notmuch config list" to merged config David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 17/28] CLI/config: use notmuch_database_reopen David Bremner
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

notmuch_config_open will be preserved in the medium term for use by
the commands that are manipulating the config file directly (config
and setup)
---
 lib/config.cc                                 |   5 +-
 notmuch-client.h                              |   2 +-
 notmuch-config.c                              | 371 +++++-------------
 notmuch.c                                     |   2 +-
 test/T030-config.sh                           |   2 +-
 test/T590-libconfig.sh                        |  12 +-
 .../config-with-comments                      |   2 -
 7 files changed, 106 insertions(+), 290 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 36f242f2..26280842 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -598,7 +598,7 @@ _notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key)
     case NOTMUCH_CONFIG_EXCLUDE_TAGS:
 	return "";
     case NOTMUCH_CONFIG_NEW_TAGS:
-	return "inbox;unread";
+	return "unread;inbox";
     case NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS:
 	return "true";
     case NOTMUCH_CONFIG_USER_NAME:
@@ -615,9 +615,10 @@ _notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key)
 	else
 	    email = _get_email_from_passwd_file (notmuch);
 	return email;
+    case NOTMUCH_CONFIG_NEW_IGNORE:
+	return "";
     case NOTMUCH_CONFIG_HOOK_DIR:
     case NOTMUCH_CONFIG_BACKUP_DIR:
-    case NOTMUCH_CONFIG_NEW_IGNORE:
     case NOTMUCH_CONFIG_OTHER_EMAIL:
 	return NULL;
     default:
diff --git a/notmuch-client.h b/notmuch-client.h
index b560e3ed..7911c20c 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -276,7 +276,7 @@ typedef enum {
 } notmuch_command_mode_t;
 
 notmuch_config_t *
-notmuch_config_open (void *ctx,
+notmuch_config_open (notmuch_database_t *notmuch,
 		     const char *filename,
 		     notmuch_command_mode_t config_mode);
 
diff --git a/notmuch-config.c b/notmuch-config.c
index ae315cb7..0c618d51 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -31,87 +31,88 @@ static const char toplevel_config_comment[] =
     "\n"
     " For more information about notmuch, see https://notmuchmail.org";
 
-static const char database_config_comment[] =
-    " Database configuration\n"
-    "\n"
-    " The only value supported here is 'path' which should be the top-level\n"
-    " directory where your mail currently exists and to where mail will be\n"
-    " delivered in the future. Files should be individual email messages.\n"
-    " Notmuch will store its database within a sub-directory of the path\n"
-    " configured here named \".notmuch\".\n";
-
-static const char new_config_comment[] =
-    " Configuration for \"notmuch new\"\n"
-    "\n"
-    " The following options are supported here:\n"
-    "\n"
-    "\ttags	A list (separated by ';') of the tags that will be\n"
-    "\t	added to all messages incorporated by \"notmuch new\".\n"
-    "\n"
-    "\tignore	A list (separated by ';') of file and directory names\n"
-    "\t	that will not be searched for messages by \"notmuch new\".\n"
-    "\n"
-    "\t	NOTE: *Every* file/directory that goes by one of those\n"
-    "\t	names will be ignored, independent of its depth/location\n"
-    "\t	in the mail store.\n";
-
-static const char user_config_comment[] =
-    " User configuration\n"
-    "\n"
-    " Here is where you can let notmuch know how you would like to be\n"
-    " addressed. Valid settings are\n"
-    "\n"
-    "\tname		Your full name.\n"
-    "\tprimary_email	Your primary email address.\n"
-    "\tother_email	A list (separated by ';') of other email addresses\n"
-    "\t		at which you receive email.\n"
-    "\n"
-    " Notmuch will use the various email addresses configured here when\n"
-    " formatting replies. It will avoid including your own addresses in the\n"
-    " recipient list of replies, and will set the From address based on the\n"
-    " address to which the original email was addressed.\n";
-
-static const char maildir_config_comment[] =
-    " Maildir compatibility configuration\n"
-    "\n"
-    " The following option is supported here:\n"
-    "\n"
-    "\tsynchronize_flags      Valid values are true and false.\n"
-    "\n"
-    "\tIf true, then the following maildir flags (in message filenames)\n"
-    "\twill be synchronized with the corresponding notmuch tags:\n"
-    "\n"
-    "\t\tFlag	Tag\n"
-    "\t\t----	-------\n"
-    "\t\tD	draft\n"
-    "\t\tF	flagged\n"
-    "\t\tP	passed\n"
-    "\t\tR	replied\n"
-    "\t\tS	unread (added when 'S' flag is not present)\n"
-    "\n"
-    "\tThe \"notmuch new\" command will notice flag changes in filenames\n"
-    "\tand update tags, while the \"notmuch tag\" and \"notmuch restore\"\n"
-    "\tcommands will notice tag changes and update flags in filenames\n";
-
-static const char search_config_comment[] =
-    " Search configuration\n"
-    "\n"
-    " The following option is supported here:\n"
-    "\n"
-    "\texclude_tags\n"
-    "\t\tA ;-separated list of tags that will be excluded from\n"
-    "\t\tsearch results by default.  Using an excluded tag in a\n"
-    "\t\tquery will override that exclusion.\n";
-
-static const char crypto_config_comment[] =
-    " Cryptography related configuration\n"
-    "\n"
-    " The following old option is now ignored:\n"
-    "\n"
-    "\tgpgpath\n"
-    "\t\tThis option was used by older builds of notmuch to choose\n"
-    "\t\tthe version of gpg to use.\n"
-    "\t\tSetting $PATH is a better approach.\n";
+struct config_group {
+    const char *group_name;
+    const char *comment;
+} group_comment_table [] = {
+    {
+	"database",
+	" Database configuration\n"
+	"\n"
+	" The only value supported here is 'path' which should be the top-level\n"
+	" directory where your mail currently exists and to where mail will be\n"
+	" delivered in the future. Files should be individual email messages.\n"
+	" Notmuch will store its database within a sub-directory of the path\n"
+	" configured here named \".notmuch\".\n"
+    },
+    {
+	"user",
+	" User configuration\n"
+	"\n"
+	" Here is where you can let notmuch know how you would like to be\n"
+	" addressed. Valid settings are\n"
+	"\n"
+	"\tname		Your full name.\n"
+	"\tprimary_email	Your primary email address.\n"
+	"\tother_email	A list (separated by ';') of other email addresses\n"
+	"\t		at which you receive email.\n"
+	"\n"
+	" Notmuch will use the various email addresses configured here when\n"
+	" formatting replies. It will avoid including your own addresses in the\n"
+	" recipient list of replies, and will set the From address based on the\n"
+	" address to which the original email was addressed.\n"
+    },
+    {
+	"new",
+	" Configuration for \"notmuch new\"\n"
+	"\n"
+	" The following options are supported here:\n"
+	"\n"
+	"\ttags	A list (separated by ';') of the tags that will be\n"
+	"\t	added to all messages incorporated by \"notmuch new\".\n"
+	"\n"
+	"\tignore	A list (separated by ';') of file and directory names\n"
+	"\t	that will not be searched for messages by \"notmuch new\".\n"
+	"\n"
+	"\t	NOTE: *Every* file/directory that goes by one of those\n"
+	"\t	names will be ignored, independent of its depth/location\n"
+	"\t	in the mail store.\n"
+    },
+    {
+	"search",
+	" Search configuration\n"
+	"\n"
+	" The following option is supported here:\n"
+	"\n"
+	"\texclude_tags\n"
+	"\t\tA ;-separated list of tags that will be excluded from\n"
+	"\t\tsearch results by default.  Using an excluded tag in a\n"
+	"\t\tquery will override that exclusion.\n"
+    },
+    {
+	"maildir",
+	" Maildir compatibility configuration\n"
+	"\n"
+	" The following option is supported here:\n"
+	"\n"
+	"\tsynchronize_flags      Valid values are true and false.\n"
+	"\n"
+	"\tIf true, then the following maildir flags (in message filenames)\n"
+	"\twill be synchronized with the corresponding notmuch tags:\n"
+	"\n"
+	"\t\tFlag	Tag\n"
+	"\t\t----	-------\n"
+	"\t\tD	draft\n"
+	"\t\tF	flagged\n"
+	"\t\tP	passed\n"
+	"\t\tR	replied\n"
+	"\t\tS	unread (added when 'S' flag is not present)\n"
+	"\n"
+	"\tThe \"notmuch new\" command will notice flag changes in filenames\n"
+	"\tand update tags, while the \"notmuch tag\" and \"notmuch restore\"\n"
+	"\tcommands will notice tag changes and update flags in filenames\n"
+    },
+};
 
 struct _notmuch_config {
     char *filename;
@@ -141,69 +142,6 @@ notmuch_config_destructor (notmuch_config_t *config)
     return 0;
 }
 
-static char *
-get_name_from_passwd_file (void *ctx)
-{
-    long pw_buf_size;
-    char *pw_buf;
-    struct passwd passwd, *ignored;
-    char *name;
-    int e;
-
-    pw_buf_size = sysconf (_SC_GETPW_R_SIZE_MAX);
-    if (pw_buf_size == -1) pw_buf_size = 64;
-    pw_buf = talloc_size (ctx, pw_buf_size);
-
-    while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
-			    pw_buf_size, &ignored)) == ERANGE) {
-	pw_buf_size = pw_buf_size * 2;
-	pw_buf = talloc_zero_size (ctx, pw_buf_size);
-    }
-
-    if (e == 0) {
-	char *comma = strchr (passwd.pw_gecos, ',');
-	if (comma)
-	    name = talloc_strndup (ctx, passwd.pw_gecos,
-				   comma - passwd.pw_gecos);
-	else
-	    name = talloc_strdup (ctx, passwd.pw_gecos);
-    } else {
-	name = talloc_strdup (ctx, "");
-    }
-
-    talloc_free (pw_buf);
-
-    return name;
-}
-
-static char *
-get_username_from_passwd_file (void *ctx)
-{
-    long pw_buf_size;
-    char *pw_buf;
-    struct passwd passwd, *ignored;
-    char *name;
-    int e;
-
-    pw_buf_size = sysconf (_SC_GETPW_R_SIZE_MAX);
-    if (pw_buf_size == -1) pw_buf_size = 64;
-    pw_buf = talloc_zero_size (ctx, pw_buf_size);
-
-    while ((e = getpwuid_r (getuid (), &passwd, pw_buf,
-			    pw_buf_size, &ignored)) == ERANGE) {
-	pw_buf_size = pw_buf_size * 2;
-	pw_buf = talloc_zero_size (ctx, pw_buf_size);
-    }
-
-    if (e == 0)
-	name = talloc_strdup (ctx, passwd.pw_name);
-    else
-	name = talloc_strdup (ctx, "");
-
-    talloc_free (pw_buf);
-
-    return name;
-}
 
 static bool
 get_config_from_file (notmuch_config_t *config, bool create_new)
@@ -322,21 +260,13 @@ get_config_from_file (notmuch_config_t *config, bool create_new)
  *	user in editing the file directly.
  */
 notmuch_config_t *
-notmuch_config_open (void *ctx,
+notmuch_config_open (notmuch_database_t *notmuch,
 		     const char *filename,
 		     notmuch_command_mode_t config_mode)
 {
-    GError *error = NULL;
-    size_t tmp;
     char *notmuch_config_env = NULL;
-    int file_had_database_group;
-    int file_had_new_group;
-    int file_had_user_group;
-    int file_had_maildir_group;
-    int file_had_search_group;
-    int file_had_crypto_group;
 
-    notmuch_config_t *config = talloc_zero (ctx, notmuch_config_t);
+    notmuch_config_t *config = talloc_zero (notmuch, notmuch_config_t);
 
     if (config == NULL) {
 	fprintf (stderr, "Out of memory.\n");
@@ -368,133 +298,20 @@ notmuch_config_open (void *ctx,
 	}
     }
 
-    /* Whenever we know of configuration sections that don't appear in
-     * the configuration file, we add some comments to help the user
-     * understand what can be done.
-     *
-     * It would be convenient to just add those comments now, but
-     * apparently g_key_file will clear any comments when keys are
-     * added later that create the groups. So we have to check for the
-     * groups now, but add the comments only after setting all of our
-     * values.
-     */
-    file_had_database_group = g_key_file_has_group (config->key_file,
-						    "database");
-    file_had_new_group = g_key_file_has_group (config->key_file, "new");
-    file_had_user_group = g_key_file_has_group (config->key_file, "user");
-    file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir");
-    file_had_search_group = g_key_file_has_group (config->key_file, "search");
-    file_had_crypto_group = g_key_file_has_group (config->key_file, "crypto");
-
-    if (notmuch_config_get_database_path (config) == NULL) {
-	char *path = getenv ("MAILDIR");
-	if (path)
-	    path = talloc_strdup (config, path);
-	else
-	    path = talloc_asprintf (config, "%s/mail",
-				    getenv ("HOME"));
-	notmuch_config_set_database_path (config, path);
-	talloc_free (path);
-    }
-
-    if (notmuch_config_get_user_name (config) == NULL) {
-	char *name = getenv ("NAME");
-	if (name)
-	    name = talloc_strdup (config, name);
-	else
-	    name = get_name_from_passwd_file (config);
-	notmuch_config_set_user_name (config, name);
-	talloc_free (name);
-    }
-
-    if (notmuch_config_get_user_primary_email (config) == NULL) {
-	char *email = getenv ("EMAIL");
-	if (email) {
-	    notmuch_config_set_user_primary_email (config, email);
-	} else {
-	    char hostname[256];
-	    struct hostent *hostent;
-	    const char *domainname;
-
-	    char *username = get_username_from_passwd_file (config);
-
-	    gethostname (hostname, 256);
-	    hostname[255] = '\0';
-
-	    hostent = gethostbyname (hostname);
-	    if (hostent && (domainname = strchr (hostent->h_name, '.')))
-		domainname += 1;
-	    else
-		domainname = "(none)";
-
-	    email = talloc_asprintf (config, "%s@%s.%s",
-				     username, hostname, domainname);
-
-	    notmuch_config_set_user_primary_email (config, email);
-
-	    talloc_free (username);
-	    talloc_free (email);
-	}
-    }
-
-    if (notmuch_config_get_new_tags (config, &tmp) == NULL) {
-	const char *tags[] = { "unread", "inbox" };
-	notmuch_config_set_new_tags (config, tags, 2);
-    }
-
-    if (notmuch_config_get_new_ignore (config, &tmp) == NULL) {
-	notmuch_config_set_new_ignore (config, NULL, 0);
-    }
-
-    if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) {
-	if (config->is_new) {
-	    const char *tags[] = { "deleted", "spam" };
-	    notmuch_config_set_search_exclude_tags (config, tags, 2);
-	} else {
-	    notmuch_config_set_search_exclude_tags (config, NULL, 0);
-	}
-    }
-
-    error = NULL;
-    config->maildir_synchronize_flags =
-	g_key_file_get_boolean (config->key_file,
-				"maildir", "synchronize_flags", &error);
-    if (error) {
-	notmuch_config_set_maildir_synchronize_flags (config, true);
-	g_error_free (error);
-    }
-
-    /* Whenever we know of configuration sections that don't appear in
-     * the configuration file, we add some comments to help the user
-     * understand what can be done. */
     if (config->is_new)
 	g_key_file_set_comment (config->key_file, NULL, NULL,
 				toplevel_config_comment, NULL);
 
-    if (! file_had_database_group)
-	g_key_file_set_comment (config->key_file, "database", NULL,
-				database_config_comment, NULL);
-
-    if (! file_had_new_group)
-	g_key_file_set_comment (config->key_file, "new", NULL,
-				new_config_comment, NULL);
-
-    if (! file_had_user_group)
-	g_key_file_set_comment (config->key_file, "user", NULL,
-				user_config_comment, NULL);
-
-    if (! file_had_maildir_group)
-	g_key_file_set_comment (config->key_file, "maildir", NULL,
-				maildir_config_comment, NULL);
-
-    if (! file_had_search_group)
-	g_key_file_set_comment (config->key_file, "search", NULL,
-				search_config_comment, NULL);
-
-    if (! file_had_crypto_group)
-	g_key_file_set_comment (config->key_file, "crypto", NULL,
-				crypto_config_comment, NULL);
-
+    for (size_t i = 0; i < ARRAY_SIZE (group_comment_table); i++) {
+	const char *name = group_comment_table[i].group_name;
+	if (! g_key_file_has_group (config->key_file,  name)) {
+	    /* Force group to exist before adding comment */
+	    g_key_file_set_value (config->key_file, name, "dummy_key", "dummy_val");
+	    g_key_file_remove_key (config->key_file, name, "dummy_key", NULL);
+	    g_key_file_set_comment (config->key_file, name, NULL,
+				    group_comment_table[i].comment, NULL);
+	}
+    }
     return config;
 }
 
diff --git a/notmuch.c b/notmuch.c
index 0f387b00..4132e561 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -588,7 +588,7 @@ main (int argc, char *argv[])
     }
 
     if (command->mode & NOTMUCH_COMMAND_CONFIG_OPEN) {
-	config = notmuch_config_open (local, config_file_name, command->mode);
+	config = notmuch_config_open (notmuch, config_file_name, command->mode);
 	if (! config) {
 	    ret = EXIT_FAILURE;
 	    goto DONE;
diff --git a/test/T030-config.sh b/test/T030-config.sh
index ffbd7681..c87d35b6 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -57,7 +57,7 @@ foo.list=this;is another;list value;
 foo.string=this is another string value
 maildir.synchronize_flags=true
 new.ignore=
-new.tags=unread;inbox;
+new.tags=unread;inbox
 search.exclude_tags=
 user.name=Notmuch Test Suite
 user.other_email=test_suite_other@notmuchmail.org;test_suite@otherdomain.org
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 292778d5..51dd29c8 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -394,8 +394,8 @@ MAIL_DIR
 MAIL_DIR/.notmuch/hooks
 MAIL_DIR/.notmuch/backups
 
-inbox;unread
-NULL
+unread;inbox
+
 true
 USERNAME@FQDN
 NULL
@@ -705,7 +705,7 @@ MAIL_DIR
 MAIL_DIR/.notmuch/hooks
 MAIL_DIR/.notmuch/backups
 foo;bar;fub
-unread;inbox;
+unread;inbox
 sekrit_junk
 true
 test_suite@notmuchmail.org
@@ -736,8 +736,8 @@ MAIL_DIR
 MAIL_DIR/.notmuch/hooks
 MAIL_DIR/.notmuch/backups
 
-inbox;unread
-NULL
+unread;inbox
+
 true
 USERNAME@FQDN
 NULL
@@ -815,7 +815,7 @@ database.path MAIL_DIR
 key with spaces value, with, spaces!
 maildir.synchronize_flags true
 new.ignore sekrit_junk
-new.tags unread;inbox;
+new.tags unread;inbox
 search.exclude_tags foo;bar;fub
 test.key1 testvalue1
 test.key2 testvalue2
diff --git a/test/setup.expected-output/config-with-comments b/test/setup.expected-output/config-with-comments
index d9f796f2..56c628e5 100644
--- a/test/setup.expected-output/config-with-comments
+++ b/test/setup.expected-output/config-with-comments
@@ -49,7 +49,6 @@ other_email=another.suite@example.com;
 #
 [new]
 tags=foo;bar;
-ignore=
 
 # Search configuration
 #
@@ -85,4 +84,3 @@ exclude_tags=baz;
 #	commands will notice tag changes and update flags in filenames
 #
 [maildir]
-synchronize_flags=true
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 17/28] CLI/config: use notmuch_database_reopen
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (15 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 16/28] CLI/config: migrate notmuch_config_open to new config David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 18/28] CLI/notmuch: switch notmuch_command to notmuch_config_get David Bremner
                   ` (11 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This allows `notmuch config` to use the common configuration
information carried by the notmuch_database_t opened at the top level.
---
 notmuch-config.c         | 17 ++++++++---------
 test/T750-user-header.sh |  3 ++-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index 0c618d51..2278ab2f 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -696,9 +696,8 @@ notmuch_config_command_get (notmuch_database_t *notmuch, char *item)
 }
 
 static int
-_set_db_config (notmuch_config_t *config, const char *key, int argc, char **argv)
+_set_db_config (notmuch_database_t *notmuch, const char *key, int argc, char **argv)
 {
-    notmuch_database_t *notmuch;
     const char *val = "";
 
     if (argc > 1) {
@@ -711,12 +710,11 @@ _set_db_config (notmuch_config_t *config, const char *key, int argc, char **argv
 	val = argv[0];
     }
 
-    if (notmuch_database_open (notmuch_config_get_database_path (config),
-			       NOTMUCH_DATABASE_MODE_READ_WRITE, &notmuch))
+    if (print_status_database ("notmuch config", notmuch,
+			       notmuch_database_reopen (notmuch,
+							NOTMUCH_DATABASE_MODE_READ_WRITE)))
 	return EXIT_FAILURE;
 
-    /* XXX Handle UUID mismatch? */
-
     if (print_status_database ("notmuch config", notmuch,
 			       notmuch_database_set_config (notmuch, key, val)))
 	return EXIT_FAILURE;
@@ -729,7 +727,8 @@ _set_db_config (notmuch_config_t *config, const char *key, int argc, char **argv
 }
 
 static int
-notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
+notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuch, char *item,
+			    int argc, char *argv[])
 {
     char *group, *key;
     config_key_info_t *key_info;
@@ -744,7 +743,7 @@ notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char
 	return 1;
 
     if (key_info && key_info->in_db) {
-	return _set_db_config (config, item, argc, argv);
+	return _set_db_config (notmuch, item, argc, argv);
     }
 
     if (_item_split (item, &group, &key))
@@ -842,7 +841,7 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
 		     "one argument.\n");
 	    return EXIT_FAILURE;
 	}
-	ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
+	ret = notmuch_config_command_set (config, notmuch, argv[1], argc - 2, argv + 2);
     } else if (strcmp (argv[0], "list") == 0) {
 	ret = notmuch_config_command_list (notmuch);
     } else {
diff --git a/test/T750-user-header.sh b/test/T750-user-header.sh
index b19db571..586788b3 100755
--- a/test/T750-user-header.sh
+++ b/test/T750-user-header.sh
@@ -5,7 +5,8 @@ test_description='indexing user specified headers'
 test_begin_subtest "error adding user header before initializing DB"
 notmuch config set index.header.List List-Id 2>&1 | notmuch_dir_sanitize > OUTPUT
 cat <<EOF > EXPECTED
-Error: Cannot open database at MAIL_DIR/.notmuch: No such file or directory.
+notmuch config: Illegal argument for function
+Cannot reopen closed or nonexistent database
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 18/28] CLI/notmuch: switch notmuch_command to notmuch_config_get
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (16 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 17/28] CLI/config: use notmuch_database_reopen David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 19/28] CLI/config: drop obsolete notmuch_config_get_* David Bremner
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

The goal at this point is to remove the dependence on
notmuch_config_get_* without breaking any existing functionality. This
is a step towards removing notmuch_config_get_* in a future commit.
---
 notmuch.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/notmuch.c b/notmuch.c
index 4132e561..ff9ad18b 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -391,7 +391,7 @@ notmuch_command (notmuch_config_t *config,
 
     /* Notmuch is already configured, but is there a database? */
     db_path = talloc_asprintf (config, "%s/%s",
-			       notmuch_config_get_database_path (config),
+			       notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH),
 			       ".notmuch");
     if (stat (db_path, &st)) {
 	if (errno != ENOENT) {
@@ -422,8 +422,8 @@ notmuch_command (notmuch_config_t *config,
 	    "or any other interface described at https://notmuchmail.org\n\n"
 	    "And don't forget to run \"notmuch new\" whenever new mail arrives.\n\n"
 	    "Have fun, and may your inbox never have much mail.\n\n",
-	    notmuch_config_get_user_name (config),
-	    notmuch_config_get_user_primary_email (config));
+	    notmuch_config_get (notmuch, NOTMUCH_CONFIG_USER_NAME),
+	    notmuch_config_get (notmuch, NOTMUCH_CONFIG_PRIMARY_EMAIL));
 
     return EXIT_SUCCESS;
 }
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 19/28] CLI/config: drop obsolete notmuch_config_get_*
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (17 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 18/28] CLI/notmuch: switch notmuch_command to notmuch_config_get David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 20/28] CLI/config: drop cached data from notmuch_config_t David Bremner
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

These are no longer used, replaced by notmuch_config_get.
---
 notmuch-client.h |  29 ------------
 notmuch-config.c | 121 -----------------------------------------------
 2 files changed, 150 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index 7911c20c..a1d8dfe9 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -289,70 +289,41 @@ notmuch_config_save (notmuch_config_t *config);
 bool
 notmuch_config_is_new (notmuch_config_t *config);
 
-const char *
-notmuch_config_get_database_path (notmuch_config_t *config);
-
 void
 notmuch_config_set_database_path (notmuch_config_t *config,
 				  const char *database_path);
 
-const char *
-notmuch_config_get_user_name (notmuch_config_t *config);
-
 void
 notmuch_config_set_user_name (notmuch_config_t *config,
 			      const char *user_name);
 
-const char *
-notmuch_config_get_user_primary_email (notmuch_config_t *config);
-
 void
 notmuch_config_set_user_primary_email (notmuch_config_t *config,
 				       const char *primary_email);
 
-const char **
-notmuch_config_get_user_other_email (notmuch_config_t *config,
-				     size_t *length);
-
 void
 notmuch_config_set_user_other_email (notmuch_config_t *config,
 				     const char *other_email[],
 				     size_t length);
 
-const char **
-notmuch_config_get_new_tags (notmuch_config_t *config,
-			     size_t *length);
 void
 notmuch_config_set_new_tags (notmuch_config_t *config,
 			     const char *new_tags[],
 			     size_t length);
 
-const char **
-notmuch_config_get_new_ignore (notmuch_config_t *config,
-			       size_t *length);
-
 void
 notmuch_config_set_new_ignore (notmuch_config_t *config,
 			       const char *new_ignore[],
 			       size_t length);
 
-bool
-notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config);
-
 void
 notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
 					      bool synchronize_flags);
 
-const char **
-notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length);
-
 void
 notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
 					const char *list[],
 					size_t length);
-const char *
-_notmuch_config_get_path (notmuch_config_t *config);
-
 int
 notmuch_run_hook (notmuch_database_t *notmuch, const char *hook);
 
diff --git a/notmuch-config.c b/notmuch-config.c
index 2278ab2f..c13f0ecf 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -327,11 +327,6 @@ notmuch_config_close (notmuch_config_t *config)
     talloc_free (config);
 }
 
-const char *
-_notmuch_config_get_path (notmuch_config_t *config)
-{
-    return config->filename;
-}
 /* Save any changes made to the notmuch configuration.
  *
  * Any comments originally in the file will be preserved.
@@ -395,22 +390,6 @@ notmuch_config_is_new (notmuch_config_t *config)
     return config->is_new;
 }
 
-static const char *
-_config_get (notmuch_config_t *config, char **field,
-	     const char *group, const char *key)
-{
-    /* read from config file and cache value, if not cached already */
-    if (*field == NULL) {
-	char *value;
-	value = g_key_file_get_string (config->key_file, group, key, NULL);
-	if (value) {
-	    *field = talloc_strdup (config, value);
-	    free (value);
-	}
-    }
-    return *field;
-}
-
 static void
 _config_set (notmuch_config_t *config, char **field,
 	     const char *group, const char *key, const char *value)
@@ -422,38 +401,6 @@ _config_set (notmuch_config_t *config, char **field,
     *field = NULL;
 }
 
-static const char **
-_config_get_list (notmuch_config_t *config,
-		  const char *section, const char *key,
-		  const char ***outlist, size_t *list_length, size_t *ret_length)
-{
-    assert (outlist);
-
-    /* read from config file and cache value, if not cached already */
-    if (*outlist == NULL) {
-
-	char **inlist = g_key_file_get_string_list (config->key_file,
-						    section, key, list_length, NULL);
-	if (inlist) {
-	    unsigned int i;
-
-	    *outlist = talloc_size (config, sizeof (char *) * (*list_length + 1));
-
-	    for (i = 0; i < *list_length; i++)
-		(*outlist)[i] = talloc_strdup (*outlist, inlist[i]);
-
-	    (*outlist)[i] = NULL;
-
-	    g_strfreev (inlist);
-	}
-    }
-
-    if (ret_length)
-	*ret_length = *list_length;
-
-    return *outlist;
-}
-
 static void
 _config_set_list (notmuch_config_t *config,
 		  const char *group, const char *key,
@@ -467,24 +414,6 @@ _config_set_list (notmuch_config_t *config,
     *config_var = NULL;
 }
 
-const char *
-notmuch_config_get_database_path (notmuch_config_t *config)
-{
-    char *db_path = (char *) _config_get (config, &config->database_path, "database", "path");
-
-    if (db_path && *db_path != '/') {
-	/* If the path in the configuration file begins with any
-	 * character other than /, presume that it is relative to
-	 * $HOME and update as appropriate.
-	 */
-	char *abs_path = talloc_asprintf (config, "%s/%s", getenv ("HOME"), db_path);
-	talloc_free (db_path);
-	db_path = config->database_path = abs_path;
-    }
-
-    return db_path;
-}
-
 void
 notmuch_config_set_database_path (notmuch_config_t *config,
 				  const char *database_path)
@@ -492,12 +421,6 @@ notmuch_config_set_database_path (notmuch_config_t *config,
     _config_set (config, &config->database_path, "database", "path", database_path);
 }
 
-const char *
-notmuch_config_get_user_name (notmuch_config_t *config)
-{
-    return _config_get (config, &config->user_name, "user", "name");
-}
-
 void
 notmuch_config_set_user_name (notmuch_config_t *config,
 			      const char *user_name)
@@ -505,12 +428,6 @@ notmuch_config_set_user_name (notmuch_config_t *config,
     _config_set (config, &config->user_name, "user", "name", user_name);
 }
 
-const char *
-notmuch_config_get_user_primary_email (notmuch_config_t *config)
-{
-    return _config_get (config, &config->user_primary_email, "user", "primary_email");
-}
-
 void
 notmuch_config_set_user_primary_email (notmuch_config_t *config,
 				       const char *primary_email)
@@ -518,30 +435,6 @@ notmuch_config_set_user_primary_email (notmuch_config_t *config,
     _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
 }
 
-const char **
-notmuch_config_get_user_other_email (notmuch_config_t *config,   size_t *length)
-{
-    return _config_get_list (config, "user", "other_email",
-			     &(config->user_other_email),
-			     &(config->user_other_email_length), length);
-}
-
-const char **
-notmuch_config_get_new_tags (notmuch_config_t *config,   size_t *length)
-{
-    return _config_get_list (config, "new", "tags",
-			     &(config->new_tags),
-			     &(config->new_tags_length), length);
-}
-
-const char **
-notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length)
-{
-    return _config_get_list (config, "new", "ignore",
-			     &(config->new_ignore),
-			     &(config->new_ignore_length), length);
-}
-
 void
 notmuch_config_set_user_other_email (notmuch_config_t *config,
 				     const char *list[],
@@ -569,14 +462,6 @@ notmuch_config_set_new_ignore (notmuch_config_t *config,
 		      &(config->new_ignore));
 }
 
-const char **
-notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length)
-{
-    return _config_get_list (config, "search", "exclude_tags",
-			     &(config->search_exclude_tags),
-			     &(config->search_exclude_tags_length), length);
-}
-
 void
 notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
 					const char *list[],
@@ -854,12 +739,6 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
 
 }
 
-bool
-notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config)
-{
-    return config->maildir_synchronize_flags;
-}
-
 void
 notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
 					      bool synchronize_flags)
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 20/28] CLI/config: drop cached data from notmuch_config_t
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (18 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 19/28] CLI/config: drop obsolete notmuch_config_get_* David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 21/28] CLI/config: default to storing all config in external files David Bremner
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

The idea is to preserve notmuch_config_t as a thin wrapper for GKeyFile.
---
 notmuch-config.c | 48 +++++++++---------------------------------------
 1 file changed, 9 insertions(+), 39 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index c13f0ecf..24c16833 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -118,19 +118,6 @@ struct _notmuch_config {
     char *filename;
     GKeyFile *key_file;
     bool is_new;
-
-    char *database_path;
-    char *user_name;
-    char *user_primary_email;
-    const char **user_other_email;
-    size_t user_other_email_length;
-    const char **new_tags;
-    size_t new_tags_length;
-    const char **new_ignore;
-    size_t new_ignore_length;
-    bool maildir_synchronize_flags;
-    const char **search_exclude_tags;
-    size_t search_exclude_tags_length;
 };
 
 static int
@@ -142,7 +129,6 @@ notmuch_config_destructor (notmuch_config_t *config)
     return 0;
 }
 
-
 static bool
 get_config_from_file (notmuch_config_t *config, bool create_new)
 {
@@ -275,9 +261,6 @@ notmuch_config_open (notmuch_database_t *notmuch,
 
     talloc_set_destructor (config, notmuch_config_destructor);
 
-    /* non-zero defaults */
-    config->maildir_synchronize_flags = true;
-
     if (filename) {
 	config->filename = talloc_strdup (config, filename);
     } else if ((notmuch_config_env = getenv ("NOTMUCH_CONFIG"))) {
@@ -391,48 +374,40 @@ notmuch_config_is_new (notmuch_config_t *config)
 }
 
 static void
-_config_set (notmuch_config_t *config, char **field,
+_config_set (notmuch_config_t *config,
 	     const char *group, const char *key, const char *value)
 {
     g_key_file_set_string (config->key_file, group, key, value);
-
-    /* drop the cached value */
-    talloc_free (*field);
-    *field = NULL;
 }
 
 static void
 _config_set_list (notmuch_config_t *config,
 		  const char *group, const char *key,
 		  const char *list[],
-		  size_t length, const char ***config_var )
+		  size_t length)
 {
     g_key_file_set_string_list (config->key_file, group, key, list, length);
-
-    /* drop the cached value */
-    talloc_free (*config_var);
-    *config_var = NULL;
 }
 
 void
 notmuch_config_set_database_path (notmuch_config_t *config,
 				  const char *database_path)
 {
-    _config_set (config, &config->database_path, "database", "path", database_path);
+    _config_set (config, "database", "path", database_path);
 }
 
 void
 notmuch_config_set_user_name (notmuch_config_t *config,
 			      const char *user_name)
 {
-    _config_set (config, &config->user_name, "user", "name", user_name);
+    _config_set (config, "user", "name", user_name);
 }
 
 void
 notmuch_config_set_user_primary_email (notmuch_config_t *config,
 				       const char *primary_email)
 {
-    _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
+    _config_set (config, "user", "primary_email", primary_email);
 }
 
 void
@@ -440,8 +415,7 @@ notmuch_config_set_user_other_email (notmuch_config_t *config,
 				     const char *list[],
 				     size_t length)
 {
-    _config_set_list (config, "user", "other_email", list, length,
-		      &(config->user_other_email));
+    _config_set_list (config, "user", "other_email", list, length);
 }
 
 void
@@ -449,8 +423,7 @@ notmuch_config_set_new_tags (notmuch_config_t *config,
 			     const char *list[],
 			     size_t length)
 {
-    _config_set_list (config, "new", "tags", list, length,
-		      &(config->new_tags));
+    _config_set_list (config, "new", "tags", list, length);
 }
 
 void
@@ -458,8 +431,7 @@ notmuch_config_set_new_ignore (notmuch_config_t *config,
 			       const char *list[],
 			       size_t length)
 {
-    _config_set_list (config, "new", "ignore", list, length,
-		      &(config->new_ignore));
+    _config_set_list (config, "new", "ignore", list, length);
 }
 
 void
@@ -467,8 +439,7 @@ notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
 					const char *list[],
 					size_t length)
 {
-    _config_set_list (config, "search", "exclude_tags", list, length,
-		      &(config->search_exclude_tags));
+    _config_set_list (config, "search", "exclude_tags", list, length);
 }
 
 
@@ -745,5 +716,4 @@ notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
 {
     g_key_file_set_boolean (config->key_file,
 			    "maildir", "synchronize_flags", synchronize_flags);
-    config->maildir_synchronize_flags = synchronize_flags;
 }
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 21/28] CLI/config: default to storing all config in external files
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (19 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 20/28] CLI/config: drop cached data from notmuch_config_t David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 22/28] lib: add NOTMUCH_STATUS_NO_DATABASE David Bremner
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Previously the fact that some configuration options were only stored
in the database (and thus editing the config file had no effect) was a
source of user confusion. This was fixed with the series ending at
d9af0af1646.

On the other hand, the underlying partition of config options into
those stored by default in the database and those stored in the config
file remained. This is also confusing, since now some invocations of
"notmuch config set" modify the config file, and others silently
modify the database instead.

With this commit, it is up to the user to decide which configuration
to modify. A new "--database" option is provided for notmuch config to
enable modifying the configuration information in the database;
otherwise the default is to update an external config file.
---
 doc/man1/notmuch-config.rst |  6 +++++-
 doc/man1/notmuch.rst        |  4 +++-
 notmuch-config.c            | 43 ++++++++++++++++++++++++++-----------
 test/T030-config.sh         | 20 +++++++++++++++++
 test/T600-named-queries.sh  | 17 ++++++---------
 test/T750-user-header.sh    |  8 -------
 6 files changed, 66 insertions(+), 32 deletions(-)

diff --git a/doc/man1/notmuch-config.rst b/doc/man1/notmuch-config.rst
index 223d2de5..32290a38 100644
--- a/doc/man1/notmuch-config.rst
+++ b/doc/man1/notmuch-config.rst
@@ -7,7 +7,7 @@ SYNOPSIS
 
 **notmuch** **config** **get** <*section*>.<*item*>
 
-**notmuch** **config** **set** <*section*>.<*item*> [*value* ...]
+**notmuch** **config** **set** [--database] <*section*>.<*item*> [*value* ...]
 
 **notmuch** **config** **list**
 
@@ -30,6 +30,10 @@ configuration file and corresponding database.
     If no values are provided, the specified configuration item will
     be removed from the configuration file.
 
+    With the `--database` option, updates configuration metadata
+    stored in the database, rather than the default (text)
+    configuration file.
+
 **list**
     Every configuration item is printed to stdout, each on a separate
     line of the form::
diff --git a/doc/man1/notmuch.rst b/doc/man1/notmuch.rst
index fecfd08a..48351588 100644
--- a/doc/man1/notmuch.rst
+++ b/doc/man1/notmuch.rst
@@ -48,7 +48,9 @@ Supported global options for ``notmuch`` include
 
 ``--config=FILE``
     Specify the configuration file to use. This overrides any
-    configuration file specified by ${NOTMUCH\_CONFIG}.
+    configuration file specified by ${NOTMUCH\_CONFIG}. The empty
+    string is a permitted and sometimes useful value of *FILE*, which
+    tells ``notmuch`` to use only configuration metadata from the database.
 
 ``--uuid=HEX``
     Enforce that the database UUID (a unique identifier which persists
diff --git a/notmuch-config.c b/notmuch-config.c
index 24c16833..c4283576 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -511,16 +511,15 @@ validate_field_name (const char *str)
 
 typedef struct config_key {
     const char *name;
-    bool in_db;
     bool prefix;
     bool (*validate)(const char *);
 } config_key_info_t;
 
 static struct config_key
     config_key_table[] = {
-    { "index.decrypt",   true,   false,  NULL },
-    { "index.header.",   true,   true,   validate_field_name },
-    { "query.",          true,   true,   NULL },
+    { "index.decrypt",   false,  NULL },
+    { "index.header.",   true,   validate_field_name },
+    { "query.",          true,   NULL },
 };
 
 static config_key_info_t *
@@ -583,11 +582,36 @@ _set_db_config (notmuch_database_t *notmuch, const char *key, int argc, char **a
 }
 
 static int
-notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuch, char *item,
+notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuch,
 			    int argc, char *argv[])
 {
     char *group, *key;
     config_key_info_t *key_info;
+    bool update_database = false;
+    int opt_index;
+    char *item;
+
+    notmuch_opt_desc_t options[] = {
+	{ .opt_bool = &update_database, .name = "database" },
+	{ }
+    };
+
+    opt_index = parse_arguments (argc, argv, options, 1);
+    if (opt_index < 0)
+	return EXIT_FAILURE;
+
+    argc -= opt_index;
+    argv += opt_index;
+
+    if (argc < 1) {
+	fprintf (stderr, "Error: notmuch config set requires at least "
+		 "one argument.\n");
+	return EXIT_FAILURE;
+    }
+
+    item = argv[0];
+    argv++;
+    argc--;
 
     if (STRNCMP_LITERAL (item, BUILT_WITH_PREFIX) == 0) {
 	fprintf (stderr, "Error: read only option: %s\n", item);
@@ -598,7 +622,7 @@ notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuc
     if (key_info && key_info->validate && (! key_info->validate (item)))
 	return 1;
 
-    if (key_info && key_info->in_db) {
+    if (update_database) {
 	return _set_db_config (notmuch, item, argc, argv);
     }
 
@@ -692,12 +716,7 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
 	}
 	ret = notmuch_config_command_get (notmuch, argv[1]);
     } else if (strcmp (argv[0], "set") == 0) {
-	if (argc < 2) {
-	    fprintf (stderr, "Error: notmuch config set requires at least "
-		     "one argument.\n");
-	    return EXIT_FAILURE;
-	}
-	ret = notmuch_config_command_set (config, notmuch, argv[1], argc - 2, argv + 2);
+	ret = notmuch_config_command_set (config, notmuch, argc, argv);
     } else if (strcmp (argv[0], "list") == 0) {
 	ret = notmuch_config_command_list (notmuch);
     } else {
diff --git a/test/T030-config.sh b/test/T030-config.sh
index c87d35b6..b22d8f29 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -124,4 +124,24 @@ count=$(notmuch count '*')
 test_expect_equal "${path} ${count}" \
 		  "Maildir 52"
 
+test_begin_subtest "Add config to database"
+notmuch new
+key=g${RANDOM}.m${RANDOM}
+value=${RANDOM}
+notmuch config set --database ${key} ${value}
+notmuch dump --include=config > OUTPUT
+cat <<EOF > EXPECTED
+#notmuch-dump batch-tag:3 config
+#@ ${key} ${value}
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "Roundtrip config to/from database"
+notmuch new
+key=g${RANDOM}.m${RANDOM}
+value=${RANDOM}
+notmuch config set --database ${key} ${value}
+output=$(notmuch config get ${key})
+test_expect_equal "${output}" "${value}"
+
 test_done
diff --git a/test/T600-named-queries.sh b/test/T600-named-queries.sh
index 0ae8b83d..a7b84995 100755
--- a/test/T600-named-queries.sh
+++ b/test/T600-named-queries.sh
@@ -4,13 +4,13 @@ test_description='named queries'
 
 QUERYSTR="date:2009-11-18..2009-11-18 and tag:unread"
 
-test_begin_subtest "error adding named query before initializing DB"
-test_expect_code 1 "notmuch config set query.test \"$QUERYSTR\""
+test_begin_subtest "error adding named query to DB before initialization"
+test_expect_code 1 "notmuch config set --database query.test \"$QUERYSTR\""
 
 add_email_corpus
 
-test_begin_subtest "adding named query"
-test_expect_success "notmuch config set query.test \"$QUERYSTR\""
+test_begin_subtest "adding named query (database)"
+test_expect_success "notmuch config set --database query.test \"$QUERYSTR\""
 
 test_begin_subtest "adding nested named query"
 QUERYSTR2="query:test and subject:Maildir"
@@ -32,7 +32,6 @@ test_begin_subtest "dump named queries"
 notmuch dump | grep '^#@' > OUTPUT
 cat<<EOF > QUERIES.BEFORE
 #@ query.test date%3a2009-11-18..2009-11-18%20and%20tag%3aunread
-#@ query.test2 query%3atest%20and%20subject%3aMaildir
 EOF
 test_expect_equal_file QUERIES.BEFORE OUTPUT
 
@@ -40,23 +39,21 @@ test_begin_subtest 'dumping large queries'
 # This value is just large enough to trigger a limitation of gzprintf
 # to 8191 bytes in total (by default).
 repeat=1329
-notmuch config set query.big "$(seq -s' ' $repeat)"
+notmuch config set --database query.big "$(seq -s' ' $repeat)"
 notmuch dump --include=config > OUTPUT
-notmuch config set query.big ''
+notmuch config set --database query.big
 printf "#notmuch-dump batch-tag:3 config\n#@ query.big " > EXPECTED
 seq -s'%20' $repeat >> EXPECTED
 cat <<EOF >> EXPECTED
 #@ query.test date%3a2009-11-18..2009-11-18%20and%20tag%3aunread
-#@ query.test2 query%3atest%20and%20subject%3aMaildir
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
 test_begin_subtest "delete named queries"
 notmuch dump > BEFORE
-notmuch config set query.test
+notmuch config set --database query.test
 notmuch dump | grep '^#@' > OUTPUT
 cat<<EOF > EXPECTED
-#@ query.test2 query%3atest%20and%20subject%3aMaildir
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
diff --git a/test/T750-user-header.sh b/test/T750-user-header.sh
index 586788b3..05f80885 100755
--- a/test/T750-user-header.sh
+++ b/test/T750-user-header.sh
@@ -2,14 +2,6 @@
 test_description='indexing user specified headers'
 . $(dirname "$0")/test-lib.sh || exit 1
 
-test_begin_subtest "error adding user header before initializing DB"
-notmuch config set index.header.List List-Id 2>&1 | notmuch_dir_sanitize > OUTPUT
-cat <<EOF > EXPECTED
-notmuch config: Illegal argument for function
-Cannot reopen closed or nonexistent database
-EOF
-test_expect_equal_file EXPECTED OUTPUT
-
 add_email_corpus
 
 notmuch search '*' | notmuch_search_sanitize > initial-threads
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 22/28] lib: add NOTMUCH_STATUS_NO_DATABASE
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (20 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 21/28] CLI/config: default to storing all config in external files David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 23/28] CLI+lib: detect missing database in split configurations David Bremner
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This will allow more precise return values from various open related functions.
---
 bindings/python-cffi/notmuch2/_build.py  | 1 +
 bindings/python-cffi/notmuch2/_errors.py | 3 +++
 lib/database.cc                          | 2 ++
 lib/notmuch-private.h                    | 1 +
 lib/notmuch.h                            | 4 ++++
 5 files changed, 11 insertions(+)

diff --git a/bindings/python-cffi/notmuch2/_build.py b/bindings/python-cffi/notmuch2/_build.py
index f67b4de6..f712b6c5 100644
--- a/bindings/python-cffi/notmuch2/_build.py
+++ b/bindings/python-cffi/notmuch2/_build.py
@@ -51,6 +51,7 @@ ffibuilder.cdef(
         NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION,
         NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL,
         NOTMUCH_STATUS_NO_CONFIG,
+        NOTMUCH_STATUS_NO_DATABASE,
         NOTMUCH_STATUS_DATABASE_EXISTS,
         NOTMUCH_STATUS_LAST_STATUS
     } notmuch_status_t;
diff --git a/bindings/python-cffi/notmuch2/_errors.py b/bindings/python-cffi/notmuch2/_errors.py
index 65064d4e..9301073e 100644
--- a/bindings/python-cffi/notmuch2/_errors.py
+++ b/bindings/python-cffi/notmuch2/_errors.py
@@ -52,6 +52,8 @@ class NotmuchError(Exception):
                 IllegalArgumentError,
             capi.lib.NOTMUCH_STATUS_NO_CONFIG:
                 NoConfigError,
+            capi.lib.NOTMUCH_STATUS_NO_DATABASE:
+                NoDatabaseError,
             capi.lib.NOTMUCH_STATUS_DATABASE_EXISTS:
                 DatabaseExistsError,
         }
@@ -99,6 +101,7 @@ class UpgradeRequiredError(NotmuchError): pass
 class PathError(NotmuchError): pass
 class IllegalArgumentError(NotmuchError): pass
 class NoConfigError(NotmuchError): pass
+class NoDatabaseError(NotmuchError): pass
 class DatabaseExistsError(NotmuchError): pass
 
 class ObjectDestroyedError(NotmuchError):
diff --git a/lib/database.cc b/lib/database.cc
index d2ccdd58..96458f6f 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -305,6 +305,8 @@ notmuch_status_to_string (notmuch_status_t status)
 	return "Unknown crypto protocol";
     case NOTMUCH_STATUS_NO_CONFIG:
 	return "No configuration file found";
+    case NOTMUCH_STATUS_NO_DATABASE:
+	return "No database found";
     case NOTMUCH_STATUS_DATABASE_EXISTS:
 	return "Database exists, not recreated";
     default:
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 387f0c1e..10b1b024 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -142,6 +142,7 @@ typedef enum _notmuch_private_status {
     NOTMUCH_PRIVATE_STATUS_FAILED_CRYPTO_CONTEXT_CREATION	= NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION,
     NOTMUCH_PRIVATE_STATUS_UNKNOWN_CRYPTO_PROTOCOL		= NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL,
     NOTMUCH_PRIVATE_STATUS_NO_CONFIG				= NOTMUCH_STATUS_NO_CONFIG,
+    NOTMUCH_PRIVATE_STATUS_NO_DATABASE				= NOTMUCH_STATUS_NO_DATABASE,
     NOTMUCH_PRIVATE_STATUS_DATABASE_EXISTS			= NOTMUCH_STATUS_DATABASE_EXISTS,
 
     /* Then add our own private values. */
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 2a013be0..9ea05fc5 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -212,6 +212,10 @@ typedef enum _notmuch_status {
      * Unable to load a config file
      */
     NOTMUCH_STATUS_NO_CONFIG,
+    /**
+     * Unable to load a database
+     */
+    NOTMUCH_STATUS_NO_DATABASE,
     /**
      * Database exists, so not (re)-created
      */
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 23/28] CLI+lib: detect missing database in split configurations.
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (21 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 22/28] lib: add NOTMUCH_STATUS_NO_DATABASE David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 24/28] lib: provide notmuch_config_path David Bremner
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Eventually we want to do all opening of databases in the top
level (main function). This means that detection of missing databases
needs to move out of subcommands. It also requires updating the
library to use the new NO_DATABASE status code.
---
 lib/open.cc              | 24 +++++++++++++-------
 notmuch.c                | 47 +++++++++++++++++-----------------------
 test/T040-setup.sh       |  7 ++----
 test/T055-path-config.sh | 16 ++++++++++++++
 4 files changed, 54 insertions(+), 40 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index d0493950..387e4ddb 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -209,8 +209,8 @@ _choose_database_path (void *ctx,
     }
 
     if (*database_path == NULL) {
-	*message = strdup ("Error: Cannot open a database for a NULL path.\n");
-	return NOTMUCH_STATUS_NULL_POINTER;
+	*message = strdup ("Error: could not locate database.\n");
+	return NOTMUCH_STATUS_NO_DATABASE;
     }
 
     if (*database_path[0] != '/') {
@@ -750,12 +750,12 @@ _maybe_load_config_from_database (notmuch_database_t *notmuch,
     char *message; /* ignored */
 
     if (_db_dir_exists (database_path, &message))
-	return NOTMUCH_STATUS_SUCCESS;
+	return NOTMUCH_STATUS_NO_DATABASE;
 
     _set_database_path (notmuch, database_path);
 
     if (_notmuch_choose_xapian_path (notmuch, database_path, &notmuch->xapian_path, &message))
-	return NOTMUCH_STATUS_SUCCESS;
+	return NOTMUCH_STATUS_NO_DATABASE;
 
     (void) _finish_open (notmuch, profile, NOTMUCH_DATABASE_MODE_READ_ONLY, key_file, &message);
 
@@ -798,19 +798,27 @@ notmuch_database_load_config (const char *database_path,
     status = _choose_database_path (local, profile, key_file,
 				    &database_path, &split, &message);
     switch (status) {
-    /* weirdly NULL_POINTER is what is returned if we fail to find
-     * a database */
-    case NOTMUCH_STATUS_NULL_POINTER:
+    case NOTMUCH_STATUS_NO_DATABASE:
     case NOTMUCH_STATUS_SUCCESS:
+	if (! warning)
+	    warning = status;
 	break;
     default:
 	goto DONE;
     }
 
+
     if (database_path) {
 	status = _maybe_load_config_from_database (notmuch, key_file, database_path, profile);
-	if (status)
+	switch (status) {
+	case NOTMUCH_STATUS_NO_DATABASE:
+	case NOTMUCH_STATUS_SUCCESS:
+	    if (! warning)
+		warning = status;
+	    break;
+	default:
 	    goto DONE;
+	}
     }
 
     if (key_file) {
diff --git a/notmuch.c b/notmuch.c
index ff9ad18b..bcb4b768 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -380,34 +380,12 @@ notmuch_command (notmuch_config_t *config,
 		 notmuch_database_t *notmuch,
 		 unused(int argc), unused(char **argv))
 {
-    char *db_path;
-    struct stat st;
-
     /* If the user has never configured notmuch, then run
      * notmuch_setup_command which will give a nice welcome message,
      * and interactively guide the user through the configuration. */
     if (notmuch_config_is_new (config))
 	return notmuch_setup_command (config, notmuch, 0, NULL);
 
-    /* Notmuch is already configured, but is there a database? */
-    db_path = talloc_asprintf (config, "%s/%s",
-			       notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH),
-			       ".notmuch");
-    if (stat (db_path, &st)) {
-	if (errno != ENOENT) {
-	    fprintf (stderr, "Error looking for notmuch database at %s: %s\n",
-		     db_path, strerror (errno));
-	    return EXIT_FAILURE;
-	}
-	printf ("Notmuch is configured, but there's not yet a database at\n\n\t%s\n\n",
-		db_path);
-	printf ("You probably want to run \"notmuch new\" now to create that database.\n\n"
-		"Note that the first run of \"notmuch new\" can take a very long time\n"
-		"and that the resulting database will use roughly the same amount of\n"
-		"storage space as the email being indexed.\n\n");
-	return EXIT_SUCCESS;
-    }
-
     printf ("Notmuch is configured and appears to have a database. Excellent!\n\n"
 	    "At this point you can start exploring the functionality of notmuch by\n"
 	    "using commands such as:\n\n"
@@ -576,12 +554,27 @@ main (int argc, char *argv[])
 	    fputs ("Try running 'notmuch setup' to create a configuration.", stderr);
 	    goto DONE;
 	}
-
-	if (status && (status != NOTMUCH_STATUS_NO_CONFIG)) {
-	    if (status_string) {
-		fputs (status_string, stderr);
-		free (status_string);
+	switch (status) {
+	case NOTMUCH_STATUS_NO_CONFIG:
+	    if (! (command->mode & NOTMUCH_COMMAND_CONFIG_CREATE)) {
+		fputs ("Try running 'notmuch setup' to create a configuration.", stderr);
+		goto DONE;
+	    }
+	    break;
+	case NOTMUCH_STATUS_NO_DATABASE:
+	    if (! command_name) {
+		printf ("Notmuch is configured, but no database was found.\n");
+		printf ("You probably want to run \"notmuch new\" now to create a database.\n\n"
+			"Note that the first run of \"notmuch new\" can take a very long time\n"
+			"and that the resulting database will use roughly the same amount of\n"
+			"storage space as the email being indexed.\n\n");
+		status = NOTMUCH_STATUS_SUCCESS;
+		goto DONE;
 	    }
+	    break;
+	case NOTMUCH_STATUS_SUCCESS:
+	    break;
+	default:
 	    goto DONE;
 	}
 
diff --git a/test/T040-setup.sh b/test/T040-setup.sh
index daeca3e4..42c621c8 100755
--- a/test/T040-setup.sh
+++ b/test/T040-setup.sh
@@ -26,11 +26,8 @@ test_expect_equal_file ${expected_dir}/config-with-comments new-notmuch-config
 test_begin_subtest "notmuch with a config but without a database suggests notmuch new"
 notmuch 2>&1 | notmuch_dir_sanitize > OUTPUT
 cat <<EOF > EXPECTED
-Notmuch is configured, but there's not yet a database at
-
-	MAIL_DIR/.notmuch
-
-You probably want to run "notmuch new" now to create that database.
+Notmuch is configured, but no database was found.
+You probably want to run "notmuch new" now to create a database.
 
 Note that the first run of "notmuch new" can take a very long time
 and that the resulting database will use roughly the same amount of
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index d8828342..0a34e67f 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -199,6 +199,22 @@ EOF
 	"$output" \
 	"Welcome to a new version of notmuch! Your database will now be upgraded."
 
+    test_begin_subtest "notmuch +config -database suggests notmuch new ($config)"
+    mv "$XAPIAN_PATH" "${XAPIAN_PATH}.bak"
+    notmuch > OUTPUT
+cat <<EOF > EXPECTED
+Notmuch is configured, but no database was found.
+You probably want to run "notmuch new" now to create a database.
+
+Note that the first run of "notmuch new" can take a very long time
+and that the resulting database will use roughly the same amount of
+storage space as the email being indexed.
+
+EOF
+    mv "${XAPIAN_PATH}.bak" "$XAPIAN_PATH"
+
+   test_expect_equal_file EXPECTED OUTPUT
+
     restore_config
 done
 
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 24/28] lib: provide notmuch_config_path
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (22 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 23/28] CLI+lib: detect missing database in split configurations David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 25/28] CLI/config: support set/get with split configuration David Bremner
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Since the library searches in several locations for a config file, the
caller does not know which of these is chosen in the usual case of
passing NULL as a config file. This changes provides an API for the
caller to retrieve the name of the config file chosen. It will be
tested in a following commit.
---
 lib/config.cc          |  6 ++++++
 lib/database-private.h |  3 +++
 lib/notmuch.h          | 16 +++++++++++++++-
 lib/open.cc            | 28 +++++++++++++++++-----------
 4 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 26280842..7a0da971 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -654,6 +654,12 @@ notmuch_config_get (notmuch_database_t *notmuch, notmuch_config_key_t key)
     return _notmuch_string_map_get (notmuch->config, _notmuch_config_key_to_string (key));
 }
 
+const char *
+notmuch_config_path (notmuch_database_t *notmuch)
+{
+    return notmuch->config_path;
+}
+
 notmuch_status_t
 notmuch_config_set (notmuch_database_t *notmuch, notmuch_config_key_t key, const char *val)
 {
diff --git a/lib/database-private.h b/lib/database-private.h
index 2900382d..0d12ec1e 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -192,6 +192,9 @@ struct _notmuch_database {
     /* Path to actual database */
     const char *xapian_path;
 
+    /* Path to config loaded, if any */
+    const char *config_path;
+
     int atomic_nesting;
     /* true if changes have been made in this atomic section */
     bool atomic_dirty;
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 9ea05fc5..4b053932 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -454,7 +454,12 @@ notmuch_database_open_with_config (const char *database_path,
  *
  * For description of arguments, @see notmuch_database_open_with_config
  *
- * @retval NOTMUCH_STATUS_SUCCESS: Successfully loaded (some) configuration.
+ * @retval NOTMUCH_STATUS_SUCCESS: Successfully loaded configuration.
+ *
+ * @retval NOTMUCH_STATUS_NO_CONFIG: No config file was loaded. Not fatal.
+ *
+ * @retval NOTMUCH_STATUS_NO_DATABASE: No config information was
+ *	loaded from a database. Not fatal.
  *
  * @retval NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory.
  *
@@ -2737,6 +2742,15 @@ notmuch_status_t
 notmuch_config_get_bool (notmuch_database_t *notmuch,
 			 notmuch_config_key_t key,
 			 notmuch_bool_t *val);
+
+/**
+ * return the path of the config file loaded, if any
+ *
+ * @retval NULL if no config file was loaded
+ */
+const char *
+notmuch_config_path (notmuch_database_t *notmuch);
+
 /**
  * get the current default indexing options for a given database.
  *
diff --git a/lib/open.cc b/lib/open.cc
index 387e4ddb..5d80a884 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -113,12 +113,12 @@ _choose_dir (notmuch_database_t *notmuch,
 }
 
 static notmuch_status_t
-_load_key_file (const char *path,
+_load_key_file (notmuch_database_t *notmuch,
+		const char *path,
 		const char *profile,
 		GKeyFile **key_file)
 {
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
-    void *local = talloc_new (NULL);
 
     if (path && EMPTY_STRING (path))
 	goto DONE;
@@ -126,11 +126,13 @@ _load_key_file (const char *path,
     if (! path)
 	path = getenv ("NOTMUCH_CONFIG");
 
-    if (! path) {
-	const char *dir = _xdg_dir (local, "XDG_CONFIG_HOME", ".config", profile);
+    if (path)
+	path = talloc_strdup (notmuch, path);
+    else {
+	const char *dir = _xdg_dir (notmuch, "XDG_CONFIG_HOME", ".config", profile);
 
 	if (dir) {
-	    path = talloc_asprintf (local, "%s/config", dir);
+	    path = talloc_asprintf (notmuch, "%s/config", dir);
 	    if (access (path, R_OK) != 0)
 		path = NULL;
 	}
@@ -139,13 +141,13 @@ _load_key_file (const char *path,
     if (! path) {
 	const char *home = getenv ("HOME");
 
-	path = talloc_asprintf (local, "%s/.notmuch-config", home);
+	path = talloc_asprintf (notmuch, "%s/.notmuch-config", home);
 
 	if (! profile)
 	    profile = getenv ("NOTMUCH_PROFILE");
 
 	if (profile)
-	    path = talloc_asprintf (local, "%s.%s", path, profile);
+	    path = talloc_asprintf (notmuch, "%s.%s", path, profile);
     }
 
     *key_file = g_key_file_new ();
@@ -154,7 +156,9 @@ _load_key_file (const char *path,
     }
 
   DONE:
-    talloc_free (local);
+    if (path)
+	notmuch->config_path = path;
+
     return status;
 }
 
@@ -232,6 +236,7 @@ _alloc_notmuch ()
     notmuch->exception_reported = false;
     notmuch->status_string = NULL;
     notmuch->writable_xapian_db = NULL;
+    notmuch->config_path = NULL;
     notmuch->atomic_nesting = 0;
     notmuch->view = 1;
     return notmuch;
@@ -493,7 +498,7 @@ notmuch_database_open_with_config (const char *database_path,
 	goto DONE;
     }
 
-    status = _load_key_file (config_path, profile, &key_file);
+    status = _load_key_file (notmuch, config_path, profile, &key_file);
     if (status) {
 	message = strdup ("Error: cannot load config file.\n");
 	goto DONE;
@@ -590,7 +595,7 @@ notmuch_database_create_with_config (const char *database_path,
 	goto DONE;
     }
 
-    status = _load_key_file (config_path, profile, &key_file);
+    status = _load_key_file (notmuch, config_path, profile, &key_file);
     if (status) {
 	message = strdup ("Error: cannot load config file.\n");
 	goto DONE;
@@ -784,9 +789,10 @@ notmuch_database_load_config (const char *database_path,
 	goto DONE;
     }
 
-    status = _load_key_file (config_path, profile, &key_file);
+    status = _load_key_file (notmuch, config_path, profile, &key_file);
     switch (status) {
     case NOTMUCH_STATUS_SUCCESS:
+	break;
     case NOTMUCH_STATUS_NO_CONFIG:
 	warning = status;
 	break;
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 25/28] CLI/config: support set/get with split configuration
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (23 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 24/28] lib: provide notmuch_config_path David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 26/28] CLI/config: remove calls to notmuch_config_open from top level David Bremner
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

There are two small code changes. The main one is to retrieve the
possibly updated config file name found during the database opening
call. The second change is to allow empty config file names, as
a (currently broken) way of specifying that configuration should only
be taken from the database.
---
 notmuch.c                |  5 +++-
 test/T055-path-config.sh | 60 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/notmuch.c b/notmuch.c
index bcb4b768..61663908 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -454,7 +454,7 @@ main (int argc, char *argv[])
     int ret = EXIT_SUCCESS;
 
     notmuch_opt_desc_t options[] = {
-	{ .opt_string = &config_file_name, .name = "config" },
+	{ .opt_string = &config_file_name, .name = "config", .allow_empty = TRUE },
 	{ .opt_inherit = notmuch_shared_options },
 	{ }
     };
@@ -581,6 +581,9 @@ main (int argc, char *argv[])
     }
 
     if (command->mode & NOTMUCH_COMMAND_CONFIG_OPEN) {
+	if (! config_file_name)
+	    config_file_name = notmuch_config_path (notmuch);
+
 	config = notmuch_config_open (notmuch, config_file_name, command->mode);
 	if (! config) {
 	    ret = EXIT_FAILURE;
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index 0a34e67f..535c41e9 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -215,7 +215,65 @@ EOF
 
    test_expect_equal_file EXPECTED OUTPUT
 
-    restore_config
+   test_begin_subtest "Set config value ($config)"
+   name=${RANDOM}
+   value=${RANDOM}
+   notmuch config set test${test_count}.${name} ${value}
+   output=$(notmuch config get test${test_count}.${name})
+   notmuch config set test${test_count}.${name}
+   output2=$(notmuch config get test${test_count}.${name})
+   test_expect_equal "${output}+${output2}" "${value}+"
+
+   test_begin_subtest "Set config value in database ($config)"
+   name=${RANDOM}
+   value=${RANDOM}
+   notmuch config set --database test${test_count}.${name} ${value}
+   output=$(notmuch config get test${test_count}.${name})
+   notmuch config set --database test${test_count}.${name}
+   output2=$(notmuch config get test${test_count}.${name})
+   test_expect_equal "${output}+${output2}" "${value}+"
+
+   test_begin_subtest "Config list ($config)"
+   notmuch config list | notmuch_dir_sanitize | sed -e "s/^database.backup_dir=.*$/database.backup_dir/"  \
+						    -e "s/^database.hook_dir=.*$/database.hook_dir/" \
+						    -e "s/^database.path=.*$/database.path/" > OUTPUT
+   cat <<EOF > EXPECTED
+built_with.compact=true
+built_with.field_processor=true
+built_with.retry_lock=true
+database.backup_dir
+database.hook_dir
+database.mail_root=MAIL_DIR
+database.path
+maildir.synchronize_flags=true
+new.ignore=
+new.tags=unread;inbox
+search.exclude_tags=
+user.name=Notmuch Test Suite
+user.other_email=test_suite_other@notmuchmail.org;test_suite@otherdomain.org
+user.primary_email=test_suite@notmuchmail.org
+EOF
+   test_expect_equal_file EXPECTED OUTPUT
+
+   case $config in
+       XDG*)
+	   test_begin_subtest "Set shadowed config value in database ($config)"
+	   test_subtest_known_broken
+	   name=${RANDOM}
+	   value=${RANDOM}
+	   key=test${test_count}.${name}
+	   notmuch config set --database ${key}  ${value}
+	   notmuch config set ${key} shadow${value}
+	   output=$(notmuch --config='' config get ${key})
+	   notmuch config set --database ${key}
+	   output2=$(notmuch --config='' config get ${key})
+	   notmuch config set ${key}
+	   test_expect_equal "${output}+${output2}" "${value}+"
+	   ;;
+   esac
+   restore_config
+   rm -rf home/.local
+   rm -rf home/.config
 done
 
 test_done
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 26/28] CLI/config: remove calls to notmuch_config_open from top level
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (24 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 25/28] CLI/config: support set/get with split configuration David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 27/28] CLI: drop notmuch_config_t from subcommand interface David Bremner
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This will allow simplifying the subcommand interface.

Change the internal API to notmuch_config_open to not tie it to the
implementation of subcommands in notmuch.c.

It also fixes a previously broken test, since notmuch_config_open does
not understand the notion of the empty string as a config file name.
---
 notmuch-client.h         |  3 +--
 notmuch-config.c         | 28 +++++++++++++++++-----------
 notmuch-setup.c          | 11 ++++++++++-
 notmuch.c                | 40 ++++++++++++++++++----------------------
 test/T055-path-config.sh |  1 -
 5 files changed, 46 insertions(+), 37 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index a1d8dfe9..a5b3c518 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -267,7 +267,6 @@ json_quote_str (const void *ctx, const char *str);
 /* notmuch-config.c */
 
 typedef enum {
-    NOTMUCH_COMMAND_CONFIG_OPEN		= 1 << 0,
     NOTMUCH_COMMAND_CONFIG_CREATE	= 1 << 1,
     NOTMUCH_COMMAND_DATABASE_EARLY	= 1 << 2,
     NOTMUCH_COMMAND_DATABASE_WRITE	= 1 << 3,
@@ -278,7 +277,7 @@ typedef enum {
 notmuch_config_t *
 notmuch_config_open (notmuch_database_t *notmuch,
 		     const char *filename,
-		     notmuch_command_mode_t config_mode);
+		     bool create);
 
 void
 notmuch_config_close (notmuch_config_t *config);
diff --git a/notmuch-config.c b/notmuch-config.c
index c4283576..7aac8e94 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -248,7 +248,7 @@ get_config_from_file (notmuch_config_t *config, bool create_new)
 notmuch_config_t *
 notmuch_config_open (notmuch_database_t *notmuch,
 		     const char *filename,
-		     notmuch_command_mode_t config_mode)
+		     bool create)
 {
     char *notmuch_config_env = NULL;
 
@@ -272,13 +272,9 @@ notmuch_config_open (notmuch_database_t *notmuch,
 
     config->key_file = g_key_file_new ();
 
-    if (config_mode & NOTMUCH_COMMAND_CONFIG_OPEN) {
-	bool create_new = (config_mode & NOTMUCH_COMMAND_CONFIG_CREATE) != 0;
-
-	if (! get_config_from_file (config, create_new)) {
-	    talloc_free (config);
-	    return NULL;
-	}
+    if (! get_config_from_file (config, create)) {
+	talloc_free (config);
+	return NULL;
     }
 
     if (config->is_new)
@@ -582,13 +578,14 @@ _set_db_config (notmuch_database_t *notmuch, const char *key, int argc, char **a
 }
 
 static int
-notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuch,
+notmuch_config_command_set (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
 			    int argc, char *argv[])
 {
     char *group, *key;
     config_key_info_t *key_info;
+    notmuch_config_t *config;
     bool update_database = false;
-    int opt_index;
+    int opt_index, ret;
     char *item;
 
     notmuch_opt_desc_t options[] = {
@@ -629,6 +626,11 @@ notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuc
     if (_item_split (item, &group, &key))
 	return 1;
 
+    config = notmuch_config_open (notmuch,
+				  notmuch_config_path (notmuch), false);
+    if (! config)
+	return 1;
+
     /* With only the name of an item, we clear it from the
      * configuration file.
      *
@@ -649,7 +651,11 @@ notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuc
 	break;
     }
 
-    return notmuch_config_save (config);
+    ret = notmuch_config_save (config);
+
+    notmuch_config_close (config);
+
+    return ret;
 }
 
 static
diff --git a/notmuch-setup.c b/notmuch-setup.c
index e9b81be8..221ce934 100644
--- a/notmuch-setup.c
+++ b/notmuch-setup.c
@@ -124,7 +124,7 @@ parse_tag_list (void *ctx, char *response)
 }
 
 int
-notmuch_setup_command (notmuch_config_t *config,
+notmuch_setup_command (unused(notmuch_config_t *config),
 		       notmuch_database_t *notmuch,
 		       int argc, char *argv[])
 {
@@ -132,6 +132,7 @@ notmuch_setup_command (notmuch_config_t *config,
     size_t response_size = 0;
     GPtrArray *other_emails;
     notmuch_config_values_t *new_tags, *search_exclude_tags, *emails;
+    notmuch_config_t *config;
 
 #define prompt(format, ...)                                     \
     do {                                                        \
@@ -151,6 +152,11 @@ notmuch_setup_command (notmuch_config_t *config,
 	fprintf (stderr, "Warning: ignoring --uuid=%s\n",
 		 notmuch_requested_db_uuid);
 
+    config = notmuch_config_open (notmuch,
+				  notmuch_config_path (notmuch), true);
+    if (! config)
+	return EXIT_FAILURE;
+
     if (notmuch_config_is_new (config))
 	welcome_message_pre_setup ();
 
@@ -232,6 +238,9 @@ notmuch_setup_command (notmuch_config_t *config,
     if (notmuch_config_save (config))
 	return EXIT_FAILURE;
 
+    if (config)
+	notmuch_config_close (config);
+
     if (notmuch_config_is_new (config))
 	welcome_message_post_setup ();
 
diff --git a/notmuch.c b/notmuch.c
index 61663908..757d0eae 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -141,11 +141,9 @@ notmuch_process_shared_indexing_options (notmuch_database_t *notmuch)
 
 
 static command_t commands[] = {
-    { NULL, notmuch_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_CREATE
-      | NOTMUCH_COMMAND_CONFIG_LOAD,
+    { NULL, notmuch_command, NOTMUCH_COMMAND_CONFIG_CREATE | NOTMUCH_COMMAND_CONFIG_LOAD,
       "Notmuch main command." },
-    { "setup", notmuch_setup_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_CREATE
-      | NOTMUCH_COMMAND_CONFIG_LOAD,
+    { "setup", notmuch_setup_command, NOTMUCH_COMMAND_CONFIG_CREATE | NOTMUCH_COMMAND_CONFIG_LOAD,
       "Interactively set up notmuch for first use." },
     { "new", notmuch_new_command,
       NOTMUCH_COMMAND_DATABASE_EARLY | NOTMUCH_COMMAND_DATABASE_WRITE |
@@ -177,7 +175,7 @@ static command_t commands[] = {
     { "reindex", notmuch_reindex_command, NOTMUCH_COMMAND_DATABASE_EARLY |
       NOTMUCH_COMMAND_DATABASE_WRITE,
       "Re-index all messages matching the search terms." },
-    { "config", notmuch_config_command, NOTMUCH_COMMAND_CONFIG_OPEN | NOTMUCH_COMMAND_CONFIG_LOAD,
+    { "config", notmuch_config_command, NOTMUCH_COMMAND_CONFIG_LOAD,
       "Get or set settings in the notmuch configuration file." },
 #if WITH_EMACS
     { "emacs-mua", NULL, 0,
@@ -376,15 +374,26 @@ notmuch_help_command (unused (notmuch_config_t *config), unused(notmuch_database
  * to be more clever about this in the future.
  */
 static int
-notmuch_command (notmuch_config_t *config,
+notmuch_command (unused(notmuch_config_t *config),
 		 notmuch_database_t *notmuch,
 		 unused(int argc), unused(char **argv))
 {
-    /* If the user has never configured notmuch, then run
+
+    const char *config_path;
+
+    /* If the user has not created a configuration file, then run
      * notmuch_setup_command which will give a nice welcome message,
      * and interactively guide the user through the configuration. */
-    if (notmuch_config_is_new (config))
-	return notmuch_setup_command (config, notmuch, 0, NULL);
+    config_path = notmuch_config_path (notmuch);
+    if (access (config_path, R_OK | F_OK) == -1) {
+	if (errno != ENOENT) {
+	    fprintf (stderr, "Error: %s config file access failed: %s\n", config_path,
+		     strerror (errno));
+	    return EXIT_FAILURE;
+	} else {
+	    return notmuch_setup_command (NULL, notmuch, 0, NULL);
+	}
+    }
 
     printf ("Notmuch is configured and appears to have a database. Excellent!\n\n"
 	    "At this point you can start exploring the functionality of notmuch by\n"
@@ -580,22 +589,9 @@ main (int argc, char *argv[])
 
     }
 
-    if (command->mode & NOTMUCH_COMMAND_CONFIG_OPEN) {
-	if (! config_file_name)
-	    config_file_name = notmuch_config_path (notmuch);
-
-	config = notmuch_config_open (notmuch, config_file_name, command->mode);
-	if (! config) {
-	    ret = EXIT_FAILURE;
-	    goto DONE;
-	}
-    }
     ret = (command->function)(config, notmuch, argc - opt_index, argv + opt_index);
 
   DONE:
-    if (config)
-	notmuch_config_close (config);
-
     talloc_report = getenv ("NOTMUCH_TALLOC_REPORT");
     if (talloc_report && strcmp (talloc_report, "") != 0) {
 	/* this relies on the previous call to
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index 535c41e9..2045a555 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -258,7 +258,6 @@ EOF
    case $config in
        XDG*)
 	   test_begin_subtest "Set shadowed config value in database ($config)"
-	   test_subtest_known_broken
 	   name=${RANDOM}
 	   value=${RANDOM}
 	   key=test${test_count}.${name}
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 27/28] CLI: drop notmuch_config_t from subcommand interface.
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (25 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 26/28] CLI/config: remove calls to notmuch_config_open from top level David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-07  1:55 ` [PATCH 28/28] CLI: rename notmuch_config_t to notmuch_conffile_t David Bremner
  2021-04-10 12:12 ` v2 convert remaining CLI to new configuration David Bremner
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

At this point it is unused in all subcommands.
---
 notmuch-client.h  | 42 ++++++++++++++----------------------------
 notmuch-compact.c |  3 +--
 notmuch-config.c  |  7 +++----
 notmuch-count.c   |  3 +--
 notmuch-dump.c    |  3 +--
 notmuch-insert.c  |  3 +--
 notmuch-new.c     |  3 +--
 notmuch-reindex.c |  3 +--
 notmuch-reply.c   |  3 +--
 notmuch-restore.c |  3 +--
 notmuch-search.c  |  6 ++----
 notmuch-setup.c   |  3 +--
 notmuch-show.c    |  3 +--
 notmuch-tag.c     |  3 +--
 notmuch.c         | 18 +++++++-----------
 15 files changed, 37 insertions(+), 69 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index a5b3c518..8815bb11 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -171,60 +171,46 @@ void
 notmuch_exit_if_unsupported_format (void);
 
 int
-notmuch_count_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-		       int argc, char *argv[]);
+notmuch_count_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_dump_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-		      int argc, char *argv[]);
+notmuch_dump_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_new_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-		     int argc, char *argv[]);
+notmuch_new_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_insert_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			int argc, char *argv[]);
+notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_reindex_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			 int argc, char *argv[]);
+notmuch_reindex_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_reply_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-		       int argc, char *argv[]);
+notmuch_reply_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_restore_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			 int argc, char *argv[]);
+notmuch_restore_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_search_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			int argc, char *argv[]);
+notmuch_search_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_address_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			 int argc, char *argv[]);
+notmuch_address_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_setup_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-		       int argc, char *argv[]);
+notmuch_setup_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_show_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-		      int argc, char *argv[]);
+notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_tag_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-		     int argc, char *argv[]);
+notmuch_tag_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			int argc, char *argv[]);
+notmuch_config_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 int
-notmuch_compact_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			 int argc, char *argv[]);
+notmuch_compact_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 const char *
 notmuch_time_relative_date (const void *ctx, time_t then);
diff --git a/notmuch-compact.c b/notmuch-compact.c
index cc45afa1..2648434e 100644
--- a/notmuch-compact.c
+++ b/notmuch-compact.c
@@ -27,8 +27,7 @@ status_update_cb (const char *msg, unused (void *closure))
 }
 
 int
-notmuch_compact_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-			 int argc, char *argv[])
+notmuch_compact_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     const char *backup_path = NULL;
     notmuch_status_t ret;
diff --git a/notmuch-config.c b/notmuch-config.c
index 7aac8e94..34482b4e 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -578,7 +578,7 @@ _set_db_config (notmuch_database_t *notmuch, const char *key, int argc, char **a
 }
 
 static int
-notmuch_config_command_set (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
+notmuch_config_command_set (notmuch_database_t *notmuch,
 			    int argc, char *argv[])
 {
     char *group, *key;
@@ -691,8 +691,7 @@ notmuch_config_command_list (notmuch_database_t *notmuch)
 }
 
 int
-notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
-			int argc, char *argv[])
+notmuch_config_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     int ret;
     int opt_index;
@@ -722,7 +721,7 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch,
 	}
 	ret = notmuch_config_command_get (notmuch, argv[1]);
     } else if (strcmp (argv[0], "set") == 0) {
-	ret = notmuch_config_command_set (config, notmuch, argc, argv);
+	ret = notmuch_config_command_set (notmuch, argc, argv);
     } else if (strcmp (argv[0], "list") == 0) {
 	ret = notmuch_config_command_list (notmuch);
     } else {
diff --git a/notmuch-count.c b/notmuch-count.c
index bfa0363a..5ac4292b 100644
--- a/notmuch-count.c
+++ b/notmuch-count.c
@@ -151,8 +151,7 @@ count_file (notmuch_database_t *notmuch, FILE *input, notmuch_config_values_t *e
 }
 
 int
-notmuch_count_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-		       int argc, char *argv[])
+notmuch_count_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     char *query_str;
     int opt_index;
diff --git a/notmuch-dump.c b/notmuch-dump.c
index 04ecd6a3..ae89e4da 100644
--- a/notmuch-dump.c
+++ b/notmuch-dump.c
@@ -361,8 +361,7 @@ notmuch_database_dump (notmuch_database_t *notmuch,
 }
 
 int
-notmuch_dump_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-		      int argc, char *argv[])
+notmuch_dump_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     const char *query_str = NULL;
     int ret;
diff --git a/notmuch-insert.c b/notmuch-insert.c
index 865b6b69..00c00468 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -444,8 +444,7 @@ add_file (notmuch_database_t *notmuch, const char *path, tag_op_list_t *tag_ops,
 }
 
 int
-notmuch_insert_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-			int argc, char *argv[])
+notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     notmuch_status_t status, close_status;
     struct sigaction action;
diff --git a/notmuch-new.c b/notmuch-new.c
index 8e2bf4a8..993359d6 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -1104,8 +1104,7 @@ _maybe_upgrade (notmuch_database_t *notmuch, add_files_state_t *state)
 }
 
 int
-notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-		     int argc, char *argv[])
+notmuch_new_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     add_files_state_t add_files_state = {
 	.verbosity = VERBOSITY_NORMAL,
diff --git a/notmuch-reindex.c b/notmuch-reindex.c
index df566a7c..8904c1f4 100644
--- a/notmuch-reindex.c
+++ b/notmuch-reindex.c
@@ -83,8 +83,7 @@ reindex_query (notmuch_database_t *notmuch, const char *query_string,
 }
 
 int
-notmuch_reindex_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-			 int argc, char *argv[])
+notmuch_reindex_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     char *query_string = NULL;
     struct sigaction action;
diff --git a/notmuch-reply.c b/notmuch-reply.c
index b40ce96b..08140799 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -705,8 +705,7 @@ do_reply (notmuch_database_t *notmuch,
 }
 
 int
-notmuch_reply_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-		       int argc, char *argv[])
+notmuch_reply_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     notmuch_query_t *query;
     char *query_string;
diff --git a/notmuch-restore.c b/notmuch-restore.c
index 081b504c..1a81212f 100644
--- a/notmuch-restore.c
+++ b/notmuch-restore.c
@@ -219,8 +219,7 @@ parse_sup_line (void *ctx, char *line,
 }
 
 int
-notmuch_restore_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-			 int argc, char *argv[])
+notmuch_restore_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     bool accumulate = false;
     tag_op_flag_t flags = 0;
diff --git a/notmuch-search.c b/notmuch-search.c
index a5c49477..244817a9 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -794,8 +794,7 @@ static const notmuch_opt_desc_t common_options[] = {
 };
 
 int
-notmuch_search_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-			int argc, char *argv[])
+notmuch_search_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     search_context_t *ctx = &search_context;
     int opt_index, ret;
@@ -862,8 +861,7 @@ notmuch_search_command (unused(notmuch_config_t *config), notmuch_database_t *no
 }
 
 int
-notmuch_address_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-			 int argc, char *argv[])
+notmuch_address_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     search_context_t *ctx = &search_context;
     int opt_index, ret;
diff --git a/notmuch-setup.c b/notmuch-setup.c
index 221ce934..567e3b56 100644
--- a/notmuch-setup.c
+++ b/notmuch-setup.c
@@ -124,8 +124,7 @@ parse_tag_list (void *ctx, char *response)
 }
 
 int
-notmuch_setup_command (unused(notmuch_config_t *config),
-		       notmuch_database_t *notmuch,
+notmuch_setup_command (notmuch_database_t *notmuch,
 		       int argc, char *argv[])
 {
     char *response = NULL;
diff --git a/notmuch-show.c b/notmuch-show.c
index 481e5d54..bdb87321 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -1225,8 +1225,7 @@ static const notmuch_show_format_t *formatters[] = {
 };
 
 int
-notmuch_show_command (unused (notmuch_config_t *config), notmuch_database_t *notmuch,
-		      int argc, char *argv[])
+notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     notmuch_query_t *query;
     char *query_string;
diff --git a/notmuch-tag.c b/notmuch-tag.c
index 9c3d4f8b..667a75d6 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -187,8 +187,7 @@ tag_file (void *ctx, notmuch_database_t *notmuch, tag_op_flag_t flags,
 }
 
 int
-notmuch_tag_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch,
-		     int argc, char *argv[])
+notmuch_tag_command (notmuch_database_t *notmuch, int argc, char *argv[])
 {
     tag_op_list_t *tag_ops = NULL;
     char *query_string = NULL;
diff --git a/notmuch.c b/notmuch.c
index 757d0eae..2429999c 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -31,8 +31,7 @@
  * Each subcommand should be passed either a config object, or an open
  * database
  */
-typedef int (*command_function_t) (notmuch_config_t *config, notmuch_database_t *notmuch,
-				   int argc, char *argv[]);
+typedef int (*command_function_t) (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 typedef struct command {
     const char *name;
@@ -42,10 +41,10 @@ typedef struct command {
 } command_t;
 
 static int
-notmuch_help_command (notmuch_config_t *config, notmuch_database_t *notmuch, int argc, char *argv[]);
+notmuch_help_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 static int
-notmuch_command (notmuch_config_t *config, notmuch_database_t *notmuch, int argc, char *argv[]);
+notmuch_command (notmuch_database_t *notmuch, int argc, char *argv[]);
 
 static int
 _help_for (const char *topic);
@@ -349,8 +348,7 @@ _help_for (const char *topic_name)
 }
 
 static int
-notmuch_help_command (unused (notmuch_config_t *config), unused(notmuch_database_t *notmuch), int
-		      argc, char *argv[])
+notmuch_help_command (unused(notmuch_database_t *notmuch), int argc, char *argv[])
 {
     int opt_index;
 
@@ -374,8 +372,7 @@ notmuch_help_command (unused (notmuch_config_t *config), unused(notmuch_database
  * to be more clever about this in the future.
  */
 static int
-notmuch_command (unused(notmuch_config_t *config),
-		 notmuch_database_t *notmuch,
+notmuch_command (notmuch_database_t *notmuch,
 		 unused(int argc), unused(char **argv))
 {
 
@@ -391,7 +388,7 @@ notmuch_command (unused(notmuch_config_t *config),
 		     strerror (errno));
 	    return EXIT_FAILURE;
 	} else {
-	    return notmuch_setup_command (NULL, notmuch, 0, NULL);
+	    return notmuch_setup_command (notmuch, 0, NULL);
 	}
     }
 
@@ -457,7 +454,6 @@ main (int argc, char *argv[])
     const char *command_name = NULL;
     command_t *command;
     const char *config_file_name = NULL;
-    notmuch_config_t *config = NULL;
     notmuch_database_t *notmuch = NULL;
     int opt_index;
     int ret = EXIT_SUCCESS;
@@ -589,7 +585,7 @@ main (int argc, char *argv[])
 
     }
 
-    ret = (command->function)(config, notmuch, argc - opt_index, argv + opt_index);
+    ret = (command->function)(notmuch, argc - opt_index, argv + opt_index);
 
   DONE:
     talloc_report = getenv ("NOTMUCH_TALLOC_REPORT");
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 28/28] CLI: rename notmuch_config_t to notmuch_conffile_t
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (26 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 27/28] CLI: drop notmuch_config_t from subcommand interface David Bremner
@ 2021-04-07  1:55 ` David Bremner
  2021-04-10 12:12 ` v2 convert remaining CLI to new configuration David Bremner
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-07  1:55 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

The name is a compromise between keeping function names from getting
too long, and avoiding confusion with the newer notmuch_config library
API. Try to make clear that the residual functionality is only about
updating configuration files.
---
 notmuch-client.h | 56 ++++++++++++++++----------------
 notmuch-config.c | 84 ++++++++++++++++++++++++------------------------
 notmuch-setup.c  | 38 +++++++++++-----------
 3 files changed, 89 insertions(+), 89 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index 8815bb11..270553ad 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -156,7 +156,7 @@ chomp_newline (char *str)
  */
 extern int notmuch_format_version;
 
-typedef struct _notmuch_config notmuch_config_t;
+typedef struct _notmuch_conffile notmuch_conffile_t;
 
 /* Commands that support structured output should support the
  * following argument
@@ -260,55 +260,55 @@ typedef enum {
     NOTMUCH_COMMAND_CONFIG_LOAD		= 1 << 5,
 } notmuch_command_mode_t;
 
-notmuch_config_t *
-notmuch_config_open (notmuch_database_t *notmuch,
-		     const char *filename,
-		     bool create);
+notmuch_conffile_t *
+notmuch_conffile_open (notmuch_database_t *notmuch,
+		       const char *filename,
+		       bool create);
 
 void
-notmuch_config_close (notmuch_config_t *config);
+notmuch_conffile_close (notmuch_conffile_t *config);
 
 int
-notmuch_config_save (notmuch_config_t *config);
+notmuch_conffile_save (notmuch_conffile_t *config);
 
 bool
-notmuch_config_is_new (notmuch_config_t *config);
+notmuch_conffile_is_new (notmuch_conffile_t *config);
 
 void
-notmuch_config_set_database_path (notmuch_config_t *config,
-				  const char *database_path);
+notmuch_conffile_set_database_path (notmuch_conffile_t *config,
+				    const char *database_path);
 
 void
-notmuch_config_set_user_name (notmuch_config_t *config,
-			      const char *user_name);
+notmuch_conffile_set_user_name (notmuch_conffile_t *config,
+				const char *user_name);
 
 void
-notmuch_config_set_user_primary_email (notmuch_config_t *config,
-				       const char *primary_email);
+notmuch_conffile_set_user_primary_email (notmuch_conffile_t *config,
+					 const char *primary_email);
 
 void
-notmuch_config_set_user_other_email (notmuch_config_t *config,
-				     const char *other_email[],
-				     size_t length);
+notmuch_conffile_set_user_other_email (notmuch_conffile_t *config,
+				       const char *other_email[],
+				       size_t length);
 
 void
-notmuch_config_set_new_tags (notmuch_config_t *config,
-			     const char *new_tags[],
-			     size_t length);
+notmuch_conffile_set_new_tags (notmuch_conffile_t *config,
+			       const char *new_tags[],
+			       size_t length);
 
 void
-notmuch_config_set_new_ignore (notmuch_config_t *config,
-			       const char *new_ignore[],
-			       size_t length);
+notmuch_conffile_set_new_ignore (notmuch_conffile_t *config,
+				 const char *new_ignore[],
+				 size_t length);
 
 void
-notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
-					      bool synchronize_flags);
+notmuch_conffile_set_maildir_synchronize_flags (notmuch_conffile_t *config,
+						bool synchronize_flags);
 
 void
-notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
-					const char *list[],
-					size_t length);
+notmuch_conffile_set_search_exclude_tags (notmuch_conffile_t *config,
+					  const char *list[],
+					  size_t length);
 int
 notmuch_run_hook (notmuch_database_t *notmuch, const char *hook);
 
diff --git a/notmuch-config.c b/notmuch-config.c
index 34482b4e..16e86916 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -114,14 +114,14 @@ struct config_group {
     },
 };
 
-struct _notmuch_config {
+struct _notmuch_conffile {
     char *filename;
     GKeyFile *key_file;
     bool is_new;
 };
 
 static int
-notmuch_config_destructor (notmuch_config_t *config)
+notmuch_conffile_destructor (notmuch_conffile_t *config)
 {
     if (config->key_file)
 	g_key_file_free (config->key_file);
@@ -130,7 +130,7 @@ notmuch_config_destructor (notmuch_config_t *config)
 }
 
 static bool
-get_config_from_file (notmuch_config_t *config, bool create_new)
+get_config_from_file (notmuch_conffile_t *config, bool create_new)
 {
     #define BUF_SIZE 4096
     char *config_str = NULL;
@@ -245,21 +245,21 @@ get_config_from_file (notmuch_config_t *config, bool create_new)
  *	The default configuration also contains comments to guide the
  *	user in editing the file directly.
  */
-notmuch_config_t *
-notmuch_config_open (notmuch_database_t *notmuch,
-		     const char *filename,
-		     bool create)
+notmuch_conffile_t *
+notmuch_conffile_open (notmuch_database_t *notmuch,
+		       const char *filename,
+		       bool create)
 {
     char *notmuch_config_env = NULL;
 
-    notmuch_config_t *config = talloc_zero (notmuch, notmuch_config_t);
+    notmuch_conffile_t *config = talloc_zero (notmuch, notmuch_conffile_t);
 
     if (config == NULL) {
 	fprintf (stderr, "Out of memory.\n");
 	return NULL;
     }
 
-    talloc_set_destructor (config, notmuch_config_destructor);
+    talloc_set_destructor (config, notmuch_conffile_destructor);
 
     if (filename) {
 	config->filename = talloc_strdup (config, filename);
@@ -294,14 +294,14 @@ notmuch_config_open (notmuch_database_t *notmuch,
     return config;
 }
 
-/* Close the given notmuch_config_t object, freeing all resources.
+/* Close the given notmuch_conffile_t object, freeing all resources.
  *
  * Note: Any changes made to the configuration are *not* saved by this
- * function. To save changes, call notmuch_config_save before
- * notmuch_config_close.
+ * function. To save changes, call notmuch_conffile_save before
+ * notmuch_conffile_close.
  */
 void
-notmuch_config_close (notmuch_config_t *config)
+notmuch_conffile_close (notmuch_conffile_t *config)
 {
     talloc_free (config);
 }
@@ -314,7 +314,7 @@ notmuch_config_close (notmuch_config_t *config)
  * printing a description of the error to stderr).
  */
 int
-notmuch_config_save (notmuch_config_t *config)
+notmuch_conffile_save (notmuch_conffile_t *config)
 {
     size_t length;
     char *data, *filename;
@@ -364,20 +364,20 @@ notmuch_config_save (notmuch_config_t *config)
 }
 
 bool
-notmuch_config_is_new (notmuch_config_t *config)
+notmuch_conffile_is_new (notmuch_conffile_t *config)
 {
     return config->is_new;
 }
 
 static void
-_config_set (notmuch_config_t *config,
+_config_set (notmuch_conffile_t *config,
 	     const char *group, const char *key, const char *value)
 {
     g_key_file_set_string (config->key_file, group, key, value);
 }
 
 static void
-_config_set_list (notmuch_config_t *config,
+_config_set_list (notmuch_conffile_t *config,
 		  const char *group, const char *key,
 		  const char *list[],
 		  size_t length)
@@ -386,54 +386,54 @@ _config_set_list (notmuch_config_t *config,
 }
 
 void
-notmuch_config_set_database_path (notmuch_config_t *config,
-				  const char *database_path)
+notmuch_conffile_set_database_path (notmuch_conffile_t *config,
+				    const char *database_path)
 {
     _config_set (config, "database", "path", database_path);
 }
 
 void
-notmuch_config_set_user_name (notmuch_config_t *config,
-			      const char *user_name)
+notmuch_conffile_set_user_name (notmuch_conffile_t *config,
+				const char *user_name)
 {
     _config_set (config, "user", "name", user_name);
 }
 
 void
-notmuch_config_set_user_primary_email (notmuch_config_t *config,
-				       const char *primary_email)
+notmuch_conffile_set_user_primary_email (notmuch_conffile_t *config,
+					 const char *primary_email)
 {
     _config_set (config, "user", "primary_email", primary_email);
 }
 
 void
-notmuch_config_set_user_other_email (notmuch_config_t *config,
-				     const char *list[],
-				     size_t length)
+notmuch_conffile_set_user_other_email (notmuch_conffile_t *config,
+				       const char *list[],
+				       size_t length)
 {
     _config_set_list (config, "user", "other_email", list, length);
 }
 
 void
-notmuch_config_set_new_tags (notmuch_config_t *config,
-			     const char *list[],
-			     size_t length)
+notmuch_conffile_set_new_tags (notmuch_conffile_t *config,
+			       const char *list[],
+			       size_t length)
 {
     _config_set_list (config, "new", "tags", list, length);
 }
 
 void
-notmuch_config_set_new_ignore (notmuch_config_t *config,
-			       const char *list[],
-			       size_t length)
+notmuch_conffile_set_new_ignore (notmuch_conffile_t *config,
+				 const char *list[],
+				 size_t length)
 {
     _config_set_list (config, "new", "ignore", list, length);
 }
 
 void
-notmuch_config_set_search_exclude_tags (notmuch_config_t *config,
-					const char *list[],
-					size_t length)
+notmuch_conffile_set_search_exclude_tags (notmuch_conffile_t *config,
+					  const char *list[],
+					  size_t length)
 {
     _config_set_list (config, "search", "exclude_tags", list, length);
 }
@@ -583,7 +583,7 @@ notmuch_config_command_set (notmuch_database_t *notmuch,
 {
     char *group, *key;
     config_key_info_t *key_info;
-    notmuch_config_t *config;
+    notmuch_conffile_t *config;
     bool update_database = false;
     int opt_index, ret;
     char *item;
@@ -626,8 +626,8 @@ notmuch_config_command_set (notmuch_database_t *notmuch,
     if (_item_split (item, &group, &key))
 	return 1;
 
-    config = notmuch_config_open (notmuch,
-				  notmuch_config_path (notmuch), false);
+    config = notmuch_conffile_open (notmuch,
+				    notmuch_config_path (notmuch), false);
     if (! config)
 	return 1;
 
@@ -651,9 +651,9 @@ notmuch_config_command_set (notmuch_database_t *notmuch,
 	break;
     }
 
-    ret = notmuch_config_save (config);
+    ret = notmuch_conffile_save (config);
 
-    notmuch_config_close (config);
+    notmuch_conffile_close (config);
 
     return ret;
 }
@@ -735,8 +735,8 @@ notmuch_config_command (notmuch_database_t *notmuch, int argc, char *argv[])
 }
 
 void
-notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
-					      bool synchronize_flags)
+notmuch_conffile_set_maildir_synchronize_flags (notmuch_conffile_t *config,
+						bool synchronize_flags)
 {
     g_key_file_set_boolean (config->key_file,
 			    "maildir", "synchronize_flags", synchronize_flags);
diff --git a/notmuch-setup.c b/notmuch-setup.c
index 567e3b56..ace56967 100644
--- a/notmuch-setup.c
+++ b/notmuch-setup.c
@@ -131,7 +131,7 @@ notmuch_setup_command (notmuch_database_t *notmuch,
     size_t response_size = 0;
     GPtrArray *other_emails;
     notmuch_config_values_t *new_tags, *search_exclude_tags, *emails;
-    notmuch_config_t *config;
+    notmuch_conffile_t *config;
 
 #define prompt(format, ...)                                     \
     do {                                                        \
@@ -151,22 +151,22 @@ notmuch_setup_command (notmuch_database_t *notmuch,
 	fprintf (stderr, "Warning: ignoring --uuid=%s\n",
 		 notmuch_requested_db_uuid);
 
-    config = notmuch_config_open (notmuch,
-				  notmuch_config_path (notmuch), true);
+    config = notmuch_conffile_open (notmuch,
+				    notmuch_config_path (notmuch), true);
     if (! config)
 	return EXIT_FAILURE;
 
-    if (notmuch_config_is_new (config))
+    if (notmuch_conffile_is_new (config))
 	welcome_message_pre_setup ();
 
     prompt ("Your full name [%s]: ", notmuch_config_get (notmuch, NOTMUCH_CONFIG_USER_NAME));
     if (strlen (response))
-	notmuch_config_set_user_name (config, response);
+	notmuch_conffile_set_user_name (config, response);
 
     prompt ("Your primary email address [%s]: ",
 	    notmuch_config_get (notmuch, NOTMUCH_CONFIG_PRIMARY_EMAIL));
     if (strlen (response))
-	notmuch_config_set_user_primary_email (config, response);
+	notmuch_conffile_set_user_primary_email (config, response);
 
     other_emails = g_ptr_array_new ();
 
@@ -188,10 +188,10 @@ notmuch_setup_command (notmuch_database_t *notmuch,
 	    g_ptr_array_add (other_emails, talloc_strdup (config, response));
     } while (strlen (response));
     if (other_emails->len)
-	notmuch_config_set_user_other_email (config,
-					     (const char **)
-					     other_emails->pdata,
-					     other_emails->len);
+	notmuch_conffile_set_user_other_email (config,
+					       (const char **)
+					       other_emails->pdata,
+					       other_emails->len);
     g_ptr_array_free (other_emails, true);
 
     prompt ("Top-level directory of your email archive [%s]: ",
@@ -200,7 +200,7 @@ notmuch_setup_command (notmuch_database_t *notmuch,
 	const char *absolute_path;
 
 	absolute_path = make_path_absolute (config, response);
-	notmuch_config_set_database_path (config, absolute_path);
+	notmuch_conffile_set_database_path (config, absolute_path);
     }
 
     new_tags = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_NEW_TAGS);
@@ -212,8 +212,8 @@ notmuch_setup_command (notmuch_database_t *notmuch,
     if (strlen (response)) {
 	GPtrArray *tags = parse_tag_list (config, response);
 
-	notmuch_config_set_new_tags (config, (const char **) tags->pdata,
-				     tags->len);
+	notmuch_conffile_set_new_tags (config, (const char **) tags->pdata,
+				       tags->len);
 
 	g_ptr_array_free (tags, true);
     }
@@ -227,20 +227,20 @@ notmuch_setup_command (notmuch_database_t *notmuch,
     if (strlen (response)) {
 	GPtrArray *tags = parse_tag_list (config, response);
 
-	notmuch_config_set_search_exclude_tags (config,
-						(const char **) tags->pdata,
-						tags->len);
+	notmuch_conffile_set_search_exclude_tags (config,
+						  (const char **) tags->pdata,
+						  tags->len);
 
 	g_ptr_array_free (tags, true);
     }
 
-    if (notmuch_config_save (config))
+    if (notmuch_conffile_save (config))
 	return EXIT_FAILURE;
 
     if (config)
-	notmuch_config_close (config);
+	notmuch_conffile_close (config);
 
-    if (notmuch_config_is_new (config))
+    if (notmuch_conffile_is_new (config))
 	welcome_message_post_setup ();
 
     return EXIT_SUCCESS;
-- 
2.30.2

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: v2 convert remaining CLI to new configuration
  2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
                   ` (27 preceding siblings ...)
  2021-04-07  1:55 ` [PATCH 28/28] CLI: rename notmuch_config_t to notmuch_conffile_t David Bremner
@ 2021-04-10 12:12 ` David Bremner
  28 siblings, 0 replies; 30+ messages in thread
From: David Bremner @ 2021-04-10 12:12 UTC (permalink / raw)
  To: notmuch

David Bremner <david@tethera.net> writes:

> This obsoletes [1] and [2].
>
> I've been using it for a month, I think it's probably ready to
> apply to master. Since the last posted version the only difference (other than
> incorporating [2]) is that I changed the call to access to test the
> config file not to check for write access.

I applied this series to master.

d

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2021-04-10 12:13 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-07  1:55 v2 convert remaining CLI to new configuration David Bremner
2021-04-07  1:55 ` [PATCH 01/28] lib/open: fix leaks calling _trial_open David Bremner
2021-04-07  1:55 ` [PATCH 02/28] lib: add missing status strings David Bremner
2021-04-07  1:55 ` [PATCH 03/28] test: convert random-corpus to use n_d_open_with_config David Bremner
2021-04-07  1:55 ` [PATCH 04/28] lib/open: pull _load_key_file out of _choose_database_path David Bremner
2021-04-07  1:55 ` [PATCH 05/28] lib: provide notmuch_database_load_config David Bremner
2021-04-07  1:55 ` [PATCH 06/28] lib/config: add notmuch_config_get_values_string David Bremner
2021-04-07  1:55 ` [PATCH 07/28] lib/config: add config_pairs iterators David Bremner
2021-04-07  1:55 ` [PATCH 08/28] lib/config: set defaults for user full name David Bremner
2021-04-07  1:55 ` [PATCH 09/28] lib/config: set default for primary user email David Bremner
2021-04-07  1:55 ` [PATCH 10/28] lib/open: canonicalize relative path read from config file David Bremner
2021-04-07  1:55 ` [PATCH 11/28] CLI: load merged config at top level David Bremner
2021-04-07  1:55 ` [PATCH 12/28] CLI/config: use merged config for "config get" David Bremner
2021-04-07  1:55 ` [PATCH 13/28] test/setup: check file output instead of notmuch config list David Bremner
2021-04-07  1:55 ` [PATCH 14/28] CLI/setup: switch to new configuration framework David Bremner
2021-04-07  1:55 ` [PATCH 15/28] CLI/config: switch "notmuch config list" to merged config David Bremner
2021-04-07  1:55 ` [PATCH 16/28] CLI/config: migrate notmuch_config_open to new config David Bremner
2021-04-07  1:55 ` [PATCH 17/28] CLI/config: use notmuch_database_reopen David Bremner
2021-04-07  1:55 ` [PATCH 18/28] CLI/notmuch: switch notmuch_command to notmuch_config_get David Bremner
2021-04-07  1:55 ` [PATCH 19/28] CLI/config: drop obsolete notmuch_config_get_* David Bremner
2021-04-07  1:55 ` [PATCH 20/28] CLI/config: drop cached data from notmuch_config_t David Bremner
2021-04-07  1:55 ` [PATCH 21/28] CLI/config: default to storing all config in external files David Bremner
2021-04-07  1:55 ` [PATCH 22/28] lib: add NOTMUCH_STATUS_NO_DATABASE David Bremner
2021-04-07  1:55 ` [PATCH 23/28] CLI+lib: detect missing database in split configurations David Bremner
2021-04-07  1:55 ` [PATCH 24/28] lib: provide notmuch_config_path David Bremner
2021-04-07  1:55 ` [PATCH 25/28] CLI/config: support set/get with split configuration David Bremner
2021-04-07  1:55 ` [PATCH 26/28] CLI/config: remove calls to notmuch_config_open from top level David Bremner
2021-04-07  1:55 ` [PATCH 27/28] CLI: drop notmuch_config_t from subcommand interface David Bremner
2021-04-07  1:55 ` [PATCH 28/28] CLI: rename notmuch_config_t to notmuch_conffile_t David Bremner
2021-04-10 12:12 ` v2 convert remaining CLI to new configuration David Bremner

unofficial mirror of notmuch@notmuchmail.org

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://yhetil.org/notmuch/0 notmuch/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 notmuch notmuch/ https://yhetil.org/notmuch \
		notmuch@notmuchmail.org
	public-inbox-index notmuch

Example config snippet for mirrors.
Newsgroups are available over NNTP:
	nntp://news.yhetil.org/yhetil.mail.notmuch.general
	nntp://news.gmane.io/gmane.mail.notmuch.general


code repositories for project(s) associated with this inbox:

	notmuch.git.git (no URL configured)

AGPL code for this site: git clone http://ou63pmih66umazou.onion/public-inbox.git