From: Junio C Hamano Date: Fri, 26 Feb 2016 21:37:17 +0000 (-0800) Subject: Merge branch 'ls/config-origin' X-Git-Tag: v2.8.0-rc0~18 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/dd0f567f1041a3caea7856b3efe20f8fb9b487b5?hp=-c Merge branch 'ls/config-origin' The configuration system has been taught to phrase where it found a bad configuration variable in a better way in its error messages. "git config" learnt a new "--show-origin" option to indicate where the values come from. * ls/config-origin: config: add '--show-origin' option to print the origin of a config value config: add 'origin_type' to config_source struct rename git_config_from_buf to git_config_from_mem t: do not hide Git's exit code in tests using 'nul_to_q' --- dd0f567f1041a3caea7856b3efe20f8fb9b487b5 diff --combined Documentation/git-config.txt index 242fa5d1bb,499fc0f8a6..153b2d89b5 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@@ -9,18 -9,18 +9,18 @@@ git-config - Get and set repository or SYNOPSIS -------- [verse] - 'git config' [] [type] [-z|--null] name [value [value_regex]] + 'git config' [] [type] [--show-origin] [-z|--null] name [value [value_regex]] 'git config' [] [type] --add name value 'git config' [] [type] --replace-all name value [value_regex] - 'git config' [] [type] [-z|--null] --get name [value_regex] - 'git config' [] [type] [-z|--null] --get-all name [value_regex] - 'git config' [] [type] [-z|--null] [--name-only] --get-regexp name_regex [value_regex] + 'git config' [] [type] [--show-origin] [-z|--null] --get name [value_regex] + 'git config' [] [type] [--show-origin] [-z|--null] --get-all name [value_regex] + 'git config' [] [type] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex] 'git config' [] [type] [-z|--null] --get-urlmatch name URL 'git config' [] --unset name [value_regex] 'git config' [] --unset-all name [value_regex] 'git config' [] --rename-section old_name new_name 'git config' [] --remove-section name - 'git config' [] [-z|--null] [--name-only] -l | --list + 'git config' [] [--show-origin] [-z|--null] [--name-only] -l | --list 'git config' [] --get-color name [default] 'git config' [] --get-colorbool name [stdout-is-tty] 'git config' [] -e | --edit @@@ -194,6 -194,12 +194,12 @@@ See also <> Output only the names of config variables for `--list` or `--get-regexp`. + --show-origin:: + Augment the output of all queried config options with the + origin type (file, standard input, blob, command line) and + the actual origin (config file path, ref, or blob id if + applicable). + --get-colorbool name [stdout-is-tty]:: Find the color setting for `name` (e.g. `color.diff`) and output @@@ -219,9 -225,7 +225,9 @@@ --[no-]includes:: Respect `include.*` directives in config files when looking up - values. Defaults to on. + values. Defaults to `off` when a specific file is given (e.g., + using `--file`, `--global`, etc) and `on` when searching all + config files. [[FILES]] FILES diff --combined cache.h index 83b688cca6,ad7fcfc0f2..61c6e0abe3 --- a/cache.h +++ b/cache.h @@@ -9,7 -9,6 +9,7 @@@ #include "convert.h" #include "trace.h" #include "string-list.h" +#include "pack-revindex.h" #include SHA1_HEADER #ifndef platform_SHA_CTX @@@ -215,7 -214,7 +215,7 @@@ struct cache_entry #define CE_INTENT_TO_ADD (1 << 29) #define CE_SKIP_WORKTREE (1 << 30) /* CE_EXTENDED2 is for future extension */ -#define CE_EXTENDED2 (1 << 31) +#define CE_EXTENDED2 (1U << 31) #define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD | CE_SKIP_WORKTREE) @@@ -229,9 -228,7 +229,9 @@@ #error "CE_EXTENDED_FLAGS out of range" #endif +/* Forward structure decls */ struct pathspec; +struct child_process; /* * Copy the sha1 and stat state of a cache entry from one to @@@ -262,7 -259,6 +262,7 @@@ static inline unsigned create_ce_flags( #define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE) #define ce_skip_worktree(ce) ((ce)->ce_flags & CE_SKIP_WORKTREE) #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE) +#define ce_intent_to_add(ce) ((ce)->ce_flags & CE_INTENT_TO_ADD) #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) static inline unsigned int create_ce_mode(unsigned int mode) @@@ -460,6 -456,7 +460,6 @@@ extern char *git_work_tree_cfg extern int is_inside_work_tree(void); extern const char *get_git_dir(void); extern const char *get_git_common_dir(void); -extern int is_git_directory(const char *path); extern char *get_object_directory(void); extern char *get_index_file(void); extern char *get_graft_file(void); @@@ -470,25 -467,6 +470,25 @@@ extern const char *get_git_namespace(vo extern const char *strip_namespace(const char *namespaced_ref); extern const char *get_git_work_tree(void); +/* + * Return true if the given path is a git directory; note that this _just_ + * looks at the directory itself. If you want to know whether "foo/.git" + * is a repository, you must feed that path, not just "foo". + */ +extern int is_git_directory(const char *path); + +/* + * Return 1 if the given path is the root of a git repository or + * submodule, else 0. Will not return 1 for bare repositories with the + * exception of creating a bare repository in "foo/.git" and calling + * is_git_repository("foo"). + * + * If we run into read errors, we err on the side of saying "yes, it is", + * as we usually consider sub-repos precious, and would prefer to err on the + * side of not disrupting or deleting them. + */ +extern int is_nonbare_repository_dir(struct strbuf *path); + #define READ_GITFILE_ERR_STAT_FAILED 1 #define READ_GITFILE_ERR_NOT_A_FILE 2 #define READ_GITFILE_ERR_OPEN_FAILED 3 @@@ -1321,7 -1299,6 +1321,7 @@@ extern struct packed_git freshened:1, do_not_close:1; unsigned char sha1[20]; + struct revindex_entry *revindex; /* something like ".git/objects/pack/xxxxx.pack" */ char pack_name[FLEX_ARRAY]; /* more */ } *packed_git; @@@ -1508,8 -1485,8 +1508,8 @@@ struct git_config_source typedef int (*config_fn_t)(const char *, const char *, void *); extern int git_default_config(const char *, const char *, void *); extern int git_config_from_file(config_fn_t fn, const char *, void *); - extern int git_config_from_buf(config_fn_t fn, const char *name, - const char *buf, size_t len, void *data); + extern int git_config_from_mem(config_fn_t fn, const char *origin_type, + const char *name, const char *buf, size_t len, void *data); extern void git_config_push_parameter(const char *text); extern int git_config_from_parameters(config_fn_t fn, void *data); extern void git_config(config_fn_t fn, void *); @@@ -1548,6 -1525,8 +1548,8 @@@ extern const char *get_log_output_encod extern const char *get_commit_output_encoding(void); extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data); + extern const char *current_config_origin_type(void); + extern const char *current_config_name(void); struct config_include_data { int depth; @@@ -1626,14 -1605,6 +1628,14 @@@ extern int git_config_get_bool(const ch extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest); extern int git_config_get_maybe_bool(const char *key, int *dest); extern int git_config_get_pathname(const char *key, const char **dest); +extern int git_config_get_untracked_cache(void); + +/* + * This is a hack for test programs like test-dump-untracked-cache to + * ensure that they do not modify the untracked cache when reading it. + * Do not use it otherwise! + */ +extern int ignore_untracked_cache_config; struct key_value_info { const char *filename; @@@ -1687,7 -1658,6 +1689,7 @@@ extern int pager_use_color extern int term_columns(void); extern int decimal_width(uintmax_t); extern int check_pager_config(const char *cmd); +extern void prepare_pager_args(struct child_process *, const char *pager); extern const char *editor_program; extern const char *askpass_program; diff --combined config.c index e7b589a3a8,0fce371111..d732e0b3d8 --- a/config.c +++ b/config.c @@@ -24,6 -24,7 +24,7 @@@ struct config_source size_t pos; } buf; } u; + const char *origin_type; const char *name; const char *path; int die_on_error; @@@ -471,9 -472,9 +472,9 @@@ static int git_parse_source(config_fn_ break; } if (cf->die_on_error) - die(_("bad config file line %d in %s"), cf->linenr, cf->name); + die(_("bad config line %d in %s %s"), cf->linenr, cf->origin_type, cf->name); else - return error(_("bad config file line %d in %s"), cf->linenr, cf->name); + return error(_("bad config line %d in %s %s"), cf->linenr, cf->origin_type, cf->name); } static int parse_unit_factor(const char *end, uintmax_t *val) @@@ -588,9 -589,9 +589,9 @@@ static void die_bad_number(const char * if (!value) value = ""; - if (cf && cf->name) - die(_("bad numeric config value '%s' for '%s' in %s: %s"), - value, name, cf->name, reason); + if (cf && cf->origin_type && cf->name) + die(_("bad numeric config value '%s' for '%s' in %s %s: %s"), + value, name, cf->origin_type, cf->name, reason); die(_("bad numeric config value '%s' for '%s': %s"), value, name, reason); } @@@ -1061,11 -1062,13 +1062,13 @@@ static int do_config_from(struct config } static int do_config_from_file(config_fn_t fn, - const char *name, const char *path, FILE *f, void *data) + const char *origin_type, const char *name, const char *path, FILE *f, + void *data) { struct config_source top; top.u.file = f; + top.origin_type = origin_type; top.name = name; top.path = path; top.die_on_error = 1; @@@ -1078,7 -1081,7 +1081,7 @@@ static int git_config_from_stdin(config_fn_t fn, void *data) { - return do_config_from_file(fn, "", NULL, stdin, data); + return do_config_from_file(fn, "standard input", "", NULL, stdin, data); } int git_config_from_file(config_fn_t fn, const char *filename, void *data) @@@ -1089,21 -1092,22 +1092,22 @@@ f = fopen(filename, "r"); if (f) { flockfile(f); - ret = do_config_from_file(fn, filename, filename, f, data); + ret = do_config_from_file(fn, "file", filename, filename, f, data); funlockfile(f); fclose(f); } return ret; } - int git_config_from_buf(config_fn_t fn, const char *name, const char *buf, - size_t len, void *data) + int git_config_from_mem(config_fn_t fn, const char *origin_type, + const char *name, const char *buf, size_t len, void *data) { struct config_source top; top.u.buf.buf = buf; top.u.buf.len = len; top.u.buf.pos = 0; + top.origin_type = origin_type; top.name = name; top.path = NULL; top.die_on_error = 0; @@@ -1132,7 -1136,7 +1136,7 @@@ static int git_config_from_blob_sha1(co return error("reference '%s' does not point to a blob", name); } - ret = git_config_from_buf(fn, name, buf, size, data); + ret = git_config_from_mem(fn, "blob", name, buf, size, data); free(buf); return ret; @@@ -1594,30 -1598,6 +1598,30 @@@ int git_config_get_pathname(const char return ret; } +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 */ +} + NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr) { @@@ -1902,7 -1882,7 +1906,7 @@@ static int git_config_parse_key_1(cons * Validate the key and while at it, lower case it for matching. */ if (store_key) - *store_key = xmalloc(strlen(key) + 1); + *store_key = xmallocz(strlen(key)); dot = 0; for (i = 0; key[i]; i++) { @@@ -1926,6 -1906,8 +1930,6 @@@ if (store_key) (*store_key)[i] = c; } - if (store_key) - (*store_key)[i] = 0; return 0; @@@ -2407,3 -2389,13 +2411,13 @@@ int parse_config_key(const char *var return 0; } + + const char *current_config_origin_type(void) + { + return cf && cf->origin_type ? cf->origin_type : "command line"; + } + + const char *current_config_name(void) + { + return cf && cf->name ? cf->name : ""; + }