diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-07-06 13:38:11 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-07-06 13:38:11 -0700 |
commit | 1e4bf907890e094f1c1c8c5086387e7d5fdb0655 (patch) | |
tree | 50bf586083db40ec2dc4213110381f73e6d6c9dd /config.c | |
parent | 7a738b40f67fc44c2a2c1abcffe474241af3d30e (diff) | |
parent | 20b20a22f8f7c1420e259c97ef790cb93091f475 (diff) | |
download | git-1e4bf907890e094f1c1c8c5086387e7d5fdb0655.tar.gz |
Merge branch 'jk/upload-pack-hook'
"upload-pack" allows a custom "git pack-objects" replacement when
responding to "fetch/clone" via the uploadpack.packObjectsHook.
* jk/upload-pack-hook:
upload-pack: provide a hook for running pack-objects
t1308: do not get fooled by symbolic links to the source tree
config: add a notion of "scope"
config: return configset value for current_config_ functions
config: set up config_source for command-line config
git_config_parse_parameter: refactor cleanup code
git_config_with_options: drop "found" counting
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 134 |
1 files changed, 95 insertions, 39 deletions
@@ -38,7 +38,33 @@ struct config_source { long (*do_ftell)(struct config_source *c); }; +/* + * These variables record the "current" config source, which + * can be accessed by parsing callbacks. + * + * The "cf" variable will be non-NULL only when we are actually parsing a real + * config source (file, blob, cmdline, etc). + * + * The "current_config_kvi" variable will be non-NULL only when we are feeding + * cached config from a configset into a callback. + * + * They should generally never 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). + */ static struct config_source *cf; +static struct key_value_info *current_config_kvi; + +/* + * Similar to the variables above, this gives access to the "scope" of the + * current value (repo, global, etc). For cached values, it can be found via + * the current_config_kvi as above. During parsing, the current value can be + * found in this variable. It's not part of "cf" because it transcends a single + * file (i.e., a file included from .git/config is still in "repo" scope). + */ +static enum config_scope current_parsing_scope; static int zlib_compression_seen; @@ -131,7 +157,9 @@ static int handle_path_include(const char *path, struct config_include_data *inc if (!access_or_die(path, R_OK, 0)) { if (++inc->depth > MAX_INCLUDE_DEPTH) die(include_depth_advice, MAX_INCLUDE_DEPTH, path, - cf && cf->name ? cf->name : "the command line"); + !cf ? "<unknown>" : + cf->name ? cf->name : + "the command line"); ret = git_config_from_file(git_config_include, path, inc); inc->depth--; } @@ -205,32 +233,40 @@ int git_config_parse_parameter(const char *text, int git_config_from_parameters(config_fn_t fn, void *data) { const char *env = getenv(CONFIG_DATA_ENVIRONMENT); + int ret = 0; char *envw; const char **argv = NULL; int nr = 0, alloc = 0; int i; + struct config_source source; if (!env) return 0; + + memset(&source, 0, sizeof(source)); + source.prev = cf; + cf = &source; + /* sq_dequote will write over it */ envw = xstrdup(env); if (sq_dequote_to_argv(envw, &argv, &nr, &alloc) < 0) { - free(envw); - return error("bogus format in " CONFIG_DATA_ENVIRONMENT); + ret = error("bogus format in " CONFIG_DATA_ENVIRONMENT); + goto out; } for (i = 0; i < nr; i++) { if (git_config_parse_parameter(argv[i], fn, data) < 0) { - free(argv); - free(envw); - return -1; + ret = -1; + goto out; } } +out: free(argv); free(envw); - return nr > 0; + cf = source.prev; + return ret; } static int get_next_char(void) @@ -1197,47 +1233,36 @@ int git_config_system(void) static int do_git_config_sequence(config_fn_t fn, void *data) { - int ret = 0, found = 0; + int ret = 0; char *xdg_config = xdg_config_home("config"); char *user_config = expand_user_path("~/.gitconfig"); char *repo_config = git_pathdup("config"); - if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) { + current_parsing_scope = CONFIG_SCOPE_SYSTEM; + if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) ret += git_config_from_file(fn, git_etc_gitconfig(), data); - found += 1; - } - if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK)) { + current_parsing_scope = CONFIG_SCOPE_GLOBAL; + if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK)) ret += git_config_from_file(fn, xdg_config, data); - found += 1; - } - if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK)) { + if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK)) ret += git_config_from_file(fn, user_config, data); - found += 1; - } - if (repo_config && !access_or_die(repo_config, R_OK, 0)) { + current_parsing_scope = CONFIG_SCOPE_REPO; + if (repo_config && !access_or_die(repo_config, R_OK, 0)) ret += git_config_from_file(fn, repo_config, data); - found += 1; - } - switch (git_config_from_parameters(fn, data)) { - case -1: /* error */ + current_parsing_scope = CONFIG_SCOPE_CMDLINE; + if (git_config_from_parameters(fn, data) < 0) die(_("unable to parse command-line config")); - break; - case 0: /* found nothing */ - break; - default: /* found at least one item */ - found++; - break; - } + current_parsing_scope = CONFIG_SCOPE_UNKNOWN; free(xdg_config); free(user_config); free(repo_config); - return ret == 0 ? found : ret; + return ret; } int git_config_with_options(config_fn_t fn, void *data, @@ -1272,7 +1297,7 @@ static void git_config_raw(config_fn_t fn, void *data) if (git_config_with_options(fn, data, NULL, 1) < 0) /* * git_config_with_options() normally returns only - * positive values, as most errors are fatal, and + * zero, as most errors are fatal, and * non-fatal potential errors are guarded by "if" * statements that are entered only when no error is * possible. @@ -1290,16 +1315,20 @@ static void configset_iter(struct config_set *cs, config_fn_t fn, void *data) struct string_list *values; struct config_set_element *entry; struct configset_list *list = &cs->list; - struct key_value_info *kv_info; for (i = 0; i < list->nr; i++) { entry = list->items[i].e; value_index = list->items[i].value_index; values = &entry->value_list; - if (fn(entry->key, values->items[value_index].string, data) < 0) { - kv_info = values->items[value_index].util; - git_die_config_linenr(entry->key, kv_info->filename, kv_info->linenr); - } + + current_config_kvi = values->items[value_index].util; + + if (fn(entry->key, values->items[value_index].string, data) < 0) + git_die_config_linenr(entry->key, + current_config_kvi->filename, + current_config_kvi->linenr); + + current_config_kvi = NULL; } } @@ -1356,14 +1385,19 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha l_item->e = e; l_item->value_index = e->value_list.nr - 1; - if (cf) { + if (!cf) + die("BUG: configset_add_value has no source"); + if (cf->name) { kv_info->filename = strintern(cf->name); kv_info->linenr = cf->linenr; + kv_info->origin_type = strintern(cf->origin_type); } else { /* for values read from `git_config_from_parameters()` */ kv_info->filename = NULL; kv_info->linenr = -1; + kv_info->origin_type = NULL; } + kv_info->scope = current_parsing_scope; si->util = kv_info; return 0; @@ -2442,10 +2476,32 @@ int parse_config_key(const char *var, const char *current_config_origin_type(void) { - return cf && cf->origin_type ? cf->origin_type : "command line"; + const char *type; + if (current_config_kvi) + type = current_config_kvi->origin_type; + else if(cf) + type = cf->origin_type; + else + die("BUG: current_config_origin_type called outside config callback"); + return type ? type : "command line"; } const char *current_config_name(void) { - return cf && cf->name ? cf->name : ""; + const char *name; + if (current_config_kvi) + name = current_config_kvi->filename; + else if (cf) + name = cf->name; + else + die("BUG: current_config_name called outside config callback"); + return name ? name : ""; +} + +enum config_scope current_config_scope(void) +{ + if (current_config_kvi) + return current_config_kvi->scope; + else + return current_parsing_scope; } |