On Thu, Oct 18 2018, Ævar Arnfjörð Bjarmason wrote: > +static void init_cmd_history(struct strbuf *env, struct string_list *cmd_list) > +{ > + const char *old = getenv(COMMAND_HISTORY_ENVIRONMENT); > + struct strbuf **cmd_history, **ptr; > + > + if (!old || !*old) > + return; > + > + strbuf_addstr(env, old); > + strbuf_rtrim(env); > + > + cmd_history = strbuf_split_buf(old, strlen(old), ' ', 0); > + for (ptr = cmd_history; *ptr; ptr++) { > + strbuf_rtrim(*ptr); > + string_list_append(cmd_list, (*ptr)->buf); > + } > + strbuf_list_free(cmd_history); > +} > + > +static void add_cmd_history(struct strbuf *env, struct string_list *cmd_list, > + const char *cmd) > +{ > + string_list_append(cmd_list, cmd); > + if (env->len) > + strbuf_addch(env, ' '); > + strbuf_addstr(env, cmd); > + setenv(COMMAND_HISTORY_ENVIRONMENT, env->buf, 1); > +} > + > static int run_argv(int *argcp, const char ***argv) > { > int done_alias = 0; > - struct string_list cmd_list = STRING_LIST_INIT_NODUP; > + struct string_list cmd_list = STRING_LIST_INIT_DUP; > struct string_list_item *seen; > + struct strbuf env = STRBUF_INIT; > > + init_cmd_history(&env, &cmd_list); > while (1) { > /* > * If we tried alias and futzed with our environment, > @@ -711,7 +742,7 @@ static int run_argv(int *argcp, const char ***argv) > " not terminate:%s"), cmd_list.items[0].string, sb.buf); > } > > - string_list_append(&cmd_list, *argv[0]); > + add_cmd_history(&env, &cmd_list, *argv[0]); > > /* > * It could be an alias -- this works around the insanity Just to sanity check an assumption of mine: One thing I didn't do is use sq_quote_buf() and sq_dequote_to_argv() like we do for CONFIG_DATA_ENVIRONMENT. This is because in the case of config we need to deal with: $ git config alias.cfgdump !env $ git -c x.y=z -c "foo.bar='baz'" cfgdump|grep baz GIT_CONFIG_PARAMETERS='x.y=z' 'foo.bar='\''baz'\''' But in this case I don't see how a command-name would ever contain whitespace. So we skip quoting and just delimit by space. There's also nothing stopping you from doing e.g.: $ GIT_COMMAND_HISTORY='foo bar' ~/g/git/git --exec-path=$PWD one fatal: alias loop detected: expansion of 'foo' does not terminate: foo bar one two <== three four five ==> Or even confuse the code by adding a whitespace at the beginning: $ GIT_COMMAND_HISTORY=' foo bar' ~/g/git/git --exec-path=$PWD one fatal: alias loop detected: expansion of '' does not terminate: foo bar one two <== three four five ==> I thought none of this was worth dealing with. Worst case someone's screwing with this, but I don't see how it would happen accidentally, and even then we detect the infinite loop and just degrade to confusing error messages because you decided to screw with git's GIT_* env vars.