diff options
author | Junio C Hamano <gitster@pobox.com> | 2007-12-01 22:09:22 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-06-23 22:45:41 -0700 |
commit | 7550be0a2bbf47aaa63c806bb5d7fcb8ab197cf8 (patch) | |
tree | 6039b53ba7b8b3bbd425113734c0a9996eed4d37 /git.c | |
parent | 0a47dc110e042b5bcc63dc94c8d517e67efe9306 (diff) | |
download | git-7550be0a2bbf47aaa63c806bb5d7fcb8ab197cf8.tar.gz |
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>
Diffstat (limited to 'git.c')
-rw-r--r-- | git.c | 32 |
1 files changed, 31 insertions, 1 deletions
@@ -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) { 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); /* .. then try the external ones */ - execv_git_cmd(argv); + execv_dashed_external(argv); /* It could be an alias -- this works around the insanity * of overriding "git log" with "git show" by having |