diff options
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 165 |
1 files changed, 105 insertions, 60 deletions
@@ -19,6 +19,7 @@ #include "utf8.h" #include "dir.h" #include "color.h" +#include "refs.h" struct config_source { struct config_source *prev; @@ -170,6 +171,12 @@ static int handle_path_include(const char *path, struct config_include_data *inc return ret; } +static void add_trailing_starstar_for_dir(struct strbuf *pat) +{ + if (pat->len && is_dir_sep(pat->buf[pat->len - 1])) + strbuf_addstr(pat, "**"); +} + static int prepare_include_condition_pattern(struct strbuf *pat) { struct strbuf path = STRBUF_INIT; @@ -197,10 +204,9 @@ static int prepare_include_condition_pattern(struct strbuf *pat) strbuf_splice(pat, 0, 1, path.buf, slash - path.buf); prefix = slash - path.buf + 1 /* slash */; } else if (!is_absolute_path(pat->buf)) - strbuf_insert(pat, 0, "**/", 3); + strbuf_insertstr(pat, 0, "**/"); - if (pat->len && is_dir_sep(pat->buf[pat->len - 1])) - strbuf_addstr(pat, "**"); + add_trailing_starstar_for_dir(pat); strbuf_release(&path); return prefix; @@ -264,6 +270,26 @@ done: return ret; } +static int include_by_branch(const char *cond, size_t cond_len) +{ + int flags; + int ret; + struct strbuf pattern = STRBUF_INIT; + const char *refname = !the_repository->gitdir ? + NULL : resolve_ref_unsafe("HEAD", 0, NULL, &flags); + const char *shortname; + + if (!refname || !(flags & REF_ISSYMREF) || + !skip_prefix(refname, "refs/heads/", &shortname)) + return 0; + + strbuf_add(&pattern, cond, cond_len); + add_trailing_starstar_for_dir(&pattern); + ret = !wildmatch(pattern.buf, shortname, WM_PATHNAME); + strbuf_release(&pattern); + return ret; +} + static int include_condition_is_true(const struct config_options *opts, const char *cond, size_t cond_len) { @@ -272,6 +298,8 @@ static int include_condition_is_true(const struct config_options *opts, return include_by_gitdir(opts, cond, cond_len, 0); else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len)) return include_by_gitdir(opts, cond, cond_len, 1); + else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len)) + return include_by_branch(cond, cond_len); /* unknown conditionals are always false */ return 0; @@ -946,34 +974,44 @@ int git_parse_ssize_t(const char *value, ssize_t *ret) NORETURN static void die_bad_number(const char *name, const char *value) { - const char * error_type = (errno == ERANGE)? _("out of range"):_("invalid unit"); + 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"); if (!value) value = ""; + if (!strcmp(name, "GIT_TEST_GETTEXT_POISON")) + /* + * We explicitly *don't* use _() here since it would + * cause an infinite loop with _() needing to call + * use_gettext_poison(). This is why marked up + * translations with N_() above. + */ + die(bad_numeric, value, name, error_type); + if (!(cf && cf->name)) - die(_("bad numeric config value '%s' for '%s': %s"), - value, name, error_type); + die(_(bad_numeric), value, name, _(error_type)); switch (cf->origin_type) { case CONFIG_ORIGIN_BLOB: die(_("bad numeric config value '%s' for '%s' in blob %s: %s"), - value, name, cf->name, error_type); + value, name, cf->name, _(error_type)); case CONFIG_ORIGIN_FILE: die(_("bad numeric config value '%s' for '%s' in file %s: %s"), - value, name, cf->name, error_type); + value, name, cf->name, _(error_type)); case CONFIG_ORIGIN_STDIN: die(_("bad numeric config value '%s' for '%s' in standard input: %s"), - value, name, error_type); + value, name, _(error_type)); case CONFIG_ORIGIN_SUBMODULE_BLOB: die(_("bad numeric config value '%s' for '%s' in submodule-blob %s: %s"), - value, name, cf->name, error_type); + value, name, cf->name, _(error_type)); case CONFIG_ORIGIN_CMDLINE: die(_("bad numeric config value '%s' for '%s' in command line %s: %s"), - value, name, cf->name, error_type); + value, name, cf->name, _(error_type)); default: die(_("bad numeric config value '%s' for '%s' in %s: %s"), - value, name, cf->name, error_type); + value, name, cf->name, _(error_type)); } } @@ -1166,7 +1204,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb) default_abbrev = -1; else { int abbrev = git_config_int(var, value); - if (abbrev < minimum_abbrev || abbrev > 40) + if (abbrev < minimum_abbrev || abbrev > the_hash_algo->hexsz) return error(_("abbrev length out of range: %d"), abbrev); default_abbrev = abbrev; } @@ -1326,6 +1364,11 @@ static int git_default_core_config(const char *var, const char *value, void *cb) return 0; } + if (!strcmp(var, "core.sparsecheckoutcone")) { + core_sparse_checkout_cone = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.precomposeunicode")) { precomposed_unicode = git_config_bool(var, value); return 0; @@ -1341,11 +1384,6 @@ static int git_default_core_config(const char *var, const char *value, void *cb) return 0; } - if (!strcmp(var, "core.partialclonefilter")) { - return git_config_string(&core_partial_clone_filter_default, - var, value); - } - if (!strcmp(var, "core.usereplacerefs")) { read_replace_refs = git_config_bool(var, value); return 0; @@ -1664,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts, char *xdg_config = xdg_config_home("config"); char *user_config = expand_user_path("~/.gitconfig", 0); char *repo_config; + enum config_scope prev_parsing_scope = current_parsing_scope; if (opts->commondir) repo_config = mkpathdup("%s/config", opts->commondir); @@ -1686,15 +1725,12 @@ static int do_git_config_sequence(const struct config_options *opts, if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK)) ret += git_config_from_file(fn, user_config, data); - current_parsing_scope = CONFIG_SCOPE_REPO; + current_parsing_scope = 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); - /* - * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE. - * But let's not complicate things before it's actually needed. - */ + current_parsing_scope = 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)) @@ -1702,11 +1738,11 @@ static int do_git_config_sequence(const struct config_options *opts, free(path); } - current_parsing_scope = CONFIG_SCOPE_CMDLINE; + current_parsing_scope = CONFIG_SCOPE_COMMAND; if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0) die(_("unable to parse command-line config")); - current_parsing_scope = CONFIG_SCOPE_UNKNOWN; + current_parsing_scope = prev_parsing_scope; free(xdg_config); free(user_config); free(repo_config); @@ -1727,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data, data = &inc; } + if (config_source) + current_parsing_scope = config_source->scope; + /* * If we have a specific filename, use it. Otherwise, follow the * regular lookup sequence. @@ -1823,9 +1862,9 @@ static struct config_set_element *configset_find_element(struct config_set *cs, if (git_config_parse_key(key, &normalized_key, NULL)) return NULL; - hashmap_entry_init(&k, strhash(normalized_key)); + hashmap_entry_init(&k.ent, strhash(normalized_key)); k.key = normalized_key; - found_entry = hashmap_get(&cs->config_hash, &k, NULL); + found_entry = hashmap_get_entry(&cs->config_hash, &k, ent, NULL); free(normalized_key); return found_entry; } @@ -1844,10 +1883,10 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha */ if (!e) { e = xmalloc(sizeof(*e)); - hashmap_entry_init(e, strhash(key)); + hashmap_entry_init(&e->ent, strhash(key)); e->key = xstrdup(key); string_list_init(&e->value_list, 1); - hashmap_add(&cs->config_hash, e); + hashmap_add(&cs->config_hash, &e->ent); } si = string_list_append_nodup(&e->value_list, xstrdup_or_null(value)); @@ -1875,12 +1914,14 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha } static int config_set_element_cmp(const void *unused_cmp_data, - const void *entry, - const void *entry_or_key, + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, const void *unused_keydata) { - const struct config_set_element *e1 = entry; - const struct config_set_element *e2 = entry_or_key; + const struct config_set_element *e1, *e2; + + e1 = container_of(eptr, const struct config_set_element, ent); + e2 = container_of(entry_or_key, const struct config_set_element, ent); return strcmp(e1->key, e2->key); } @@ -1901,12 +1942,12 @@ void git_configset_clear(struct config_set *cs) if (!cs->hash_initialized) return; - hashmap_iter_init(&cs->config_hash, &iter); - while ((entry = hashmap_iter_next(&iter))) { + hashmap_for_each_entry(&cs->config_hash, &iter, entry, + ent /* member name */) { free(entry->key); string_list_clear(&entry->value_list, 1); } - hashmap_free(&cs->config_hash, 1); + hashmap_free_entries(&cs->config_hash, struct config_set_element, ent); cs->hash_initialized = 0; free(cs->list.items); cs->list.nr = 0; @@ -2250,30 +2291,6 @@ int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestam return -1; /* thing exists but cannot be parsed */ } -int git_config_get_untracked_cache(void) -{ - int val = -1; - const char *v; - - /* Hack for test programs like test-dump-untracked-cache */ - if (ignore_untracked_cache_config) - return -1; - - if (!git_config_get_maybe_bool("core.untrackedcache", &val)) - return val; - - if (!git_config_get_value("core.untrackedcache", &v)) { - if (!strcasecmp(v, "keep")) - return -1; - - error(_("unknown core.untrackedCache value '%s'; " - "using 'keep' default value"), v); - return -1; - } - - return -1; /* default value */ -} - int git_config_get_split_index(void) { int val; @@ -3281,6 +3298,26 @@ const char *current_config_origin_type(void) } } +const char *config_scope_name(enum config_scope scope) +{ + switch (scope) { + case CONFIG_SCOPE_SYSTEM: + return "system"; + case CONFIG_SCOPE_GLOBAL: + return "global"; + case CONFIG_SCOPE_LOCAL: + return "local"; + case CONFIG_SCOPE_WORKTREE: + return "worktree"; + case CONFIG_SCOPE_COMMAND: + return "command"; + case CONFIG_SCOPE_SUBMODULE: + return "submodule"; + default: + return "unknown"; + } +} + const char *current_config_name(void) { const char *name; @@ -3301,6 +3338,14 @@ enum config_scope current_config_scope(void) return current_parsing_scope; } +int current_config_line(void) +{ + if (current_config_kvi) + return current_config_kvi->linenr; + else + return cf->linenr; +} + int lookup_config(const char **mapping, int nr_mapping, const char *var) { int i; |