зеркало из https://github.com/microsoft/git.git
run-command.c: print env vars in trace_run_command()
Occasionally submodule code could execute new commands with GIT_DIR set to some submodule. GIT_TRACE prints just the command line which makes it hard to tell that it's not really executed on this repository. Print the env delta (compared to parent environment) in this case. Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
21dfc5e08f
Коммит
c61a975df1
|
@ -557,6 +557,63 @@ static int wait_or_whine(pid_t pid, const char *argv0, int in_signal)
|
|||
return code;
|
||||
}
|
||||
|
||||
static void trace_add_env(struct strbuf *dst, const char *const *deltaenv)
|
||||
{
|
||||
struct string_list envs = STRING_LIST_INIT_DUP;
|
||||
const char *const *e;
|
||||
int i;
|
||||
int printed_unset = 0;
|
||||
|
||||
/* Last one wins, see run-command.c:prep_childenv() for context */
|
||||
for (e = deltaenv; e && *e; e++) {
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
char *equals = strchr(*e, '=');
|
||||
|
||||
if (equals) {
|
||||
strbuf_add(&key, *e, equals - *e);
|
||||
string_list_insert(&envs, key.buf)->util = equals + 1;
|
||||
} else {
|
||||
string_list_insert(&envs, *e)->util = NULL;
|
||||
}
|
||||
strbuf_release(&key);
|
||||
}
|
||||
|
||||
/* "unset X Y...;" */
|
||||
for (i = 0; i < envs.nr; i++) {
|
||||
const char *var = envs.items[i].string;
|
||||
const char *val = envs.items[i].util;
|
||||
|
||||
if (val || !getenv(var))
|
||||
continue;
|
||||
|
||||
if (!printed_unset) {
|
||||
strbuf_addstr(dst, " unset");
|
||||
printed_unset = 1;
|
||||
}
|
||||
strbuf_addf(dst, " %s", var);
|
||||
}
|
||||
if (printed_unset)
|
||||
strbuf_addch(dst, ';');
|
||||
|
||||
/* ... followed by "A=B C=D ..." */
|
||||
for (i = 0; i < envs.nr; i++) {
|
||||
const char *var = envs.items[i].string;
|
||||
const char *val = envs.items[i].util;
|
||||
const char *oldval;
|
||||
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
oldval = getenv(var);
|
||||
if (oldval && !strcmp(val, oldval))
|
||||
continue;
|
||||
|
||||
strbuf_addf(dst, " %s=", var);
|
||||
sq_quote_buf_pretty(dst, val);
|
||||
}
|
||||
string_list_clear(&envs, 0);
|
||||
}
|
||||
|
||||
static void trace_run_command(const struct child_process *cp)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
@ -565,6 +622,12 @@ static void trace_run_command(const struct child_process *cp)
|
|||
return;
|
||||
|
||||
strbuf_addf(&buf, "trace: run_command:");
|
||||
/*
|
||||
* The caller is responsible for initializing cp->env from
|
||||
* cp->env_array if needed. We only check one place.
|
||||
*/
|
||||
if (cp->env)
|
||||
trace_add_env(&buf, cp->env);
|
||||
if (cp->git_cmd)
|
||||
strbuf_addstr(&buf, " git");
|
||||
sq_quote_argv_pretty(&buf, cp->argv);
|
||||
|
|
|
@ -54,6 +54,15 @@ int cmd_main(int argc, const char **argv)
|
|||
struct child_process proc = CHILD_PROCESS_INIT;
|
||||
int jobs;
|
||||
|
||||
if (argc < 3)
|
||||
return 1;
|
||||
while (!strcmp(argv[1], "env")) {
|
||||
if (!argv[2])
|
||||
die("env specifier without a value");
|
||||
argv_array_push(&proc.env_array, argv[2]);
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
}
|
||||
if (argc < 3)
|
||||
return 1;
|
||||
proc.argv = (const char **)argv + 2;
|
||||
|
|
|
@ -141,4 +141,41 @@ test_expect_success 'run_command outputs ' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_trace () {
|
||||
expect="$1"
|
||||
shift
|
||||
GIT_TRACE=1 test-run-command "$@" run-command true 2>&1 >/dev/null | \
|
||||
sed 's/.* run_command: //' >actual &&
|
||||
echo "$expect true" >expect &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
||||
test_expect_success 'GIT_TRACE with environment variables' '
|
||||
test_trace "abc=1 def=2" env abc=1 env def=2 &&
|
||||
test_trace "abc=2" env abc env abc=1 env abc=2 &&
|
||||
test_trace "abc=2" env abc env abc=2 &&
|
||||
(
|
||||
abc=1 && export abc &&
|
||||
test_trace "def=1" env abc=1 env def=1
|
||||
) &&
|
||||
(
|
||||
abc=1 && export abc &&
|
||||
test_trace "def=1" env abc env abc=1 env def=1
|
||||
) &&
|
||||
test_trace "def=1" env non-exist env def=1 &&
|
||||
test_trace "abc=2" env abc=1 env abc env abc=2 &&
|
||||
(
|
||||
abc=1 def=2 && export abc def &&
|
||||
test_trace "unset abc def;" env abc env def
|
||||
) &&
|
||||
(
|
||||
abc=1 def=2 && export abc def &&
|
||||
test_trace "unset def; abc=3" env abc env def env abc=3
|
||||
) &&
|
||||
(
|
||||
abc=1 && export abc &&
|
||||
test_trace "unset abc;" env abc=2 env abc
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Загрузка…
Ссылка в новой задаче