From 22db9ed893e9f44c216f9c32157be2a782dc3812 Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Sun, 31 Mar 2019 20:06:05 +0200 Subject: [PATCH] Ignore unknown keys in configuration files This way legacy ccache versions can still work with modern ccache configuration keys in the configuration files. The downside is of course that errors like typos no longer will be corrected. --- doc/NEWS.adoc | 2 ++ src/conf.c | 26 +++++++++++++++++--------- unittest/test_conf.c | 22 +++++++++++++++++----- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/doc/NEWS.adoc b/doc/NEWS.adoc index 5da73720f..44cabf638 100644 --- a/doc/NEWS.adoc +++ b/doc/NEWS.adoc @@ -34,6 +34,8 @@ Changes * The rewriting of absolute paths into relative paths in the dependency file is now enabled in the depend mode as well. +* ccache now ignores unknown keys in configuration files. + ccache 3.6 ---------- diff --git a/src/conf.c b/src/conf.c index 4c7d35df3..9fe2f660e 100644 --- a/src/conf.c +++ b/src/conf.c @@ -19,6 +19,12 @@ #include "envtoconfitems.h" #include "ccache.h" +enum handle_conf_result { + HANDLE_CONF_OK, + HANDLE_CONF_UNKNOWN, + HANDLE_CONF_FAIL +}; + static const struct conf_item * find_conf(const char *name) { @@ -31,15 +37,14 @@ find_env_to_conf(const char *name) return envtoconfitems_get(name, strlen(name)); } -static bool +static enum handle_conf_result handle_conf_setting(struct conf *conf, const char *key, const char *value, char **errmsg, bool from_env_variable, bool negate_boolean, const char *origin) { const struct conf_item *item = find_conf(key); if (!item) { - *errmsg = format("unknown configuration option \"%s\"", key); - return false; + return HANDLE_CONF_UNKNOWN; } if (from_env_variable && item->parser == confitem_parse_bool) { @@ -61,15 +66,15 @@ handle_conf_setting(struct conf *conf, const char *key, const char *value, } if (!item->parser(value, (char *)conf + item->offset, errmsg)) { - return false; + return HANDLE_CONF_FAIL; } if (item->verifier && !item->verifier((char *)conf + item->offset, errmsg)) { - return false; + return HANDLE_CONF_FAIL; } out: conf->item_origins[item->number] = origin; - return true; + return HANDLE_CONF_OK; } static bool @@ -210,9 +215,12 @@ conf_read(struct conf *conf, const char *path, char **errmsg) char *key; char *value; char *errmsg2; + enum handle_conf_result hcr = HANDLE_CONF_OK; bool ok = parse_line(buf, &key, &value, &errmsg2); if (ok && key) { // key == NULL if comment or blank line. - ok = handle_conf_setting(conf, key, value, &errmsg2, false, false, path); + hcr = + handle_conf_setting(conf, key, value, &errmsg2, false, false, path); + ok = hcr != HANDLE_CONF_FAIL; // unknown is OK } free(key); free(value); @@ -266,10 +274,10 @@ conf_update_from_environment(struct conf *conf, char **errmsg) } char *errmsg2; - bool ok = handle_conf_setting( + enum handle_conf_result hcr = handle_conf_setting( conf, env_to_conf_item->conf_name, q, &errmsg2, true, negate, "environment"); - if (!ok) { + if (hcr != HANDLE_CONF_OK) { *errmsg = format("%s: %s", key, errmsg2); free(errmsg2); free(key); diff --git a/unittest/test_conf.c b/unittest/test_conf.c index 371a39516..9ef670857 100644 --- a/unittest/test_conf.c +++ b/unittest/test_conf.c @@ -203,15 +203,12 @@ TEST(conf_read_with_missing_equal_sign) conf_free(conf); } -TEST(conf_read_with_bad_config_key) +TEST(conf_read_with_unknown_config_key) { struct conf *conf = conf_create(); char *errmsg; create_file("ccache.conf", "# Comment\nfoo = bar"); - CHECK(!conf_read(conf, "ccache.conf", &errmsg)); - CHECK_INT_EQ(errno, 0); - CHECK_STR_EQ_FREE2("ccache.conf:2: unknown configuration option \"foo\"", - errmsg); + CHECK(conf_read(conf, "ccache.conf", &errmsg)); conf_free(conf); } @@ -392,6 +389,21 @@ TEST(conf_set_existing_value) CHECK_STR_EQ_FREE2("path = vanilla\nstats = chocolate\n", data); } +TEST(conf_set_unknown_option) +{ + char *errmsg; + char *data; + + create_file("ccache.conf", "path = chocolate\nstats = chocolate\n"); + CHECKM(!conf_set_value_in_file("ccache.conf", "foo", "bar", &errmsg), + errmsg); + CHECK_STR_EQ_FREE2("unknown configuration option \"foo\"", errmsg); + + data = read_text_file("ccache.conf", 0); + CHECK(data); + CHECK_STR_EQ_FREE2("path = chocolate\nstats = chocolate\n", data); +} + TEST(conf_print_existing_value) { struct conf *conf = conf_create(); -- 2.47.2