Prepare execv_git_cmd() for removal of builtins from the filesystem
Currently, execv_git_cmd() always try running the dashed form, which means we cannot easily remove the git-foo hardlinks for built-in commands. This updates the function to always exec "git foo" form, and makes sure "git" potty does not infinitely recurse to itself. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
0a47dc110e
commit
7550be0a2b
31
exec_cmd.c
31
exec_cmd.c
@ -65,32 +65,25 @@ void setup_path(const char *cmd_path)
|
|||||||
|
|
||||||
int execv_git_cmd(const char **argv)
|
int execv_git_cmd(const char **argv)
|
||||||
{
|
{
|
||||||
struct strbuf cmd;
|
int argc;
|
||||||
const char *tmp;
|
const char **nargv;
|
||||||
|
|
||||||
strbuf_init(&cmd, 0);
|
for (argc = 0; argv[argc]; argc++)
|
||||||
strbuf_addf(&cmd, "git-%s", argv[0]);
|
; /* just counting */
|
||||||
|
nargv = xmalloc(sizeof(*nargv) * (argc + 2));
|
||||||
|
|
||||||
/*
|
nargv[0] = "git";
|
||||||
* argv[0] must be the git command, but the argv array
|
for (argc = 0; argv[argc]; argc++)
|
||||||
* belongs to the caller, and may be reused in
|
nargv[argc + 1] = argv[argc];
|
||||||
* subsequent loop iterations. Save argv[0] and
|
nargv[argc + 1] = NULL;
|
||||||
* restore it on error.
|
trace_argv_printf(nargv, "trace: exec:");
|
||||||
*/
|
|
||||||
tmp = argv[0];
|
|
||||||
argv[0] = cmd.buf;
|
|
||||||
|
|
||||||
trace_argv_printf(argv, "trace: exec:");
|
|
||||||
|
|
||||||
/* execvp() can only ever return if it fails */
|
/* execvp() can only ever return if it fails */
|
||||||
execvp(cmd.buf, (char **)argv);
|
execvp("git", (char **)nargv);
|
||||||
|
|
||||||
trace_printf("trace: exec failed: %s\n", strerror(errno));
|
trace_printf("trace: exec failed: %s\n", strerror(errno));
|
||||||
|
|
||||||
argv[0] = tmp;
|
free(nargv);
|
||||||
|
|
||||||
strbuf_release(&cmd);
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
git.c
32
git.c
@ -384,6 +384,36 @@ static void handle_internal_command(int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void execv_dashed_external(const char **argv)
|
||||||
|
{
|
||||||
|
struct strbuf cmd;
|
||||||
|
const char *tmp;
|
||||||
|
|
||||||
|
strbuf_init(&cmd, 0);
|
||||||
|
strbuf_addf(&cmd, "git-%s", argv[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* argv[0] must be the git command, but the argv array
|
||||||
|
* belongs to the caller, and may be reused in
|
||||||
|
* subsequent loop iterations. Save argv[0] and
|
||||||
|
* restore it on error.
|
||||||
|
*/
|
||||||
|
tmp = argv[0];
|
||||||
|
argv[0] = cmd.buf;
|
||||||
|
|
||||||
|
trace_argv_printf(argv, "trace: exec:");
|
||||||
|
|
||||||
|
/* execvp() can only ever return if it fails */
|
||||||
|
execvp(cmd.buf, (char **)argv);
|
||||||
|
|
||||||
|
trace_printf("trace: exec failed: %s\n", strerror(errno));
|
||||||
|
|
||||||
|
argv[0] = tmp;
|
||||||
|
|
||||||
|
strbuf_release(&cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
const char *cmd = argv[0] ? argv[0] : "git-help";
|
const char *cmd = argv[0] ? argv[0] : "git-help";
|
||||||
@ -448,7 +478,7 @@ int main(int argc, const char **argv)
|
|||||||
handle_internal_command(argc, argv);
|
handle_internal_command(argc, argv);
|
||||||
|
|
||||||
/* .. then try the external ones */
|
/* .. then try the external ones */
|
||||||
execv_git_cmd(argv);
|
execv_dashed_external(argv);
|
||||||
|
|
||||||
/* It could be an alias -- this works around the insanity
|
/* It could be an alias -- this works around the insanity
|
||||||
* of overriding "git log" with "git show" by having
|
* of overriding "git log" with "git show" by having
|
||||||
|
Loading…
Reference in New Issue
Block a user