Merge branch 'ab/config-multi-and-nonbool'
Assorted config API updates. * ab/config-multi-and-nonbool: for-each-repo: with bad config, don't conflate <path> and <cmd> config API: add "string" version of *_value_multi(), fix segfaults config API users: test for *_get_value_multi() segfaults for-each-repo: error on bad --config config API: have *_multi() return an "int" and take a "dest" versioncmp.c: refactor config reading next commit config API: add and use a "git_config_get()" family of functions config tests: add "NULL" tests for *_get_value_multi() config tests: cover blind spots in git_die_config() tests
This commit is contained in:
commit
87daf40750
@ -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++)
|
||||
|
15
builtin/gc.c
15
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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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'"),
|
||||
|
109
config.c
109
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 = 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;
|
||||
*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;
|
||||
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);
|
||||
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_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);
|
||||
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_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);
|
||||
}
|
||||
|
70
config.h
70
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.
|
||||
* `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.
|
||||
*/
|
||||
const struct string_list *git_config_get_value_multi(const char *key);
|
||||
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.
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
'
|
||||
|
@ -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
|
||||
'
|
||||
|
@ -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
|
||||
|
@ -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' '
|
||||
|
@ -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 &&
|
||||
|
@ -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
|
||||
|
@ -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 &&
|
||||
|
@ -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" &&
|
||||
|
@ -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" &&
|
||||
|
22
versioncmp.c
22
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))
|
||||
|
Loading…
Reference in New Issue
Block a user