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;
|
static const char *config_key = NULL;
|
||||||
int i, result = 0;
|
int i, result = 0;
|
||||||
const struct string_list *values;
|
const struct string_list *values;
|
||||||
|
int err;
|
||||||
|
|
||||||
const struct option options[] = {
|
const struct option options[] = {
|
||||||
OPT_STRING(0, "config", &config_key, N_("config"),
|
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)
|
if (!config_key)
|
||||||
die(_("missing --config=<config>"));
|
die(_("missing --config=<config>"));
|
||||||
|
|
||||||
values = repo_config_get_value_multi(the_repository,
|
err = repo_config_get_string_multi(the_repository, config_key, &values);
|
||||||
config_key);
|
if (err < 0)
|
||||||
|
usage_msg_optf(_("got bad config --config=%s"),
|
||||||
/*
|
for_each_repo_usage, options, config_key);
|
||||||
* Do nothing on an empty list, which is equivalent to the case
|
else if (err)
|
||||||
* where the config variable does not exist at all.
|
|
||||||
*/
|
|
||||||
if (!values)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0; !result && i < values->nr; i++)
|
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;
|
int found = 0;
|
||||||
const char *key = "maintenance.repo";
|
const char *key = "maintenance.repo";
|
||||||
char *config_value;
|
|
||||||
char *maintpath = get_maintpath();
|
char *maintpath = get_maintpath();
|
||||||
struct string_list_item *item;
|
struct string_list_item *item;
|
||||||
const struct string_list *list;
|
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");
|
git_config_set("maintenance.auto", "false");
|
||||||
|
|
||||||
/* Set maintenance strategy, if unset */
|
/* Set maintenance strategy, if unset */
|
||||||
if (!git_config_get_string("maintenance.strategy", &config_value))
|
if (git_config_get("maintenance.strategy"))
|
||||||
free(config_value);
|
|
||||||
else
|
|
||||||
git_config_set("maintenance.strategy", "incremental");
|
git_config_set("maintenance.strategy", "incremental");
|
||||||
|
|
||||||
list = git_config_get_value_multi(key);
|
if (!git_config_get_string_multi(key, &list)) {
|
||||||
if (list) {
|
|
||||||
for_each_string_list_item(item, list) {
|
for_each_string_list_item(item, list) {
|
||||||
if (!strcmp(maintpath, item->string)) {
|
if (!strcmp(maintpath, item->string)) {
|
||||||
found = 1;
|
found = 1;
|
||||||
@ -1581,11 +1577,10 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
|
|||||||
if (config_file) {
|
if (config_file) {
|
||||||
git_configset_init(&cs);
|
git_configset_init(&cs);
|
||||||
git_configset_add_file(&cs, config_file);
|
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) {
|
for_each_string_list_item(item, list) {
|
||||||
if (!strcmp(maintpath, item->string)) {
|
if (!strcmp(maintpath, item->string)) {
|
||||||
found = 1;
|
found = 1;
|
||||||
|
@ -185,10 +185,10 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f
|
|||||||
int i;
|
int i;
|
||||||
char *value = NULL;
|
char *value = NULL;
|
||||||
struct string_list *include = decoration_filter->include_ref_pattern;
|
struct string_list *include = decoration_filter->include_ref_pattern;
|
||||||
const struct string_list *config_exclude =
|
const struct string_list *config_exclude;
|
||||||
git_config_get_value_multi("log.excludeDecoration");
|
|
||||||
|
|
||||||
if (config_exclude) {
|
if (!git_config_get_string_multi("log.excludeDecoration",
|
||||||
|
&config_exclude)) {
|
||||||
struct string_list_item *item;
|
struct string_list_item *item;
|
||||||
for_each_string_list_item(item, config_exclude)
|
for_each_string_list_item(item, config_exclude)
|
||||||
string_list_append(decoration_filter->exclude_ref_config_pattern,
|
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,
|
* If there are no path args and submodule.active is set then,
|
||||||
* by default, only initialize 'active' modules.
|
* 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);
|
module_list_active(&list);
|
||||||
|
|
||||||
info.prefix = prefix;
|
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,
|
* If there are no path args and submodule.active is set then,
|
||||||
* by default, only initialize 'active' modules.
|
* 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);
|
module_list_active(&list);
|
||||||
|
|
||||||
info.prefix = opt.prefix;
|
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)
|
static void configure_added_submodule(struct add_data *add_data)
|
||||||
{
|
{
|
||||||
char *key;
|
char *key;
|
||||||
const char *val;
|
|
||||||
struct child_process add_submod = CHILD_PROCESS_INIT;
|
struct child_process add_submod = CHILD_PROCESS_INIT;
|
||||||
struct child_process add_gitmodules = 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
|
* is_submodule_active(), since that function needs to find
|
||||||
* out the value of "submodule.active" again anyway.
|
* 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
|
* If the submodule being added isn't already covered by the
|
||||||
* current configured pathspec, set the submodule's active flag
|
* 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)) {
|
if (file_exists(from_file)) {
|
||||||
struct config_set cs = { { 0 } };
|
struct config_set cs = { { 0 } };
|
||||||
const char *core_worktree;
|
|
||||||
int bare;
|
int bare;
|
||||||
|
|
||||||
if (safe_create_leading_directories(to_file) ||
|
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))
|
to_file, "core.bare", NULL, "true", 0))
|
||||||
error(_("failed to unset '%s' in '%s'"),
|
error(_("failed to unset '%s' in '%s'"),
|
||||||
"core.bare", to_file);
|
"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,
|
git_config_set_in_file_gently(to_file,
|
||||||
"core.worktree", NULL))
|
"core.worktree", NULL))
|
||||||
error(_("failed to unset '%s' in '%s'"),
|
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);
|
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 k;
|
||||||
struct config_set_element *found_entry;
|
struct config_set_element *found_entry;
|
||||||
char *normalized_key;
|
char *normalized_key;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* `key` may come from the user, so normalize it before using it
|
* `key` may come from the user, so normalize it before using it
|
||||||
* for querying entries from the hashmap.
|
* for querying entries from the hashmap.
|
||||||
*/
|
*/
|
||||||
if (git_config_parse_key(key, &normalized_key, NULL))
|
ret = git_config_parse_key(key, &normalized_key, NULL);
|
||||||
return NULL;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
hashmap_entry_init(&k.ent, strhash(normalized_key));
|
hashmap_entry_init(&k.ent, strhash(normalized_key));
|
||||||
k.key = normalized_key;
|
k.key = normalized_key;
|
||||||
found_entry = hashmap_get_entry(&cs->config_hash, &k, ent, NULL);
|
found_entry = hashmap_get_entry(&cs->config_hash, &k, ent, NULL);
|
||||||
free(normalized_key);
|
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)
|
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 string_list_item *si;
|
||||||
struct configset_list_item *l_item;
|
struct configset_list_item *l_item;
|
||||||
struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
|
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
|
* Since the keys are being fed by git_config*() callback mechanism, they
|
||||||
* are already normalized. So simply add them without any further munging.
|
* 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)
|
int git_configset_get_value(struct config_set *cs, const char *key, const char **value)
|
||||||
{
|
{
|
||||||
const struct string_list *values = NULL;
|
const struct string_list *values = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Follows "last one wins" semantic, i.e., if there are multiple matches for the
|
* 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
|
* queried key in the files of the configset, the value returned will be the last
|
||||||
* value in the value list for that key.
|
* 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);
|
assert(values->nr > 0);
|
||||||
*value = values->items[values->nr - 1].string;
|
*value = values->items[values->nr - 1].string;
|
||||||
return 0;
|
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);
|
struct config_set_element *e;
|
||||||
return e ? &e->value_list : NULL;
|
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)
|
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);
|
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,
|
int repo_config_get_value(struct repository *repo,
|
||||||
const char *key, const char **value)
|
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);
|
return git_configset_get_value(repo->config, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct string_list *repo_config_get_value_multi(struct repository *repo,
|
int repo_config_get_value_multi(struct repository *repo, const char *key,
|
||||||
const char *key)
|
const struct string_list **dest)
|
||||||
{
|
{
|
||||||
git_config_check_init(repo);
|
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,
|
int repo_config_get_string(struct repository *repo,
|
||||||
@ -2682,14 +2745,25 @@ void git_config_clear(void)
|
|||||||
repo_config_clear(the_repository);
|
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)
|
int git_config_get_value(const char *key, const char **value)
|
||||||
{
|
{
|
||||||
return repo_config_get_value(the_repository, key, 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)
|
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);
|
error_fn(err, params);
|
||||||
va_end(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;
|
kv_info = values->items[values->nr - 1].util;
|
||||||
git_die_config_linenr(key, kv_info->filename, kv_info->linenr);
|
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
|
* Finds and returns the value list, sorted in order of increasing priority
|
||||||
* for the configuration variable `key` and config set `cs`. When the
|
* for the configuration variable `key` and config set `cs`. When the
|
||||||
* configuration variable `key` is not found, returns NULL. The caller
|
* configuration variable `key` is not found, returns 1 without touching
|
||||||
* should not free or modify the returned pointer, as it is owned by the cache.
|
* `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.
|
* 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.
|
* 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`
|
* Finds the highest-priority value for the configuration variable `key`
|
||||||
* and config set `cs`, stores the pointer to it in `value` and returns 0.
|
* 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 */
|
/* Functions for reading a repository's config */
|
||||||
struct repository;
|
struct repository;
|
||||||
void repo_config(struct repository *repo, config_fn_t fn, void *data);
|
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,
|
int repo_config_get_value(struct repository *repo,
|
||||||
const char *key, const char **value);
|
const char *key, const char **value);
|
||||||
const struct string_list *repo_config_get_value_multi(struct repository *repo,
|
RESULT_MUST_BE_USED
|
||||||
const char *key);
|
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,
|
int repo_config_get_string(struct repository *repo,
|
||||||
const char *key, char **dest);
|
const char *key, char **dest);
|
||||||
int repo_config_get_string_tmp(struct repository *repo,
|
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`
|
* manner, the config API provides two functions `git_config_get_value`
|
||||||
* and `git_config_get_value_multi`. They both read values from an internal
|
* and `git_config_get_value_multi`. They both read values from an internal
|
||||||
* cache generated previously from reading the config files.
|
* 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`,
|
* Finds the highest-priority value for the configuration variable `key`,
|
||||||
* stores the pointer to it in `value` and returns 0. When the
|
* 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
|
* Finds and returns the value list, sorted in order of increasing priority
|
||||||
* for the configuration variable `key`. When the configuration variable
|
* for the configuration variable `key`. When the configuration variable
|
||||||
* `key` is not found, returns NULL. The caller should not free or modify
|
* `key` is not found, returns 1 without touching `value`.
|
||||||
* the returned pointer, as it is owned by the cache.
|
*
|
||||||
|
* 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.
|
* 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)
|
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)
|
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);
|
free(key);
|
||||||
|
|
||||||
/* submodule.active is set */
|
/* submodule.active is set */
|
||||||
sl = repo_config_get_value_multi(repo, "submodule.active");
|
if (!repo_config_get_string_multi(repo, "submodule.active", &sl)) {
|
||||||
if (sl) {
|
|
||||||
struct pathspec ps;
|
struct pathspec ps;
|
||||||
struct strvec args = STRVEC_INIT;
|
struct strvec args = STRVEC_INIT;
|
||||||
const struct string_list_item *item;
|
const struct string_list_item *item;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
* get_value_multi -> prints all values for the entered key in increasing order
|
* get_value_multi -> prints all values for the entered key in increasing order
|
||||||
* of priority
|
* of priority
|
||||||
*
|
*
|
||||||
|
* get -> print return value for the entered key
|
||||||
|
*
|
||||||
* get_int -> print integer value for the entered key or die
|
* get_int -> print integer value for the entered key or die
|
||||||
*
|
*
|
||||||
* get_bool -> print bool 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;
|
goto exit1;
|
||||||
}
|
}
|
||||||
} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
|
} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
|
||||||
strptr = git_config_get_value_multi(argv[2]);
|
if (!git_config_get_value_multi(argv[2], &strptr)) {
|
||||||
if (strptr) {
|
|
||||||
for (i = 0; i < strptr->nr; i++) {
|
for (i = 0; i < strptr->nr; i++) {
|
||||||
v = strptr->items[i].string;
|
v = strptr->items[i].string;
|
||||||
if (!v)
|
if (!v)
|
||||||
@ -109,6 +110,26 @@ int cmd__config(int argc, const char **argv)
|
|||||||
printf("Value not found for \"%s\"\n", argv[2]);
|
printf("Value not found for \"%s\"\n", argv[2]);
|
||||||
goto exit1;
|
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")) {
|
} else if (argc == 3 && !strcmp(argv[1], "get_int")) {
|
||||||
if (!git_config_get_int(argv[2], &val)) {
|
if (!git_config_get_int(argv[2], &val)) {
|
||||||
printf("%d\n", val);
|
printf("%d\n", val);
|
||||||
@ -159,8 +180,7 @@ int cmd__config(int argc, const char **argv)
|
|||||||
goto exit2;
|
goto exit2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strptr = git_configset_get_value_multi(&cs, argv[2]);
|
if (!git_configset_get_value_multi(&cs, argv[2], &strptr)) {
|
||||||
if (strptr) {
|
|
||||||
for (i = 0; i < strptr->nr; i++) {
|
for (i = 0; i < strptr->nr; i++) {
|
||||||
v = strptr->items[i].string;
|
v = strptr->items[i].string;
|
||||||
if (!v)
|
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
|
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
|
test_done
|
||||||
|
@ -58,6 +58,8 @@ test_expect_success 'setup default config' '
|
|||||||
skin = false
|
skin = false
|
||||||
nose = 1
|
nose = 1
|
||||||
horns
|
horns
|
||||||
|
[value]
|
||||||
|
less
|
||||||
EOF
|
EOF
|
||||||
'
|
'
|
||||||
|
|
||||||
@ -116,6 +118,45 @@ test_expect_success 'find value with the highest priority' '
|
|||||||
check_config get_value case.baz "hask"
|
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' '
|
test_expect_success 'find integer value for a key' '
|
||||||
check_config get_int lamb.chop 65
|
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
|
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' '
|
test_expect_success 'find value from a configset' '
|
||||||
cat >config2 <<-\EOF &&
|
cat >config2 <<-\EOF &&
|
||||||
[case]
|
[case]
|
||||||
@ -207,7 +313,7 @@ test_expect_success 'proper error on error in default config files' '
|
|||||||
cp .git/config .git/config.old &&
|
cp .git/config .git/config.old &&
|
||||||
test_when_finished "mv .git/config.old .git/config" &&
|
test_when_finished "mv .git/config.old .git/config" &&
|
||||||
echo "[" >>.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_expect_code 128 test-tool config get_value foo.bar 2>actual &&
|
||||||
test_cmp expect 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' '
|
test_expect_success 'merge z into y with invalid configuration option => Fail/No changes' '
|
||||||
git config core.notesRef refs/notes/y &&
|
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 no changes (y)
|
||||||
verify_notes y 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' '
|
test_expect_success 'decorate-refs with glob' '
|
||||||
cat >expect.decorate <<-\EOF &&
|
cat >expect.decorate <<-\EOF &&
|
||||||
Merge-tag-reach
|
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' '
|
test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' '
|
||||||
git config gc.pruneExpire invalid &&
|
test_when_finished "rm -rf repo" &&
|
||||||
test_must_fail git gc
|
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' '
|
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' '
|
test_expect_success 'complains about multiple pack bitmaps' '
|
||||||
rm -fr repo &&
|
rm -fr repo &&
|
||||||
git init repo &&
|
git init repo &&
|
||||||
|
@ -3,6 +3,22 @@
|
|||||||
test_description='test skipping fetch negotiator'
|
test_description='test skipping fetch negotiator'
|
||||||
. ./test-lib.sh
|
. ./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 () {
|
have_sent () {
|
||||||
while test "$#" -ne 0
|
while test "$#" -ne 0
|
||||||
do
|
do
|
||||||
|
@ -1871,6 +1871,23 @@ test_expect_success 'invalid sort parameter in configuratoin' '
|
|||||||
test_must_fail git tag -l "foo*"
|
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_expect_success 'version sort with prerelease reordering' '
|
||||||
test_config versionsort.prereleaseSuffix -rc &&
|
test_config versionsort.prereleaseSuffix -rc &&
|
||||||
git tag foo1.6-rc1 &&
|
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-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_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 submodule.sub1.URL ../sub" &&
|
||||||
test_when_finished "git -C super config --unset-all submodule.active" &&
|
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
|
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' '
|
test_expect_success !MINGW 'register and unregister with regex metacharacters' '
|
||||||
META="a+b*c" &&
|
META="a+b*c" &&
|
||||||
git init "$META" &&
|
git init "$META" &&
|
||||||
|
22
versioncmp.c
22
versioncmp.c
@ -160,15 +160,21 @@ int versioncmp(const char *s1, const char *s2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!initialized) {
|
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;
|
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,
|
if (prereleases && swap_prereleases(s1, s2, (const char *) p1 - s1 - 1,
|
||||||
&diff))
|
&diff))
|
||||||
|
Loading…
Reference in New Issue
Block a user