Skip to content

Commit

Permalink
Merge branch 'sp/help'
Browse files Browse the repository at this point in the history
* sp/help:
  shell should call the new setup_path() to setup $PATH
  include $PATH in generating list of commands for "help -a"
  use only the $PATH for exec'ing git commands
  list_commands(): simplify code by using chdir()
  "current_exec_path" is a misleading name, use "argv_exec_path"
  remove unused/unneeded "pattern" argument of list_commands
  "git" returns 1; "git help" and "git help -a" return 0
  • Loading branch information
Junio C Hamano committed Nov 1, 2007
2 parents 3770138 + e8f5d87 commit 452b800
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 178 deletions.
1 change: 1 addition & 0 deletions builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
extern const char git_version_string[];
extern const char git_usage_string[];

extern void list_common_cmds_help(void);
extern void help_unknown_cmd(const char *cmd);
extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
extern void prune_packed_objects(int);
Expand Down
132 changes: 58 additions & 74 deletions exec_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

extern char **environ;
static const char *builtin_exec_path = GIT_EXEC_PATH;
static const char *current_exec_path;
static const char *argv_exec_path;

void git_set_exec_path(const char *exec_path)
void git_set_argv_exec_path(const char *exec_path)
{
current_exec_path = exec_path;
argv_exec_path = exec_path;
}


Expand All @@ -18,8 +18,8 @@ const char *git_exec_path(void)
{
const char *env;

if (current_exec_path)
return current_exec_path;
if (argv_exec_path)
return argv_exec_path;

env = getenv(EXEC_PATH_ENVIRONMENT);
if (env && *env) {
Expand All @@ -29,85 +29,69 @@ const char *git_exec_path(void)
return builtin_exec_path;
}

static void add_path(struct strbuf *out, const char *path)
{
if (path && *path) {
if (is_absolute_path(path))
strbuf_addstr(out, path);
else
strbuf_addstr(out, make_absolute_path(path));

strbuf_addch(out, ':');
}
}

void setup_path(const char *cmd_path)
{
const char *old_path = getenv("PATH");
struct strbuf new_path;

strbuf_init(&new_path, 0);

add_path(&new_path, argv_exec_path);
add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
add_path(&new_path, builtin_exec_path);
add_path(&new_path, cmd_path);

if (old_path)
strbuf_addstr(&new_path, old_path);
else
strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");

setenv("PATH", new_path.buf, 1);

strbuf_release(&new_path);
}

int execv_git_cmd(const char **argv)
{
char git_command[PATH_MAX + 1];
int i;
const char *paths[] = { current_exec_path,
getenv(EXEC_PATH_ENVIRONMENT),
builtin_exec_path };

for (i = 0; i < ARRAY_SIZE(paths); ++i) {
size_t len;
int rc;
const char *exec_dir = paths[i];
const char *tmp;

if (!exec_dir || !*exec_dir) continue;

if (*exec_dir != '/') {
if (!getcwd(git_command, sizeof(git_command))) {
fprintf(stderr, "git: cannot determine "
"current directory: %s\n",
strerror(errno));
break;
}
len = strlen(git_command);

/* Trivial cleanup */
while (!prefixcmp(exec_dir, "./")) {
exec_dir += 2;
while (*exec_dir == '/')
exec_dir++;
}

rc = snprintf(git_command + len,
sizeof(git_command) - len, "/%s",
exec_dir);
if (rc < 0 || rc >= sizeof(git_command) - len) {
fprintf(stderr, "git: command name given "
"is too long.\n");
break;
}
} else {
if (strlen(exec_dir) + 1 > sizeof(git_command)) {
fprintf(stderr, "git: command name given "
"is too long.\n");
break;
}
strcpy(git_command, exec_dir);
}

len = strlen(git_command);
rc = snprintf(git_command + len, sizeof(git_command) - len,
"/git-%s", argv[0]);
if (rc < 0 || rc >= sizeof(git_command) - len) {
fprintf(stderr,
"git: command name given is too long.\n");
break;
}
struct strbuf cmd;
const char *tmp;

/* argv[0] must be the git command, but the argv array
* belongs to the caller, and my be reused in
* subsequent loop iterations. Save argv[0] and
* restore it on error.
*/
strbuf_init(&cmd, 0);
strbuf_addf(&cmd, "git-%s", argv[0]);

tmp = argv[0];
argv[0] = git_command;
/*
* 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, -1, "trace: exec:");
trace_argv_printf(argv, -1, "trace: exec:");

/* execve() can only ever return if it fails */
execve(git_command, (char **)argv, environ);
/* execvp() can only ever return if it fails */
execvp(cmd.buf, (char **)argv);

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

argv[0] = tmp;
}
return -1;
argv[0] = tmp;

strbuf_release(&cmd);

return -1;
}


Expand Down
3 changes: 2 additions & 1 deletion exec_cmd.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#ifndef GIT_EXEC_CMD_H
#define GIT_EXEC_CMD_H

extern void git_set_exec_path(const char *exec_path);
extern void git_set_argv_exec_path(const char *exec_path);
extern const char* git_exec_path(void);
extern void setup_path(const char *);
extern int execv_git_cmd(const char **argv); /* NULL terminated */
extern int execl_git_cmd(const char *cmd, ...);

Expand Down
52 changes: 12 additions & 40 deletions git.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,6 @@
const char git_usage_string[] =
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";

static void prepend_to_path(const char *dir, int len)
{
const char *old_path = getenv("PATH");
char *path;
int path_len = len;

if (!old_path)
old_path = "/usr/local/bin:/usr/bin:/bin";

path_len = len + strlen(old_path) + 1;

path = xmalloc(path_len + 1);

memcpy(path, dir, len);
path[len] = ':';
memcpy(path + len + 1, old_path, path_len - len);

setenv("PATH", path, 1);

free(path);
}

static int handle_options(const char*** argv, int* argc, int* envchanged)
{
int handled = 0;
Expand All @@ -51,7 +29,7 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
if (!prefixcmp(cmd, "--exec-path")) {
cmd += 11;
if (*cmd == '=')
git_set_exec_path(cmd + 1);
git_set_argv_exec_path(cmd + 1);
else {
puts(git_exec_path());
exit(0);
Expand Down Expand Up @@ -408,7 +386,7 @@ int main(int argc, const char **argv)
{
const char *cmd = argv[0] ? argv[0] : "git-help";
char *slash = strrchr(cmd, '/');
const char *exec_path = NULL;
const char *cmd_path = NULL;
int done_alias = 0;

/*
Expand All @@ -418,10 +396,7 @@ int main(int argc, const char **argv)
*/
if (slash) {
*slash++ = 0;
if (*cmd == '/')
exec_path = cmd;
else
exec_path = xstrdup(make_absolute_path(cmd));
cmd_path = cmd;
cmd = slash;
}

Expand Down Expand Up @@ -450,23 +425,20 @@ int main(int argc, const char **argv)
if (!prefixcmp(argv[0], "--"))
argv[0] += 2;
} else {
/* Default command: "help" */
argv[0] = "help";
argc = 1;
/* The user didn't specify a command; give them help */
printf("usage: %s\n\n", git_usage_string);
list_common_cmds_help();
exit(1);
}
cmd = argv[0];

/*
* We execute external git command via execv_git_cmd(),
* which looks at "--exec-path" option, GIT_EXEC_PATH
* environment, and $(gitexecdir) in Makefile while built,
* in this order. For scripted commands, we prepend
* the value of the exec_path variable to the PATH.
* We use PATH to find git commands, but we prepend some higher
* precidence paths: the "--exec-path" option, the GIT_EXEC_PATH
* environment, and the $(gitexecdir) from the Makefile at build
* time.
*/
if (exec_path)
prepend_to_path(exec_path, strlen(exec_path));
exec_path = git_exec_path();
prepend_to_path(exec_path, strlen(exec_path));
setup_path(cmd_path);

while (1) {
/* See if it's an internal command */
Expand Down
Loading

0 comments on commit 452b800

Please sign in to comment.