@@ -252,6 +252,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) {
@@ -78,16 +78,6 @@ struct config_reader {
*/
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
@@ -113,16 +103,21 @@ static inline struct config_source *config_reader_pop_source(struct config_reade
return ret;
}
-static inline void config_reader_set_kvi(struct config_reader *reader,
- struct key_value_info *kvi)
+static inline void config_reader_push_kvi(struct config_reader *reader,
+ struct key_value_info *kvi)
{
+ kvi->prev = reader->config_kvi;
reader->config_kvi = kvi;
}
-static inline void config_reader_set_scope(struct config_reader *reader,
- enum config_scope scope)
+static inline struct key_value_info *config_reader_pop_kvi(struct config_reader *reader)
{
- reader->parsing_scope = scope;
+ struct key_value_info *ret;
+ if (!reader->config_kvi)
+ BUG("tried to pop config_kvi, but we weren't reading config");
+ ret = reader->config_kvi;
+ reader->config_kvi = reader->config_kvi->prev;
+ return ret;
}
static int pack_compression_seen;
@@ -244,7 +239,9 @@ static int handle_path_include(struct config_source *cs, const char *path,
!cs ? "<unknown>" :
cs->name ? cs->name :
"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,
+ current_config_scope(),
+ NULL);
inc->depth--;
}
cleanup:
@@ -393,18 +390,12 @@ 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, &opts);
-
- config_reader_set_scope(inc->config_reader, store_scope);
}
static int forbid_remote_url(const char *var, const char *value UNUSED,
@@ -471,10 +462,13 @@ static int include_condition_is_true(struct config_source *cs,
return 0;
}
+static int kvi_fn(config_fn_t fn, const char *key, const char *value,
+ struct key_value_info *kvi, void *data);
static int git_config_include(const char *var, const char *value, void *data)
{
struct config_include_data *inc = data;
struct config_source *cs = inc->config_reader->source;
+ struct key_value_info *kvi = inc->config_reader->config_kvi;
const char *cond, *key;
size_t cond_len;
int ret;
@@ -483,7 +477,7 @@ 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 = kvi_fn(inc->fn, var, value, kvi, inc->data);
if (ret < 0)
return ret;
@@ -655,13 +649,12 @@ out_free_ret_1:
}
static int kvi_fn(config_fn_t fn, const char *key, const char *value,
- struct key_value_info *kvi,
- void *data)
+ struct key_value_info *kvi, void *data)
{
int ret;
- config_reader_set_kvi(&the_reader, kvi);
+ config_reader_push_kvi(&the_reader, kvi);
ret = fn(key, value, data);
- config_reader_set_kvi(&the_reader, NULL);
+ config_reader_pop_kvi(&the_reader);
return ret;
}
@@ -942,8 +935,8 @@ 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;
@@ -976,7 +969,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 = kvi_fn(fn, name->buf, value, kvi, data);
if (ret >= 0)
cs->linenr++;
return ret;
@@ -1075,8 +1069,19 @@ 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;
+}
+
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;
@@ -1160,7 +1165,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;
}
@@ -2016,9 +2021,11 @@ int git_default_config(const char *var, const char *value, void *cb)
* this function.
*/
static int do_config_from(struct config_reader *reader,
- struct config_source *top, config_fn_t fn, void *data,
+ struct config_source *top, config_fn_t fn,
+ void *data, enum config_scope scope,
const struct config_options *opts)
{
+ struct key_value_info kvi = { 0 };
int ret;
/* push config-file parsing state stack */
@@ -2028,8 +2035,9 @@ static int do_config_from(struct config_reader *reader,
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);
@@ -2043,7 +2051,8 @@ static int do_config_from_file(struct config_reader *reader,
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;
@@ -2058,19 +2067,21 @@ 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(reader, &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);
+ 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;
@@ -2081,7 +2092,8 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename,
f = fopen_or_warn(filename, "r");
if (f) {
ret = do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_FILE,
- filename, filename, f, data, opts);
+ filename, filename, f, data, scope,
+ opts);
fclose(f);
}
return ret;
@@ -2089,13 +2101,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;
@@ -2110,14 +2124,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(&the_reader, &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;
@@ -2133,7 +2148,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;
@@ -2142,13 +2157,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)
@@ -2201,8 +2217,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,
config_fn_t fn, void *data)
{
int ret = 0;
@@ -2210,7 +2225,6 @@ static int do_git_config_sequence(struct config_reader *reader,
char *xdg_config = NULL;
char *user_config = NULL;
char *repo_config;
- enum config_scope prev_parsing_scope = reader->parsing_scope;
if (opts->commondir)
repo_config = mkpathdup("%s/config", opts->commondir);
@@ -2219,39 +2233,40 @@ static int do_git_config_sequence(struct config_reader *reader,
else
repo_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 && repository_format_worktree_config) {
char *path = git_pathdup("config.worktree");
if (!access_or_die(path, R_OK, 0))
- ret += git_config_from_file(fn, path, data);
+ ret += git_config_from_file_with_options(fn, path, data,
+ CONFIG_SCOPE_WORKTREE,
+ NULL);
free(path);
}
- config_reader_set_scope(reader, 0);
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);
@@ -2264,7 +2279,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) {
@@ -2277,31 +2291,29 @@ int config_with_options(config_fn_t fn, void *data,
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) {
struct repository *repo = config_source->repo ?
config_source->repo : the_repository;
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, fn, data);
+ ret = do_git_config_sequence(opts, 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;
}
@@ -2429,13 +2441,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 && reader->source->name) {
- kv_info->filename = strintern(reader->source->name);
- kv_info->linenr = reader->source->linenr;
- kv_info->origin_type = reader->source->origin_type;
- kv_info->scope = reader->parsing_scope;
- } else
- kvi_from_param(kv_info);
+ memcpy(kv_info, reader->config_kvi, sizeof(struct key_value_info));
si->util = kv_info;
return 0;
@@ -3473,7 +3479,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;
@@ -4018,7 +4025,13 @@ enum config_scope current_config_scope(void)
if (the_reader.config_kvi)
return the_reader.config_kvi->scope;
else
- return the_reader.parsing_scope;
+ /*
+ * FIXME This should be a BUG, but tr2_list_env_vars_fl is
+ * calling this outside of a config callback. This will be
+ * easier to fix when we plumb kvi through the config callbacks,
+ * so leave this untouched for now.
+ */
+ return CONFIG_SCOPE_UNKNOWN;
}
int current_config_line(void)
@@ -142,16 +142,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);
@@ -672,6 +674,7 @@ struct key_value_info {
int linenr;
enum config_origin_type origin_type;
enum config_scope scope;
+ struct key_value_info *prev;
};
/**
@@ -1235,7 +1235,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");
@@ -603,7 +603,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, ¶meter, NULL);
+ config, config_size, ¶meter, CONFIG_SCOPE_UNKNOWN, NULL);
strbuf_release(&rev);
free(config);
@@ -711,7 +711,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);