Skip to content

Commit 9d54ea6

Browse files
committed
Merge branch 'jc/dashless' (early part)
* 'jc/dashless' (early part): Prepare execv_git_cmd() for removal of builtins from the filesystem git-shell: accept "git foo" form
2 parents 605acb6 + 7550be0 commit 9d54ea6

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

exec_cmd.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,32 +65,25 @@ void setup_path(const char *cmd_path)
6565

6666
int execv_git_cmd(const char **argv)
6767
{
68-
struct strbuf cmd;
69-
const char *tmp;
70-
71-
strbuf_init(&cmd, 0);
72-
strbuf_addf(&cmd, "git-%s", argv[0]);
68+
int argc;
69+
const char **nargv;
7370

74-
/*
75-
* argv[0] must be the git command, but the argv array
76-
* belongs to the caller, and may be reused in
77-
* subsequent loop iterations. Save argv[0] and
78-
* restore it on error.
79-
*/
80-
tmp = argv[0];
81-
argv[0] = cmd.buf;
71+
for (argc = 0; argv[argc]; argc++)
72+
; /* just counting */
73+
nargv = xmalloc(sizeof(*nargv) * (argc + 2));
8274

83-
trace_argv_printf(argv, "trace: exec:");
75+
nargv[0] = "git";
76+
for (argc = 0; argv[argc]; argc++)
77+
nargv[argc + 1] = argv[argc];
78+
nargv[argc + 1] = NULL;
79+
trace_argv_printf(nargv, "trace: exec:");
8480

8581
/* execvp() can only ever return if it fails */
86-
execvp(cmd.buf, (char **)argv);
82+
execvp("git", (char **)nargv);
8783

8884
trace_printf("trace: exec failed: %s\n", strerror(errno));
8985

90-
argv[0] = tmp;
91-
92-
strbuf_release(&cmd);
93-
86+
free(nargv);
9487
return -1;
9588
}
9689

git.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,36 @@ static void handle_internal_command(int argc, const char **argv)
384384
}
385385
}
386386

387+
static void execv_dashed_external(const char **argv)
388+
{
389+
struct strbuf cmd;
390+
const char *tmp;
391+
392+
strbuf_init(&cmd, 0);
393+
strbuf_addf(&cmd, "git-%s", argv[0]);
394+
395+
/*
396+
* argv[0] must be the git command, but the argv array
397+
* belongs to the caller, and may be reused in
398+
* subsequent loop iterations. Save argv[0] and
399+
* restore it on error.
400+
*/
401+
tmp = argv[0];
402+
argv[0] = cmd.buf;
403+
404+
trace_argv_printf(argv, "trace: exec:");
405+
406+
/* execvp() can only ever return if it fails */
407+
execvp(cmd.buf, (char **)argv);
408+
409+
trace_printf("trace: exec failed: %s\n", strerror(errno));
410+
411+
argv[0] = tmp;
412+
413+
strbuf_release(&cmd);
414+
}
415+
416+
387417
int main(int argc, const char **argv)
388418
{
389419
const char *cmd = argv[0] ? argv[0] : "git-help";
@@ -448,7 +478,7 @@ int main(int argc, const char **argv)
448478
handle_internal_command(argc, argv);
449479

450480
/* .. then try the external ones */
451-
execv_git_cmd(argv);
481+
execv_dashed_external(argv);
452482

453483
/* It could be an alias -- this works around the insanity
454484
* of overriding "git log" with "git show" by having

0 commit comments

Comments
 (0)