unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / Atom feed
* RFC convert remaining CLI to new configuration
@ 2021-02-20 16:44 David Bremner
  2021-02-20 16:44 ` [PATCH 01/18] lib: add missing status strings David Bremner
                   ` (17 more replies)
  0 siblings, 18 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch

This is an early version of a series to convert the remaining CLI
(config, setup, and notmuch_command) to the new configuration framework.

There are a few design decisions / compromomises that people might
have opinions about.

- The merged config API uses a notmuch_data_t as the primary
  "object". This mostly makes sense (since you nead a database
  anyway), but here I needed to add a function
  "notmuch_database_load_config", which does not really open the database.

- There is a bit of growth in the public API here, including
  notmuch_database_get_config_values, and the config_pairs iterators.

- The notmuch_config_set_{field} API is kept around soley for use in
  notmuch-setup

- The location of the backups when upgrading is now configurable, with
  the default changing to a subdirectory. The latter change is
  arguably gratitous.

- The behaviour of "notmuch config set" is changed with respect to
  storing in the database. Rather than silently doing so for a
  selected set of keys, it now does so optionally for any set of keys.
  I think this is positive for users, but requires e.g. a few tweaks
  to our test suite. It is conceivable that it may require some
  updates to advanced users scripts as well.

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

* [PATCH 01/18] lib: add missing status strings
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 02/18] test: convert random-corpus to use n_d_open_with_config David Bremner
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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 ffd42ac4..87ad1385 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -292,12 +292,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.0

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

* [PATCH 02/18] test: convert random-corpus to use n_d_open_with_config
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
  2021-02-20 16:44 ` [PATCH 01/18] lib: add missing status strings David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 03/18] lib/open: pull _load_key_file out of _choose_database_path David Bremner
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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 ff413252..67e106e0 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.0

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

* [PATCH 03/18] lib/open: pull _load_key_file out of _choose_database_path
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
  2021-02-20 16:44 ` [PATCH 01/18] lib: add missing status strings David Bremner
  2021-02-20 16:44 ` [PATCH 02/18] test: convert random-corpus to use n_d_open_with_config David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 04/18] WIP: add notmuch_database_load_config David Bremner
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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, 19 insertions(+), 17 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index e5ef351e..e1ad957f 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)
-	*database_path = g_key_file_get_value (*key_file, "database", "path", NULL);
+    if (! *database_path && key_file)
+	*database_path = g_key_file_get_value (key_file, "database", "path", NULL);
 
     if (! *database_path) {
 	*database_path = _xdg_dir (ctx, "XDG_DATA_HOME", ".local/share", profile);
@@ -482,8 +473,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;
 
@@ -569,9 +566,14 @@ notmuch_database_create_with_config (const char *database_path,
 	goto DONE;
     }
 
-    if ((status = _choose_database_path (local, config_path, profile,
-					 &key_file, &database_path, &split,
-					 &message)))
+    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;
 
     status = _db_dir_exists (database_path, &message);
-- 
2.30.0

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

* [PATCH 04/18] WIP: add notmuch_database_load_config
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (2 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 03/18] lib/open: pull _load_key_file out of _choose_database_path David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 05/18] WIP: add n_d_get_config_values David Bremner
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

This needs at least documentation and probably more tests.
---
 lib/notmuch.h          |   9 ++
 lib/open.cc            |  96 ++++++++++++++++++++++
 test/T590-libconfig.sh | 182 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 284 insertions(+), 3 deletions(-)

diff --git a/lib/notmuch.h b/lib/notmuch.h
index 5e4f1dac..60c79696 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -442,6 +442,15 @@ notmuch_database_open_with_config (const char *database_path,
 				   const char *profile,
 				   notmuch_database_t **database,
 				   char **error_message);
+
+
+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 e1ad957f..be9151b0 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -709,3 +709,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, status2 = 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:
+	status2 = 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 status2;
+}
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.0

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

* [PATCH 05/18] WIP: add n_d_get_config_values
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (3 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 04/18] WIP: add notmuch_database_load_config David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 06/18] lib/config: add config_pairs iterators David Bremner
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

---
 lib/config.cc          | 14 ++++++++++----
 lib/notmuch.h          |  2 ++
 test/T590-libconfig.sh | 23 +++++++++++++++++++++++
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 32ed6f8f..47e8bf82 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -258,13 +258,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_database_get_config_values (notmuch, key_str);
+}
+
+notmuch_config_values_t *
+notmuch_database_get_config_values (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 60c79696..45616a22 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -2475,6 +2475,8 @@ notmuch_config_list_move_to_next (notmuch_config_list_t *config_list);
 void
 notmuch_config_list_destroy (notmuch_config_list_t *config_list);
 
+notmuch_config_values_t *
+notmuch_database_get_config_values (notmuch_database_t *notmuch, const char *key_string);
 
 /**
  * Configuration keys known to libnotmuch
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index dc9964cf..ad044275 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_database_get_config_values"
+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_database_get_config_values (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.0

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

* [PATCH 06/18] lib/config: add config_pairs iterators
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (4 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 05/18] WIP: add n_d_get_config_values David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 07/18] lib/config: set defaults for user full name David Bremner
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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          | 39 ++++++++++++++++++++++++++++++
 lib/notmuch.h          | 21 ++++++++++++++++
 test/T590-libconfig.sh | 54 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+)

diff --git a/lib/config.cc b/lib/config.cc
index 47e8bf82..490cb1c3 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
@@ -331,6 +335,41 @@ 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 45616a22..e6e26fe5 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__ */
 
@@ -2607,6 +2608,26 @@ notmuch_config_values_start (notmuch_config_values_t *values);
 void
 notmuch_config_values_destroy (notmuch_config_values_t *values);
 
+
+notmuch_config_pairs_t *
+notmuch_config_get_pairs (notmuch_database_t *notmuch,
+			  const char *prefix);
+
+notmuch_bool_t
+notmuch_config_pairs_valid (notmuch_config_pairs_t *pairs);
+
+void
+notmuch_config_pairs_move_to_next (notmuch_config_pairs_t *pairs);
+
+const char *
+notmuch_config_pairs_key (notmuch_config_pairs_t *pairs);
+
+const char *
+notmuch_config_pairs_value (notmuch_config_pairs_t *pairs);
+
+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 ad044275..c93c2859 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.0

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

* [PATCH 07/18] lib/config: set defaults for user full name
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (5 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 06/18] lib/config: add config_pairs iterators David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 08/18] lib/config: set default for primary user email David Bremner
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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 490cb1c3..d07aac5e 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 {
@@ -430,6 +432,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) {
     switch (key) {
@@ -463,6 +500,7 @@ _notmuch_config_key_to_string (notmuch_config_key_t key) {
 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:
@@ -482,10 +520,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 c93c2859..95538bba 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 29baa0c1..e881dc40 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.0

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

* [PATCH 08/18] lib/config: set default for primary user email
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (6 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 07/18] lib/config: set defaults for user full name David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 09/18] CLI/notmuch: replace use of notmuch_config_get_* David Bremner
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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 |  4 +--
 test/test-lib.sh       |  6 +++-
 3 files changed, 73 insertions(+), 7 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index d07aac5e..03ba2731 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";
 
@@ -467,6 +468,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) {
     switch (key) {
@@ -500,7 +558,7 @@ _notmuch_config_key_to_string (notmuch_config_key_t key) {
 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:
@@ -526,13 +584,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 95538bba..01a9ac06 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 ==
@@ -742,7 +742,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 e881dc40..cb27cb78 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.0

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

* [PATCH 09/18] CLI/notmuch: replace use of notmuch_config_get_*
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (7 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 08/18] lib/config: set default for primary user email David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 10/18] CLI/config: WIP: load merged config David Bremner
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

The notmuch_config_get_{field_name} internal API will be removed in a
subsequent commit.
---
 notmuch.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/notmuch.c b/notmuch.c
index 71482e43..a161f127 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -364,7 +364,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;
@@ -378,7 +378,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) {
@@ -409,8 +409,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.0

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

* [PATCH 10/18] CLI/config: WIP: load merged config
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (8 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 09/18] CLI/notmuch: replace use of notmuch_config_get_* David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 11/18] WIP: CLI/config: use merged config for "config get" David Bremner
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

---
 notmuch-client.h       |  1 +
 notmuch.c              | 29 ++++++++++++++++++++++++++---
 test/T030-config.sh    | 11 +++++++----
 test/T590-libconfig.sh |  3 ---
 4 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index f60f5406..db88daf8 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -258,6 +258,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 a161f127..90504d37 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -168,7 +168,7 @@ static command_t commands[] = {
       "Compact the notmuch database." },
     { "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,
@@ -460,7 +460,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" },
@@ -548,7 +548,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;
diff --git a/test/T030-config.sh b/test/T030-config.sh
index 67c9545c..14d1f4f2 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -96,14 +96,17 @@ 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"
 
+db_path=${HOME}/database-path
+
 test_begin_subtest "Absolute database path returned"
-notmuch config set database.path ${HOME}/Maildir
+mkdir -p ${db_path}
+notmuch config set database.path ${db_path}
 test_expect_equal "$(notmuch config get database.path)" \
-		  "${HOME}/Maildir"
+		  "${db_path}"
 
 test_begin_subtest "Relative database path properly expanded"
-notmuch config set database.path Maildir
+notmuch config set database.path ${db_path}
 test_expect_equal "$(notmuch config get database.path)" \
-		  "${HOME}/Maildir"
+		  "${db_path}"
 
 test_done
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 01a9ac06..cf294d04 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -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));
-- 
2.30.0

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

* [PATCH 11/18] WIP: CLI/config: use merged config for "config get"
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (9 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 10/18] CLI/config: WIP: load merged config David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 12/18] WIP: switch notmuch-setup to new configuration framework David Bremner
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

---
 notmuch-config.c    | 92 +++++----------------------------------------
 test/T030-config.sh | 20 +++++++++-
 2 files changed, 28 insertions(+), 84 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index 0193401f..a4613227 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -862,89 +862,17 @@ _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_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);
-
-    return EXIT_SUCCESS;
-}
-
 static int
-notmuch_config_command_get (notmuch_config_t *config, char *item)
+notmuch_config_command_get (notmuch_database_t *notmuch, 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);
+    notmuch_config_values_t *list;
+    for (list = notmuch_database_get_config_values (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
@@ -1105,7 +1033,7 @@ notmuch_config_command_list (notmuch_config_t *config)
 }
 
 int
-notmuch_config_command (notmuch_config_t *config, unused(notmuch_database_t *notmuch), int argc, char *argv[])
+notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch, int argc, char *argv[])
 {
     int ret;
     int opt_index;
@@ -1133,7 +1061,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 14d1f4f2..023e97b3 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,6 +99,18 @@ 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"
@@ -109,4 +124,5 @@ notmuch config set database.path ${db_path}
 test_expect_equal "$(notmuch config get database.path)" \
 		  "${db_path}"
 
+
 test_done
-- 
2.30.0

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

* [PATCH 12/18] WIP: switch notmuch-setup to new configuration framework
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (10 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 11/18] WIP: CLI/config: use merged config for "config get" David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 13/18] WIP: CLI/config: switch list to new config David Bremner
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

---
 notmuch-setup.c | 55 +++++++++++++++++++++++--------------------------
 notmuch.c       | 19 ++++++++++-------
 2 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/notmuch-setup.c b/notmuch-setup.c
index 67214470..1e22412b 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;
-
-    for (i = 0; i < tags_len; i++) {
-	if (i != 0)
-	    printf (" ");
-	printf ("%s", tags[i]);
+    bool first = false;
+
+    for (;
+	 notmuch_config_values_valid(tags);
+	 notmuch_config_values_move_to_next (tags)) {
+	if (!first)
+	    printf(" ");
+	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 90504d37..7beeb177 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -139,9 +139,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 | NOTMUCH_COMMAND_DATABASE_CREATE,
@@ -374,7 +376,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",
@@ -558,14 +560,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.0

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

* [PATCH 13/18] WIP: CLI/config: switch list to new config
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (11 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 12/18] WIP: switch notmuch-setup to new configuration framework David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 14/18] CLI/config: migrate notmuch_config_open " David Bremner
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

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 ++++++++----------
 test/T040-setup.sh  | 27 +++++++++++-------
 3 files changed, 40 insertions(+), 83 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index a4613227..f46e5c27 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -969,69 +969,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[])
 {
@@ -1070,7 +1023,7 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch, i
 	}
 	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 023e97b3..d974850f 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
 
diff --git a/test/T040-setup.sh b/test/T040-setup.sh
index 1223ebf7..87d386fd 100755
--- a/test/T040-setup.sh
+++ b/test/T040-setup.sh
@@ -20,18 +20,25 @@ foo bar
 baz
 EOF
 
-output=$(notmuch --config=new-notmuch-config config list | notmuch_built_with_sanitize)
-test_expect_equal "$output" "\
+cat <<EOF > EXPECTED
+built_with.compact=something
+built_with.field_processor=something
+built_with.retry_lock=something
+database.mail_root=/path/to/maildir
 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;
+maildir.synchronize_flags=true
 new.ignore=
+new.tags=foo;bar;
 search.exclude_tags=baz;
-maildir.synchronize_flags=true
-built_with.compact=something
-built_with.field_processor=something
-built_with.retry_lock=something"
+user.name=Test Suite
+user.other_email=another.suite@example.com;
+user.primary_email=test.suite@example.com
+EOF
+
+notmuch --config=new-notmuch-config config list | notmuch_built_with_sanitize > OUTPUT
+
+test_expect_equal_file EXPECTED OUTPUT
+
+
 
 test_done
-- 
2.30.0

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

* [PATCH 14/18] CLI/config: migrate notmuch_config_open to new config
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (12 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 13/18] WIP: CLI/config: switch list to new config David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 15/18] WIP: cli/config: convert to new config API David Bremner
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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       | 157 +----------------------------------------
 notmuch.c              |   2 +-
 test/T030-config.sh    |   2 +-
 test/T590-libconfig.sh |  12 ++--
 6 files changed, 15 insertions(+), 165 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 03ba2731..44cbe711 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -575,7 +575,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:
@@ -592,9 +592,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 db88daf8..dfdfc876 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -262,7 +262,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 f46e5c27..3d0959fb 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -141,69 +141,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,12 +259,10 @@ 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;
@@ -336,7 +271,7 @@ notmuch_config_open (void *ctx,
     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,15 +303,10 @@ 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");
@@ -386,87 +316,6 @@ notmuch_config_open (void *ctx,
     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);
diff --git a/notmuch.c b/notmuch.c
index 7beeb177..093af0a5 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -577,7 +577,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 d974850f..9a43c1e4 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 cf294d04..75b47073 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
-- 
2.30.0

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

* [PATCH 15/18] WIP: cli/config: convert to new config API
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (13 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 14/18] CLI/config: migrate notmuch_config_open " David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 16/18] cli/config: drop obsolete notmuch_config_get_* David Bremner
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

---
 notmuch-config.c         | 16 +++++++---------
 test/T750-user-header.sh |  3 ++-
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index 3d0959fb..390998b1 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -725,9 +725,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) {
@@ -740,12 +739,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;
@@ -758,7 +756,7 @@ _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;
@@ -773,7 +771,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))
@@ -870,7 +868,7 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch, i
 		     "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.0

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

* [PATCH 16/18] cli/config: drop obsolete notmuch_config_get_*
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (14 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 15/18] WIP: cli/config: convert to new config API David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 17/18] CLI/config: drop cached data from notmuch_config_t David Bremner
  2021-02-20 16:44 ` [PATCH 18/18] WIP: CLI/config: make storing configuration in database optional David Bremner
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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 | 119 -----------------------------------------------
 2 files changed, 148 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index dfdfc876..677f2f39 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -275,70 +275,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 390998b1..1382b0a3 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -359,9 +359,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.
@@ -425,22 +422,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)
@@ -452,38 +433,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,
@@ -497,24 +446,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)
@@ -522,12 +453,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)
@@ -535,12 +460,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)
@@ -548,30 +467,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[],
@@ -599,14 +494,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[],
@@ -881,12 +768,6 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch, i
 
 }
 
-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.0

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

* [PATCH 17/18] CLI/config: drop cached data from notmuch_config_t
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (15 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 16/18] cli/config: drop obsolete notmuch_config_get_* David Bremner
@ 2021-02-20 16:44 ` David Bremner
  2021-02-20 16:44 ` [PATCH 18/18] WIP: CLI/config: make storing configuration in database optional David Bremner
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 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 1382b0a3..0b2976f4 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -117,19 +117,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
@@ -141,7 +128,6 @@ notmuch_config_destructor (notmuch_config_t *config)
     return 0;
 }
 
-
 static bool
 get_config_from_file (notmuch_config_t *config, bool create_new)
 {
@@ -280,9 +266,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"))) {
@@ -423,48 +406,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
@@ -472,8 +447,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
@@ -481,8 +455,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
@@ -490,8 +463,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
@@ -499,8 +471,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);
 }
 
 
@@ -774,5 +745,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.0

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

* [PATCH 18/18] WIP: CLI/config: make storing configuration in database optional
  2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
                   ` (16 preceding siblings ...)
  2021-02-20 16:44 ` [PATCH 17/18] CLI/config: drop cached data from notmuch_config_t David Bremner
@ 2021-02-20 16:44 ` David Bremner
  17 siblings, 0 replies; 19+ messages in thread
From: David Bremner @ 2021-02-20 16:44 UTC (permalink / raw)
  To: notmuch; +Cc: David Bremner

Originally I planned to drop this functionality, but it is useful
e.g. for our test suite to be able to set config keys in the database
without using notmuch-restore.

New option needs documentation
---
 notmuch-config.c           | 26 ++++++++++++++++++--------
 test/T030-config.sh        | 19 +++++++++++++++++++
 test/T600-named-queries.sh | 17 +++++++----------
 test/T750-user-header.sh   |  8 --------
 4 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index 0b2976f4..f786e462 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -543,16 +543,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 *
@@ -614,7 +613,9 @@ _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, int argc, char *argv[])
+notmuch_config_command_set (notmuch_config_t *config, notmuch_database_t *notmuch,
+			    char *item, bool update_db,
+			    int argc, char *argv[])
 {
     char *group, *key;
     config_key_info_t *key_info;
@@ -628,7 +629,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_db) {
 	return _set_db_config (notmuch, item, argc, argv);
     }
 
@@ -695,11 +696,20 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch, i
 {
     int ret;
     int opt_index;
+    bool update_database;
 
-    opt_index = notmuch_minimal_options ("config", argc, argv);
+    notmuch_opt_desc_t options[] = {
+	{ .opt_bool = &update_database, .name = "database" },
+	{ .opt_inherit = notmuch_shared_options },
+	{ }
+    };
+
+    opt_index = parse_arguments (argc, argv, options, 1);
     if (opt_index < 0)
 	return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (notmuch_requested_db_uuid)
 	fprintf (stderr, "Warning: ignoring --uuid=%s\n",
 		 notmuch_requested_db_uuid);
@@ -726,7 +736,7 @@ notmuch_config_command (notmuch_config_t *config, notmuch_database_t *notmuch, i
 		     "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, argv[1], update_database, argc - 2, argv + 2);
     } 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 9a43c1e4..31aa550c 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -121,5 +121,24 @@ notmuch config set database.path ${db_path}
 test_expect_equal "$(notmuch config get database.path)" \
 		  "${db_path}"
 
+test_begin_subtest "Add config to database"
+notmuch new
+key=g${RANDOM}.m${RANDOM}
+value=${RANDOM}
+notmuch config --database set ${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 --database set ${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..d70156eb 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 --database set 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 --database set 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 --database set query.big "$(seq -s' ' $repeat)"
 notmuch dump --include=config > OUTPUT
-notmuch config set query.big ''
+notmuch config --database set 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 --database set 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.0

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

end of thread, other threads:[~2021-02-20 16:47 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-20 16:44 RFC convert remaining CLI to new configuration David Bremner
2021-02-20 16:44 ` [PATCH 01/18] lib: add missing status strings David Bremner
2021-02-20 16:44 ` [PATCH 02/18] test: convert random-corpus to use n_d_open_with_config David Bremner
2021-02-20 16:44 ` [PATCH 03/18] lib/open: pull _load_key_file out of _choose_database_path David Bremner
2021-02-20 16:44 ` [PATCH 04/18] WIP: add notmuch_database_load_config David Bremner
2021-02-20 16:44 ` [PATCH 05/18] WIP: add n_d_get_config_values David Bremner
2021-02-20 16:44 ` [PATCH 06/18] lib/config: add config_pairs iterators David Bremner
2021-02-20 16:44 ` [PATCH 07/18] lib/config: set defaults for user full name David Bremner
2021-02-20 16:44 ` [PATCH 08/18] lib/config: set default for primary user email David Bremner
2021-02-20 16:44 ` [PATCH 09/18] CLI/notmuch: replace use of notmuch_config_get_* David Bremner
2021-02-20 16:44 ` [PATCH 10/18] CLI/config: WIP: load merged config David Bremner
2021-02-20 16:44 ` [PATCH 11/18] WIP: CLI/config: use merged config for "config get" David Bremner
2021-02-20 16:44 ` [PATCH 12/18] WIP: switch notmuch-setup to new configuration framework David Bremner
2021-02-20 16:44 ` [PATCH 13/18] WIP: CLI/config: switch list to new config David Bremner
2021-02-20 16:44 ` [PATCH 14/18] CLI/config: migrate notmuch_config_open " David Bremner
2021-02-20 16:44 ` [PATCH 15/18] WIP: cli/config: convert to new config API David Bremner
2021-02-20 16:44 ` [PATCH 16/18] cli/config: drop obsolete notmuch_config_get_* David Bremner
2021-02-20 16:44 ` [PATCH 17/18] CLI/config: drop cached data from notmuch_config_t David Bremner
2021-02-20 16:44 ` [PATCH 18/18] WIP: CLI/config: make storing configuration in database optional 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


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