1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-04-27 11:45:08 +02:00

Merge branch 'gc/config-context'

Reduce reliance on a global state in the config reading API.

* gc/config-context:
  config: pass source to config_parser_event_fn_t
  config: add kvi.path, use it to evaluate includes
  config.c: remove config_reader from configsets
  config: pass kvi to die_bad_number()
  trace2: plumb config kvi
  config.c: pass ctx with CLI config
  config: pass ctx with config files
  config.c: pass ctx in configsets
  config: add ctx arg to config_fn_t
  urlmatch.h: use config_fn_t type
  config: inline git_color_default_config
This commit is contained in:
Junio C Hamano 2023-07-06 11:54:48 -07:00
commit b3d1c85d48
103 changed files with 960 additions and 632 deletions

View File

@ -12,7 +12,8 @@ struct config_alias_data {
struct string_list *list;
};
static int config_alias_cb(const char *key, const char *value, void *d)
static int config_alias_cb(const char *key, const char *value,
const struct config_context *ctx UNUSED, void *d)
{
struct config_alias_data *data = d;
const char *p;

View File

@ -411,14 +411,15 @@ static int tar_filter_config(const char *var, const char *value,
return 0;
}
static int git_tar_config(const char *var, const char *value, void *cb)
static int git_tar_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "tar.umask")) {
if (value && !strcmp(value, "user")) {
tar_umask = umask(0);
umask(tar_umask);
} else {
tar_umask = git_config_int(var, value);
tar_umask = git_config_int(var, value, ctx->kvi);
}
return 0;
}

View File

@ -617,6 +617,7 @@ static void dos_time(timestamp_t *timestamp, int *dos_date, int *dos_time)
}
static int archive_zip_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *data UNUSED)
{
return userdiff_config(var, value);

View File

@ -266,7 +266,8 @@ static struct option builtin_add_options[] = {
OPT_END(),
};
static int add_config(const char *var, const char *value, void *cb)
static int add_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "add.ignoreerrors") ||
!strcmp(var, "add.ignore-errors")) {
@ -274,7 +275,10 @@ static int add_config(const char *var, const char *value, void *cb)
return 0;
}
return git_color_default_config(var, value, cb);
if (git_color_config(var, value, cb) < 0)
return -1;
return git_default_config(var, value, ctx, cb);
}
static const char embedded_advice[] = N_(

View File

@ -694,7 +694,8 @@ static const char *add_prefix(const char *prefix, const char *path)
return prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
}
static int git_blame_config(const char *var, const char *value, void *cb)
static int git_blame_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "blame.showroot")) {
show_root = git_config_bool(var, value);
@ -767,7 +768,7 @@ static int git_blame_config(const char *var, const char *value, void *cb)
if (userdiff_config(var, value) < 0)
return -1;
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static int blame_copy_callback(const struct option *option, const char *arg, int unset)

View File

@ -83,7 +83,8 @@ static unsigned int colopts;
define_list_config_array(color_branch_slots);
static int git_branch_config(const char *var, const char *value, void *cb)
static int git_branch_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
const char *slot_name;
@ -117,7 +118,10 @@ static int git_branch_config(const char *var, const char *value, void *cb)
return 0;
}
return git_color_default_config(var, value, cb);
if (git_color_config(var, value, cb) < 0)
return -1;
return git_default_config(var, value, ctx, cb);
}
static const char *branch_get_color(enum color_branch ix)

View File

@ -871,12 +871,13 @@ static int batch_objects(struct batch_options *opt)
return retval;
}
static int git_cat_file_config(const char *var, const char *value, void *cb)
static int git_cat_file_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (userdiff_config(var, value) < 0)
return -1;
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static int batch_option_callback(const struct option *opt,

View File

@ -1189,7 +1189,8 @@ static int switch_branches(const struct checkout_opts *opts,
return ret || writeout_error;
}
static int git_checkout_config(const char *var, const char *value, void *cb)
static int git_checkout_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct checkout_opts *opts = cb;
@ -1205,7 +1206,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
if (starts_with(var, "submodule."))
return git_default_submodule_config(var, value, NULL);
return git_xmerge_config(var, value, NULL);
return git_xmerge_config(var, value, ctx, NULL);
}
static void setup_new_branch_info_and_source_tree(
@ -1692,8 +1693,13 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
}
if (opts->conflict_style) {
struct key_value_info kvi = KVI_INIT;
struct config_context ctx = {
.kvi = &kvi,
};
opts->merge = 1; /* implied */
git_xmerge_config("merge.conflictstyle", opts->conflict_style, NULL);
git_xmerge_config("merge.conflictstyle", opts->conflict_style,
&ctx, NULL);
}
if (opts->force) {
opts->discard_changes = 1;

View File

@ -104,7 +104,8 @@ struct menu_stuff {
define_list_config_array(color_interactive_slots);
static int git_clean_config(const char *var, const char *value, void *cb)
static int git_clean_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
const char *slot_name;
@ -131,8 +132,10 @@ static int git_clean_config(const char *var, const char *value, void *cb)
return 0;
}
/* inspect the color.ui config variable and others */
return git_color_default_config(var, value, cb);
if (git_color_config(var, value, cb) < 0)
return -1;
return git_default_config(var, value, ctx, cb);
}
static const char *clean_get_color(enum color_clean ix)

View File

@ -791,7 +791,8 @@ static int checkout(int submodule_progress, int filter_submodules)
return err;
}
static int git_clone_config(const char *k, const char *v, void *cb)
static int git_clone_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
if (!strcmp(k, "clone.defaultremotename")) {
free(remote_name);
@ -802,17 +803,19 @@ static int git_clone_config(const char *k, const char *v, void *cb)
if (!strcmp(k, "clone.filtersubmodules"))
config_filter_submodules = git_config_bool(k, v);
return git_default_config(k, v, cb);
return git_default_config(k, v, ctx, cb);
}
static int write_one_config(const char *key, const char *value, void *data)
static int write_one_config(const char *key, const char *value,
const struct config_context *ctx,
void *data)
{
/*
* give git_clone_config a chance to write config values back to the
* environment, since git_config_set_multivar_gently only deals with
* config-file writes
*/
int apply_failed = git_clone_config(key, value, data);
int apply_failed = git_clone_config(key, value, ctx, data);
if (apply_failed)
return apply_failed;

View File

@ -12,7 +12,8 @@ static const char * const builtin_column_usage[] = {
};
static unsigned int colopts;
static int column_config(const char *var, const char *value, void *cb)
static int column_config(const char *var, const char *value,
const struct config_context *ctx UNUSED, void *cb)
{
return git_column_config(var, value, cb, &colopts);
}

View File

@ -187,10 +187,11 @@ static int write_option_max_new_filters(const struct option *opt,
}
static int git_commit_graph_write_config(const char *var, const char *value,
const struct config_context *ctx,
void *cb UNUSED)
{
if (!strcmp(var, "commitgraph.maxnewfilters"))
write_opts.max_new_filters = git_config_int(var, value);
write_opts.max_new_filters = git_config_int(var, value, ctx->kvi);
/*
* No need to fall-back to 'git_default_config', since this was already
* called in 'cmd_commit_graph()'.

View File

@ -1410,7 +1410,8 @@ static int parse_status_slot(const char *slot)
return LOOKUP_CONFIG(color_status_slots, slot);
}
static int git_status_config(const char *k, const char *v, void *cb)
static int git_status_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
struct wt_status *s = cb;
const char *slot_name;
@ -1419,7 +1420,8 @@ static int git_status_config(const char *k, const char *v, void *cb)
return git_column_config(k, v, "status", &s->colopts);
if (!strcmp(k, "status.submodulesummary")) {
int is_bool;
s->submodule_summary = git_config_bool_or_int(k, v, &is_bool);
s->submodule_summary = git_config_bool_or_int(k, v, ctx->kvi,
&is_bool);
if (is_bool && s->submodule_summary)
s->submodule_summary = -1;
return 0;
@ -1479,11 +1481,11 @@ static int git_status_config(const char *k, const char *v, void *cb)
}
if (!strcmp(k, "diff.renamelimit")) {
if (s->rename_limit == -1)
s->rename_limit = git_config_int(k, v);
s->rename_limit = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "status.renamelimit")) {
s->rename_limit = git_config_int(k, v);
s->rename_limit = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "diff.renames")) {
@ -1495,7 +1497,7 @@ static int git_status_config(const char *k, const char *v, void *cb)
s->detect_rename = git_config_rename(k, v);
return 0;
}
return git_diff_ui_config(k, v, NULL);
return git_diff_ui_config(k, v, ctx, NULL);
}
int cmd_status(int argc, const char **argv, const char *prefix)
@ -1610,7 +1612,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
return 0;
}
static int git_commit_config(const char *k, const char *v, void *cb)
static int git_commit_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
struct wt_status *s = cb;
@ -1628,11 +1631,12 @@ static int git_commit_config(const char *k, const char *v, void *cb)
}
if (!strcmp(k, "commit.verbose")) {
int is_bool;
config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
config_commit_verbose = git_config_bool_or_int(k, v, ctx->kvi,
&is_bool);
return 0;
}
return git_status_config(k, v, s);
return git_status_config(k, v, ctx, s);
}
int cmd_commit(int argc, const char **argv, const char *prefix)

View File

@ -195,37 +195,42 @@ static void check_argc(int argc, int min, int max)
usage_builtin_config();
}
static void show_config_origin(struct strbuf *buf)
static void show_config_origin(const struct key_value_info *kvi,
struct strbuf *buf)
{
const char term = end_nul ? '\0' : '\t';
strbuf_addstr(buf, current_config_origin_type());
strbuf_addstr(buf, config_origin_type_name(kvi->origin_type));
strbuf_addch(buf, ':');
if (end_nul)
strbuf_addstr(buf, current_config_name());
strbuf_addstr(buf, kvi->filename ? kvi->filename : "");
else
quote_c_style(current_config_name(), buf, NULL, 0);
quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0);
strbuf_addch(buf, term);
}
static void show_config_scope(struct strbuf *buf)
static void show_config_scope(const struct key_value_info *kvi,
struct strbuf *buf)
{
const char term = end_nul ? '\0' : '\t';
const char *scope = config_scope_name(current_config_scope());
const char *scope = config_scope_name(kvi->scope);
strbuf_addstr(buf, N_(scope));
strbuf_addch(buf, term);
}
static int show_all_config(const char *key_, const char *value_,
const struct config_context *ctx,
void *cb UNUSED)
{
const struct key_value_info *kvi = ctx->kvi;
if (show_origin || show_scope) {
struct strbuf buf = STRBUF_INIT;
if (show_scope)
show_config_scope(&buf);
show_config_scope(kvi, &buf);
if (show_origin)
show_config_origin(&buf);
show_config_origin(kvi, &buf);
/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
fwrite(buf.buf, 1, buf.len, stdout);
strbuf_release(&buf);
@ -243,12 +248,13 @@ struct strbuf_list {
int alloc;
};
static int format_config(struct strbuf *buf, const char *key_, const char *value_)
static int format_config(struct strbuf *buf, const char *key_,
const char *value_, const struct key_value_info *kvi)
{
if (show_scope)
show_config_scope(buf);
show_config_scope(kvi, buf);
if (show_origin)
show_config_origin(buf);
show_config_origin(kvi, buf);
if (show_keys)
strbuf_addstr(buf, key_);
if (!omit_values) {
@ -257,13 +263,14 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
if (type == TYPE_INT)
strbuf_addf(buf, "%"PRId64,
git_config_int64(key_, value_ ? value_ : ""));
git_config_int64(key_, value_ ? value_ : "", kvi));
else if (type == TYPE_BOOL)
strbuf_addstr(buf, git_config_bool(key_, value_) ?
"true" : "false");
else if (type == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key_, value_, &is_bool);
v = git_config_bool_or_int(key_, value_, kvi,
&is_bool);
if (is_bool)
strbuf_addstr(buf, v ? "true" : "false");
else
@ -302,9 +309,11 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
return 0;
}
static int collect_config(const char *key_, const char *value_, void *cb)
static int collect_config(const char *key_, const char *value_,
const struct config_context *ctx, void *cb)
{
struct strbuf_list *values = cb;
const struct key_value_info *kvi = ctx->kvi;
if (!use_key_regexp && strcmp(key_, key))
return 0;
@ -319,7 +328,7 @@ static int collect_config(const char *key_, const char *value_, void *cb)
ALLOC_GROW(values->items, values->nr + 1, values->alloc);
strbuf_init(&values->items[values->nr], 0);
return format_config(&values->items[values->nr++], key_, value_);
return format_config(&values->items[values->nr++], key_, value_, kvi);
}
static int get_value(const char *key_, const char *regex_, unsigned flags)
@ -381,11 +390,14 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
&config_options);
if (!values.nr && default_value) {
struct key_value_info kvi = KVI_INIT;
struct strbuf *item;
kvi_from_param(&kvi);
ALLOC_GROW(values.items, values.nr + 1, values.alloc);
item = &values.items[values.nr++];
strbuf_init(item, 0);
if (format_config(item, key_, default_value) < 0)
if (format_config(item, key_, default_value, &kvi) < 0)
die(_("failed to format default config value: %s"),
default_value);
}
@ -414,7 +426,8 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
return ret;
}
static char *normalize_value(const char *key, const char *value)
static char *normalize_value(const char *key, const char *value,
struct key_value_info *kvi)
{
if (!value)
return NULL;
@ -429,12 +442,12 @@ static char *normalize_value(const char *key, const char *value)
*/
return xstrdup(value);
if (type == TYPE_INT)
return xstrfmt("%"PRId64, git_config_int64(key, value));
return xstrfmt("%"PRId64, git_config_int64(key, value, kvi));
if (type == TYPE_BOOL)
return xstrdup(git_config_bool(key, value) ? "true" : "false");
if (type == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key, value, &is_bool);
v = git_config_bool_or_int(key, value, kvi, &is_bool);
if (!is_bool)
return xstrfmt("%d", v);
else
@ -471,6 +484,7 @@ static const char *get_colorbool_slot;
static char parsed_color[COLOR_MAXLEN];
static int git_get_color_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
if (!strcmp(var, get_color_slot)) {
@ -504,6 +518,7 @@ static int get_colorbool_found;
static int get_diff_color_found;
static int get_color_ui_found;
static int git_get_colorbool_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *data UNUSED)
{
if (!strcmp(var, get_colorbool_slot))
@ -560,13 +575,17 @@ static void check_write(void)
struct urlmatch_current_candidate_value {
char value_is_null;
struct strbuf value;
struct key_value_info kvi;
};
static int urlmatch_collect_fn(const char *var, const char *value, void *cb)
static int urlmatch_collect_fn(const char *var, const char *value,
const struct config_context *ctx,
void *cb)
{
struct string_list *values = cb;
struct string_list_item *item = string_list_insert(values, var);
struct urlmatch_current_candidate_value *matched = item->util;
const struct key_value_info *kvi = ctx->kvi;
if (!matched) {
matched = xmalloc(sizeof(*matched));
@ -575,6 +594,7 @@ static int urlmatch_collect_fn(const char *var, const char *value, void *cb)
} else {
strbuf_reset(&matched->value);
}
matched->kvi = *kvi;
if (value) {
strbuf_addstr(&matched->value, value);
@ -622,7 +642,8 @@ static int get_urlmatch(const char *var, const char *url)
struct strbuf buf = STRBUF_INIT;
format_config(&buf, item->string,
matched->value_is_null ? NULL : matched->value.buf);
matched->value_is_null ? NULL : matched->value.buf,
&matched->kvi);
fwrite(buf.buf, 1, buf.len, stdout);
strbuf_release(&buf);
@ -656,6 +677,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
char *value = NULL;
int flags = 0;
int ret = 0;
struct key_value_info default_kvi = KVI_INIT;
given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
@ -873,7 +895,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
else if (actions == ACTION_SET) {
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
value = normalize_value(argv[0], argv[1], &default_kvi);
ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
if (ret == CONFIG_NOTHING_SET)
error(_("cannot overwrite multiple values with a single value\n"
@ -882,7 +904,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
else if (actions == ACTION_SET_ALL) {
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
value = normalize_value(argv[0], argv[1], &default_kvi);
ret = git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value, argv[2],
flags);
@ -890,7 +912,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
else if (actions == ACTION_ADD) {
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
value = normalize_value(argv[0], argv[1], &default_kvi);
ret = git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value,
CONFIG_REGEX_NONE,
@ -899,7 +921,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
else if (actions == ACTION_REPLACE_ALL) {
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
value = normalize_value(argv[0], argv[1], &default_kvi);
ret = git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value, argv[2],
flags | CONFIG_FLAGS_MULTI_REPLACE);

View File

@ -41,14 +41,15 @@ static const char *const builtin_difftool_usage[] = {
NULL
};
static int difftool_config(const char *var, const char *value, void *cb)
static int difftool_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "difftool.trustexitcode")) {
trust_exit_code = git_config_bool(var, value);
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static int print_tool_help(void)

View File

@ -110,7 +110,8 @@ struct fetch_config {
int submodule_fetch_jobs;
};
static int git_fetch_config(const char *k, const char *v, void *cb)
static int git_fetch_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
struct fetch_config *fetch_config = cb;
@ -136,7 +137,7 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
}
if (!strcmp(k, "submodule.fetchjobs")) {
fetch_config->submodule_fetch_jobs = parse_submodule_fetchjobs(k, v);
fetch_config->submodule_fetch_jobs = parse_submodule_fetchjobs(k, v, ctx->kvi);
return 0;
} else if (!strcmp(k, "fetch.recursesubmodules")) {
fetch_config->recurse_submodules = parse_fetch_recurse_submodules_arg(k, v);
@ -144,7 +145,7 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
}
if (!strcmp(k, "fetch.parallel")) {
fetch_config->parallel = git_config_int(k, v);
fetch_config->parallel = git_config_int(k, v, ctx->kvi);
if (fetch_config->parallel < 0)
die(_("fetch.parallel cannot be negative"));
if (!fetch_config->parallel)
@ -164,7 +165,7 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
"fetch.output", v);
}
return git_default_config(k, v, cb);
return git_default_config(k, v, ctx, cb);
}
static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
@ -1799,7 +1800,9 @@ struct remote_group_data {
struct string_list *list;
};
static int get_remote_group(const char *key, const char *value, void *priv)
static int get_remote_group(const char *key, const char *value,
const struct config_context *ctx UNUSED,
void *priv)
{
struct remote_group_data *g = priv;

View File

@ -39,10 +39,11 @@ static int fsmonitor__start_timeout_sec = 60;
#define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup"
static int fsmonitor__announce_startup = 0;
static int fsmonitor_config(const char *var, const char *value, void *cb)
static int fsmonitor_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, FSMONITOR__IPC_THREADS)) {
int i = git_config_int(var, value);
int i = git_config_int(var, value, ctx->kvi);
if (i < 1)
return error(_("value of '%s' out of range: %d"),
FSMONITOR__IPC_THREADS, i);
@ -51,7 +52,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb)
}
if (!strcmp(var, FSMONITOR__START_TIMEOUT)) {
int i = git_config_int(var, value);
int i = git_config_int(var, value, ctx->kvi);
if (i < 0)
return error(_("value of '%s' out of range: %d"),
FSMONITOR__START_TIMEOUT, i);
@ -61,7 +62,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb)
if (!strcmp(var, FSMONITOR__ANNOUNCE_STARTUP)) {
int is_bool;
int i = git_config_bool_or_int(var, value, &is_bool);
int i = git_config_bool_or_int(var, value, ctx->kvi, &is_bool);
if (i < 0)
return error(_("value of '%s' not bool or int: %d"),
var, i);
@ -69,7 +70,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb)
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
/*

View File

@ -291,14 +291,18 @@ static int wait_all(void)
return hit;
}
static int grep_cmd_config(const char *var, const char *value, void *cb)
static int grep_cmd_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
int st = grep_config(var, value, cb);
if (git_color_default_config(var, value, NULL) < 0)
int st = grep_config(var, value, ctx, cb);
if (git_color_config(var, value, cb) < 0)
st = -1;
else if (git_default_config(var, value, ctx, cb) < 0)
st = -1;
if (!strcmp(var, "grep.threads")) {
num_threads = git_config_int(var, value);
num_threads = git_config_int(var, value, ctx->kvi);
if (num_threads < 0)
die(_("invalid number of threads specified (%d) for %s"),
num_threads, var);

View File

@ -397,7 +397,8 @@ static int add_man_viewer_info(const char *var, const char *value)
return 0;
}
static int git_help_config(const char *var, const char *value, void *cb)
static int git_help_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "help.format")) {
if (!value)
@ -420,7 +421,7 @@ static int git_help_config(const char *var, const char *value, void *cb)
if (starts_with(var, "man."))
return add_man_viewer_info(var, value);
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static struct cmdnames main_cmds, other_cmds;

View File

@ -1582,18 +1582,19 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
strbuf_release(&pack_name);
}
static int git_index_pack_config(const char *k, const char *v, void *cb)
static int git_index_pack_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
struct pack_idx_option *opts = cb;
if (!strcmp(k, "pack.indexversion")) {
opts->version = git_config_int(k, v);
opts->version = git_config_int(k, v, ctx->kvi);
if (opts->version > 2)
die(_("bad pack.indexVersion=%"PRIu32), opts->version);
return 0;
}
if (!strcmp(k, "pack.threads")) {
nr_threads = git_config_int(k, v);
nr_threads = git_config_int(k, v, ctx->kvi);
if (nr_threads < 0)
die(_("invalid number of threads specified (%d)"),
nr_threads);
@ -1609,7 +1610,7 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
else
opts->flags &= ~WRITE_REV;
}
return git_default_config(k, v, cb);
return git_default_config(k, v, ctx, cb);
}
static int cmp_uint32(const void *a_, const void *b_)

View File

@ -564,7 +564,8 @@ static int cmd_log_walk(struct rev_info *rev)
return retval;
}
static int git_log_config(const char *var, const char *value, void *cb)
static int git_log_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
const char *slot_name;
@ -573,7 +574,7 @@ static int git_log_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "format.subjectprefix"))
return git_config_string(&fmt_patch_subject_prefix, var, value);
if (!strcmp(var, "format.filenamemaxlength")) {
fmt_patch_name_max = git_config_int(var, value);
fmt_patch_name_max = git_config_int(var, value, ctx->kvi);
return 0;
}
if (!strcmp(var, "format.encodeemailheaders")) {
@ -613,7 +614,7 @@ static int git_log_config(const char *var, const char *value, void *cb)
return 0;
}
return git_diff_ui_config(var, value, cb);
return git_diff_ui_config(var, value, ctx, cb);
}
int cmd_whatchanged(int argc, const char **argv, const char *prefix)
@ -979,7 +980,8 @@ static enum cover_from_description parse_cover_from_description(const char *arg)
die(_("%s: invalid cover from description mode"), arg);
}
static int git_format_config(const char *var, const char *value, void *cb)
static int git_format_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "format.headers")) {
if (!value)
@ -1108,7 +1110,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "diff.noprefix"))
return 0;
return git_log_config(var, value, cb);
return git_log_config(var, value, ctx, cb);
}
static const char *output_directory = NULL;

View File

@ -624,7 +624,8 @@ static void parse_branch_merge_options(char *bmo)
free(argv);
}
static int git_merge_config(const char *k, const char *v, void *cb)
static int git_merge_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
int status;
const char *str;
@ -669,10 +670,10 @@ static int git_merge_config(const char *k, const char *v, void *cb)
return 0;
}
status = fmt_merge_msg_config(k, v, cb);
status = fmt_merge_msg_config(k, v, ctx, cb);
if (status)
return status;
return git_diff_ui_config(k, v, cb);
return git_diff_ui_config(k, v, ctx, cb);
}
static int read_tree_trivial(struct object_id *common, struct object_id *head,

View File

@ -82,6 +82,7 @@ static struct option *add_common_options(struct option *prev)
}
static int git_multi_pack_index_write_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
if (!strcmp(var, "pack.writebitmaphashcache")) {

View File

@ -3135,26 +3135,27 @@ static void prepare_pack(int window, int depth)
free(delta_list);
}
static int git_pack_config(const char *k, const char *v, void *cb)
static int git_pack_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
if (!strcmp(k, "pack.window")) {
window = git_config_int(k, v);
window = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "pack.windowmemory")) {
window_memory_limit = git_config_ulong(k, v);
window_memory_limit = git_config_ulong(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "pack.depth")) {
depth = git_config_int(k, v);
depth = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "pack.deltacachesize")) {
max_delta_cache_size = git_config_int(k, v);
max_delta_cache_size = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "pack.deltacachelimit")) {
cache_max_small_delta_size = git_config_int(k, v);
cache_max_small_delta_size = git_config_int(k, v, ctx->kvi);
return 0;
}
if (!strcmp(k, "pack.writebitmaphashcache")) {
@ -3180,7 +3181,7 @@ static int git_pack_config(const char *k, const char *v, void *cb)
return 0;
}
if (!strcmp(k, "pack.threads")) {
delta_search_threads = git_config_int(k, v);
delta_search_threads = git_config_int(k, v, ctx->kvi);
if (delta_search_threads < 0)
die(_("invalid number of threads specified (%d)"),
delta_search_threads);
@ -3191,7 +3192,7 @@ static int git_pack_config(const char *k, const char *v, void *cb)
return 0;
}
if (!strcmp(k, "pack.indexversion")) {
pack_idx_opts.version = git_config_int(k, v);
pack_idx_opts.version = git_config_int(k, v, ctx->kvi);
if (pack_idx_opts.version > 2)
die(_("bad pack.indexVersion=%"PRIu32),
pack_idx_opts.version);
@ -3227,7 +3228,7 @@ static int git_pack_config(const char *k, const char *v, void *cb)
ex->uri = xstrdup(pack_end + 1);
oidmap_put(&configured_exclusions, ex);
}
return git_default_config(k, v, cb);
return git_default_config(k, v, ctx, cb);
}
/* Counters for trace2 output when in --stdin-packs mode. */

View File

@ -196,7 +196,8 @@ struct patch_id_opts {
int verbatim;
};
static int git_patch_id_config(const char *var, const char *value, void *cb)
static int git_patch_id_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct patch_id_opts *opts = cb;
@ -209,7 +210,7 @@ static int git_patch_id_config(const char *var, const char *value, void *cb)
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
int cmd_patch_id(int argc, const char **argv, const char *prefix)

View File

@ -363,7 +363,8 @@ static enum rebase_type config_get_rebase(int *rebase_unspecified)
/**
* Read config variables.
*/
static int git_pull_config(const char *var, const char *value, void *cb)
static int git_pull_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "rebase.autostash")) {
config_autostash = git_config_bool(var, value);
@ -376,7 +377,7 @@ static int git_pull_config(const char *var, const char *value, void *cb)
check_trust_level = 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
/**

View File

@ -509,7 +509,8 @@ static void set_push_cert_flags(int *flags, int v)
}
static int git_push_config(const char *k, const char *v, void *cb)
static int git_push_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
const char *slot_name;
int *flags = cb;
@ -576,7 +577,7 @@ static int git_push_config(const char *k, const char *v, void *cb)
return 0;
}
return git_default_config(k, v, NULL);
return git_default_config(k, v, ctx, NULL);
}
int cmd_push(int argc, const char **argv, const char *prefix)

View File

@ -102,12 +102,13 @@ static int debug_merge(const struct cache_entry * const *stages,
return 0;
}
static int git_read_tree_config(const char *var, const char *value, void *cb)
static int git_read_tree_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "submodule.recurse"))
return git_default_submodule_config(var, value, cb);
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)

View File

@ -773,7 +773,8 @@ static void parse_rebase_merges_value(struct rebase_options *options, const char
die(_("Unknown rebase-merges mode: %s"), value);
}
static int rebase_config(const char *var, const char *value, void *data)
static int rebase_config(const char *var, const char *value,
const struct config_context *ctx, void *data)
{
struct rebase_options *opts = data;
@ -832,7 +833,7 @@ static int rebase_config(const char *var, const char *value, void *data)
return git_config_string(&opts->default_backend, var, value);
}
return git_default_config(var, value, data);
return git_default_config(var, value, ctx, data);
}
static int checkout_up_to_date(struct rebase_options *options)

View File

@ -140,7 +140,8 @@ static enum deny_action parse_deny_action(const char *var, const char *value)
return DENY_IGNORE;
}
static int receive_pack_config(const char *var, const char *value, void *cb)
static int receive_pack_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
int status = parse_hide_refs_config(var, value, "receive", &hidden_refs);
@ -158,12 +159,12 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
}
if (strcmp(var, "receive.unpacklimit") == 0) {
receive_unpack_limit = git_config_int(var, value);
receive_unpack_limit = git_config_int(var, value, ctx->kvi);
return 0;
}
if (strcmp(var, "transfer.unpacklimit") == 0) {
transfer_unpack_limit = git_config_int(var, value);
transfer_unpack_limit = git_config_int(var, value, ctx->kvi);
return 0;
}
@ -231,7 +232,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return git_config_string(&cert_nonce_seed, var, value);
if (strcmp(var, "receive.certnonceslop") == 0) {
nonce_stamp_slop_limit = git_config_ulong(var, value);
nonce_stamp_slop_limit = git_config_ulong(var, value, ctx->kvi);
return 0;
}
@ -246,12 +247,12 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
}
if (strcmp(var, "receive.keepalive") == 0) {
keepalive_in_sec = git_config_int(var, value);
keepalive_in_sec = git_config_int(var, value, ctx->kvi);
return 0;
}
if (strcmp(var, "receive.maxinputsize") == 0) {
max_input_size = git_config_int64(var, value);
max_input_size = git_config_int64(var, value, ctx->kvi);
return 0;
}
@ -267,7 +268,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static void show_ref(const char *path, const struct object_id *oid)

View File

@ -110,7 +110,8 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
#define EXPIRE_TOTAL 01
#define EXPIRE_UNREACH 02
static int reflog_expire_config(const char *var, const char *value, void *cb)
static int reflog_expire_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
const char *pattern, *key;
size_t pattern_len;
@ -119,7 +120,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)
struct reflog_expire_cfg *ent;
if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0)
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
if (!strcmp(key, "reflogexpire")) {
slot = EXPIRE_TOTAL;
@ -130,7 +131,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)
if (git_config_expiry_date(&expire, var, value))
return -1;
} else
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
if (!pattern) {
switch (slot) {

View File

@ -269,6 +269,7 @@ static const char *abbrev_ref(const char *name, const char *prefix)
#define abbrev_branch(name) abbrev_ref((name), "refs/heads/")
static int config_read_branches(const char *key, const char *value,
const struct config_context *ctx UNUSED,
void *data UNUSED)
{
const char *orig_key = key;
@ -646,17 +647,19 @@ struct push_default_info
};
static int config_read_push_default(const char *key, const char *value,
void *cb)
const struct config_context *ctx, void *cb)
{
const struct key_value_info *kvi = ctx->kvi;
struct push_default_info* info = cb;
if (strcmp(key, "remote.pushdefault") ||
!value || strcmp(value, info->old_name))
return 0;
info->scope = current_config_scope();
info->scope = kvi->scope;
strbuf_reset(&info->origin);
strbuf_addstr(&info->origin, current_config_name());
info->linenr = current_config_line();
strbuf_addstr(&info->origin, config_origin_type_name(kvi->origin_type));
info->linenr = kvi->linenr;
return 0;
}
@ -1495,7 +1498,9 @@ static int prune(int argc, const char **argv, const char *prefix)
return result;
}
static int get_remote_default(const char *key, const char *value UNUSED, void *priv)
static int get_remote_default(const char *key, const char *value UNUSED,
const struct config_context *ctx UNUSED,
void *priv)
{
if (strcmp(key, "remotes.default") == 0) {
int *found = priv;

View File

@ -60,7 +60,8 @@ struct pack_objects_args {
int local;
};
static int repack_config(const char *var, const char *value, void *cb)
static int repack_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct pack_objects_args *cruft_po_args = cb;
if (!strcmp(var, "repack.usedeltabaseoffset")) {
@ -92,7 +93,7 @@ static int repack_config(const char *var, const char *value, void *cb)
return git_config_string(&cruft_po_args->depth, var, value);
if (!strcmp(var, "repack.cruftthreads"))
return git_config_string(&cruft_po_args->threads, var, value);
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
/*

View File

@ -315,12 +315,13 @@ static int reset_refs(const char *rev, const struct object_id *oid)
return update_ref_status;
}
static int git_reset_config(const char *var, const char *value, void *cb)
static int git_reset_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "submodule.recurse"))
return git_default_submodule_config(var, value, cb);
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
int cmd_reset(int argc, const char **argv, const char *prefix)

View File

@ -131,7 +131,8 @@ static void print_helper_status(struct ref *ref)
strbuf_release(&buf);
}
static int send_pack_config(const char *k, const char *v, void *cb)
static int send_pack_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
if (!strcmp(k, "push.gpgsign")) {
const char *value;
@ -151,7 +152,7 @@ static int send_pack_config(const char *k, const char *v, void *cb)
}
}
}
return git_default_config(k, v, cb);
return git_default_config(k, v, ctx, cb);
}
int cmd_send_pack(int argc, const char **argv, const char *prefix)

View File

@ -559,7 +559,8 @@ static void append_one_rev(const char *av)
die("bad sha1 reference %s", av);
}
static int git_show_branch_config(const char *var, const char *value, void *cb)
static int git_show_branch_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "showbranch.default")) {
if (!value)
@ -579,7 +580,10 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
return 0;
}
return git_color_default_config(var, value, cb);
if (git_color_config(var, value, cb) < 0)
return -1;
return git_default_config(var, value, ctx, cb);
}
static int omit_in_dense(struct commit *commit, struct commit **rev, int n)

View File

@ -841,7 +841,8 @@ static int show_stat = 1;
static int show_patch;
static int show_include_untracked;
static int git_stash_config(const char *var, const char *value, void *cb)
static int git_stash_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "stash.showstat")) {
show_stat = git_config_bool(var, value);
@ -855,7 +856,7 @@ static int git_stash_config(const char *var, const char *value, void *cb)
show_include_untracked = git_config_bool(var, value);
return 0;
}
return git_diff_basic_config(var, value, cb);
return git_diff_basic_config(var, value, ctx, cb);
}
static void diff_include_untracked(const struct stash_info *info, struct diff_options *diff_opt)

View File

@ -2195,12 +2195,13 @@ static int update_clone_task_finished(int result,
}
static int git_update_clone_config(const char *var, const char *value,
const struct config_context *ctx,
void *cb)
{
int *max_jobs = cb;
if (!strcmp(var, "submodule.fetchjobs"))
*max_jobs = parse_submodule_fetchjobs(var, value);
*max_jobs = parse_submodule_fetchjobs(var, value, ctx->kvi);
return 0;
}

View File

@ -188,7 +188,8 @@ static const char tag_template_nocleanup[] =
"Lines starting with '%c' will be kept; you may remove them"
" yourself if you want to.\n");
static int git_tag_config(const char *var, const char *value, void *cb)
static int git_tag_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "tag.gpgsign")) {
config_sign_tag = git_config_bool(var, value);
@ -209,7 +210,11 @@ static int git_tag_config(const char *var, const char *value, void *cb)
if (starts_with(var, "column."))
return git_column_config(var, value, "tag", &colopts);
return git_color_default_config(var, value, cb);
if (git_color_config(var, value, cb) < 0)
return -1;
return git_default_config(var, value, ctx, cb);
}
static void write_tag_body(int fd, const struct object_id *oid)

View File

@ -199,13 +199,14 @@ static const struct git_var *get_git_var(const char *var)
return NULL;
}
static int show_config(const char *var, const char *value, void *cb)
static int show_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (value)
printf("%s=%s\n", var, value);
else
printf("%s\n", var);
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
int cmd_var(int argc, const char **argv, const char *prefix UNUSED)

View File

@ -129,14 +129,15 @@ static int verbose;
static int guess_remote;
static timestamp_t expire;
static int git_worktree_config(const char *var, const char *value, void *cb)
static int git_worktree_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "worktree.guessremote")) {
guess_remote = git_config_bool(var, value);
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static int delete_git_dir(const char *id)

View File

@ -224,7 +224,9 @@ static int bundle_list_update(const char *key, const char *value,
return 0;
}
static int config_to_bundle_list(const char *key, const char *value, void *data)
static int config_to_bundle_list(const char *key, const char *value,
const struct config_context *ctx UNUSED,
void *data)
{
struct bundle_list *list = data;
return bundle_list_update(key, value, list);
@ -253,6 +255,7 @@ int bundle_uri_parse_config_format(const char *uri,
}
result = git_config_from_file_with_options(config_to_bundle_list,
filename, list,
CONFIG_SCOPE_UNKNOWN,
&opts);
if (!result && list->mode == BUNDLE_MODE_NONE) {
@ -871,7 +874,9 @@ int bundle_uri_advertise(struct repository *r, struct strbuf *value UNUSED)
return advertise_bundle_uri;
}
static int config_to_packet_line(const char *key, const char *value, void *data)
static int config_to_packet_line(const char *key, const char *value,
const struct config_context *ctx UNUSED,
void *data)
{
struct packet_reader *writer = data;

View File

@ -430,14 +430,6 @@ int git_color_config(const char *var, const char *value, void *cb UNUSED)
return 0;
}
int git_color_default_config(const char *var, const char *value, void *cb)
{
if (git_color_config(var, value, cb) < 0)
return -1;
return git_default_config(var, value, cb);
}
void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb)
{
if (*color)

View File

@ -88,12 +88,8 @@ extern const int column_colors_ansi_max;
*/
extern int color_stdout_is_tty;
/*
* Use the first one if you need only color config; the second is a convenience
* if you are just going to change to git_default_config, too.
*/
/* Parse color config. */
int git_color_config(const char *var, const char *value, void *cb);
int git_color_default_config(const char *var, const char *value, void *cb);
/*
* Parse a config option, which can be a boolean or one of

View File

@ -243,7 +243,8 @@ static int core_restrict_inherited_handles = -1;
static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
static char *unset_environment_variables;
int mingw_core_config(const char *var, const char *value, void *cb)
int mingw_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "core.hidedotfiles")) {
if (value && !strcasecmp(value, "dotgitonly"))

View File

@ -11,7 +11,9 @@ typedef _sigset_t sigset_t;
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#endif
int mingw_core_config(const char *var, const char *value, void *cb);
struct config_context;
int mingw_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
#define platform_core_config mingw_core_config
/*

546
config.c
View File

@ -69,72 +69,6 @@ struct config_source {
};
#define CONFIG_SOURCE_INIT { 0 }
struct config_reader {
/*
* These members record the "current" config source, which can be
* accessed by parsing callbacks.
*
* The "source" variable will be non-NULL only when we are actually
* parsing a real config source (file, blob, cmdline, etc).
*
* The "config_kvi" variable will be non-NULL only when we are feeding
* cached config from a configset into a callback.
*
* They cannot be non-NULL at the same time. If they are both NULL, then
* we aren't parsing anything (and depending on the function looking at
* the variables, it's either a bug for it to be called in the first
* place, or it's a function which can be reused for non-config
* purposes, and should fall back to some sane behavior).
*/
struct config_source *source;
struct key_value_info *config_kvi;
/*
* The "scope" of the current config source being parsed (repo, global,
* etc). Like "source", this is only set when parsing a config source.
* It's not part of "source" because it transcends a single file (i.e.,
* a file included from .git/config is still in "repo" scope).
*
* When iterating through a configset, the equivalent value is
* "config_kvi.scope" (see above).
*/
enum config_scope parsing_scope;
};
/*
* Where possible, prefer to accept "struct config_reader" as an arg than to use
* "the_reader". "the_reader" should only be used if that is infeasible, e.g. in
* a public function.
*/
static struct config_reader the_reader;
static inline void config_reader_push_source(struct config_reader *reader,
struct config_source *top)
{
top->prev = reader->source;
reader->source = top;
}
static inline struct config_source *config_reader_pop_source(struct config_reader *reader)
{
struct config_source *ret;
if (!reader->source)
BUG("tried to pop config source, but we weren't reading config");
ret = reader->source;
reader->source = reader->source->prev;
return ret;
}
static inline void config_reader_set_kvi(struct config_reader *reader,
struct key_value_info *kvi)
{
reader->config_kvi = kvi;
}
static inline void config_reader_set_scope(struct config_reader *reader,
enum config_scope scope)
{
reader->parsing_scope = scope;
}
static int pack_compression_seen;
static int zlib_compression_seen;
@ -197,7 +131,6 @@ struct config_include_data {
const struct config_options *opts;
struct git_config_source *config_source;
struct repository *repo;
struct config_reader *config_reader;
/*
* All remote URLs discovered when reading all config files.
@ -206,7 +139,8 @@ struct config_include_data {
};
#define CONFIG_INCLUDE_INIT { 0 }
static int git_config_include(const char *var, const char *value, void *data);
static int git_config_include(const char *var, const char *value,
const struct config_context *ctx, void *data);
#define MAX_INCLUDE_DEPTH 10
static const char include_depth_advice[] = N_(
@ -215,7 +149,8 @@ static const char include_depth_advice[] = N_(
"from\n"
" %s\n"
"This might be due to circular includes.");
static int handle_path_include(struct config_source *cs, const char *path,
static int handle_path_include(const struct key_value_info *kvi,
const char *path,
struct config_include_data *inc)
{
int ret = 0;
@ -237,14 +172,14 @@ static int handle_path_include(struct config_source *cs, const char *path,
if (!is_absolute_path(path)) {
char *slash;
if (!cs || !cs->path) {
if (!kvi || !kvi->path) {
ret = error(_("relative config includes must come from files"));
goto cleanup;
}
slash = find_last_dir_sep(cs->path);
slash = find_last_dir_sep(kvi->path);
if (slash)
strbuf_add(&buf, cs->path, slash - cs->path + 1);
strbuf_add(&buf, kvi->path, slash - kvi->path + 1);
strbuf_addstr(&buf, path);
path = buf.buf;
}
@ -252,10 +187,11 @@ static int handle_path_include(struct config_source *cs, const char *path,
if (!access_or_die(path, R_OK, 0)) {
if (++inc->depth > MAX_INCLUDE_DEPTH)
die(_(include_depth_advice), MAX_INCLUDE_DEPTH, path,
!cs ? "<unknown>" :
cs->name ? cs->name :
!kvi ? "<unknown>" :
kvi->filename ? kvi->filename :
"the command line");
ret = git_config_from_file(git_config_include, path, inc);
ret = git_config_from_file_with_options(git_config_include, path, inc,
kvi->scope, NULL);
inc->depth--;
}
cleanup:
@ -270,7 +206,7 @@ static void add_trailing_starstar_for_dir(struct strbuf *pat)
strbuf_addstr(pat, "**");
}
static int prepare_include_condition_pattern(struct config_source *cs,
static int prepare_include_condition_pattern(const struct key_value_info *kvi,
struct strbuf *pat)
{
struct strbuf path = STRBUF_INIT;
@ -287,11 +223,11 @@ static int prepare_include_condition_pattern(struct config_source *cs,
if (pat->buf[0] == '.' && is_dir_sep(pat->buf[1])) {
const char *slash;
if (!cs || !cs->path)
if (!kvi || !kvi->path)
return error(_("relative config include "
"conditionals must come from files"));
strbuf_realpath(&path, cs->path, 1);
strbuf_realpath(&path, kvi->path, 1);
slash = find_last_dir_sep(path.buf);
if (!slash)
BUG("how is this possible?");
@ -306,7 +242,7 @@ static int prepare_include_condition_pattern(struct config_source *cs,
return prefix;
}
static int include_by_gitdir(struct config_source *cs,
static int include_by_gitdir(const struct key_value_info *kvi,
const struct config_options *opts,
const char *cond, size_t cond_len, int icase)
{
@ -323,7 +259,7 @@ static int include_by_gitdir(struct config_source *cs,
strbuf_realpath(&text, git_dir, 1);
strbuf_add(&pattern, cond, cond_len);
prefix = prepare_include_condition_pattern(cs, &pattern);
prefix = prepare_include_condition_pattern(kvi, &pattern);
again:
if (prefix < 0)
@ -385,7 +321,8 @@ static int include_by_branch(const char *cond, size_t cond_len)
return ret;
}
static int add_remote_url(const char *var, const char *value, void *data)
static int add_remote_url(const char *var, const char *value,
const struct config_context *ctx UNUSED, void *data)
{
struct string_list *remote_urls = data;
const char *remote_name;
@ -404,22 +341,17 @@ static void populate_remote_urls(struct config_include_data *inc)
{
struct config_options opts;
enum config_scope store_scope = inc->config_reader->parsing_scope;
opts = *inc->opts;
opts.unconditional_remote_url = 1;
config_reader_set_scope(inc->config_reader, 0);
inc->remote_urls = xmalloc(sizeof(*inc->remote_urls));
string_list_init_dup(inc->remote_urls);
config_with_options(add_remote_url, inc->remote_urls,
inc->config_source, inc->repo, &opts);
config_reader_set_scope(inc->config_reader, store_scope);
}
static int forbid_remote_url(const char *var, const char *value UNUSED,
const struct config_context *ctx UNUSED,
void *data UNUSED)
{
const char *remote_name;
@ -463,16 +395,16 @@ static int include_by_remote_url(struct config_include_data *inc,
inc->remote_urls);
}
static int include_condition_is_true(struct config_source *cs,
static int include_condition_is_true(const struct key_value_info *kvi,
struct config_include_data *inc,
const char *cond, size_t cond_len)
{
const struct config_options *opts = inc->opts;
if (skip_prefix_mem(cond, cond_len, "gitdir:", &cond, &cond_len))
return include_by_gitdir(cs, opts, cond, cond_len, 0);
return include_by_gitdir(kvi, opts, cond, cond_len, 0);
else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len))
return include_by_gitdir(cs, opts, cond, cond_len, 1);
return include_by_gitdir(kvi, opts, cond, cond_len, 1);
else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len))
return include_by_branch(cond, cond_len);
else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
@ -483,10 +415,11 @@ static int include_condition_is_true(struct config_source *cs,
return 0;
}
static int git_config_include(const char *var, const char *value, void *data)
static int git_config_include(const char *var, const char *value,
const struct config_context *ctx,
void *data)
{
struct config_include_data *inc = data;
struct config_source *cs = inc->config_reader->source;
const char *cond, *key;
size_t cond_len;
int ret;
@ -495,21 +428,21 @@ static int git_config_include(const char *var, const char *value, void *data)
* Pass along all values, including "include" directives; this makes it
* possible to query information on the includes themselves.
*/
ret = inc->fn(var, value, inc->data);
ret = inc->fn(var, value, ctx, inc->data);
if (ret < 0)
return ret;
if (!strcmp(var, "include.path"))
ret = handle_path_include(cs, value, inc);
ret = handle_path_include(ctx->kvi, value, inc);
if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
cond && include_condition_is_true(cs, inc, cond, cond_len) &&
cond && include_condition_is_true(ctx->kvi, inc, cond, cond_len) &&
!strcmp(key, "path")) {
config_fn_t old_fn = inc->fn;
if (inc->opts->unconditional_remote_url)
inc->fn = forbid_remote_url;
ret = handle_path_include(cs, value, inc);
ret = handle_path_include(ctx->kvi, value, inc);
inc->fn = old_fn;
}
@ -667,27 +600,45 @@ int git_config_parse_key(const char *key, char **store_key, size_t *baselen_)
}
static int config_parse_pair(const char *key, const char *value,
config_fn_t fn, void *data)
struct key_value_info *kvi,
config_fn_t fn, void *data)
{
char *canonical_name;
int ret;
struct config_context ctx = {
.kvi = kvi,
};
if (!strlen(key))
return error(_("empty config key"));
if (git_config_parse_key(key, &canonical_name, NULL))
return -1;
ret = (fn(canonical_name, value, data) < 0) ? -1 : 0;
ret = (fn(canonical_name, value, &ctx, data) < 0) ? -1 : 0;
free(canonical_name);
return ret;
}
/* for values read from `git_config_from_parameters()` */
void kvi_from_param(struct key_value_info *out)
{
out->filename = NULL;
out->linenr = -1;
out->origin_type = CONFIG_ORIGIN_CMDLINE;
out->scope = CONFIG_SCOPE_COMMAND;
out->path = NULL;
}
int git_config_parse_parameter(const char *text,
config_fn_t fn, void *data)
{
const char *value;
struct strbuf **pair;
int ret;
struct key_value_info kvi = KVI_INIT;
kvi_from_param(&kvi);
pair = strbuf_split_str(text, '=', 2);
if (!pair[0])
@ -706,12 +657,13 @@ int git_config_parse_parameter(const char *text,
return error(_("bogus config parameter: %s"), text);
}
ret = config_parse_pair(pair[0]->buf, value, fn, data);
ret = config_parse_pair(pair[0]->buf, value, &kvi, fn, data);
strbuf_list_free(pair);
return ret;
}
static int parse_config_env_list(char *env, config_fn_t fn, void *data)
static int parse_config_env_list(char *env, struct key_value_info *kvi,
config_fn_t fn, void *data)
{
char *cur = env;
while (cur && *cur) {
@ -745,7 +697,7 @@ static int parse_config_env_list(char *env, config_fn_t fn, void *data)
CONFIG_DATA_ENVIRONMENT);
}
if (config_parse_pair(key, value, fn, data) < 0)
if (config_parse_pair(key, value, kvi, fn, data) < 0)
return -1;
}
else {
@ -769,11 +721,9 @@ int git_config_from_parameters(config_fn_t fn, void *data)
struct strvec to_free = STRVEC_INIT;
int ret = 0;
char *envw = NULL;
struct config_source source = CONFIG_SOURCE_INIT;
source.origin_type = CONFIG_ORIGIN_CMDLINE;
config_reader_push_source(&the_reader, &source);
struct key_value_info kvi = KVI_INIT;
kvi_from_param(&kvi);
env = getenv(CONFIG_COUNT_ENVIRONMENT);
if (env) {
unsigned long count;
@ -809,7 +759,7 @@ int git_config_from_parameters(config_fn_t fn, void *data)
}
strbuf_reset(&envvar);
if (config_parse_pair(key, value, fn, data) < 0) {
if (config_parse_pair(key, value, &kvi, fn, data) < 0) {
ret = -1;
goto out;
}
@ -820,7 +770,7 @@ int git_config_from_parameters(config_fn_t fn, void *data)
if (env) {
/* sq_dequote will write over it */
envw = xstrdup(env);
if (parse_config_env_list(envw, fn, data) < 0) {
if (parse_config_env_list(envw, &kvi, fn, data) < 0) {
ret = -1;
goto out;
}
@ -830,7 +780,6 @@ int git_config_from_parameters(config_fn_t fn, void *data)
strbuf_release(&envvar);
strvec_clear(&to_free);
free(envw);
config_reader_pop_source(&the_reader);
return ret;
}
@ -931,12 +880,15 @@ static char *parse_value(struct config_source *cs)
}
}
static int get_value(struct config_source *cs, config_fn_t fn, void *data,
struct strbuf *name)
static int get_value(struct config_source *cs, struct key_value_info *kvi,
config_fn_t fn, void *data, struct strbuf *name)
{
int c;
char *value;
int ret;
struct config_context ctx = {
.kvi = kvi,
};
/* Get the full name */
for (;;) {
@ -965,7 +917,8 @@ static int get_value(struct config_source *cs, config_fn_t fn, void *data,
* accurate line number in error messages.
*/
cs->linenr--;
ret = fn(name->buf, value, data);
kvi->linenr = cs->linenr;
ret = fn(name->buf, value, &ctx, data);
if (ret >= 0)
cs->linenr++;
return ret;
@ -1055,7 +1008,7 @@ static int do_event(struct config_source *cs, enum config_event_t type,
if (data->previous_type != CONFIG_EVENT_EOF &&
data->opts->event_fn(data->previous_type, data->previous_offset,
offset, data->opts->event_fn_data) < 0)
offset, cs, data->opts->event_fn_data) < 0)
return -1;
data->previous_type = type;
@ -1064,8 +1017,20 @@ static int do_event(struct config_source *cs, enum config_event_t type,
return 0;
}
static void kvi_from_source(struct config_source *cs,
enum config_scope scope,
struct key_value_info *out)
{
out->filename = strintern(cs->name);
out->origin_type = cs->origin_type;
out->linenr = cs->linenr;
out->scope = scope;
out->path = cs->path;
}
static int git_parse_source(struct config_source *cs, config_fn_t fn,
void *data, const struct config_options *opts)
struct key_value_info *kvi, void *data,
const struct config_options *opts)
{
int comment = 0;
size_t baselen = 0;
@ -1149,7 +1114,7 @@ static int git_parse_source(struct config_source *cs, config_fn_t fn,
*/
strbuf_setlen(var, baselen);
strbuf_addch(var, tolower(c));
if (get_value(cs, fn, data, var) < 0)
if (get_value(cs, kvi, fn, data, var) < 0)
break;
}
@ -1325,80 +1290,78 @@ int git_parse_ssize_t(const char *value, ssize_t *ret)
return 1;
}
static int reader_config_name(struct config_reader *reader, const char **out);
static int reader_origin_type(struct config_reader *reader,
enum config_origin_type *type);
NORETURN
static void die_bad_number(struct config_reader *reader, const char *name,
const char *value)
static void die_bad_number(const char *name, const char *value,
const struct key_value_info *kvi)
{
const char *error_type = (errno == ERANGE) ?
N_("out of range") : N_("invalid unit");
const char *bad_numeric = N_("bad numeric config value '%s' for '%s': %s");
const char *config_name = NULL;
enum config_origin_type config_origin = CONFIG_ORIGIN_UNKNOWN;
if (!kvi)
BUG("kvi should not be NULL");
if (!value)
value = "";
/* Ignoring the return value is okay since we handle missing values. */
reader_config_name(reader, &config_name);
reader_origin_type(reader, &config_origin);
if (!config_name)
if (!kvi->filename)
die(_(bad_numeric), value, name, _(error_type));
switch (config_origin) {
switch (kvi->origin_type) {
case CONFIG_ORIGIN_BLOB:
die(_("bad numeric config value '%s' for '%s' in blob %s: %s"),
value, name, config_name, _(error_type));
value, name, kvi->filename, _(error_type));
case CONFIG_ORIGIN_FILE:
die(_("bad numeric config value '%s' for '%s' in file %s: %s"),
value, name, config_name, _(error_type));
value, name, kvi->filename, _(error_type));
case CONFIG_ORIGIN_STDIN:
die(_("bad numeric config value '%s' for '%s' in standard input: %s"),
value, name, _(error_type));
case CONFIG_ORIGIN_SUBMODULE_BLOB:
die(_("bad numeric config value '%s' for '%s' in submodule-blob %s: %s"),
value, name, config_name, _(error_type));
value, name, kvi->filename, _(error_type));
case CONFIG_ORIGIN_CMDLINE:
die(_("bad numeric config value '%s' for '%s' in command line %s: %s"),
value, name, config_name, _(error_type));
value, name, kvi->filename, _(error_type));
default:
die(_("bad numeric config value '%s' for '%s' in %s: %s"),
value, name, config_name, _(error_type));
value, name, kvi->filename, _(error_type));
}
}
int git_config_int(const char *name, const char *value)
int git_config_int(const char *name, const char *value,
const struct key_value_info *kvi)
{
int ret;
if (!git_parse_int(value, &ret))
die_bad_number(&the_reader, name, value);
die_bad_number(name, value, kvi);
return ret;
}
int64_t git_config_int64(const char *name, const char *value)
int64_t git_config_int64(const char *name, const char *value,
const struct key_value_info *kvi)
{
int64_t ret;
if (!git_parse_int64(value, &ret))
die_bad_number(&the_reader, name, value);
die_bad_number(name, value, kvi);
return ret;
}
unsigned long git_config_ulong(const char *name, const char *value)
unsigned long git_config_ulong(const char *name, const char *value,
const struct key_value_info *kvi)
{
unsigned long ret;
if (!git_parse_ulong(value, &ret))
die_bad_number(&the_reader, name, value);
die_bad_number(name, value, kvi);
return ret;
}
ssize_t git_config_ssize_t(const char *name, const char *value)
ssize_t git_config_ssize_t(const char *name, const char *value,
const struct key_value_info *kvi)
{
ssize_t ret;
if (!git_parse_ssize_t(value, &ret))
die_bad_number(&the_reader, name, value);
die_bad_number(name, value, kvi);
return ret;
}
@ -1503,7 +1466,8 @@ int git_parse_maybe_bool(const char *value)
return -1;
}
int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
int git_config_bool_or_int(const char *name, const char *value,
const struct key_value_info *kvi, int *is_bool)
{
int v = git_parse_maybe_bool_text(value);
if (0 <= v) {
@ -1511,7 +1475,7 @@ int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
return v;
}
*is_bool = 0;
return git_config_int(name, value);
return git_config_int(name, value, kvi);
}
int git_config_bool(const char *name, const char *value)
@ -1559,7 +1523,8 @@ int git_config_color(char *dest, const char *var, const char *value)
return 0;
}
static int git_default_core_config(const char *var, const char *value, void *cb)
static int git_default_core_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
/* This needs a better name */
if (!strcmp(var, "core.filemode")) {
@ -1636,7 +1601,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
else if (!git_parse_maybe_bool_text(value))
default_abbrev = the_hash_algo->hexsz;
else {
int abbrev = git_config_int(var, value);
int abbrev = git_config_int(var, value, ctx->kvi);
if (abbrev < minimum_abbrev || abbrev > the_hash_algo->hexsz)
return error(_("abbrev length out of range: %d"), abbrev);
default_abbrev = abbrev;
@ -1648,7 +1613,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
return set_disambiguate_hint_config(var, value);
if (!strcmp(var, "core.loosecompression")) {
int level = git_config_int(var, value);
int level = git_config_int(var, value, ctx->kvi);
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level < 0 || level > Z_BEST_COMPRESSION)
@ -1659,7 +1624,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
}
if (!strcmp(var, "core.compression")) {
int level = git_config_int(var, value);
int level = git_config_int(var, value, ctx->kvi);
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level < 0 || level > Z_BEST_COMPRESSION)
@ -1673,7 +1638,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "core.packedgitwindowsize")) {
int pgsz_x2 = getpagesize() * 2;
packed_git_window_size = git_config_ulong(var, value);
packed_git_window_size = git_config_ulong(var, value, ctx->kvi);
/* This value must be multiple of (pagesize * 2) */
packed_git_window_size /= pgsz_x2;
@ -1684,17 +1649,17 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
}
if (!strcmp(var, "core.bigfilethreshold")) {
big_file_threshold = git_config_ulong(var, value);
big_file_threshold = git_config_ulong(var, value, ctx->kvi);
return 0;
}
if (!strcmp(var, "core.packedgitlimit")) {
packed_git_limit = git_config_ulong(var, value);
packed_git_limit = git_config_ulong(var, value, ctx->kvi);
return 0;
}
if (!strcmp(var, "core.deltabasecachelimit")) {
delta_base_cache_limit = git_config_ulong(var, value);
delta_base_cache_limit = git_config_ulong(var, value, ctx->kvi);
return 0;
}
@ -1839,7 +1804,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
}
/* Add other config variables here and to Documentation/config.txt. */
return platform_core_config(var, value, cb);
return platform_core_config(var, value, ctx, cb);
}
static int git_default_sparse_config(const char *var, const char *value)
@ -1941,15 +1906,16 @@ static int git_default_mailmap_config(const char *var, const char *value)
return 0;
}
int git_default_config(const char *var, const char *value, void *cb)
int git_default_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (starts_with(var, "core."))
return git_default_core_config(var, value, cb);
return git_default_core_config(var, value, ctx, cb);
if (starts_with(var, "user.") ||
starts_with(var, "author.") ||
starts_with(var, "committer."))
return git_ident_config(var, value, cb);
return git_ident_config(var, value, ctx, cb);
if (starts_with(var, "i18n."))
return git_default_i18n_config(var, value);
@ -1972,12 +1938,12 @@ int git_default_config(const char *var, const char *value, void *cb)
}
if (!strcmp(var, "pack.packsizelimit")) {
pack_size_limit_cfg = git_config_ulong(var, value);
pack_size_limit_cfg = git_config_ulong(var, value, ctx->kvi);
return 0;
}
if (!strcmp(var, "pack.compression")) {
int level = git_config_int(var, value);
int level = git_config_int(var, value, ctx->kvi);
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level < 0 || level > Z_BEST_COMPRESSION)
@ -1999,10 +1965,11 @@ int git_default_config(const char *var, const char *value, void *cb)
* fgetc, ungetc, ftell of top need to be initialized before calling
* this function.
*/
static int do_config_from(struct config_reader *reader,
struct config_source *top, config_fn_t fn, void *data,
static int do_config_from(struct config_source *top, config_fn_t fn,
void *data, enum config_scope scope,
const struct config_options *opts)
{
struct key_value_info kvi = KVI_INIT;
int ret;
/* push config-file parsing state stack */
@ -2011,23 +1978,21 @@ static int do_config_from(struct config_reader *reader,
top->total_len = 0;
strbuf_init(&top->value, 1024);
strbuf_init(&top->var, 1024);
config_reader_push_source(reader, top);
kvi_from_source(top, scope, &kvi);
ret = git_parse_source(top, fn, data, opts);
ret = git_parse_source(top, fn, &kvi, data, opts);
/* pop config-file parsing state stack */
strbuf_release(&top->value);
strbuf_release(&top->var);
config_reader_pop_source(reader);
return ret;
}
static int do_config_from_file(struct config_reader *reader,
config_fn_t fn,
static int do_config_from_file(config_fn_t fn,
const enum config_origin_type origin_type,
const char *name, const char *path, FILE *f,
void *data, const struct config_options *opts)
void *data, enum config_scope scope,
const struct config_options *opts)
{
struct config_source top = CONFIG_SOURCE_INIT;
int ret;
@ -2042,19 +2007,20 @@ static int do_config_from_file(struct config_reader *reader,
top.do_ftell = config_file_ftell;
flockfile(f);
ret = do_config_from(reader, &top, fn, data, opts);
ret = do_config_from(&top, fn, data, scope, opts);
funlockfile(f);
return ret;
}
static int git_config_from_stdin(config_fn_t fn, void *data)
static int git_config_from_stdin(config_fn_t fn, void *data,
enum config_scope scope)
{
return do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_STDIN, "",
NULL, stdin, data, NULL);
return do_config_from_file(fn, CONFIG_ORIGIN_STDIN, "", NULL, stdin,
data, scope, NULL);
}
int git_config_from_file_with_options(config_fn_t fn, const char *filename,
void *data,
void *data, enum config_scope scope,
const struct config_options *opts)
{
int ret = -1;
@ -2064,8 +2030,8 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename,
BUG("filename cannot be NULL");
f = fopen_or_warn(filename, "r");
if (f) {
ret = do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_FILE,
filename, filename, f, data, opts);
ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename,
filename, f, data, scope, opts);
fclose(f);
}
return ret;
@ -2073,13 +2039,15 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename,
int git_config_from_file(config_fn_t fn, const char *filename, void *data)
{
return git_config_from_file_with_options(fn, filename, data, NULL);
return git_config_from_file_with_options(fn, filename, data,
CONFIG_SCOPE_UNKNOWN, NULL);
}
int git_config_from_mem(config_fn_t fn,
const enum config_origin_type origin_type,
const char *name, const char *buf, size_t len,
void *data, const struct config_options *opts)
void *data, enum config_scope scope,
const struct config_options *opts)
{
struct config_source top = CONFIG_SOURCE_INIT;
@ -2094,14 +2062,15 @@ int git_config_from_mem(config_fn_t fn,
top.do_ungetc = config_buf_ungetc;
top.do_ftell = config_buf_ftell;
return do_config_from(&the_reader, &top, fn, data, opts);
return do_config_from(&top, fn, data, scope, opts);
}
int git_config_from_blob_oid(config_fn_t fn,
const char *name,
struct repository *repo,
const struct object_id *oid,
void *data)
void *data,
enum config_scope scope)
{
enum object_type type;
char *buf;
@ -2117,7 +2086,7 @@ int git_config_from_blob_oid(config_fn_t fn,
}
ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size,
data, NULL);
data, scope, NULL);
free(buf);
return ret;
@ -2126,13 +2095,14 @@ int git_config_from_blob_oid(config_fn_t fn,
static int git_config_from_blob_ref(config_fn_t fn,
struct repository *repo,
const char *name,
void *data)
void *data,
enum config_scope scope)
{
struct object_id oid;
if (repo_get_oid(repo, name, &oid) < 0)
return error(_("unable to resolve config blob '%s'"), name);
return git_config_from_blob_oid(fn, name, repo, &oid, data);
return git_config_from_blob_oid(fn, name, repo, &oid, data, scope);
}
char *git_system_config(void)
@ -2185,8 +2155,7 @@ int git_config_system(void)
return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
}
static int do_git_config_sequence(struct config_reader *reader,
const struct config_options *opts,
static int do_git_config_sequence(const struct config_options *opts,
const struct repository *repo,
config_fn_t fn, void *data)
{
@ -2196,7 +2165,6 @@ static int do_git_config_sequence(struct config_reader *reader,
char *user_config = NULL;
char *repo_config;
char *worktree_config;
enum config_scope prev_parsing_scope = reader->parsing_scope;
/*
* Ensure that either:
@ -2214,38 +2182,39 @@ static int do_git_config_sequence(struct config_reader *reader,
worktree_config = NULL;
}
config_reader_set_scope(reader, CONFIG_SCOPE_SYSTEM);
if (git_config_system() && system_config &&
!access_or_die(system_config, R_OK,
opts->system_gently ? ACCESS_EACCES_OK : 0))
ret += git_config_from_file(fn, system_config, data);
ret += git_config_from_file_with_options(fn, system_config,
data, CONFIG_SCOPE_SYSTEM,
NULL);
config_reader_set_scope(reader, CONFIG_SCOPE_GLOBAL);
git_global_config(&user_config, &xdg_config);
if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK))
ret += git_config_from_file(fn, xdg_config, data);
ret += git_config_from_file_with_options(fn, xdg_config, data,
CONFIG_SCOPE_GLOBAL, NULL);
if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
ret += git_config_from_file(fn, user_config, data);
ret += git_config_from_file_with_options(fn, user_config, data,
CONFIG_SCOPE_GLOBAL, NULL);
config_reader_set_scope(reader, CONFIG_SCOPE_LOCAL);
if (!opts->ignore_repo && repo_config &&
!access_or_die(repo_config, R_OK, 0))
ret += git_config_from_file(fn, repo_config, data);
ret += git_config_from_file_with_options(fn, repo_config, data,
CONFIG_SCOPE_LOCAL, NULL);
config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE);
if (!opts->ignore_worktree && worktree_config &&
repo && repo->repository_format_worktree_config &&
!access_or_die(worktree_config, R_OK, 0)) {
ret += git_config_from_file(fn, worktree_config, data);
ret += git_config_from_file_with_options(fn, worktree_config, data,
CONFIG_SCOPE_WORKTREE,
NULL);
}
config_reader_set_scope(reader, CONFIG_SCOPE_COMMAND);
if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
die(_("unable to parse command-line config"));
config_reader_set_scope(reader, prev_parsing_scope);
free(system_config);
free(xdg_config);
free(user_config);
@ -2260,7 +2229,6 @@ int config_with_options(config_fn_t fn, void *data,
const struct config_options *opts)
{
struct config_include_data inc = CONFIG_INCLUDE_INIT;
enum config_scope prev_scope = the_reader.parsing_scope;
int ret;
if (opts->respect_includes) {
@ -2269,58 +2237,52 @@ int config_with_options(config_fn_t fn, void *data,
inc.opts = opts;
inc.repo = repo;
inc.config_source = config_source;
inc.config_reader = &the_reader;
fn = git_config_include;
data = &inc;
}
if (config_source)
config_reader_set_scope(&the_reader, config_source->scope);
/*
* If we have a specific filename, use it. Otherwise, follow the
* regular lookup sequence.
*/
if (config_source && config_source->use_stdin) {
ret = git_config_from_stdin(fn, data);
ret = git_config_from_stdin(fn, data, config_source->scope);
} else if (config_source && config_source->file) {
ret = git_config_from_file(fn, config_source->file, data);
ret = git_config_from_file_with_options(fn, config_source->file,
data, config_source->scope,
NULL);
} else if (config_source && config_source->blob) {
ret = git_config_from_blob_ref(fn, repo, config_source->blob,
data);
data, config_source->scope);
} else {
ret = do_git_config_sequence(&the_reader, opts, repo, fn, data);
ret = do_git_config_sequence(opts, repo, fn, data);
}
if (inc.remote_urls) {
string_list_clear(inc.remote_urls, 0);
FREE_AND_NULL(inc.remote_urls);
}
config_reader_set_scope(&the_reader, prev_scope);
return ret;
}
static void configset_iter(struct config_reader *reader, struct config_set *set,
config_fn_t fn, void *data)
static void configset_iter(struct config_set *set, config_fn_t fn, void *data)
{
int i, value_index;
struct string_list *values;
struct config_set_element *entry;
struct configset_list *list = &set->list;
struct config_context ctx = CONFIG_CONTEXT_INIT;
for (i = 0; i < list->nr; i++) {
entry = list->items[i].e;
value_index = list->items[i].value_index;
values = &entry->value_list;
config_reader_set_kvi(reader, values->items[value_index].util);
if (fn(entry->key, values->items[value_index].string, data) < 0)
ctx.kvi = values->items[value_index].util;
if (fn(entry->key, values->items[value_index].string, &ctx, data) < 0)
git_die_config_linenr(entry->key,
reader->config_kvi->filename,
reader->config_kvi->linenr);
config_reader_set_kvi(reader, NULL);
ctx.kvi->filename,
ctx.kvi->linenr);
}
}
@ -2396,7 +2358,7 @@ static int configset_find_element(struct config_set *set, const char *key,
return 0;
}
static int configset_add_value(struct config_reader *reader,
static int configset_add_value(const struct key_value_info *kvi_p,
struct config_set *set, const char *key,
const char *value)
{
@ -2427,19 +2389,7 @@ static int configset_add_value(struct config_reader *reader,
l_item->e = e;
l_item->value_index = e->value_list.nr - 1;
if (!reader->source)
BUG("configset_add_value has no source");
if (reader->source->name) {
kv_info->filename = strintern(reader->source->name);
kv_info->linenr = reader->source->linenr;
kv_info->origin_type = reader->source->origin_type;
} else {
/* for values read from `git_config_from_parameters()` */
kv_info->filename = NULL;
kv_info->linenr = -1;
kv_info->origin_type = CONFIG_ORIGIN_CMDLINE;
}
kv_info->scope = reader->parsing_scope;
*kv_info = *kvi_p;
si->util = kv_info;
return 0;
@ -2487,32 +2437,26 @@ void git_configset_clear(struct config_set *set)
set->list.items = NULL;
}
struct configset_add_data {
struct config_set *config_set;
struct config_reader *config_reader;
};
#define CONFIGSET_ADD_INIT { 0 }
static int config_set_callback(const char *key, const char *value, void *cb)
static int config_set_callback(const char *key, const char *value,
const struct config_context *ctx,
void *cb)
{
struct configset_add_data *data = cb;
configset_add_value(data->config_reader, data->config_set, key, value);
struct config_set *set = cb;
configset_add_value(ctx->kvi, set, key, value);
return 0;
}
int git_configset_add_file(struct config_set *set, const char *filename)
{
struct configset_add_data data = CONFIGSET_ADD_INIT;
data.config_reader = &the_reader;
data.config_set = set;
return git_config_from_file(config_set_callback, filename, &data);
return git_config_from_file(config_set_callback, filename, set);
}
int git_configset_get_value(struct config_set *set, const char *key, const char **value)
int git_configset_get_value(struct config_set *set, const char *key,
const char **value, struct key_value_info *kvi)
{
const struct string_list *values = NULL;
int ret;
struct string_list_item item;
/*
* 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
@ -2522,7 +2466,10 @@ int git_configset_get_value(struct config_set *set, const char *key, const char
return ret;
assert(values->nr > 0);
*value = values->items[values->nr - 1].string;
item = values->items[values->nr - 1];
*value = item.string;
if (kvi)
*kvi = *((struct key_value_info *)item.util);
return 0;
}
@ -2575,7 +2522,7 @@ int git_configset_get(struct config_set *set, const char *key)
int git_configset_get_string(struct config_set *set, const char *key, char **dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value))
if (!git_configset_get_value(set, key, &value, NULL))
return git_config_string((const char **)dest, key, value);
else
return 1;
@ -2585,7 +2532,7 @@ static int git_configset_get_string_tmp(struct config_set *set, const char *key,
const char **dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value)) {
if (!git_configset_get_value(set, key, &value, NULL)) {
if (!value)
return config_error_nonbool(key);
*dest = value;
@ -2598,8 +2545,10 @@ static int git_configset_get_string_tmp(struct config_set *set, const char *key,
int git_configset_get_int(struct config_set *set, const char *key, int *dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value)) {
*dest = git_config_int(key, value);
struct key_value_info kvi;
if (!git_configset_get_value(set, key, &value, &kvi)) {
*dest = git_config_int(key, value, &kvi);
return 0;
} else
return 1;
@ -2608,8 +2557,10 @@ int git_configset_get_int(struct config_set *set, const char *key, int *dest)
int git_configset_get_ulong(struct config_set *set, const char *key, unsigned long *dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value)) {
*dest = git_config_ulong(key, value);
struct key_value_info kvi;
if (!git_configset_get_value(set, key, &value, &kvi)) {
*dest = git_config_ulong(key, value, &kvi);
return 0;
} else
return 1;
@ -2618,7 +2569,7 @@ int git_configset_get_ulong(struct config_set *set, const char *key, unsigned lo
int git_configset_get_bool(struct config_set *set, const char *key, int *dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value)) {
if (!git_configset_get_value(set, key, &value, NULL)) {
*dest = git_config_bool(key, value);
return 0;
} else
@ -2629,8 +2580,10 @@ int git_configset_get_bool_or_int(struct config_set *set, const char *key,
int *is_bool, int *dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value)) {
*dest = git_config_bool_or_int(key, value, is_bool);
struct key_value_info kvi;
if (!git_configset_get_value(set, key, &value, &kvi)) {
*dest = git_config_bool_or_int(key, value, &kvi, is_bool);
return 0;
} else
return 1;
@ -2639,7 +2592,7 @@ int git_configset_get_bool_or_int(struct config_set *set, const char *key,
int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value)) {
if (!git_configset_get_value(set, key, &value, NULL)) {
*dest = git_parse_maybe_bool(value);
if (*dest == -1)
return -1;
@ -2651,7 +2604,7 @@ int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *d
int git_configset_get_pathname(struct config_set *set, const char *key, const char **dest)
{
const char *value;
if (!git_configset_get_value(set, key, &value))
if (!git_configset_get_value(set, key, &value, NULL))
return git_config_pathname(dest, key, value);
else
return 1;
@ -2661,7 +2614,6 @@ int git_configset_get_pathname(struct config_set *set, const char *key, const ch
static void repo_read_config(struct repository *repo)
{
struct config_options opts = { 0 };
struct configset_add_data data = CONFIGSET_ADD_INIT;
opts.respect_includes = 1;
opts.commondir = repo->commondir;
@ -2673,10 +2625,8 @@ static void repo_read_config(struct repository *repo)
git_configset_clear(repo->config);
git_configset_init(repo->config);
data.config_set = repo->config;
data.config_reader = &the_reader;
if (config_with_options(config_set_callback, &data, NULL, repo, &opts) < 0)
if (config_with_options(config_set_callback, repo->config, NULL,
repo, &opts) < 0)
/*
* config_with_options() normally returns only
* zero, as most errors are fatal, and
@ -2708,7 +2658,7 @@ static void repo_config_clear(struct repository *repo)
void repo_config(struct repository *repo, config_fn_t fn, void *data)
{
git_config_check_init(repo);
configset_iter(&the_reader, repo->config, fn, data);
configset_iter(repo->config, fn, data);
}
int repo_config_get(struct repository *repo, const char *key)
@ -2721,7 +2671,7 @@ int repo_config_get_value(struct repository *repo,
const char *key, const char **value)
{
git_config_check_init(repo);
return git_configset_get_value(repo->config, key, value);
return git_configset_get_value(repo->config, key, value, NULL);
}
int repo_config_get_value_multi(struct repository *repo, const char *key,
@ -2815,19 +2765,17 @@ static void read_protected_config(void)
.ignore_worktree = 1,
.system_gently = 1,
};
struct configset_add_data data = CONFIGSET_ADD_INIT;
git_configset_init(&protected_config);
data.config_set = &protected_config;
data.config_reader = &the_reader;
config_with_options(config_set_callback, &data, NULL, NULL, &opts);
config_with_options(config_set_callback, &protected_config, NULL,
NULL, &opts);
}
void git_protected_config(config_fn_t fn, void *data)
{
if (!protected_config.hash_initialized)
read_protected_config();
configset_iter(&the_reader, &protected_config, fn, data);
configset_iter(&protected_config, fn, data);
}
/* Functions used historically to read configuration from 'the_repository' */
@ -3017,7 +2965,6 @@ void git_die_config(const char *key, const char *err, ...)
*/
struct config_store_data {
struct config_reader *config_reader;
size_t baselen;
char *key;
int do_not_match;
@ -3063,11 +3010,10 @@ static int matches(const char *key, const char *value,
(value && !regexec(store->value_pattern, value, 0, NULL, 0));
}
static int store_aux_event(enum config_event_t type,
size_t begin, size_t end, void *data)
static int store_aux_event(enum config_event_t type, size_t begin, size_t end,
struct config_source *cs, void *data)
{
struct config_store_data *store = data;
struct config_source *cs = store->config_reader->source;
ALLOC_GROW(store->parsed, store->parsed_nr + 1, store->parsed_alloc);
store->parsed[store->parsed_nr].begin = begin;
@ -3103,7 +3049,8 @@ static int store_aux_event(enum config_event_t type,
return 0;
}
static int store_aux(const char *key, const char *value, void *cb)
static int store_aux(const char *key, const char *value,
const struct config_context *ctx UNUSED, void *cb)
{
struct config_store_data *store = cb;
@ -3387,8 +3334,6 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
size_t contents_sz;
struct config_store_data store = CONFIG_STORE_INIT;
store.config_reader = &the_reader;
/* parse-key returns negative; flip the sign to feed exit(3) */
ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
if (ret)
@ -3477,7 +3422,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
*/
if (git_config_from_file_with_options(store_aux,
config_filename,
&store, &opts)) {
&store, CONFIG_SCOPE_UNKNOWN,
&opts)) {
error(_("invalid config file %s"), config_filename);
ret = CONFIG_INVALID_FILE;
goto out_free;
@ -3959,25 +3905,8 @@ int parse_config_key(const char *var,
return 0;
}
static int reader_origin_type(struct config_reader *reader,
enum config_origin_type *type)
const char *config_origin_type_name(enum config_origin_type type)
{
if (the_reader.config_kvi)
*type = reader->config_kvi->origin_type;
else if(the_reader.source)
*type = reader->source->origin_type;
else
return 1;
return 0;
}
const char *current_config_origin_type(void)
{
enum config_origin_type type = CONFIG_ORIGIN_UNKNOWN;
if (reader_origin_type(&the_reader, &type))
BUG("current_config_origin_type called outside config callback");
switch (type) {
case CONFIG_ORIGIN_BLOB:
return "blob";
@ -4014,41 +3943,6 @@ const char *config_scope_name(enum config_scope scope)
}
}
static int reader_config_name(struct config_reader *reader, const char **out)
{
if (the_reader.config_kvi)
*out = reader->config_kvi->filename;
else if (the_reader.source)
*out = reader->source->name;
else
return 1;
return 0;
}
const char *current_config_name(void)
{
const char *name;
if (reader_config_name(&the_reader, &name))
BUG("current_config_name called outside config callback");
return name ? name : "";
}
enum config_scope current_config_scope(void)
{
if (the_reader.config_kvi)
return the_reader.config_kvi->scope;
else
return the_reader.parsing_scope;
}
int current_config_line(void)
{
if (the_reader.config_kvi)
return the_reader.config_kvi->linenr;
else
return the_reader.source->linenr;
}
int lookup_config(const char **mapping, int nr_mapping, const char *var)
{
int i;

View File

@ -72,6 +72,7 @@ enum config_event_t {
CONFIG_EVENT_ERROR
};
struct config_source;
/*
* The parser event function (if not NULL) is called with the event type and
* the begin/end offsets of the parsed elements.
@ -81,6 +82,7 @@ enum config_event_t {
*/
typedef int (*config_parser_event_fn_t)(enum config_event_t type,
size_t begin_offset, size_t end_offset,
struct config_source *cs,
void *event_fn_data);
struct config_options {
@ -100,6 +102,10 @@ struct config_options {
const char *commondir;
const char *git_dir;
/*
* event_fn and event_fn_data are for internal use only. Handles events
* emitted by the config parser.
*/
config_parser_event_fn_t event_fn;
void *event_fn_data;
enum config_error_action {
@ -110,8 +116,31 @@ struct config_options {
} error_action;
};
/* Config source metadata for a given config key-value pair */
struct key_value_info {
const char *filename;
int linenr;
enum config_origin_type origin_type;
enum config_scope scope;
const char *path;
};
#define KVI_INIT { \
.filename = NULL, \
.linenr = -1, \
.origin_type = CONFIG_ORIGIN_UNKNOWN, \
.scope = CONFIG_SCOPE_UNKNOWN, \
.path = NULL, \
}
/* Captures additional information that a config callback can use. */
struct config_context {
/* Config source metadata for key and value. */
const struct key_value_info *kvi;
};
#define CONFIG_CONTEXT_INIT { 0 }
/**
* A config callback function takes three parameters:
* A config callback function takes four parameters:
*
* - the name of the parsed variable. This is in canonical "flat" form: the
* section, subsection, and variable segments will be separated by dots,
@ -122,15 +151,22 @@ struct config_options {
* value specified, the value will be NULL (typically this means it
* should be interpreted as boolean true).
*
* - the 'config context', that is, additional information about the config
* iteration operation provided by the config machinery. For example, this
* includes information about the config source being parsed (e.g. the
* filename).
*
* - a void pointer passed in by the caller of the config API; this can
* contain callback-specific data
*
* A config callback should return 0 for success, or -1 if the variable
* could not be parsed properly.
*/
typedef int (*config_fn_t)(const char *, const char *, void *);
typedef int (*config_fn_t)(const char *, const char *,
const struct config_context *, void *);
int git_default_config(const char *, const char *, void *);
int git_default_config(const char *, const char *,
const struct config_context *, void *);
/**
* Read a specific file in git-config format.
@ -141,16 +177,18 @@ int git_default_config(const char *, const char *, void *);
int git_config_from_file(config_fn_t fn, const char *, void *);
int git_config_from_file_with_options(config_fn_t fn, const char *,
void *,
void *, enum config_scope,
const struct config_options *);
int git_config_from_mem(config_fn_t fn,
const enum config_origin_type,
const char *name,
const char *buf, size_t len,
void *data, const struct config_options *opts);
void *data, enum config_scope scope,
const struct config_options *opts);
int git_config_from_blob_oid(config_fn_t fn, const char *name,
struct repository *repo,
const struct object_id *oid, void *data);
const struct object_id *oid, void *data,
enum config_scope scope);
void git_config_push_parameter(const char *text);
void git_config_push_env(const char *spec);
int git_config_from_parameters(config_fn_t fn, void *data);
@ -219,22 +257,26 @@ int git_parse_maybe_bool(const char *);
* Parse the string to an integer, including unit factors. Dies on error;
* otherwise, returns the parsed result.
*/
int git_config_int(const char *, const char *);
int git_config_int(const char *, const char *, const struct key_value_info *);
int64_t git_config_int64(const char *, const char *);
int64_t git_config_int64(const char *, const char *,
const struct key_value_info *);
/**
* Identical to `git_config_int`, but for unsigned longs.
*/
unsigned long git_config_ulong(const char *, const char *);
unsigned long git_config_ulong(const char *, const char *,
const struct key_value_info *);
ssize_t git_config_ssize_t(const char *, const char *);
ssize_t git_config_ssize_t(const char *, const char *,
const struct key_value_info *);
/**
* Same as `git_config_bool`, except that integers are returned as-is, and
* an `is_bool` flag is unset.
*/
int git_config_bool_or_int(const char *, const char *, int *);
int git_config_bool_or_int(const char *, const char *,
const struct key_value_info *, int *);
/**
* Parse a string into a boolean value, respecting keywords like "true" and
@ -356,10 +398,8 @@ void git_global_config(char **user, char **xdg);
int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
enum config_scope current_config_scope(void);
const char *current_config_origin_type(void);
const char *current_config_name(void);
int current_config_line(void);
const char *config_origin_type_name(enum config_origin_type type);
void kvi_from_param(struct key_value_info *out);
/*
* Match and parse a config key of the form:
@ -501,7 +541,8 @@ int git_configset_get(struct config_set *cs, const char *key);
* touching `value`. The caller should not free or modify `value`, as it
* is owned by the cache.
*/
int git_configset_get_value(struct config_set *cs, const char *key, const char **dest);
int git_configset_get_value(struct config_set *cs, const char *key,
const char **dest, struct key_value_info *kvi);
int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
@ -667,13 +708,6 @@ int git_config_get_expiry(const char *key, const char **output);
/* parse either "this many days" integer, or "5.days.ago" approxidate */
int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);
struct key_value_info {
const char *filename;
int linenr;
enum config_origin_type origin_type;
enum config_scope scope;
};
/**
* First prints the error message specified by the caller in `err` and then
* dies printing the line number and the file name of the highest priority

View File

@ -965,7 +965,7 @@ static struct child_process *git_tcp_connect(int fd[2], char *host, int flags)
static char *git_proxy_command;
static int git_proxy_command_options(const char *var, const char *value,
void *cb)
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "core.gitproxy")) {
const char *for_pos;
@ -1011,7 +1011,7 @@ static int git_proxy_command_options(const char *var, const char *value,
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static int git_use_proxy(const char *host)

View File

@ -0,0 +1,144 @@
@ get_fn @
identifier fn, R;
@@
(
(
git_config_from_file
|
git_config_from_file_with_options
|
git_config_from_mem
|
git_config_from_blob_oid
|
read_early_config
|
read_very_early_config
|
config_with_options
|
git_config
|
git_protected_config
|
config_from_gitmodules
)
(fn, ...)
|
repo_config(R, fn, ...)
)
@ extends get_fn @
identifier C1, C2, D;
@@
int fn(const char *C1, const char *C2,
+ const struct config_context *ctx,
void *D);
@ extends get_fn @
@@
int fn(const char *, const char *,
+ const struct config_context *,
void *);
@ extends get_fn @
// Don't change fns that look like callback fns but aren't
identifier fn2 != tar_filter_config && != git_diff_heuristic_config &&
!= git_default_submodule_config && != git_color_config &&
!= bundle_list_update && != parse_object_filter_config;
identifier C1, C2, D1, D2, S;
attribute name UNUSED;
@@
int fn(const char *C1, const char *C2,
+ const struct config_context *ctx,
void *D1) {
<+...
(
fn2(C1, C2
+ , ctx
, D2);
|
if(fn2(C1, C2
+ , ctx
, D2) < 0) { ... }
|
return fn2(C1, C2
+ , ctx
, D2);
|
S = fn2(C1, C2
+ , ctx
, D2);
)
...+>
}
@ extends get_fn@
identifier C1, C2, D;
attribute name UNUSED;
@@
int fn(const char *C1, const char *C2,
+ const struct config_context *ctx UNUSED,
void *D) {...}
// The previous rules don't catch all callbacks, especially if they're defined
// in a separate file from the git_config() call. Fix these manually.
@@
identifier C1, C2, D;
attribute name UNUSED;
@@
int
(
git_ident_config
|
urlmatch_collect_fn
|
write_one_config
|
forbid_remote_url
|
credential_config_callback
)
(const char *C1, const char *C2,
+ const struct config_context *ctx UNUSED,
void *D) {...}
@@
identifier C1, C2, D, D2, S, fn2;
@@
int
(
http_options
|
git_status_config
|
git_commit_config
|
git_default_core_config
|
grep_config
)
(const char *C1, const char *C2,
+ const struct config_context *ctx,
void *D) {
<+...
(
fn2(C1, C2
+ , ctx
, D2);
|
if(fn2(C1, C2
+ , ctx
, D2) < 0) { ... }
|
return fn2(C1, C2
+ , ctx
, D2);
|
S = fn2(C1, C2
+ , ctx
, D2);
)
...+>
}

View File

@ -0,0 +1,27 @@
@@
identifier C1, C2, C3;
@@
(
(
git_config_int
|
git_config_int64
|
git_config_ulong
|
git_config_ssize_t
)
(C1, C2
+ , ctx->kvi
)
|
(
git_configset_get_value
|
git_config_bool_or_int
)
(C1, C2
+ , ctx->kvi
, C3
)
)

View File

@ -1014,7 +1014,9 @@ static int apply_filter(const char *path, const char *src, size_t len,
return 0;
}
static int read_convert_config(const char *var, const char *value, void *cb UNUSED)
static int read_convert_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
const char *key, *name;
size_t namelen;

View File

@ -49,6 +49,7 @@ static int credential_from_potentially_partial_url(struct credential *c,
const char *url);
static int credential_config_callback(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *data)
{
struct credential *c = data;

View File

@ -341,7 +341,9 @@ static void free_remote_islands(kh_str_t *remote_islands)
kh_destroy_str(remote_islands);
}
static int island_config_callback(const char *k, const char *v, void *cb)
static int island_config_callback(const char *k, const char *v,
const struct config_context *ctx UNUSED,
void *cb)
{
struct island_load_data *ild = cb;

19
diff.c
View File

@ -358,7 +358,8 @@ static unsigned parse_color_moved_ws(const char *arg)
return ret;
}
int git_diff_ui_config(const char *var, const char *value, void *cb)
int git_diff_ui_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
diff_use_color_default = git_config_colorbool(var, value);
@ -379,13 +380,14 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
return 0;
}
if (!strcmp(var, "diff.context")) {
diff_context_default = git_config_int(var, value);
diff_context_default = git_config_int(var, value, ctx->kvi);
if (diff_context_default < 0)
return -1;
return 0;
}
if (!strcmp(var, "diff.interhunkcontext")) {
diff_interhunk_context_default = git_config_int(var, value);
diff_interhunk_context_default = git_config_int(var, value,
ctx->kvi);
if (diff_interhunk_context_default < 0)
return -1;
return 0;
@ -411,7 +413,7 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
return 0;
}
if (!strcmp(var, "diff.statgraphwidth")) {
diff_stat_graph_width = git_config_int(var, value);
diff_stat_graph_width = git_config_int(var, value, ctx->kvi);
return 0;
}
if (!strcmp(var, "diff.external"))
@ -441,15 +443,16 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
if (git_color_config(var, value, cb) < 0)
return -1;
return git_diff_basic_config(var, value, cb);
return git_diff_basic_config(var, value, ctx, cb);
}
int git_diff_basic_config(const char *var, const char *value, void *cb)
int git_diff_basic_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
const char *name;
if (!strcmp(var, "diff.renamelimit")) {
diff_rename_limit_default = git_config_int(var, value);
diff_rename_limit_default = git_config_int(var, value, ctx->kvi);
return 0;
}
@ -496,7 +499,7 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
if (git_diff_heuristic_config(var, value, cb) < 0)
return -1;
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static char *quote_two(const char *one, const char *two)

7
diff.h
View File

@ -533,10 +533,13 @@ void free_diffstat_info(struct diffstat_t *diffstat);
int parse_long_opt(const char *opt, const char **argv,
const char **optarg);
int git_diff_basic_config(const char *var, const char *value, void *cb);
struct config_context;
int git_diff_basic_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
int git_diff_heuristic_config(const char *var, const char *value, void *cb);
void init_diff_ui_defaults(void);
int git_diff_ui_config(const char *var, const char *value, void *cb);
int git_diff_ui_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
void repo_diff_setup(struct repository *, struct diff_options *);
struct option *add_diff_options(const struct option *, struct diff_options *);
int diff_opt_parse(struct diff_options *, const char **, int, const char *);

View File

@ -1861,7 +1861,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
return ref;
}
static int fetch_pack_config_cb(const char *var, const char *value, void *cb)
static int fetch_pack_config_cb(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (strcmp(var, "fetch.fsck.skiplist") == 0) {
const char *path;
@ -1883,7 +1884,7 @@ static int fetch_pack_config_cb(const char *var, const char *value, void *cb)
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
static void fetch_pack_config(void)

View File

@ -21,11 +21,12 @@ static int use_branch_desc;
static int suppress_dest_pattern_seen;
static struct string_list suppress_dest_patterns = STRING_LIST_INIT_DUP;
int fmt_merge_msg_config(const char *key, const char *value, void *cb)
int fmt_merge_msg_config(const char *key, const char *value,
const struct config_context *ctx, void *cb)
{
if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) {
int is_bool;
merge_log_config = git_config_bool_or_int(key, value, &is_bool);
merge_log_config = git_config_bool_or_int(key, value, ctx->kvi, &is_bool);
if (!is_bool && merge_log_config < 0)
return error("%s: negative length %s", key, value);
if (is_bool && merge_log_config)
@ -41,7 +42,7 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
string_list_append(&suppress_dest_patterns, value);
suppress_dest_pattern_seen = 1;
} else {
return git_default_config(key, value, cb);
return git_default_config(key, value, ctx, cb);
}
return 0;
}

View File

@ -13,7 +13,8 @@ struct fmt_merge_msg_opts {
};
extern int merge_log_config;
int fmt_merge_msg_config(const char *key, const char *value, void *cb);
int fmt_merge_msg_config(const char *key, const char *value,
const struct config_context *ctx, void *cb);
int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
struct fmt_merge_msg_opts *);

12
fsck.c
View File

@ -1165,7 +1165,9 @@ struct fsck_gitmodules_data {
int ret;
};
static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
static int fsck_gitmodules_fn(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *vdata)
{
struct fsck_gitmodules_data *data = vdata;
const char *subsection, *key;
@ -1238,7 +1240,8 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
data.ret = 0;
config_opts.error_action = CONFIG_ERROR_SILENT;
if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
".gitmodules", buf, size, &data, &config_opts))
".gitmodules", buf, size, &data,
CONFIG_SCOPE_UNKNOWN, &config_opts))
data.ret |= report(options, oid, OBJ_BLOB,
FSCK_MSG_GITMODULES_PARSE,
"could not parse gitmodules blob");
@ -1375,7 +1378,8 @@ int fsck_finish(struct fsck_options *options)
return ret;
}
int git_fsck_config(const char *var, const char *value, void *cb)
int git_fsck_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct fsck_options *options = cb;
if (strcmp(var, "fsck.skiplist") == 0) {
@ -1396,7 +1400,7 @@ int git_fsck_config(const char *var, const char *value, void *cb)
return 0;
}
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, cb);
}
/*

4
fsck.h
View File

@ -233,10 +233,12 @@ void fsck_put_object_name(struct fsck_options *options,
const char *fsck_describe_object(struct fsck_options *options,
const struct object_id *oid);
struct key_value_info;
/*
* git_config() callback for use by fsck-y tools that want to support
* fsck.<msg> fsck.skipList etc.
*/
int git_fsck_config(const char *var, const char *value, void *cb);
int git_fsck_config(const char *var, const char *value,
const struct config_context *ctx, void *cb);
#endif

View File

@ -440,8 +440,10 @@ typedef uintmax_t timestamp_t;
#endif
#ifndef platform_core_config
struct config_context;
static inline int noop_core_config(const char *var UNUSED,
const char *value UNUSED,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
return 0;

View File

@ -15,7 +15,8 @@
#include "wrapper.h"
#include "environment.h"
static int git_gpg_config(const char *, const char *, void *);
static int git_gpg_config(const char *, const char *,
const struct config_context *, void *);
static void gpg_interface_lazy_init(void)
{
@ -721,7 +722,9 @@ void set_signing_key(const char *key)
configured_signing_key = xstrdup(key);
}
static int git_gpg_config(const char *var, const char *value, void *cb UNUSED)
static int git_gpg_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
struct gpg_format *fmt = NULL;
char *fmtname = NULL;

7
grep.c
View File

@ -56,7 +56,8 @@ define_list_config_array_extra(color_grep_slots, {"match"});
* Read the configuration file once and store it in
* the grep_defaults template.
*/
int grep_config(const char *var, const char *value, void *cb)
int grep_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct grep_opt *opt = cb;
const char *slot;
@ -91,9 +92,9 @@ int grep_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "color.grep"))
opt->color = git_config_colorbool(var, value);
if (!strcmp(var, "color.grep.match")) {
if (grep_config("color.grep.matchcontext", value, cb) < 0)
if (grep_config("color.grep.matchcontext", value, ctx, cb) < 0)
return -1;
if (grep_config("color.grep.matchselected", value, cb) < 0)
if (grep_config("color.grep.matchselected", value, ctx, cb) < 0)
return -1;
} else if (skip_prefix(var, "color.grep.", &slot)) {
int i = LOOKUP_CONFIG(color_grep_slots, slot);

4
grep.h
View File

@ -202,7 +202,9 @@ struct grep_opt {
.output = std_output, \
}
int grep_config(const char *var, const char *value, void *);
struct config_context;
int grep_config(const char *var, const char *value,
const struct config_context *ctx, void *data);
void grep_init(struct grep_opt *, struct repository *repo);
void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);

9
help.c
View File

@ -309,7 +309,8 @@ void load_command_list(const char *prefix,
exclude_cmds(other_cmds, main_cmds);
}
static int get_colopts(const char *var, const char *value, void *data)
static int get_colopts(const char *var, const char *value,
const struct config_context *ctx UNUSED, void *data)
{
unsigned int *colopts = data;
@ -459,7 +460,8 @@ void list_developer_interfaces_help(void)
putchar('\n');
}
static int get_alias(const char *var, const char *value, void *data)
static int get_alias(const char *var, const char *value,
const struct config_context *ctx UNUSED, void *data)
{
struct string_list *list = data;
@ -543,6 +545,7 @@ static struct cmdnames aliases;
#define AUTOCORRECT_IMMEDIATELY (-1)
static int git_unknown_cmd_config(const char *var, const char *value,
const struct config_context *ctx,
void *cb UNUSED)
{
const char *p;
@ -557,7 +560,7 @@ static int git_unknown_cmd_config(const char *var, const char *value,
} else if (!strcmp(value, "prompt")) {
autocorrect = AUTOCORRECT_PROMPT;
} else {
int v = git_config_int(var, value);
int v = git_config_int(var, value, ctx->kvi);
autocorrect = (v < 0)
? AUTOCORRECT_IMMEDIATELY : v;
}

15
http.c
View File

@ -363,7 +363,8 @@ static void process_curl_messages(void)
}
}
static int http_options(const char *var, const char *value, void *cb)
static int http_options(const char *var, const char *value,
const struct config_context *ctx, void *data)
{
if (!strcmp("http.version", var)) {
return git_config_string(&curl_http_version, var, value);
@ -413,21 +414,21 @@ static int http_options(const char *var, const char *value, void *cb)
}
if (!strcmp("http.minsessions", var)) {
min_curl_sessions = git_config_int(var, value);
min_curl_sessions = git_config_int(var, value, ctx->kvi);
if (min_curl_sessions > 1)
min_curl_sessions = 1;
return 0;
}
if (!strcmp("http.maxrequests", var)) {
max_requests = git_config_int(var, value);
max_requests = git_config_int(var, value, ctx->kvi);
return 0;
}
if (!strcmp("http.lowspeedlimit", var)) {
curl_low_speed_limit = (long)git_config_int(var, value);
curl_low_speed_limit = (long)git_config_int(var, value, ctx->kvi);
return 0;
}
if (!strcmp("http.lowspeedtime", var)) {
curl_low_speed_time = (long)git_config_int(var, value);
curl_low_speed_time = (long)git_config_int(var, value, ctx->kvi);
return 0;
}
@ -463,7 +464,7 @@ static int http_options(const char *var, const char *value, void *cb)
}
if (!strcmp("http.postbuffer", var)) {
http_post_buffer = git_config_ssize_t(var, value);
http_post_buffer = git_config_ssize_t(var, value, ctx->kvi);
if (http_post_buffer < 0)
warning(_("negative value for http.postBuffer; defaulting to %d"), LARGE_PACKET_MAX);
if (http_post_buffer < LARGE_PACKET_MAX)
@ -534,7 +535,7 @@ static int http_options(const char *var, const char *value, void *cb)
}
/* Fall back on the default ones */
return git_default_config(var, value, cb);
return git_default_config(var, value, ctx, data);
}
static int curl_empty_auth_enabled(void)

View File

@ -671,7 +671,9 @@ static int set_ident(const char *var, const char *value)
return 0;
}
int git_ident_config(const char *var, const char *value, void *data UNUSED)
int git_ident_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *data UNUSED)
{
if (!strcmp(var, "user.useconfigonly")) {
ident_use_config_only = git_config_bool(var, value);

View File

@ -62,6 +62,8 @@ const char *fmt_name(enum want_ident);
int committer_ident_sufficiently_given(void);
int author_ident_sufficiently_given(void);
int git_ident_config(const char *, const char *, void *);
struct config_context;
int git_ident_config(const char *, const char *, const struct config_context *,
void *);
#endif

View File

@ -1323,7 +1323,8 @@ static int split_msg(struct strbuf *all_msgs, struct strbuf *msg, int *ofs)
return 1;
}
static int git_imap_config(const char *var, const char *val, void *cb)
static int git_imap_config(const char *var, const char *val,
const struct config_context *ctx, void *cb)
{
if (!strcmp("imap.sslverify", var))
@ -1341,7 +1342,7 @@ static int git_imap_config(const char *var, const char *val, void *cb)
else if (!strcmp("imap.authmethod", var))
return git_config_string(&server.auth_method, var, val);
else if (!strcmp("imap.port", var))
server.port = git_config_int(var, val);
server.port = git_config_int(var, val, ctx->kvi);
else if (!strcmp("imap.host", var)) {
if (!val) {
git_die_config("imap.host", "Missing value for 'imap.host'");
@ -1357,7 +1358,7 @@ static int git_imap_config(const char *var, const char *val, void *cb)
server.host = xstrdup(val);
}
} else
return git_default_config(var, val, cb);
return git_default_config(var, val, ctx, cb);
return 0;
}

View File

@ -137,6 +137,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
}
static int ls_refs_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb_data)
{
struct ls_refs_data *data = cb_data;

View File

@ -1241,12 +1241,13 @@ int mailinfo_parse_quoted_cr_action(const char *actionstr, int *action)
return 0;
}
static int git_mailinfo_config(const char *var, const char *value, void *mi_)
static int git_mailinfo_config(const char *var, const char *value,
const struct config_context *ctx, void *mi_)
{
struct mailinfo *mi = mi_;
if (!starts_with(var, "mailinfo."))
return git_default_config(var, value, NULL);
return git_default_config(var, value, ctx, NULL);
if (!strcmp(var, "mailinfo.scissors")) {
mi->use_scissors = git_config_bool(var, value);
return 0;

View File

@ -264,6 +264,7 @@ static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;
static const char *default_ll_merge;
static int read_merge_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
struct ll_merge_driver *fn;

View File

@ -94,7 +94,9 @@ static combine_notes_fn parse_combine_notes_fn(const char *v)
return NULL;
}
static int notes_rewrite_config(const char *k, const char *v, void *cb)
static int notes_rewrite_config(const char *k, const char *v,
const struct config_context *ctx UNUSED,
void *cb)
{
struct notes_rewrite_cfg *c = cb;
if (starts_with(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {

View File

@ -974,7 +974,9 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,
free(globs_copy);
}
static int notes_display_config(const char *k, const char *v, void *cb)
static int notes_display_config(const char *k, const char *v,
const struct config_context *ctx UNUSED,
void *cb)
{
int *load_refs = cb;

View File

@ -43,6 +43,7 @@ static void wait_for_pager_signal(int signo)
}
static int core_pager_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *data UNUSED)
{
if (!strcmp(var, "core.pager"))
@ -228,7 +229,9 @@ struct pager_command_config_data {
char *value;
};
static int pager_command_config(const char *var, const char *value, void *vdata)
static int pager_command_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *vdata)
{
struct pager_command_config_data *data = vdata;
const char *cmd;

View File

@ -58,6 +58,7 @@ static void save_user_format(struct rev_info *rev, const char *cp, int is_tforma
}
static int git_pretty_formats_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
struct cmt_fmt_map *commit_format = NULL;

View File

@ -100,7 +100,9 @@ static void promisor_remote_move_to_tail(struct promisor_remote_config *config,
config->promisors_tail = &r->next;
}
static int promisor_remote_config(const char *var, const char *value, void *data)
static int promisor_remote_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *data)
{
struct promisor_remote_config *config = data;
const char *name;

View File

@ -350,7 +350,8 @@ static void read_branches_file(struct remote_state *remote_state,
remote->fetch_tags = 1; /* always auto-follow */
}
static int handle_config(const char *key, const char *value, void *cb)
static int handle_config(const char *key, const char *value,
const struct config_context *ctx, void *cb)
{
const char *name;
size_t namelen;
@ -358,6 +359,7 @@ static int handle_config(const char *key, const char *value, void *cb)
struct remote *remote;
struct branch *branch;
struct remote_state *remote_state = cb;
const struct key_value_info *kvi = ctx->kvi;
if (parse_config_key(key, "branch", &name, &namelen, &subkey) >= 0) {
/* There is no subsection. */
@ -415,8 +417,8 @@ static int handle_config(const char *key, const char *value, void *cb)
}
remote = make_remote(remote_state, name, namelen);
remote->origin = REMOTE_CONFIG;
if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
current_config_scope() == CONFIG_SCOPE_WORKTREE)
if (kvi->scope == CONFIG_SCOPE_LOCAL ||
kvi->scope == CONFIG_SCOPE_WORKTREE)
remote->configured_in_repo = 1;
if (!strcmp(subkey, "mirror"))
remote->mirror = git_config_bool(key, value);

View File

@ -1575,7 +1575,9 @@ struct exclude_hidden_refs_cb {
const char *section;
};
static int hide_refs_config(const char *var, const char *value, void *cb_data)
static int hide_refs_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb_data)
{
struct exclude_hidden_refs_cb *cb = cb_data;
cb->exclusions->hidden_refs_configured = 1;

View File

@ -594,7 +594,9 @@ static int cmd_register(int argc, const char **argv)
return register_dir();
}
static int get_scalar_repos(const char *key, const char *value, void *data)
static int get_scalar_repos(const char *key, const char *value,
const struct config_context *ctx UNUSED,
void *data)
{
struct string_list *list = data;

View File

@ -222,7 +222,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref)
return rec;
}
static int git_sequencer_config(const char *k, const char *v, void *cb)
static int git_sequencer_config(const char *k, const char *v,
const struct config_context *ctx, void *cb)
{
struct replay_opts *opts = cb;
int status;
@ -277,7 +278,7 @@ static int git_sequencer_config(const char *k, const char *v, void *cb)
if (opts->action == REPLAY_REVERT && !strcmp(k, "revert.reference"))
opts->commit_use_reference = git_config_bool(k, v);
return git_diff_basic_config(k, v, NULL);
return git_diff_basic_config(k, v, ctx, NULL);
}
void sequencer_init_config(struct replay_opts *opts)
@ -2890,7 +2891,9 @@ static int git_config_string_dup(char **dest,
return 0;
}
static int populate_opts_cb(const char *key, const char *value, void *data)
static int populate_opts_cb(const char *key, const char *value,
const struct config_context *ctx,
void *data)
{
struct replay_opts *opts = data;
int error_flag = 1;
@ -2898,26 +2901,26 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
if (!value)
error_flag = 0;
else if (!strcmp(key, "options.no-commit"))
opts->no_commit = git_config_bool_or_int(key, value, &error_flag);
opts->no_commit = git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.edit"))
opts->edit = git_config_bool_or_int(key, value, &error_flag);
opts->edit = git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.allow-empty"))
opts->allow_empty =
git_config_bool_or_int(key, value, &error_flag);
git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.allow-empty-message"))
opts->allow_empty_message =
git_config_bool_or_int(key, value, &error_flag);
git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.keep-redundant-commits"))
opts->keep_redundant_commits =
git_config_bool_or_int(key, value, &error_flag);
git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.signoff"))
opts->signoff = git_config_bool_or_int(key, value, &error_flag);
opts->signoff = git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.record-origin"))
opts->record_origin = git_config_bool_or_int(key, value, &error_flag);
opts->record_origin = git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.allow-ff"))
opts->allow_ff = git_config_bool_or_int(key, value, &error_flag);
opts->allow_ff = git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
else if (!strcmp(key, "options.mainline"))
opts->mainline = git_config_int(key, value);
opts->mainline = git_config_int(key, value, ctx->kvi);
else if (!strcmp(key, "options.strategy"))
git_config_string_dup(&opts->strategy, key, value);
else if (!strcmp(key, "options.gpg-sign"))
@ -2926,7 +2929,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
strvec_push(&opts->xopts, value);
} else if (!strcmp(key, "options.allow-rerere-auto"))
opts->allow_rerere_auto =
git_config_bool_or_int(key, value, &error_flag) ?
git_config_bool_or_int(key, value, ctx->kvi, &error_flag) ?
RERERE_AUTOUPDATE : RERERE_NOAUTOUPDATE;
else if (!strcmp(key, "options.default-msg-cleanup")) {
opts->explicit_cleanup = 1;

18
setup.c
View File

@ -522,7 +522,9 @@ static void setup_original_cwd(void)
startup_info->original_cwd = NULL;
}
static int read_worktree_config(const char *var, const char *value, void *vdata)
static int read_worktree_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *vdata)
{
struct repository_format *data = vdata;
@ -593,13 +595,14 @@ static enum extension_result handle_extension(const char *var,
return EXTENSION_UNKNOWN;
}
static int check_repo_format(const char *var, const char *value, void *vdata)
static int check_repo_format(const char *var, const char *value,
const struct config_context *ctx, void *vdata)
{
struct repository_format *data = vdata;
const char *ext;
if (strcmp(var, "core.repositoryformatversion") == 0)
data->version = git_config_int(var, value);
data->version = git_config_int(var, value, ctx->kvi);
else if (skip_prefix(var, "extensions.", &ext)) {
switch (handle_extension_v0(var, value, ext, data)) {
case EXTENSION_ERROR:
@ -622,7 +625,7 @@ static int check_repo_format(const char *var, const char *value, void *vdata)
}
}
return read_worktree_config(var, value, vdata);
return read_worktree_config(var, value, ctx, vdata);
}
static int check_repository_format_gently(const char *gitdir, struct repository_format *candidate, int *nongit_ok)
@ -1120,7 +1123,8 @@ struct safe_directory_data {
int is_safe;
};
static int safe_directory_cb(const char *key, const char *value, void *d)
static int safe_directory_cb(const char *key, const char *value,
const struct config_context *ctx UNUSED, void *d)
{
struct safe_directory_data *data = d;
@ -1176,7 +1180,9 @@ static int ensure_valid_ownership(const char *gitfile,
return data.is_safe;
}
static int allowed_bare_repo_cb(const char *key, const char *value, void *d)
static int allowed_bare_repo_cb(const char *key, const char *value,
const struct config_context *ctx UNUSED,
void *d)
{
enum allowed_bare_repo *allowed_bare_repo = d;

View File

@ -305,9 +305,10 @@ static int parse_fetch_recurse(const char *opt, const char *arg,
}
}
int parse_submodule_fetchjobs(const char *var, const char *value)
int parse_submodule_fetchjobs(const char *var, const char *value,
const struct key_value_info *kvi)
{
int fetchjobs = git_config_int(var, value);
int fetchjobs = git_config_int(var, value, kvi);
if (fetchjobs < 0)
die(_("negative values not allowed for submodule.fetchJobs"));
if (!fetchjobs)
@ -427,7 +428,8 @@ struct parse_config_parameter {
* config store (.git/config, etc). Callers are responsible for
* checking for overrides in the main config store when appropriate.
*/
static int parse_config(const char *var, const char *value, void *data)
static int parse_config(const char *var, const char *value,
const struct config_context *ctx UNUSED, void *data)
{
struct parse_config_parameter *me = data;
struct submodule *submodule;
@ -606,7 +608,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
parameter.gitmodules_oid = &oid;
parameter.overwrite = 0;
git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
config, config_size, &parameter, NULL);
config, config_size, &parameter, CONFIG_SCOPE_UNKNOWN, NULL);
strbuf_release(&rev);
free(config);
@ -675,7 +677,8 @@ static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void
}
}
static int gitmodules_cb(const char *var, const char *value, void *data)
static int gitmodules_cb(const char *var, const char *value,
const struct config_context *ctx, void *data)
{
struct repository *repo = data;
struct parse_config_parameter parameter;
@ -685,7 +688,7 @@ static int gitmodules_cb(const char *var, const char *value, void *data)
parameter.gitmodules_oid = null_oid();
parameter.overwrite = 1;
return parse_config(var, value, &parameter);
return parse_config(var, value, ctx, &parameter);
}
void repo_read_gitmodules(struct repository *repo, int skip_if_read)
@ -713,7 +716,8 @@ void gitmodules_config_oid(const struct object_id *commit_oid)
if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
git_config_from_blob_oid(gitmodules_cb, rev.buf,
the_repository, &oid, the_repository);
the_repository, &oid, the_repository,
CONFIG_SCOPE_UNKNOWN);
}
strbuf_release(&rev);
@ -802,7 +806,9 @@ void submodule_free(struct repository *r)
submodule_cache_clear(r->submodule_cache);
}
static int config_print_callback(const char *var, const char *value, void *cb_data)
static int config_print_callback(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb_data)
{
char *wanted_key = cb_data;
@ -844,13 +850,15 @@ struct fetch_config {
int *recurse_submodules;
};
static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
static int gitmodules_fetch_config(const char *var, const char *value,
const struct config_context *ctx,
void *cb)
{
struct fetch_config *config = cb;
if (!strcmp(var, "submodule.fetchjobs")) {
if (config->max_children)
*(config->max_children) =
parse_submodule_fetchjobs(var, value);
parse_submodule_fetchjobs(var, value, ctx->kvi);
return 0;
} else if (!strcmp(var, "fetch.recursesubmodules")) {
if (config->recurse_submodules)
@ -872,11 +880,12 @@ void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules)
}
static int gitmodules_update_clone_config(const char *var, const char *value,
const struct config_context *ctx,
void *cb)
{
int *max_jobs = cb;
if (!strcmp(var, "submodule.fetchjobs"))
*max_jobs = parse_submodule_fetchjobs(var, value);
*max_jobs = parse_submodule_fetchjobs(var, value, ctx->kvi);
return 0;
}

View File

@ -50,7 +50,8 @@ struct repository;
void submodule_cache_free(struct submodule_cache *cache);
int parse_submodule_fetchjobs(const char *var, const char *value);
int parse_submodule_fetchjobs(const char *var, const char *value,
const struct key_value_info *kvi);
int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
struct option;
int option_fetch_parse_recurse_submodules(const struct option *opt,

View File

@ -42,8 +42,11 @@
*
*/
static int iterate_cb(const char *var, const char *value, void *data UNUSED)
static int iterate_cb(const char *var, const char *value,
const struct config_context *ctx,
void *data UNUSED)
{
const struct key_value_info *kvi = ctx->kvi;
static int nr;
if (nr++)
@ -51,26 +54,29 @@ static int iterate_cb(const char *var, const char *value, void *data UNUSED)
printf("key=%s\n", var);
printf("value=%s\n", value ? value : "(null)");
printf("origin=%s\n", current_config_origin_type());
printf("name=%s\n", current_config_name());
printf("lno=%d\n", current_config_line());
printf("scope=%s\n", config_scope_name(current_config_scope()));
printf("origin=%s\n", config_origin_type_name(kvi->origin_type));
printf("name=%s\n", kvi->filename ? kvi->filename : "");
printf("lno=%d\n", kvi->linenr);
printf("scope=%s\n", config_scope_name(kvi->scope));
return 0;
}
static int parse_int_cb(const char *var, const char *value, void *data)
static int parse_int_cb(const char *var, const char *value,
const struct config_context *ctx, void *data)
{
const char *key_to_match = data;
if (!strcmp(key_to_match, var)) {
int parsed = git_config_int(value, value);
int parsed = git_config_int(value, value, ctx->kvi);
printf("%d\n", parsed);
}
return 0;
}
static int early_config_cb(const char *var, const char *value, void *vdata)
static int early_config_cb(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *vdata)
{
const char *key = vdata;
@ -176,7 +182,7 @@ int cmd__config(int argc, const char **argv)
goto exit2;
}
}
if (!git_configset_get_value(&cs, argv[2], &v)) {
if (!git_configset_get_value(&cs, argv[2], &v, NULL)) {
if (!v)
printf("(NULL)\n");
else

View File

@ -12,7 +12,9 @@ static int driver_cb(struct userdiff_driver *driver,
return 0;
}
static int cmd__userdiff_config(const char *var, const char *value, void *cb UNUSED)
static int cmd__userdiff_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
if (userdiff_config(var, value) < 0)
return -1;

View File

@ -1668,6 +1668,21 @@ test_expect_success 'urlmatch' '
test_cmp expect actual
'
test_expect_success 'urlmatch with --show-scope' '
cat >.git/config <<-\EOF &&
[http "https://weak.example.com"]
sslVerify = false
cookieFile = /tmp/cookie.txt
EOF
cat >expect <<-EOF &&
local http.cookiefile /tmp/cookie.txt
local http.sslverify false
EOF
git config --get-urlmatch --show-scope HTTP https://weak.example.com >actual &&
test_cmp expect actual
'
test_expect_success 'urlmatch favors more specific URLs' '
cat >.git/config <<-\EOF &&
[http "https://example.com/"]
@ -2055,6 +2070,12 @@ test_expect_success '--show-origin blob ref' '
test_cmp expect output
'
test_expect_success '--show-origin with --default' '
git config --show-origin --default foo some.key >actual &&
echo "command line: foo" >expect &&
test_cmp expect actual
'
test_expect_success '--show-scope with --list' '
cat >expect <<-EOF &&
global user.global=true
@ -2123,6 +2144,12 @@ test_expect_success '--show-scope with --show-origin' '
test_cmp expect output
'
test_expect_success '--show-scope with --default' '
git config --show-scope --default foo some.key >actual &&
echo "command foo" >expect &&
test_cmp expect actual
'
test_expect_success 'override global and system config' '
test_when_finished rm -f \"\$HOME\"/.gitconfig &&
cat >"$HOME"/.gitconfig <<-EOF &&

View File

@ -634,7 +634,7 @@ void trace2_thread_exit_fl(const char *file, int line)
}
void trace2_def_param_fl(const char *file, int line, const char *param,
const char *value)
const char *value, const struct key_value_info *kvi)
{
struct tr2_tgt *tgt_j;
int j;
@ -644,7 +644,7 @@ void trace2_def_param_fl(const char *file, int line, const char *param,
for_each_wanted_builtin (j, tgt_j)
if (tgt_j->pfn_param_fl)
tgt_j->pfn_param_fl(file, line, param, value);
tgt_j->pfn_param_fl(file, line, param, value, kvi);
}
void trace2_def_repo_fl(const char *file, int line, struct repository *repo)

View File

@ -325,6 +325,7 @@ void trace2_thread_exit_fl(const char *file, int line);
#define trace2_thread_exit() trace2_thread_exit_fl(__FILE__, __LINE__)
struct key_value_info;
/*
* Emits a "def_param" message containing a key/value pair.
*
@ -334,7 +335,7 @@ void trace2_thread_exit_fl(const char *file, int line);
* `core.abbrev`, `status.showUntrackedFiles`, or `--no-ahead-behind`.
*/
void trace2_def_param_fl(const char *file, int line, const char *param,
const char *value);
const char *value, const struct key_value_info *kvi);
#define trace2_def_param(param, value) \
trace2_def_param_fl(__FILE__, __LINE__, (param), (value))

View File

@ -100,7 +100,8 @@ struct tr2_cfg_data {
/*
* See if the given config key matches any of our patterns of interest.
*/
static int tr2_cfg_cb(const char *key, const char *value, void *d)
static int tr2_cfg_cb(const char *key, const char *value,
const struct config_context *ctx, void *d)
{
struct strbuf **s;
struct tr2_cfg_data *data = (struct tr2_cfg_data *)d;
@ -109,7 +110,8 @@ static int tr2_cfg_cb(const char *key, const char *value, void *d)
struct strbuf *buf = *s;
int wm = wildmatch(buf->buf, key, WM_CASEFOLD);
if (wm == WM_MATCH) {
trace2_def_param_fl(data->file, data->line, key, value);
trace2_def_param_fl(data->file, data->line, key, value,
ctx->kvi);
return 0;
}
}
@ -127,8 +129,10 @@ void tr2_cfg_list_config_fl(const char *file, int line)
void tr2_list_env_vars_fl(const char *file, int line)
{
struct key_value_info kvi = KVI_INIT;
struct strbuf **s;
kvi_from_param(&kvi);
if (tr2_load_env_vars() <= 0)
return;
@ -136,15 +140,19 @@ void tr2_list_env_vars_fl(const char *file, int line)
struct strbuf *buf = *s;
const char *val = getenv(buf->buf);
if (val && *val)
trace2_def_param_fl(file, line, buf->buf, val);
trace2_def_param_fl(file, line, buf->buf, val, &kvi);
}
}
void tr2_cfg_set_fl(const char *file, int line, const char *key,
const char *value)
{
struct key_value_info kvi = KVI_INIT;
struct config_context ctx = {
.kvi = &kvi,
};
struct tr2_cfg_data data = { file, line };
if (tr2_cfg_load_patterns() > 0)
tr2_cfg_cb(key, value, &data);
tr2_cfg_cb(key, value, &ctx, &data);
}

View File

@ -57,7 +57,8 @@ static struct tr2_sysenv_entry tr2_sysenv_settings[] = {
};
/* clang-format on */
static int tr2_sysenv_cb(const char *key, const char *value, void *d)
static int tr2_sysenv_cb(const char *key, const char *value,
const struct config_context *ctx UNUSED, void *d)
{
int k;

View File

@ -69,8 +69,10 @@ typedef void(tr2_tgt_evt_exec_result_fl_t)(const char *file, int line,
uint64_t us_elapsed_absolute,
int exec_id, int code);
struct key_value_info;
typedef void(tr2_tgt_evt_param_fl_t)(const char *file, int line,
const char *param, const char *value);
const char *param, const char *value,
const struct key_value_info *kvi);
typedef void(tr2_tgt_evt_repo_fl_t)(const char *file, int line,
const struct repository *repo);

View File

@ -477,11 +477,11 @@ static void fn_exec_result_fl(const char *file, int line,
}
static void fn_param_fl(const char *file, int line, const char *param,
const char *value)
const char *value, const struct key_value_info *kvi)
{
const char *event_name = "def_param";
struct json_writer jw = JSON_WRITER_INIT;
enum config_scope scope = current_config_scope();
enum config_scope scope = kvi->scope;
const char *scope_name = config_scope_name(scope);
jw_object_begin(&jw, 0);

View File

@ -297,10 +297,10 @@ static void fn_exec_result_fl(const char *file, int line,
}
static void fn_param_fl(const char *file, int line, const char *param,
const char *value)
const char *value, const struct key_value_info *kvi)
{
struct strbuf buf_payload = STRBUF_INIT;
enum config_scope scope = current_config_scope();
enum config_scope scope = kvi->scope;
const char *scope_name = config_scope_name(scope);
strbuf_addf(&buf_payload, "def_param scope:%s %s=%s", scope_name, param,

View File

@ -439,12 +439,12 @@ static void fn_exec_result_fl(const char *file, int line,
}
static void fn_param_fl(const char *file, int line, const char *param,
const char *value)
const char *value, const struct key_value_info *kvi)
{
const char *event_name = "def_param";
struct strbuf buf_payload = STRBUF_INIT;
struct strbuf scope_payload = STRBUF_INIT;
enum config_scope scope = current_config_scope();
enum config_scope scope = kvi->scope;
const char *scope_name = config_scope_name(scope);
strbuf_addf(&buf_payload, "%s:%s", param, value);

View File

@ -482,6 +482,7 @@ static struct {
};
static int git_trailer_default_config(const char *conf_key, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
const char *trailer_item, *variable_name;
@ -514,6 +515,7 @@ static int git_trailer_default_config(const char *conf_key, const char *value,
}
static int git_trailer_config(const char *conf_key, const char *value,
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
const char *trailer_item, *variable_name;

View File

@ -1275,7 +1275,8 @@ static int find_symref(const char *refname,
}
static int parse_object_filter_config(const char *var, const char *value,
struct upload_pack_data *data)
const struct key_value_info *kvi,
struct upload_pack_data *data)
{
struct strbuf buf = STRBUF_INIT;
const char *sub, *key;
@ -1302,14 +1303,17 @@ static int parse_object_filter_config(const char *var, const char *value,
}
string_list_insert(&data->allowed_filters, buf.buf)->util =
(void *)(intptr_t)1;
data->tree_filter_max_depth = git_config_ulong(var, value);
data->tree_filter_max_depth = git_config_ulong(var, value,
kvi);
}
strbuf_release(&buf);
return 0;
}
static int upload_pack_config(const char *var, const char *value, void *cb_data)
static int upload_pack_config(const char *var, const char *value,
const struct config_context *ctx,
void *cb_data)
{
struct upload_pack_data *data = cb_data;
@ -1329,7 +1333,7 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)
else
data->allow_uor &= ~ALLOW_ANY_SHA1;
} else if (!strcmp("uploadpack.keepalive", var)) {
data->keepalive = git_config_int(var, value);
data->keepalive = git_config_int(var, value, ctx->kvi);
if (!data->keepalive)
data->keepalive = -1;
} else if (!strcmp("uploadpack.allowfilter", var)) {
@ -1344,13 +1348,15 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)
data->advertise_sid = git_config_bool(var, value);
}
if (parse_object_filter_config(var, value, data) < 0)
if (parse_object_filter_config(var, value, ctx->kvi, data) < 0)
return -1;
return parse_hide_refs_config(var, value, "uploadpack", &data->hidden_refs);
}
static int upload_pack_protected_config(const char *var, const char *value, void *cb_data)
static int upload_pack_protected_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
void *cb_data)
{
struct upload_pack_data *data = cb_data;

View File

@ -551,7 +551,8 @@ static int cmp_matches(const struct urlmatch_item *a,
return 0;
}
int urlmatch_config_entry(const char *var, const char *value, void *cb)
int urlmatch_config_entry(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
struct string_list_item *item;
struct urlmatch_config *collect = cb;
@ -565,7 +566,7 @@ int urlmatch_config_entry(const char *var, const char *value, void *cb)
if (!skip_prefix(var, collect->section, &key) || *(key++) != '.') {
if (collect->cascade_fn)
return collect->cascade_fn(var, value, cb);
return collect->cascade_fn(var, value, ctx, cb);
return 0; /* not interested */
}
dot = strrchr(key, '.');
@ -609,7 +610,7 @@ int urlmatch_config_entry(const char *var, const char *value, void *cb)
strbuf_addstr(&synthkey, collect->section);
strbuf_addch(&synthkey, '.');
strbuf_addstr(&synthkey, key);
retval = collect->collect_fn(synthkey.buf, value, collect->cb);
retval = collect->collect_fn(synthkey.buf, value, ctx, collect->cb);
strbuf_release(&synthkey);
return retval;

View File

@ -2,6 +2,7 @@
#define URL_MATCH_H
#include "string-list.h"
#include "config.h"
struct url_info {
/* normalized url on success, must be freed, otherwise NULL */
@ -48,8 +49,8 @@ struct urlmatch_config {
const char *key;
void *cb;
int (*collect_fn)(const char *var, const char *value, void *cb);
int (*cascade_fn)(const char *var, const char *value, void *cb);
config_fn_t collect_fn;
config_fn_t cascade_fn;
/*
* Compare the two matches, the one just discovered and the existing
* best match and return a negative value if the found item is to be
@ -70,7 +71,8 @@ struct urlmatch_config {
.vars = STRING_LIST_INIT_DUP, \
}
int urlmatch_config_entry(const char *var, const char *value, void *cb);
int urlmatch_config_entry(const char *var, const char *value,
const struct config_context *ctx, void *cb);
void urlmatch_config_release(struct urlmatch_config *config);
#endif /* URL_MATCH_H */

Some files were not shown because too many files have changed in this diff Show More