|
|
|
@ -10,6 +10,7 @@
@@ -10,6 +10,7 @@
|
|
|
|
|
#include <stdarg.h> |
|
|
|
|
#include "git-compat-util.h" |
|
|
|
|
#include "exec_cmd.h" |
|
|
|
|
#include "cache.h" |
|
|
|
|
|
|
|
|
|
#include "builtin.h" |
|
|
|
|
|
|
|
|
@ -32,6 +33,113 @@ static void prepend_to_path(const char *dir, int len)
@@ -32,6 +33,113 @@ static void prepend_to_path(const char *dir, int len)
|
|
|
|
|
setenv("PATH", path, 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const char *alias_command; |
|
|
|
|
static char *alias_string = NULL; |
|
|
|
|
|
|
|
|
|
static int git_alias_config(const char *var, const char *value) |
|
|
|
|
{ |
|
|
|
|
if (!strncmp(var, "alias.", 6) && !strcmp(var + 6, alias_command)) { |
|
|
|
|
alias_string = strdup(value); |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int split_cmdline(char *cmdline, const char ***argv) |
|
|
|
|
{ |
|
|
|
|
int src, dst, count = 0, size = 16; |
|
|
|
|
char quoted = 0; |
|
|
|
|
|
|
|
|
|
*argv = malloc(sizeof(char*) * size); |
|
|
|
|
|
|
|
|
|
/* split alias_string */ |
|
|
|
|
(*argv)[count++] = cmdline; |
|
|
|
|
for (src = dst = 0; cmdline[src];) { |
|
|
|
|
char c = cmdline[src]; |
|
|
|
|
if (!quoted && isspace(c)) { |
|
|
|
|
cmdline[dst++] = 0; |
|
|
|
|
while (cmdline[++src] |
|
|
|
|
&& isspace(cmdline[src])) |
|
|
|
|
; /* skip */ |
|
|
|
|
if (count >= size) { |
|
|
|
|
size += 16; |
|
|
|
|
*argv = realloc(*argv, sizeof(char*) * size); |
|
|
|
|
} |
|
|
|
|
(*argv)[count++] = cmdline + dst; |
|
|
|
|
} else if(!quoted && (c == '\'' || c == '"')) { |
|
|
|
|
quoted = c; |
|
|
|
|
src++; |
|
|
|
|
} else if (c == quoted) { |
|
|
|
|
quoted = 0; |
|
|
|
|
src++; |
|
|
|
|
} else { |
|
|
|
|
if (c == '\\' && quoted != '\'') { |
|
|
|
|
src++; |
|
|
|
|
c = cmdline[src]; |
|
|
|
|
if (!c) { |
|
|
|
|
free(*argv); |
|
|
|
|
*argv = NULL; |
|
|
|
|
return error("cmdline ends with \\"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
cmdline[dst++] = c; |
|
|
|
|
src++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cmdline[dst] = 0; |
|
|
|
|
|
|
|
|
|
if (quoted) { |
|
|
|
|
free(*argv); |
|
|
|
|
*argv = NULL; |
|
|
|
|
return error("unclosed quote"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return count; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int handle_alias(int *argcp, const char ***argv) |
|
|
|
|
{ |
|
|
|
|
int nongit = 0, ret = 0; |
|
|
|
|
const char *subdir; |
|
|
|
|
|
|
|
|
|
subdir = setup_git_directory_gently(&nongit); |
|
|
|
|
if (!nongit) { |
|
|
|
|
int count; |
|
|
|
|
const char** new_argv; |
|
|
|
|
|
|
|
|
|
alias_command = (*argv)[0]; |
|
|
|
|
git_config(git_alias_config); |
|
|
|
|
if (alias_string) { |
|
|
|
|
|
|
|
|
|
count = split_cmdline(alias_string, &new_argv); |
|
|
|
|
|
|
|
|
|
if (count < 1) |
|
|
|
|
die("empty alias for %s", alias_command); |
|
|
|
|
|
|
|
|
|
if (!strcmp(alias_command, new_argv[0])) |
|
|
|
|
die("recursive alias: %s", alias_command); |
|
|
|
|
|
|
|
|
|
/* insert after command name */ |
|
|
|
|
if (*argcp > 1) { |
|
|
|
|
new_argv = realloc(new_argv, sizeof(char*) * |
|
|
|
|
(count + *argcp - 1)); |
|
|
|
|
memcpy(new_argv + count, *argv, sizeof(char*) * |
|
|
|
|
(*argcp - 1)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*argv = new_argv; |
|
|
|
|
*argcp += count - 1; |
|
|
|
|
|
|
|
|
|
ret = 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (subdir) |
|
|
|
|
chdir(subdir); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char git_version_string[] = GIT_VERSION; |
|
|
|
|
|
|
|
|
|
static void handle_internal_command(int argc, const char **argv, char **envp) |
|
|
|
@ -94,6 +202,7 @@ int main(int argc, const char **argv, char **envp)
@@ -94,6 +202,7 @@ int main(int argc, const char **argv, char **envp)
|
|
|
|
|
char *slash = strrchr(cmd, '/'); |
|
|
|
|
char git_command[PATH_MAX + 1]; |
|
|
|
|
const char *exec_path = NULL; |
|
|
|
|
int done_alias = 0; |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
* Take the basename of argv[0] as the command |
|
|
|
@ -178,11 +287,21 @@ int main(int argc, const char **argv, char **envp)
@@ -178,11 +287,21 @@ int main(int argc, const char **argv, char **envp)
|
|
|
|
|
exec_path = git_exec_path(); |
|
|
|
|
prepend_to_path(exec_path, strlen(exec_path)); |
|
|
|
|
|
|
|
|
|
/* See if it's an internal command */ |
|
|
|
|
handle_internal_command(argc, argv, envp); |
|
|
|
|
while (1) { |
|
|
|
|
/* See if it's an internal command */ |
|
|
|
|
handle_internal_command(argc, argv, envp); |
|
|
|
|
|
|
|
|
|
/* .. then try the external ones */ |
|
|
|
|
execv_git_cmd(argv); |
|
|
|
|
/* .. then try the external ones */ |
|
|
|
|
execv_git_cmd(argv); |
|
|
|
|
|
|
|
|
|
/* It could be an alias -- this works around the insanity |
|
|
|
|
* of overriding "git log" with "git show" by having |
|
|
|
|
* alias.log = show |
|
|
|
|
*/ |
|
|
|
|
if (done_alias || !handle_alias(&argc, &argv)) |
|
|
|
|
break; |
|
|
|
|
done_alias = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (errno == ENOENT) |
|
|
|
|
cmd_usage(0, exec_path, "'%s' is not a git-command", cmd); |
|
|
|
|