Browse Source

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>
maint
Junio C Hamano 17 years ago
parent
commit
7550be0a2b
  1. 31
      exec_cmd.c
  2. 32
      git.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);
strbuf_addf(&cmd, "git-%s", argv[0]);


/* for (argc = 0; argv[argc]; argc++)
* argv[0] must be the git command, but the argv array ; /* just counting */
* belongs to the caller, and may be reused in nargv = xmalloc(sizeof(*nargv) * (argc + 2));
* subsequent loop iterations. Save argv[0] and
* restore it on error.
*/
tmp = argv[0];
argv[0] = cmd.buf;


trace_argv_printf(argv, "trace: exec:"); nargv[0] = "git";
for (argc = 0; argv[argc]; argc++)
nargv[argc + 1] = argv[argc];
nargv[argc + 1] = NULL;
trace_argv_printf(nargv, "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

@ -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…
Cancel
Save