From fd6f8e6c30e0443d1ead248047ab572120df85e9 Mon Sep 17 00:00:00 2001 From: David Bremner Date: Sat, 8 Aug 2020 11:16:49 -0300 Subject: [PATCH] lib/config: add config values iterator This is intended to avoid duplicating the string splitting and traversal code for all clients of the config API. --- lib/config.cc | 52 ++++++++++++++++++++++++++++++++++ lib/notmuch.h | 64 ++++++++++++++++++++++++++++++++++++++++++ notmuch.c | 35 +++++++++++++++++++---- test/T590-libconfig.sh | 48 ++++++++++++++++++++++++++++++- 4 files changed, 192 insertions(+), 7 deletions(-) diff --git a/lib/config.cc b/lib/config.cc index a6b75913..0fe9a268 100644 --- a/lib/config.cc +++ b/lib/config.cc @@ -31,6 +31,11 @@ struct _notmuch_config_list { char *current_val; }; +struct _notmuch_config_values { + const char *iterator; + size_t tok_len; +}; + static const char * _notmuch_config_key_to_string (notmuch_config_key_t key); static int @@ -248,6 +253,53 @@ _notmuch_config_load_from_database (notmuch_database_t *notmuch) return status; } +notmuch_config_values_t * +notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key) +{ + notmuch_config_values_t *values; + + const char *str; + const char *key_str = _notmuch_config_key_to_string (key); + + if (! key_str) + return NULL; + + str = _notmuch_string_map_get (notmuch->config, key_str); + if (! str) + return NULL; + + values = talloc (notmuch, notmuch_config_values_t); + if (unlikely(! values)) + return NULL; + + values->iterator = strsplit_len (str, ';', &(values->tok_len)); + return values; +} + +notmuch_bool_t +notmuch_config_values_valid (notmuch_config_values_t *values) { + if (! values) + return false; + + return (values->iterator != NULL); +} + +const char * +notmuch_config_values_get (notmuch_config_values_t *values) { + return talloc_strndup (values, values->iterator, values->tok_len); +} + +void +notmuch_config_values_move_to_next (notmuch_config_values_t *values) { + values->iterator += values->tok_len; + values->iterator = strsplit_len (values->iterator, ';', &(values->tok_len)); +} + +void +notmuch_config_values_destroy (notmuch_config_values_t *values) { + talloc_free (values); +} + 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 5c35b44b..7aeff567 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -236,6 +236,7 @@ typedef struct _notmuch_tags notmuch_tags_t; 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_indexopts notmuch_indexopts_t; #endif /* __DOXYGEN__ */ @@ -2456,6 +2457,69 @@ notmuch_config_get (notmuch_database_t *notmuch, notmuch_config_key_t key); notmuch_status_t notmuch_config_set (notmuch_database_t *notmuch, notmuch_config_key_t key, const char *val); +/** + * Returns an iterator for a ';'-delimited list of configuration values + * + * These values reflect all configuration information given at the + * time the database was opened. + * + * @param[in] notmuch database + * @param[in] key configuration key + * + * @since libnotmuch 5.4 (notmuch 0.32) + * + * @retval NULL in case of error. + */ +notmuch_config_values_t * +notmuch_config_get_values (notmuch_database_t *notmuch, notmuch_config_key_t key); + +/** + * Is the given 'config_values' iterator pointing at a valid element. + * + * @param[in] values iterator + * + * @since libnotmuch 5.4 (notmuch 0.32) + * + * @retval FALSE if passed a NULL pointer, or the iterator is exhausted. + * + */ +notmuch_bool_t +notmuch_config_values_valid (notmuch_config_values_t *values); + +/** + * Get the current value from the 'values' iterator + * + * @param[in] values iterator + * + * @since libnotmuch 5.4 (notmuch 0.32) + * + * @retval a string with the same lifetime as the iterator + */ +const char * +notmuch_config_values_get (notmuch_config_values_t *values); + +/** + * Move the 'values' iterator to the next element + * + * @param[in,out] values iterator + * + * @since libnotmuch 5.4 (notmuch 0.32) + * + */ +void +notmuch_config_values_move_to_next (notmuch_config_values_t *values); + +/** + * Destroy a config values iterator, along with any associated + * resources. + * + * @param[in,out] values iterator + * + * @since libnotmuch 5.4 (notmuch 0.32) + */ +void +notmuch_config_values_destroy (notmuch_config_values_t *values); + /** * get the current default indexing options for a given database. * diff --git a/notmuch.c b/notmuch.c index fd4a7945..e0649048 100644 --- a/notmuch.c +++ b/notmuch.c @@ -457,6 +457,7 @@ main (int argc, char *argv[]) command_t *command; const char *config_file_name = NULL; notmuch_config_t *config = NULL; + notmuch_database_t *notmuch = NULL; int opt_index; int ret; @@ -500,13 +501,35 @@ main (int argc, char *argv[]) goto DONE; } - config = notmuch_config_open (local, config_file_name, command->mode); - if (! config) { - ret = EXIT_FAILURE; - goto DONE; - } + if (command->mode & NOTMUCH_COMMAND_DATABASE_EARLY) { + char *status_string = NULL; + notmuch_database_mode_t mode; + if (command->mode & NOTMUCH_COMMAND_DATABASE_WRITE) + mode = NOTMUCH_DATABASE_MODE_READ_WRITE; + else + mode = NOTMUCH_DATABASE_MODE_READ_ONLY; + + if (notmuch_database_open_with_config (NULL, + mode, + config_file_name, + NULL, + ¬much, + &status_string)) { + if (status_string) { + fputs (status_string, stderr); + free (status_string); + } - ret = (command->function)(config, NULL, argc - opt_index, argv + opt_index); + return EXIT_FAILURE; + } + } else { + config = notmuch_config_open (local, config_file_name, command->mode); + if (! config) { + ret = EXIT_FAILURE; + goto DONE; + } + } + ret = (command->function)(config, notmuch, argc - opt_index, argv + opt_index); DONE: if (config) diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh index 0c148ad9..efbee61d 100755 --- a/test/T590-libconfig.sh +++ b/test/T590-libconfig.sh @@ -201,9 +201,55 @@ EOF test_expect_equal_file EXPECTED OUTPUT restore_database +test_begin_subtest "notmuch_config_get_values" +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% +{ + notmuch_config_values_t *values; + EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c")); + for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS); + notmuch_config_values_valid (values); + notmuch_config_values_move_to_next (values)) + { + puts (notmuch_config_values_get (values)); + } +} +EOF +cat <<'EOF' >EXPECTED +== stdout == +a +b +c +== stderr == +EOF +test_expect_equal_file EXPECTED OUTPUT +restore_database + +backup_database +test_begin_subtest "notmuch_config_get_values, trailing ;" +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% +{ + notmuch_config_values_t *values; + EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c")); + for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS); + notmuch_config_values_valid (values); + notmuch_config_values_move_to_next (values)) + { + puts (notmuch_config_values_get (values)); + } +} +EOF +cat <<'EOF' >EXPECTED +== stdout == +a +b +c +== stderr == +EOF +test_expect_equal_file EXPECTED OUTPUT +restore_database + backup_database test_begin_subtest "get config by key" -notmuch config set test.key1 overridden cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} { printf("before = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS)); -- 2.43.0