Skip to content

Commit

Permalink
Merge branch 'ls/config-origin'
Browse files Browse the repository at this point in the history
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'
  • Loading branch information
gitster committed Feb 26, 2016
2 parents 11529ec + 70bd879 commit dd0f567
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 26 deletions.
16 changes: 11 additions & 5 deletions Documentation/git-config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ git-config - Get and set repository or global options
SYNOPSIS
--------
[verse]
'git config' [<file-option>] [type] [-z|--null] name [value [value_regex]]
'git config' [<file-option>] [type] [--show-origin] [-z|--null] name [value [value_regex]]
'git config' [<file-option>] [type] --add name value
'git config' [<file-option>] [type] --replace-all name value [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get name [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
'git config' [<file-option>] [type] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
'git config' [<file-option>] [type] [--show-origin] [-z|--null] --get name [value_regex]
'git config' [<file-option>] [type] [--show-origin] [-z|--null] --get-all name [value_regex]
'git config' [<file-option>] [type] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get-urlmatch name URL
'git config' [<file-option>] --unset name [value_regex]
'git config' [<file-option>] --unset-all name [value_regex]
'git config' [<file-option>] --rename-section old_name new_name
'git config' [<file-option>] --remove-section name
'git config' [<file-option>] [-z|--null] [--name-only] -l | --list
'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
'git config' [<file-option>] --get-color name [default]
'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
'git config' [<file-option>] -e | --edit
Expand Down Expand Up @@ -194,6 +194,12 @@ See also <<FILES>>.
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
Expand Down
33 changes: 33 additions & 0 deletions builtin/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "color.h"
#include "parse-options.h"
#include "urlmatch.h"
#include "quote.h"

static const char *const builtin_config_usage[] = {
N_("git config [<options>]"),
Expand All @@ -27,6 +28,7 @@ static int actions, types;
static const char *get_color_slot, *get_colorbool_slot;
static int end_null;
static int respect_includes = -1;
static int show_origin;

#define ACTION_GET (1<<0)
#define ACTION_GET_ALL (1<<1)
Expand Down Expand Up @@ -81,6 +83,7 @@ static struct option builtin_config_options[] = {
OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")),
OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
OPT_END(),
};

Expand All @@ -91,8 +94,28 @@ static void check_argc(int argc, int min, int max) {
usage_with_options(builtin_config_usage, builtin_config_options);
}

static void show_config_origin(struct strbuf *buf)
{
const char term = end_null ? '\0' : '\t';

strbuf_addstr(buf, current_config_origin_type());
strbuf_addch(buf, ':');
if (end_null)
strbuf_addstr(buf, current_config_name());
else
quote_c_style(current_config_name(), buf, NULL, 0);
strbuf_addch(buf, term);
}

static int show_all_config(const char *key_, const char *value_, void *cb)
{
if (show_origin) {
struct strbuf buf = STRBUF_INIT;
show_config_origin(&buf);
/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
fwrite(buf.buf, 1, buf.len, stdout);
strbuf_release(&buf);
}
if (!omit_values && value_)
printf("%s%c%s%c", key_, delim, value_, term);
else
Expand All @@ -108,6 +131,8 @@ struct strbuf_list {

static int format_config(struct strbuf *buf, const char *key_, const char *value_)
{
if (show_origin)
show_config_origin(buf);
if (show_keys)
strbuf_addstr(buf, key_);
if (!omit_values) {
Expand Down Expand Up @@ -538,6 +563,14 @@ int cmd_config(int argc, const char **argv, const char *prefix)
error("--name-only is only applicable to --list or --get-regexp");
usage_with_options(builtin_config_usage, builtin_config_options);
}

if (show_origin && !(actions &
(ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) {
error("--show-origin is only applicable to --get, --get-all, "
"--get-regexp, and --list.");
usage_with_options(builtin_config_usage, builtin_config_options);
}

if (actions == ACTION_LIST) {
check_argc(argc, 0, 0);
if (git_config_with_options(show_all_config, NULL,
Expand Down
6 changes: 4 additions & 2 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -1508,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 *);
Expand Down Expand Up @@ -1548,6 +1548,8 @@ extern const char *get_log_output_encoding(void);
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;
Expand Down
36 changes: 25 additions & 11 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct config_source {
size_t pos;
} buf;
} u;
const char *origin_type;
const char *name;
const char *path;
int die_on_error;
Expand Down Expand Up @@ -471,9 +472,9 @@ static int git_parse_source(config_fn_t fn, void *data)
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)
Expand Down Expand Up @@ -588,9 +589,9 @@ static void die_bad_number(const char *name, const char *value)
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);
}

Expand Down Expand Up @@ -1061,11 +1062,13 @@ static int do_config_from(struct config_source *top, config_fn_t fn, void *data)
}

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;
Expand All @@ -1078,7 +1081,7 @@ static int do_config_from_file(config_fn_t fn,

static int git_config_from_stdin(config_fn_t fn, void *data)
{
return do_config_from_file(fn, "<stdin>", 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)
Expand All @@ -1089,21 +1092,22 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
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;
Expand Down Expand Up @@ -1132,7 +1136,7 @@ static int git_config_from_blob_sha1(config_fn_t fn,
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;
Expand Down Expand Up @@ -2407,3 +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 : "";
}
4 changes: 2 additions & 2 deletions submodule-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,8 @@ static const struct submodule *config_from(struct submodule_cache *cache,
parameter.commit_sha1 = commit_sha1;
parameter.gitmodules_sha1 = sha1;
parameter.overwrite = 0;
git_config_from_buf(parse_config, rev.buf, config, config_size,
&parameter);
git_config_from_mem(parse_config, "submodule-blob", rev.buf,
config, config_size, &parameter);
free(config);

switch (lookup_type) {
Expand Down
Loading

0 comments on commit dd0f567

Please sign in to comment.