From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id FDqoEwZhDWCfCAAA0tVLHw (envelope-from ) for ; Sun, 24 Jan 2021 11:59:02 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id SJfzDgZhDWBPUQAA1q6Kng (envelope-from ) for ; Sun, 24 Jan 2021 11:59:02 +0000 Received: from mail.notmuchmail.org (nmbug.tethera.net [144.217.243.247]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (2048 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 7EBA89404C4 for ; Sun, 24 Jan 2021 11:59:00 +0000 (UTC) Received: from nmbug.tethera.net (localhost [127.0.0.1]) by mail.notmuchmail.org (Postfix) with ESMTP id 6FC452BF52; Sun, 24 Jan 2021 06:58:54 -0500 (EST) Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) by mail.notmuchmail.org (Postfix) with ESMTPS id 5C0CC29ED5 for ; Sun, 24 Jan 2021 06:58:51 -0500 (EST) Received: from guru.guru-group.fi (unknown [IPv6:2a02:2380:1:9:5054:ff:feb7:a4bc]) (using TLSv1.2 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: too) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 2413E1B0011D; Sun, 24 Jan 2021 13:58:50 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1611489530; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=YJSSMGsXmxH3kYhddc2d9Zphw7pPka4PlM8sVxR9h6g=; b=VITh1Pgqg+ayBOfUFkk/4wn48dcPOiwwxjXmedqB4gn0Ct9v7Z+krxQ5tQUp7WD2XOVEzd tztU23T4FwlTm4YCbo7rDJEzbe1GijdVEE0oczJKN2EooV2C7PjBBjYn3bgn793v7KFBjR 6SLNToU2BqAQCvPXOefFtgKho+fYKYqeULN2c/+WDkQbZqCahVBJ9caKI8X4VTyqCx0tU9 OVzECs+/el0YJYUccA1qmzzdNfieGLIB1W+T5rYBV0ydrn8I9ZKpK9QHJAK0ycvSnBFQQY GGMbodQkApjsjv3g32rp25bSZllhMJpX4t2FMNevOtuLlZ0e0WhCTvf/y2GkUw== From: Tomi Ollila To: David Bremner , notmuch@notmuchmail.org Cc: David Bremner Subject: Re: [PATCH 04/38] lib/open: add support for config profiles and default locations In-Reply-To: <20210116170406.842014-5-david@tethera.net> References: <20210116170406.842014-1-david@tethera.net> <20210116170406.842014-5-david@tethera.net> User-Agent: Notmuch/0.31.3+85~g92bd77f (https://notmuchmail.org) Emacs/27.1 X-Face: HhBM'cA~ MIME-Version: 1.0 ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1611489530; a=rsa-sha256; cv=none; b=AJ7L5LcXPK2TbyD7/XgTH1yux88CCZ8fUPCbMz+UKZ5wvWXb2U/9GjFQnuyCRY97QAQXHa vGlYdoNOiUXJNF513a3QFjLub7zQypeIGkaeqOdQ61h0PoVvaO7+io1lVqvz6cNL3eHppS mpIxK+ykdA1D1sBR5LKJulAG9UbOMW/H3kcSPz915X7guk2Ee94aP+0vDOYxpjWlQ+oZ0k 26FNgiWH8238roy/38V0KnkO2U4RFrLb7lui35TfyCvQQKtNziOFUohe00bh5U7R+XLv3y rrcYrYcPArLLnH8IHbqF7HmMt6Efb6CgjCyUzZotVYXECrE/8V2vXhc3Ohqt/Q== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=too smtp.mailfrom=tomi.ollila@iki.fi ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1611489530; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=YJSSMGsXmxH3kYhddc2d9Zphw7pPka4PlM8sVxR9h6g=; b=Hz64E5E71ztN2+haeA97R9RXvHUwA/08+YwqOCRpIj1o62s2sWzWUU5EHPyfwx4kKe3WQs hAo2WSrGnw54KavJjhpcqmGKfUWo1retfGqcwy9Xc0ATpKsh/0sU2D2XdwdawvLnYU0NUS +sH/rz9Q8Z3CZubQ0YqI1lLhP8RIXZfGlIr64GdwFPEW7DXpe8XfJJ+DL0p66xEsw+GeJ5 2jaaPp02l/zpZGCga1Mii4tec+Wz2D+j6nYQBFH4uNwFc+PDCLyiaZywGzd1rpHz2kC/bL HryVfiibSgj7chVYfTnfZR463VnnGYAlk3b/pVqv6znhqBvJ8dhFJx53PFvRLQ== Message-ID-Hash: MDKZVA6AELYWMPQQCZCM4HTX73GTQFGD X-Message-ID-Hash: MDKZVA6AELYWMPQQCZCM4HTX73GTQFGD X-MailFrom: tomi.ollila@iki.fi X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-notmuch.notmuchmail.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.1 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: 0.93 Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=iki.fi header.s=lahtoruutu header.b=VITh1Pgq; arc=reject ("signature check failed: fail, {[1] = sig:iki.fi:reject}"); dmarc=none; spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 144.217.243.247 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org X-Migadu-Queue-Id: 7EBA89404C4 X-Spam-Score: 0.93 X-Migadu-Scanner: scn0.migadu.com X-TUID: 4eS4/kQjTNA5 On Sat, Jan 16 2021, David Bremner wrote: In id:20210116170406.842014-4-david@tethera.net there is missing space after , gchar **groups,**keys, *val; Here, perhaps s/This commits fills in/Fill in/ (?) > This commit fills in the remainder of the documented functionality for > n_d_open_with_config with respect to config file location. Similar > searching default locations of the database file still needs to be > added. > --- > lib/open.cc | 95 +++++++++++++++++++++---- > test/T590-libconfig.sh | 153 ++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 227 insertions(+), 21 deletions(-) > > diff --git a/lib/open.cc b/lib/open.cc > index 7acaea7b..76255283 100644 > --- a/lib/open.cc > +++ b/lib/open.cc > @@ -37,6 +37,82 @@ notmuch_database_open_verbose (const char *path, > database, status_string); > } > > +static const char * > +_xdg_dir (void *ctx, > + const char *xdg_root_variable, > + const char *xdg_prefix, > + const char *profile_name) > +{ > + const char *xdg_root = getenv (xdg_root_variable); > + const char *home = getenv ("HOME"); Resolving HOME from env is not needed always, move it inside next if() -- that will also make its scope smaller. > + > + if (! xdg_root) { > + if (! home) return NULL; > + > + xdg_root = talloc_asprintf (ctx, > + "%s/%s", > + home, > + xdg_prefix); > + } > + > + if (! profile_name) > + profile_name = getenv ("NOTMUCH_PROFILE"); > + > + if (! profile_name) > + profile_name = "default"; > + > + return talloc_asprintf (ctx, > + "%s/notmuch/%s", > + xdg_root, > + profile_name); > +} > + > +static notmuch_status_t > +_load_key_file (const char *path, > + const char *profile, > + GKeyFile **key_file) > +{ > + notmuch_status_t status = NOTMUCH_STATUS_SUCCESS; > + void *local = talloc_new (NULL); > + > + if (path && EMPTY_STRING (path)) > + goto DONE; > + > + if (! path) > + path = getenv ("NOTMUCH_CONFIG"); > + > + if (! path) { > + const char *dir = _xdg_dir (local, "XDG_CONFIG_HOME", ".config", profile); > + > + if (dir) { > + path = talloc_asprintf (local, "%s/config", dir); > + if (access (path, R_OK) !=0) > + path = NULL; > + } > + } > + > + if (! path) { > + const char *home = getenv ("HOME"); > + > + path = talloc_asprintf (local, "%s/.notmuch-config", home); > + > + if (! profile) > + profile = getenv ("NOTMUCH_PROFILE"); > + > + if (profile) > + path = talloc_asprintf (local, "%s.%s", path, profile); > + } > + > + *key_file = g_key_file_new (); > + if (! g_key_file_load_from_file (*key_file, path, G_KEY_FILE_NONE, NULL)) { > + status = NOTMUCH_STATUS_FILE_ERROR; > + } > + > +DONE: > + talloc_free (local); > + return status; > +} > + > notmuch_status_t > notmuch_database_open_with_config (const char *database_path, > notmuch_database_mode_t mode, > @@ -49,7 +125,6 @@ notmuch_database_open_with_config (const char *database_path, > void *local = talloc_new (NULL); > notmuch_database_t *notmuch = NULL; > char *notmuch_path, *xapian_path, *incompat_features; > - char *configured_database_path = NULL; > char *message = NULL; > struct stat st; > int err; > @@ -57,18 +132,14 @@ notmuch_database_open_with_config (const char *database_path, > GKeyFile *key_file = NULL; > static int initialized = 0; > > - /* XXX TODO: default locations for NULL case, handle profiles */ > - if (config_path != NULL && ! EMPTY_STRING (config_path)) { > - key_file = g_key_file_new (); > - if (! g_key_file_load_from_file (key_file, config_path, G_KEY_FILE_NONE, NULL)) { > - status = NOTMUCH_STATUS_FILE_ERROR; > - goto DONE; > - } > - configured_database_path = g_key_file_get_value (key_file, "database", "path", NULL); > + status = _load_key_file (config_path, profile, &key_file); > + if (status) { > + message = strdup ("Error: cannot load config file"); > + goto DONE; > } > - > - if (database_path == NULL) > - database_path = configured_database_path; > + > + if (! database_path && key_file) > + database_path = g_key_file_get_value (key_file, "database", "path", NULL); > > if (database_path == NULL) { > message = strdup ("Error: Cannot open a database for a NULL path.\n"); > diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh > index 5fb1bb87..2986284a 100755 > --- a/test/T590-libconfig.sh > +++ b/test/T590-libconfig.sh > @@ -15,14 +15,21 @@ int main (int argc, char** argv) > notmuch_database_t *db; > char *val; > notmuch_status_t stat; > + char *msg = NULL; > > - EXPECT0(notmuch_database_open_with_config (argv[1], > + for (int i=1; i + if (strcmp (argv[i], "%NULL%") == 0) argv[i] = NULL; > + > + stat = notmuch_database_open_with_config (argv[1], > NOTMUCH_DATABASE_MODE_READ_WRITE, > argv[2], > - NULL, > + argv[3], > &db, > - NULL)); > - > + &msg); > + if (stat != NOTMUCH_STATUS_SUCCESS) { > + fprintf (stderr, "error opening database: %d %s\n", stat, msg ? msg : ""); > + exit (1); > + } > EOF > > cat < c_tail > @@ -51,7 +58,7 @@ test_expect_equal_file EXPECTED OUTPUT > > > test_begin_subtest "notmuch_database_get_config_list: empty list" > -cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} > +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% > { > notmuch_config_list_t *list; > EXPECT0(notmuch_database_get_config_list (db, "nonexistent", &list)); > @@ -83,7 +90,7 @@ EOF > test_expect_equal_file EXPECTED OUTPUT > > test_begin_subtest "notmuch_database_get_config_list: all pairs" > -cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} > +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% > { > notmuch_config_list_t *list; > EXPECT0(notmuch_database_set_config (db, "zzzafter", "afterval")); > @@ -128,7 +135,7 @@ EOF > test_expect_equal_file EXPECTED OUTPUT > > test_begin_subtest "notmuch_database_get_config_list: one prefix" > -cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} > +cat c_head - 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)); > @@ -147,7 +154,7 @@ EOF > test_expect_equal_file EXPECTED OUTPUT > > test_begin_subtest "dump config" > -cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} > +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% > { > EXPECT0(notmuch_database_set_config (db, "key with spaces", "value, with, spaces!")); > } > @@ -165,7 +172,7 @@ test_expect_equal_file EXPECTED OUTPUT > > test_begin_subtest "restore config" > notmuch dump --include=config >EXPECTED > -cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} > +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% > { > EXPECT0(notmuch_database_set_config (db, "test.key1", "mutatedvalue")); > } > @@ -194,4 +201,132 @@ EOF > test_expect_equal_file EXPECTED OUTPUT > restore_database > > +backup_database > +test_begin_subtest "override config from \${NOTMUCH_CONFIG}" > +notmuch config set test.key1 overridden > +# second argument omitted to make argv[2] == NULL > +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} > +{ > + 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 > +notmuch config set test.key1 > +cat <<'EOF' >EXPECTED > +== stdout == > +test.key1 = overridden > +test.key2 = testvalue2 > +== stderr == > +EOF > +test_expect_equal_file EXPECTED OUTPUT > +restore_database > + > +backup_database > +test_begin_subtest "override config from \${HOME}/.notmuch-config" > +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_head - 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 > + > +backup_database > +test_begin_subtest "override config from \${XDG_CONFIG_HOME}/notmuch" > +ovconfig=${HOME}/.config/notmuch/default/config > +mkdir -p $(dirname ${ovconfig}) > +cp ${NOTMUCH_CONFIG} ${ovconfig} > +old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG} > +unset NOTMUCH_CONFIG > +notmuch --config=${ovconfig} config set test.key1 overridden-xdg > +cat c_head - 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-xdg > +test.key2 = testvalue2 > +== stderr == > +EOF > +test_expect_equal_file EXPECTED OUTPUT > +restore_database > + > +backup_database > +test_begin_subtest "override config from \${XDG_CONFIG_HOME}/notmuch with profile" > +ovconfig=${HOME}/.config/notmuch/work/config > +mkdir -p $(dirname ${ovconfig}) > +cp ${NOTMUCH_CONFIG} ${ovconfig} > +old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG} > +unset NOTMUCH_CONFIG > +notmuch --config=${ovconfig} config set test.key1 overridden-xdg-profile > +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% work > +{ > + 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-xdg-profile > +test.key2 = testvalue2 > +== stderr == > +EOF > +test_expect_equal_file EXPECTED OUTPUT > +restore_database > + > +backup_database > +test_begin_subtest "override config from \${HOME}/.notmuch-config.work (via args)" (left out comments where "s could be replaced w/ 's (and w/o \ before $)) > +ovconfig=${HOME}/.notmuch-config.work > +cp ${NOTMUCH_CONFIG} ${ovconfig} > +old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG} > +unset NOTMUCH_CONFIG > +notmuch --config=${ovconfig} config set test.key1 overridden-profile > +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% work > +{ > + 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-profile > +test.key2 = testvalue2 > +== stderr == > +EOF > +test_expect_equal_file EXPECTED OUTPUT > +restore_database > + > test_done > -- > 2.29.2