Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/for-each-repo.c14
-rw-r--r--builtin/gc.c15
-rw-r--r--builtin/log.c6
-rw-r--r--builtin/submodule--helper.c7
-rw-r--r--builtin/worktree.c3
-rw-r--r--config.c109
-rw-r--r--config.h72
-rw-r--r--pack-bitmap.c6
-rw-r--r--submodule.c3
-rw-r--r--t/helper/test-config.c28
-rwxr-xr-xt/t0068-for-each-repo.sh19
-rwxr-xr-xt/t1308-config-set.sh108
-rwxr-xr-xt/t3309-notes-merge-auto-resolve.sh7
-rwxr-xr-xt/t4202-log.sh15
-rwxr-xr-xt/t5304-prune.sh12
-rwxr-xr-xt/t5310-pack-bitmaps.sh20
-rwxr-xr-xt/t5552-skipping-fetch-negotiator.sh16
-rwxr-xr-xt/t7004-tag.sh17
-rwxr-xr-xt/t7413-submodule-is-active.sh16
-rwxr-xr-xt/t7900-maintenance.sh38
-rw-r--r--versioncmp.c22
21 files changed, 481 insertions, 72 deletions
diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c
index 6aeac37148..ce8f7a9908 100644
--- a/builtin/for-each-repo.c
+++ b/builtin/for-each-repo.c
@@ -32,6 +32,7 @@ int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
static const char *config_key = NULL;
int i, result = 0;
const struct string_list *values;
+ int err;
const struct option options[] = {
OPT_STRING(0, "config", &config_key, N_("config"),
@@ -45,14 +46,11 @@ int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
if (!config_key)
die(_("missing --config=<config>"));
- values = repo_config_get_value_multi(the_repository,
- config_key);
-
- /*
- * Do nothing on an empty list, which is equivalent to the case
- * where the config variable does not exist at all.
- */
- if (!values)
+ err = repo_config_get_string_multi(the_repository, config_key, &values);
+ if (err < 0)
+ usage_msg_optf(_("got bad config --config=%s"),
+ for_each_repo_usage, options, config_key);
+ else if (err)
return 0;
for (i = 0; !result && i < values->nr; i++)
diff --git a/builtin/gc.c b/builtin/gc.c
index c58fe8c936..efc1b9a0fd 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1494,7 +1494,6 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
};
int found = 0;
const char *key = "maintenance.repo";
- char *config_value;
char *maintpath = get_maintpath();
struct string_list_item *item;
const struct string_list *list;
@@ -1509,13 +1508,10 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
git_config_set("maintenance.auto", "false");
/* Set maintenance strategy, if unset */
- if (!git_config_get_string("maintenance.strategy", &config_value))
- free(config_value);
- else
+ if (git_config_get("maintenance.strategy"))
git_config_set("maintenance.strategy", "incremental");
- list = git_config_get_value_multi(key);
- if (list) {
+ if (!git_config_get_string_multi(key, &list)) {
for_each_string_list_item(item, list) {
if (!strcmp(maintpath, item->string)) {
found = 1;
@@ -1581,11 +1577,10 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
if (config_file) {
git_configset_init(&cs);
git_configset_add_file(&cs, config_file);
- list = git_configset_get_value_multi(&cs, key);
- } else {
- list = git_config_get_value_multi(key);
}
- if (list) {
+ if (!(config_file
+ ? git_configset_get_string_multi(&cs, key, &list)
+ : git_config_get_string_multi(key, &list))) {
for_each_string_list_item(item, list) {
if (!strcmp(maintpath, item->string)) {
found = 1;
diff --git a/builtin/log.c b/builtin/log.c
index 4693385e8e..0c6556b2d7 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -185,10 +185,10 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f
int i;
char *value = NULL;
struct string_list *include = decoration_filter->include_ref_pattern;
- const struct string_list *config_exclude =
- git_config_get_value_multi("log.excludeDecoration");
+ const struct string_list *config_exclude;
- if (config_exclude) {
+ if (!git_config_get_string_multi("log.excludeDecoration",
+ &config_exclude)) {
struct string_list_item *item;
for_each_string_list_item(item, config_exclude)
string_list_append(decoration_filter->exclude_ref_config_pattern,
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 65a053261a..6cd807471e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -559,7 +559,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
* If there are no path args and submodule.active is set then,
* by default, only initialize 'active' modules.
*/
- if (!argc && git_config_get_value_multi("submodule.active"))
+ if (!argc && !git_config_get("submodule.active"))
module_list_active(&list);
info.prefix = prefix;
@@ -2745,7 +2745,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
* If there are no path args and submodule.active is set then,
* by default, only initialize 'active' modules.
*/
- if (!argc && git_config_get_value_multi("submodule.active"))
+ if (!argc && !git_config_get("submodule.active"))
module_list_active(&list);
info.prefix = opt.prefix;
@@ -3142,7 +3142,6 @@ static int config_submodule_in_gitmodules(const char *name, const char *var, con
static void configure_added_submodule(struct add_data *add_data)
{
char *key;
- const char *val;
struct child_process add_submod = CHILD_PROCESS_INIT;
struct child_process add_gitmodules = CHILD_PROCESS_INIT;
@@ -3187,7 +3186,7 @@ static void configure_added_submodule(struct add_data *add_data)
* is_submodule_active(), since that function needs to find
* out the value of "submodule.active" again anyway.
*/
- if (!git_config_get_string_tmp("submodule.active", &val)) {
+ if (!git_config_get("submodule.active")) {
/*
* If the submodule being added isn't already covered by the
* current configured pathspec, set the submodule's active flag
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 80d05e246d..476325ef98 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -320,7 +320,6 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)
if (file_exists(from_file)) {
struct config_set cs = { { 0 } };
- const char *core_worktree;
int bare;
if (safe_create_leading_directories(to_file) ||
@@ -339,7 +338,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)
to_file, "core.bare", NULL, "true", 0))
error(_("failed to unset '%s' in '%s'"),
"core.bare", to_file);
- if (!git_configset_get_value(&cs, "core.worktree", &core_worktree) &&
+ if (!git_configset_get(&cs, "core.worktree") &&
git_config_set_in_file_gently(to_file,
"core.worktree", NULL))
error(_("failed to unset '%s' in '%s'"),
diff --git a/config.c b/config.c
index 0b2679994e..a30490fd58 100644
--- a/config.c
+++ b/config.c
@@ -2292,23 +2292,29 @@ void read_very_early_config(config_fn_t cb, void *data)
config_with_options(cb, data, NULL, &opts);
}
-static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
+RESULT_MUST_BE_USED
+static int configset_find_element(struct config_set *cs, const char *key,
+ struct config_set_element **dest)
{
struct config_set_element k;
struct config_set_element *found_entry;
char *normalized_key;
+ int ret;
+
/*
* `key` may come from the user, so normalize it before using it
* for querying entries from the hashmap.
*/
- if (git_config_parse_key(key, &normalized_key, NULL))
- return NULL;
+ ret = git_config_parse_key(key, &normalized_key, NULL);
+ if (ret)
+ return ret;
hashmap_entry_init(&k.ent, strhash(normalized_key));
k.key = normalized_key;
found_entry = hashmap_get_entry(&cs->config_hash, &k, ent, NULL);
free(normalized_key);
- return found_entry;
+ *dest = found_entry;
+ return 0;
}
static int configset_add_value(struct config_set *cs, const char *key, const char *value)
@@ -2317,8 +2323,11 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
struct string_list_item *si;
struct configset_list_item *l_item;
struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
+ int ret;
- e = configset_find_element(cs, key);
+ ret = configset_find_element(cs, key, &e);
+ if (ret)
+ return ret;
/*
* Since the keys are being fed by git_config*() callback mechanism, they
* are already normalized. So simply add them without any further munging.
@@ -2412,24 +2421,65 @@ int git_configset_add_file(struct config_set *cs, const char *filename)
int git_configset_get_value(struct config_set *cs, const char *key, const char **value)
{
const struct string_list *values = NULL;
+ int ret;
+
/*
* Follows "last one wins" semantic, i.e., if there are multiple matches for the
* queried key in the files of the configset, the value returned will be the last
* value in the value list for that key.
*/
- values = git_configset_get_value_multi(cs, key);
+ if ((ret = git_configset_get_value_multi(cs, key, &values)))
+ return ret;
- if (!values)
- return 1;
assert(values->nr > 0);
*value = values->items[values->nr - 1].string;
return 0;
}
-const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key)
+int git_configset_get_value_multi(struct config_set *cs, const char *key,
+ const struct string_list **dest)
+{
+ struct config_set_element *e;
+ int ret;
+
+ if ((ret = configset_find_element(cs, key, &e)))
+ return ret;
+ else if (!e)
+ return 1;
+ *dest = &e->value_list;
+
+ return 0;
+}
+
+static int check_multi_string(struct string_list_item *item, void *util)
+{
+ return item->string ? 0 : config_error_nonbool(util);
+}
+
+int git_configset_get_string_multi(struct config_set *cs, const char *key,
+ const struct string_list **dest)
+{
+ int ret;
+
+ if ((ret = git_configset_get_value_multi(cs, key, dest)))
+ return ret;
+ if ((ret = for_each_string_list((struct string_list *)*dest,
+ check_multi_string, (void *)key)))
+ return ret;
+
+ return 0;
+}
+
+int git_configset_get(struct config_set *cs, const char *key)
{
- struct config_set_element *e = configset_find_element(cs, key);
- return e ? &e->value_list : NULL;
+ struct config_set_element *e;
+ int ret;
+
+ if ((ret = configset_find_element(cs, key, &e)))
+ return ret;
+ else if (!e)
+ return 1;
+ return 0;
}
int git_configset_get_string(struct config_set *cs, const char *key, char **dest)
@@ -2568,6 +2618,12 @@ void repo_config(struct repository *repo, config_fn_t fn, void *data)
configset_iter(repo->config, fn, data);
}
+int repo_config_get(struct repository *repo, const char *key)
+{
+ git_config_check_init(repo);
+ return git_configset_get(repo->config, key);
+}
+
int repo_config_get_value(struct repository *repo,
const char *key, const char **value)
{
@@ -2575,11 +2631,18 @@ int repo_config_get_value(struct repository *repo,
return git_configset_get_value(repo->config, key, value);
}
-const struct string_list *repo_config_get_value_multi(struct repository *repo,
- const char *key)
+int repo_config_get_value_multi(struct repository *repo, const char *key,
+ const struct string_list **dest)
+{
+ git_config_check_init(repo);
+ return git_configset_get_value_multi(repo->config, key, dest);
+}
+
+int repo_config_get_string_multi(struct repository *repo, const char *key,
+ const struct string_list **dest)
{
git_config_check_init(repo);
- return git_configset_get_value_multi(repo->config, key);
+ return git_configset_get_string_multi(repo->config, key, dest);
}
int repo_config_get_string(struct repository *repo,
@@ -2682,14 +2745,25 @@ void git_config_clear(void)
repo_config_clear(the_repository);
}
+int git_config_get(const char *key)
+{
+ return repo_config_get(the_repository, key);
+}
+
int git_config_get_value(const char *key, const char **value)
{
return repo_config_get_value(the_repository, key, value);
}
-const struct string_list *git_config_get_value_multi(const char *key)
+int git_config_get_value_multi(const char *key, const struct string_list **dest)
+{
+ return repo_config_get_value_multi(the_repository, key, dest);
+}
+
+int git_config_get_string_multi(const char *key,
+ const struct string_list **dest)
{
- return repo_config_get_value_multi(the_repository, key);
+ return repo_config_get_string_multi(the_repository, key, dest);
}
int git_config_get_string(const char *key, char **dest)
@@ -2836,7 +2910,8 @@ void git_die_config(const char *key, const char *err, ...)
error_fn(err, params);
va_end(params);
}
- values = git_config_get_value_multi(key);
+ if (git_config_get_value_multi(key, &values))
+ BUG("for key '%s' we must have a value to report on", key);
kv_info = values->items[values->nr - 1].util;
git_die_config_linenr(key, kv_info->filename, kv_info->linenr);
}
diff --git a/config.h b/config.h
index 7606246531..4a6e3f19e5 100644
--- a/config.h
+++ b/config.h
@@ -450,10 +450,31 @@ int git_configset_add_file(struct config_set *cs, const char *filename);
/**
* Finds and returns the value list, sorted in order of increasing priority
* for the configuration variable `key` and config set `cs`. When the
- * configuration variable `key` is not found, returns NULL. The caller
- * should not free or modify the returned pointer, as it is owned by the cache.
+ * configuration variable `key` is not found, returns 1 without touching
+ * `value`.
+ *
+ * The key will be parsed for validity with git_config_parse_key(), on
+ * error a negative value will be returned.
+ *
+ * The caller should not free or modify the returned pointer, as it is
+ * owned by the cache.
*/
-const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
+RESULT_MUST_BE_USED
+int git_configset_get_value_multi(struct config_set *cs, const char *key,
+ const struct string_list **dest);
+
+/**
+ * A validation wrapper for git_configset_get_value_multi() which does
+ * for it what git_configset_get_string() does for
+ * git_configset_get_value().
+ *
+ * The configuration syntax allows for "[section] key", which will
+ * give us a NULL entry in the "struct string_list", as opposed to
+ * "[section] key =" which is the empty string. Most users of the API
+ * are not prepared to handle NULL in a "struct string_list".
+ */
+int git_configset_get_string_multi(struct config_set *cs, const char *key,
+ const struct string_list **dest);
/**
* Clears `config_set` structure, removes all saved variable-value pairs.
@@ -465,6 +486,13 @@ void git_configset_clear(struct config_set *cs);
* value in the 'dest' pointer.
*/
+/**
+ * git_configset_get() returns negative values on error, see
+ * repo_config_get() below.
+ */
+RESULT_MUST_BE_USED
+int git_configset_get(struct config_set *cs, const char *key);
+
/*
* Finds the highest-priority value for the configuration variable `key`
* and config set `cs`, stores the pointer to it in `value` and returns 0.
@@ -485,10 +513,22 @@ int git_configset_get_pathname(struct config_set *cs, const char *key, const cha
/* Functions for reading a repository's config */
struct repository;
void repo_config(struct repository *repo, config_fn_t fn, void *data);
+
+/**
+ * Run only the discover part of the repo_config_get_*() functions
+ * below, in addition to 1 if not found, returns negative values on
+ * error (e.g. if the key itself is invalid).
+ */
+RESULT_MUST_BE_USED
+int repo_config_get(struct repository *repo, const char *key);
int repo_config_get_value(struct repository *repo,
const char *key, const char **value);
-const struct string_list *repo_config_get_value_multi(struct repository *repo,
- const char *key);
+RESULT_MUST_BE_USED
+int repo_config_get_value_multi(struct repository *repo, const char *key,
+ const struct string_list **dest);
+RESULT_MUST_BE_USED
+int repo_config_get_string_multi(struct repository *repo, const char *key,
+ const struct string_list **dest);
int repo_config_get_string(struct repository *repo,
const char *key, char **dest);
int repo_config_get_string_tmp(struct repository *repo,
@@ -521,8 +561,15 @@ void git_protected_config(config_fn_t fn, void *data);
* manner, the config API provides two functions `git_config_get_value`
* and `git_config_get_value_multi`. They both read values from an internal
* cache generated previously from reading the config files.
+ *
+ * For those git_config_get*() functions that aren't documented,
+ * consult the corresponding repo_config_get*() function's
+ * documentation.
*/
+RESULT_MUST_BE_USED
+int git_config_get(const char *key);
+
/**
* Finds the highest-priority value for the configuration variable `key`,
* stores the pointer to it in `value` and returns 0. When the
@@ -535,10 +582,17 @@ int git_config_get_value(const char *key, const char **value);
/**
* Finds and returns the value list, sorted in order of increasing priority
* for the configuration variable `key`. When the configuration variable
- * `key` is not found, returns NULL. The caller should not free or modify
- * the returned pointer, as it is owned by the cache.
- */
-const struct string_list *git_config_get_value_multi(const char *key);
+ * `key` is not found, returns 1 without touching `value`.
+ *
+ * The caller should not free or modify the returned pointer, as it is
+ * owned by the cache.
+ */
+RESULT_MUST_BE_USED
+int git_config_get_value_multi(const char *key,
+ const struct string_list **dest);
+RESULT_MUST_BE_USED
+int git_config_get_string_multi(const char *key,
+ const struct string_list **dest);
/**
* Resets and invalidates the config cache.
diff --git a/pack-bitmap.c b/pack-bitmap.c
index ca7c81b5c9..f8ab6be411 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -2318,7 +2318,11 @@ int bitmap_is_midx(struct bitmap_index *bitmap_git)
const struct string_list *bitmap_preferred_tips(struct repository *r)
{
- return repo_config_get_value_multi(r, "pack.preferbitmaptips");
+ const struct string_list *dest;
+
+ if (!repo_config_get_string_multi(r, "pack.preferbitmaptips", &dest))
+ return dest;
+ return NULL;
}
int bitmap_is_preferred_refname(struct repository *r, const char *refname)
diff --git a/submodule.c b/submodule.c
index 2a057c35b7..c9579f9a3f 100644
--- a/submodule.c
+++ b/submodule.c
@@ -275,8 +275,7 @@ int is_tree_submodule_active(struct repository *repo,
free(key);
/* submodule.active is set */
- sl = repo_config_get_value_multi(repo, "submodule.active");
- if (sl) {
+ if (!repo_config_get_string_multi(repo, "submodule.active", &sl)) {
struct pathspec ps;
struct strvec args = STRVEC_INIT;
const struct string_list_item *item;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 4ba9eb6560..6dc4c37444 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -14,6 +14,8 @@
* get_value_multi -> prints all values for the entered key in increasing order
* of priority
*
+ * get -> print return value for the entered key
+ *
* get_int -> print integer value for the entered key or die
*
* get_bool -> print bool value for the entered key or die
@@ -95,8 +97,7 @@ int cmd__config(int argc, const char **argv)
goto exit1;
}
} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
- strptr = git_config_get_value_multi(argv[2]);
- if (strptr) {
+ if (!git_config_get_value_multi(argv[2], &strptr)) {
for (i = 0; i < strptr->nr; i++) {
v = strptr->items[i].string;
if (!v)
@@ -109,6 +110,26 @@ int cmd__config(int argc, const char **argv)
printf("Value not found for \"%s\"\n", argv[2]);
goto exit1;
}
+ } else if (argc == 3 && !strcmp(argv[1], "get")) {
+ int ret;
+
+ if (!(ret = git_config_get(argv[2])))
+ goto exit0;
+ else if (ret == 1)
+ printf("Value not found for \"%s\"\n", argv[2]);
+ else if (ret == -CONFIG_INVALID_KEY)
+ printf("Key \"%s\" is invalid\n", argv[2]);
+ else if (ret == -CONFIG_NO_SECTION_OR_NAME)
+ printf("Key \"%s\" has no section\n", argv[2]);
+ else
+ /*
+ * A normal caller should just check "ret <
+ * 0", but for our own tests let's BUG() if
+ * our whitelist of git_config_parse_key()
+ * return values isn't exhaustive.
+ */
+ BUG("Key \"%s\" has unknown return %d", argv[2], ret);
+ goto exit1;
} else if (argc == 3 && !strcmp(argv[1], "get_int")) {
if (!git_config_get_int(argv[2], &val)) {
printf("%d\n", val);
@@ -159,8 +180,7 @@ int cmd__config(int argc, const char **argv)
goto exit2;
}
}
- strptr = git_configset_get_value_multi(&cs, argv[2]);
- if (strptr) {
+ if (!git_configset_get_value_multi(&cs, argv[2], &strptr)) {
for (i = 0; i < strptr->nr; i++) {
v = strptr->items[i].string;
if (!v)
diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh
index 3648d439a8..4b90b74d5d 100755
--- a/t/t0068-for-each-repo.sh
+++ b/t/t0068-for-each-repo.sh
@@ -40,4 +40,23 @@ test_expect_success 'do nothing on empty config' '
git for-each-repo --config=bogus.config -- help --no-such-option
'
+test_expect_success 'error on bad config keys' '
+ test_expect_code 129 git for-each-repo --config=a &&
+ test_expect_code 129 git for-each-repo --config=a.b. &&
+ test_expect_code 129 git for-each-repo --config="'\''.b"
+'
+
+test_expect_success 'error on NULL value for config keys' '
+ cat >>.git/config <<-\EOF &&
+ [empty]
+ key
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''empty.key'\''
+ EOF
+ test_expect_code 129 git for-each-repo --config=empty.key 2>actual.raw &&
+ grep ^error actual.raw >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index b38e158d3b..7def7053e1 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -58,6 +58,8 @@ test_expect_success 'setup default config' '
skin = false
nose = 1
horns
+ [value]
+ less
EOF
'
@@ -116,6 +118,45 @@ test_expect_success 'find value with the highest priority' '
check_config get_value case.baz "hask"
'
+test_expect_success 'return value for an existing key' '
+ test-tool config get lamb.chop >out 2>err &&
+ test_must_be_empty out &&
+ test_must_be_empty err
+'
+
+test_expect_success 'return value for value-less key' '
+ test-tool config get value.less >out 2>err &&
+ test_must_be_empty out &&
+ test_must_be_empty err
+'
+
+test_expect_success 'return value for a missing key' '
+ cat >expect <<-\EOF &&
+ Value not found for "missing.key"
+ EOF
+ test_expect_code 1 test-tool config get missing.key >actual 2>err &&
+ test_cmp actual expect &&
+ test_must_be_empty err
+'
+
+test_expect_success 'return value for a bad key: CONFIG_INVALID_KEY' '
+ cat >expect <<-\EOF &&
+ Key "fails.iskeychar.-" is invalid
+ EOF
+ test_expect_code 1 test-tool config get fails.iskeychar.- >actual 2>err &&
+ test_cmp actual expect &&
+ test_must_be_empty out
+'
+
+test_expect_success 'return value for a bad key: CONFIG_NO_SECTION_OR_NAME' '
+ cat >expect <<-\EOF &&
+ Key "keynosection" has no section
+ EOF
+ test_expect_code 1 test-tool config get keynosection >actual 2>err &&
+ test_cmp actual expect &&
+ test_must_be_empty out
+'
+
test_expect_success 'find integer value for a key' '
check_config get_int lamb.chop 65
'
@@ -146,6 +187,71 @@ test_expect_success 'find multiple values' '
check_config get_value_multi case.baz sam bat hask
'
+test_NULL_in_multi () {
+ local op="$1" &&
+ local file="$2" &&
+
+ test_expect_success "$op: NULL value in config${file:+ in $file}" '
+ config="$file" &&
+ if test -z "$config"
+ then
+ config=.git/config &&
+ test_when_finished "mv $config.old $config" &&
+ mv "$config" "$config".old
+ fi &&
+
+ # Value-less in the middle of a list
+ cat >"$config" <<-\EOF &&
+ [a]key=x
+ [a]key
+ [a]key=y
+ EOF
+ case "$op" in
+ *_multi)
+ cat >expect <<-\EOF
+ x
+ (NULL)
+ y
+ EOF
+ ;;
+ *)
+ cat >expect <<-\EOF
+ y
+ EOF
+ ;;
+ esac &&
+ test-tool config "$op" a.key $file >actual &&
+ test_cmp expect actual &&
+
+ # Value-less at the end of a least
+ cat >"$config" <<-\EOF &&
+ [a]key=x
+ [a]key=y
+ [a]key
+ EOF
+ case "$op" in
+ *_multi)
+ cat >expect <<-\EOF
+ x
+ y
+ (NULL)
+ EOF
+ ;;
+ *)
+ cat >expect <<-\EOF
+ (NULL)
+ EOF
+ ;;
+ esac &&
+ test-tool config "$op" a.key $file >actual &&
+ test_cmp expect actual
+ '
+}
+
+test_NULL_in_multi "get_value_multi"
+test_NULL_in_multi "configset_get_value" "my.config"
+test_NULL_in_multi "configset_get_value_multi" "my.config"
+
test_expect_success 'find value from a configset' '
cat >config2 <<-\EOF &&
[case]
@@ -207,7 +313,7 @@ test_expect_success 'proper error on error in default config files' '
cp .git/config .git/config.old &&
test_when_finished "mv .git/config.old .git/config" &&
echo "[" >>.git/config &&
- echo "fatal: bad config line 34 in file .git/config" >expect &&
+ echo "fatal: bad config line 36 in file .git/config" >expect &&
test_expect_code 128 test-tool config get_value foo.bar 2>actual &&
test_cmp expect actual
'
diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh
index 141d3e4ca4..9bd5dbf341 100755
--- a/t/t3309-notes-merge-auto-resolve.sh
+++ b/t/t3309-notes-merge-auto-resolve.sh
@@ -360,7 +360,12 @@ test_expect_success 'merge z into y with invalid strategy => Fail/No changes' '
test_expect_success 'merge z into y with invalid configuration option => Fail/No changes' '
git config core.notesRef refs/notes/y &&
- test_must_fail git -c notes.mergeStrategy="foo" notes merge z &&
+ cat >expect <<-\EOF &&
+ error: unknown notes merge strategy foo
+ fatal: unable to parse '\''notes.mergeStrategy'\'' from command-line config
+ EOF
+ test_must_fail git -c notes.mergeStrategy="foo" notes merge z 2>actual &&
+ test_cmp expect actual &&
# Verify no changes (y)
verify_notes y y
'
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 2ce2b41174..ae73aef922 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -835,6 +835,21 @@ test_expect_success 'log.decorate configuration' '
'
+test_expect_success 'parse log.excludeDecoration with no value' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [log]
+ excludeDecoration
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''log.excludeDecoration'\''
+ EOF
+ git log --decorate=short 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'decorate-refs with glob' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index d65a5f94b4..5500dd0842 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -72,8 +72,16 @@ test_expect_success 'gc: implicit prune --expire' '
'
test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' '
- git config gc.pruneExpire invalid &&
- test_must_fail git gc
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ >repo/.git/config &&
+ git -C repo config gc.pruneExpire invalid &&
+ cat >expect <<-\EOF &&
+ error: Invalid gc.pruneexpire: '\''invalid'\''
+ fatal: bad config variable '\''gc.pruneexpire'\'' in file '\''.git/config'\'' at line 2
+ EOF
+ test_must_fail git -C repo gc 2>actual &&
+ test_cmp expect actual
'
test_expect_success 'gc: start with ok gc.pruneExpire' '
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 7d8dee41b0..526a5a506e 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -404,6 +404,26 @@ test_bitmap_cases () {
)
'
+ test_expect_success 'pack.preferBitmapTips' '
+ git init repo &&
+ test_when_finished "rm -rf repo" &&
+ (
+ cd repo &&
+ git config pack.writeBitmapLookupTable '"$writeLookupTable"' &&
+ test_commit_bulk --message="%s" 103 &&
+
+ cat >>.git/config <<-\EOF &&
+ [pack]
+ preferBitmapTips
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''pack.preferbitmaptips'\''
+ EOF
+ git repack -adb 2>actual &&
+ test_cmp expect actual
+ )
+ '
+
test_expect_success 'complains about multiple pack bitmaps' '
rm -fr repo &&
git init repo &&
diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh
index 165427d57e..b55a9f65e6 100755
--- a/t/t5552-skipping-fetch-negotiator.sh
+++ b/t/t5552-skipping-fetch-negotiator.sh
@@ -3,6 +3,22 @@
test_description='test skipping fetch negotiator'
. ./test-lib.sh
+test_expect_success 'fetch.negotiationalgorithm config' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ cat >repo/.git/config <<-\EOF &&
+ [fetch]
+ negotiationAlgorithm
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''fetch.negotiationalgorithm'\''
+ fatal: bad config variable '\''fetch.negotiationalgorithm'\'' in file '\''.git/config'\'' at line 2
+ EOF
+ test_expect_code 128 git -C repo fetch >out 2>actual &&
+ test_must_be_empty out &&
+ test_cmp expect actual
+'
+
have_sent () {
while test "$#" -ne 0
do
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 04a4b44183..32b312fa80 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1871,6 +1871,23 @@ test_expect_success 'invalid sort parameter in configuratoin' '
test_must_fail git tag -l "foo*"
'
+test_expect_success 'version sort handles empty value for versionsort.{prereleaseSuffix,suffix}' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [versionsort]
+ prereleaseSuffix
+ suffix
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''versionsort.suffix'\''
+ error: missing value for '\''versionsort.prereleasesuffix'\''
+ EOF
+ git tag -l --sort=version:refname 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'version sort with prerelease reordering' '
test_config versionsort.prereleaseSuffix -rc &&
git tag foo1.6-rc1 &&
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index 7cdc263764..887d181b72 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -51,6 +51,22 @@ test_expect_success 'is-active works with submodule.<name>.active config' '
test-tool -C super submodule is-active sub1
'
+test_expect_success 'is-active handles submodule.active config missing a value' '
+ cp super/.git/config super/.git/config.orig &&
+ test_when_finished mv super/.git/config.orig super/.git/config &&
+
+ cat >>super/.git/config <<-\EOF &&
+ [submodule]
+ active
+ EOF
+
+ cat >expect <<-\EOF &&
+ error: missing value for '\''submodule.active'\''
+ EOF
+ test-tool -C super submodule is-active sub1 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'is-active works with basic submodule.active config' '
test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
test_when_finished "git -C super config --unset-all submodule.active" &&
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 823331e44a..487e326b3f 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -524,6 +524,44 @@ test_expect_success 'register and unregister' '
git maintenance unregister --config-file ./other --force
'
+test_expect_success 'register with no value for maintenance.repo' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [maintenance]
+ repo
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''maintenance.repo'\''
+ EOF
+ git maintenance register 2>actual &&
+ test_cmp expect actual &&
+ git config maintenance.repo
+'
+
+test_expect_success 'unregister with no value for maintenance.repo' '
+ cp .git/config .git/config.orig &&
+ test_when_finished mv .git/config.orig .git/config &&
+
+ cat >>.git/config <<-\EOF &&
+ [maintenance]
+ repo
+ EOF
+ cat >expect <<-\EOF &&
+ error: missing value for '\''maintenance.repo'\''
+ EOF
+ test_expect_code 128 git maintenance unregister 2>actual.raw &&
+ grep ^error actual.raw >actual &&
+ test_cmp expect actual &&
+ git config maintenance.repo &&
+
+ git maintenance unregister --force 2>actual.raw &&
+ grep ^error actual.raw >actual &&
+ test_cmp expect actual &&
+ git config maintenance.repo
+'
+
test_expect_success !MINGW 'register and unregister with regex metacharacters' '
META="a+b*c" &&
git init "$META" &&
diff --git a/versioncmp.c b/versioncmp.c
index 069ee94a4d..7498da96e0 100644
--- a/versioncmp.c
+++ b/versioncmp.c
@@ -160,15 +160,21 @@ int versioncmp(const char *s1, const char *s2)
}
if (!initialized) {
- const struct string_list *deprecated_prereleases;
+ const char *const newk = "versionsort.suffix";
+ const char *const oldk = "versionsort.prereleasesuffix";
+ const struct string_list *newl;
+ const struct string_list *oldl;
+ int new = git_config_get_string_multi(newk, &newl);
+ int old = git_config_get_string_multi(oldk, &oldl);
+
+ if (!new && !old)
+ warning("ignoring %s because %s is set", oldk, newk);
+ if (!new)
+ prereleases = newl;
+ else if (!old)
+ prereleases = oldl;
+
initialized = 1;
- prereleases = git_config_get_value_multi("versionsort.suffix");
- deprecated_prereleases = git_config_get_value_multi("versionsort.prereleasesuffix");
- if (prereleases) {
- if (deprecated_prereleases)
- warning("ignoring versionsort.prereleasesuffix because versionsort.suffix is set");
- } else
- prereleases = deprecated_prereleases;
}
if (prereleases && swap_prereleases(s1, s2, (const char *) p1 - s1 - 1,
&diff))