Exec git programs without using PATH.

The git suite may not be in PATH (and thus programs such as
git-send-pack could not exec git-rev-list).  Thus there is a need for
logic that will locate these programs.  Modifying PATH is not
desirable as it result in behavior differing from the user's
intentions, as we may end up prepending "/usr/bin" to PATH.

- git C programs will use exec*_git_cmd() APIs to exec sub-commands.
- exec*_git_cmd() will execute a git program by searching for it in
  the following directories:
	1. --exec-path (as used by "git")
	2. The GIT_EXEC_PATH environment variable.
	3. $(gitexecdir) as set in Makefile (default value $(bindir)).
- git wrapper will modify PATH as before to enable shell scripts to
  invoke "git-foo" commands.

Ideally, shell scripts should use the git wrapper to become independent
of PATH, and then modifying PATH will not be necessary.

[jc: with minor updates after a brief review.]

Signed-off-by: Michal Ostrowski <mostrows@watson.ibm.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Michal Ostrowski
2006-01-10 21:12:17 -05:00
committed by Junio C Hamano
parent c884dd9a54
commit 77cb17e940
12 changed files with 176 additions and 62 deletions

50
git.c
View File

@ -10,6 +10,7 @@
#include <stdarg.h>
#include <sys/ioctl.h>
#include "git-compat-util.h"
#include "exec_cmd.h"
#ifndef PATH_MAX
# define PATH_MAX 4096
@ -233,14 +234,11 @@ int main(int argc, char **argv, char **envp)
{
char git_command[PATH_MAX + 1];
char wd[PATH_MAX + 1];
int i, len, show_help = 0;
char *exec_path = getenv("GIT_EXEC_PATH");
int i, show_help = 0;
const char *exec_path;
getcwd(wd, PATH_MAX);
if (!exec_path)
exec_path = GIT_EXEC_PATH;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
@ -256,10 +254,11 @@ int main(int argc, char **argv, char **envp)
if (!strncmp(arg, "exec-path", 9)) {
arg += 9;
if (*arg == '=')
if (*arg == '=') {
exec_path = arg + 1;
else {
puts(exec_path);
git_set_exec_path(exec_path);
} else {
puts(git_exec_path());
exit(0);
}
}
@ -275,42 +274,15 @@ int main(int argc, char **argv, char **envp)
if (i >= argc || show_help) {
if (i >= argc)
cmd_usage(exec_path, NULL);
cmd_usage(git_exec_path(), NULL);
show_man_page(argv[i]);
}
if (*exec_path != '/') {
if (!getcwd(git_command, sizeof(git_command))) {
fprintf(stderr,
"git: cannot determine current directory\n");
exit(1);
}
len = strlen(git_command);
exec_path = git_exec_path();
prepend_to_path(exec_path, strlen(exec_path));
/* Trivial cleanup */
while (!strncmp(exec_path, "./", 2)) {
exec_path += 2;
while (*exec_path == '/')
exec_path++;
}
snprintf(git_command + len, sizeof(git_command) - len,
"/%s", exec_path);
}
else
strcpy(git_command, exec_path);
len = strlen(git_command);
prepend_to_path(git_command, len);
len += snprintf(git_command + len, sizeof(git_command) - len,
"/git-%s", argv[i]);
if (sizeof(git_command) <= len) {
fprintf(stderr, "git: command name given is too long.\n");
exit(1);
}
/* execve() can only ever return if it fails */
execve(git_command, &argv[i], envp);
execv_git_cmd(argv + i);
if (errno == ENOENT)
cmd_usage(exec_path, "'%s' is not a git-command", argv[i]);