X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git.c;h=3307c078e539e150556f8b27264bbf29b05d9bb6;hb=926ab840cdc867b54fa93b8e1ece2790315c2456;hp=89b431fa28162adbd0f64d7a036a71b5bfce9eee;hpb=e4b9c36ca40a0869ee5fc64aaeabaf2655ef595b;p=git.git diff --git a/git.c b/git.c index 89b431fa2..3307c078e 100644 --- a/git.c +++ b/git.c @@ -6,6 +6,9 @@ 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]"; +const char git_more_info_string[] = + "See 'git help COMMAND' for more information on a specific command."; + static int handle_options(const char*** argv, int* argc, int* envchanged) { int handled = 0; @@ -283,9 +286,10 @@ static void handle_internal_command(int argc, const char **argv) { "checkout-index", cmd_checkout_index, RUN_SETUP | NEED_WORK_TREE}, { "check-ref-format", cmd_check_ref_format }, - { "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE }, + { "check-attr", cmd_check_attr, RUN_SETUP }, { "cherry", cmd_cherry, RUN_SETUP }, { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE }, + { "clone", cmd_clone }, { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE }, { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE }, { "commit-tree", cmd_commit_tree, RUN_SETUP }, @@ -293,7 +297,7 @@ static void handle_internal_command(int argc, const char **argv) { "count-objects", cmd_count_objects, RUN_SETUP }, { "describe", cmd_describe, RUN_SETUP }, { "diff", cmd_diff }, - { "diff-files", cmd_diff_files }, + { "diff-files", cmd_diff_files, RUN_SETUP }, { "diff-index", cmd_diff_index, RUN_SETUP }, { "diff-tree", cmd_diff_tree, RUN_SETUP }, { "fast-export", cmd_fast_export, RUN_SETUP }, @@ -365,6 +369,16 @@ static void handle_internal_command(int argc, const char **argv) { "pack-refs", cmd_pack_refs, RUN_SETUP }, }; int i; + static const char ext[] = STRIP_EXTENSION; + + if (sizeof(ext) > 1) { + i = strlen(argv[0]) - strlen(ext); + if (i > 0 && !strcmp(argv[0] + i, ext)) { + char *argv0 = strdup(argv[0]); + argv[0] = cmd = argv0; + argv0[i] = '\0'; + } + } /* Turn "git cmd --help" into "git help cmd" */ if (argc > 1 && !strcmp(argv[1], "--help")) { @@ -380,10 +394,40 @@ 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) { - const char *cmd = argv[0] ? argv[0] : "git-help"; - char *slash = strrchr(cmd, '/'); + const char *cmd = argv[0] && *argv[0] ? argv[0] : "git-help"; + char *slash = (char *)cmd + strlen(cmd); const char *cmd_path = NULL; int done_alias = 0; @@ -392,7 +436,10 @@ int main(int argc, const char **argv) * name, and the dirname as the default exec_path * if we don't have anything better. */ - if (slash) { + do + --slash; + while (cmd <= slash && !is_dir_sep(*slash)); + if (cmd <= slash) { *slash++ = 0; cmd_path = cmd; cmd = slash; @@ -426,6 +473,7 @@ int main(int argc, const char **argv) /* The user didn't specify a command; give them help */ printf("usage: %s\n\n", git_usage_string); list_common_cmds_help(); + printf("\n%s\n", git_more_info_string); exit(1); } cmd = argv[0]; @@ -443,7 +491,7 @@ int main(int argc, const char **argv) handle_internal_command(argc, argv); /* .. then try the external ones */ - execv_git_cmd(argv); + execv_dashed_external(argv); /* It could be an alias -- this works around the insanity * of overriding "git log" with "git show" by having