diff options
Diffstat (limited to 'git.c')
-rw-r--r-- | git.c | 177 |
1 files changed, 107 insertions, 70 deletions
@@ -1,9 +1,12 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "builtin.h" #include "config.h" #include "environment.h" #include "exec-cmd.h" #include "gettext.h" #include "help.h" +#include "object-file.h" #include "pager.h" #include "read-cache-ll.h" #include "run-command.h" @@ -28,16 +31,17 @@ struct cmd_struct { const char *cmd; - int (*fn)(int, const char **, const char *); + int (*fn)(int, const char **, const char *, struct repository *); unsigned int option; }; const char git_usage_string[] = N_("git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" - " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n" - " [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" - " [--config-env=<name>=<envvar>] <command> [<args>]"); + " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-lazy-fetch]\n" + " [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" + " [--work-tree=<path>] [--namespace=<name>] [--config-env=<name>=<envvar>]\n" + " <command> [<args>]"); const char git_more_info_string[] = N_("'git help -a' and 'git help -g' list available subcommands and some\n" @@ -139,6 +143,13 @@ void setup_auto_pager(const char *cmd, int def) commit_pager_choice(); } +static void print_system_path(const char *path) +{ + char *s_path = system_path(path); + puts(s_path); + free(s_path); +} + static int handle_options(const char ***argv, int *argc, int *envchanged) { const char **orig_argv = *argv; @@ -169,15 +180,15 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) exit(0); } } else if (!strcmp(cmd, "--html-path")) { - puts(system_path(GIT_HTML_PATH)); + print_system_path(GIT_HTML_PATH); trace2_cmd_name("_query_"); exit(0); } else if (!strcmp(cmd, "--man-path")) { - puts(system_path(GIT_MAN_PATH)); + print_system_path(GIT_MAN_PATH); trace2_cmd_name("_query_"); exit(0); } else if (!strcmp(cmd, "--info-path")) { - puts(system_path(GIT_INFO_PATH)); + print_system_path(GIT_INFO_PATH); trace2_cmd_name("_query_"); exit(0); } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) { @@ -186,6 +197,11 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) use_pager = 0; if (envchanged) *envchanged = 1; + } else if (!strcmp(cmd, "--no-lazy-fetch")) { + fetch_if_missing = 0; + setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1); + if (envchanged) + *envchanged = 1; } else if (!strcmp(cmd, "--no-replace-objects")) { disable_replace_refs(); setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1); @@ -331,6 +347,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) setenv(GIT_ATTR_SOURCE_ENVIRONMENT, cmd, 1); if (envchanged) *envchanged = 1; + } else if (!strcmp(cmd, "--no-advice")) { + setenv(GIT_ADVICE_ENVIRONMENT, "0", 1); + if (envchanged) + *envchanged = 1; } else { fprintf(stderr, _("unknown option: %s\n"), cmd); usage(git_usage_string); @@ -342,7 +362,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) return (*argv) - orig_argv; } -static int handle_alias(int *argcp, const char ***argv) +static int handle_alias(struct strvec *args) { int envchanged = 0, ret = 0, saved_errno = errno; int count, option_count; @@ -350,10 +370,10 @@ static int handle_alias(int *argcp, const char ***argv) const char *alias_command; char *alias_string; - alias_command = (*argv)[0]; + alias_command = args->v[0]; alias_string = alias_lookup(alias_command); if (alias_string) { - if (*argcp > 1 && !strcmp((*argv)[1], "-h")) + if (args->nr > 1 && !strcmp(args->v[1], "-h")) fprintf_ln(stderr, _("'%s' is aliased to '%s'"), alias_command, alias_string); if (alias_string[0] == '!') { @@ -370,11 +390,9 @@ static int handle_alias(int *argcp, const char ***argv) child.wait_after_clean = 1; child.trace2_child_class = "shell_alias"; strvec_push(&child.args, alias_string + 1); - strvec_pushv(&child.args, (*argv) + 1); + strvec_pushv(&child.args, args->v + 1); trace2_cmd_alias(alias_command, child.args.v); - trace2_cmd_list_config(); - trace2_cmd_list_env_vars(); trace2_cmd_name("_run_shell_alias_"); ret = run_command(&child); @@ -405,17 +423,13 @@ static int handle_alias(int *argcp, const char ***argv) trace_argv_printf(new_argv, "trace: alias expansion: %s =>", alias_command); - - REALLOC_ARRAY(new_argv, count + *argcp); - /* insert after command name */ - COPY_ARRAY(new_argv + count, *argv + 1, *argcp); - trace2_cmd_alias(alias_command, new_argv); - trace2_cmd_list_config(); - trace2_cmd_list_env_vars(); - *argv = new_argv; - *argcp += count - 1; + /* Replace the alias with the new arguments. */ + strvec_splice(args, 0, 1, new_argv, count); + + free(alias_string); + free(new_argv); ret = 1; } @@ -425,9 +439,10 @@ static int handle_alias(int *argcp, const char ***argv) return ret; } -static int run_builtin(struct cmd_struct *p, int argc, const char **argv) +static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct repository *repo) { int status, help; + int no_repo = 1; struct stat st; const char *prefix; int run_setup = (p->option & (RUN_SETUP | RUN_SETUP_GENTLY)); @@ -439,9 +454,9 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) if (run_setup & RUN_SETUP) { prefix = setup_git_directory(); + no_repo = 0; } else if (run_setup & RUN_SETUP_GENTLY) { - int nongit_ok; - prefix = setup_git_directory_gently(&nongit_ok); + prefix = setup_git_directory_gently(&no_repo); } else { prefix = NULL; } @@ -462,12 +477,10 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) trace_argv_printf(argv, "trace: built-in: git"); trace2_cmd_name(p->cmd); - trace2_cmd_list_config(); - trace2_cmd_list_env_vars(); - validate_cache_entries(the_repository->index); - status = p->fn(argc, argv, prefix); - validate_cache_entries(the_repository->index); + validate_cache_entries(repo->index); + status = p->fn(argc, argv, prefix, no_repo ? NULL : repo); + validate_cache_entries(repo->index); if (status) return status; @@ -589,11 +602,13 @@ static struct cmd_struct commands[] = { { "rebase", cmd_rebase, RUN_SETUP | NEED_WORK_TREE }, { "receive-pack", cmd_receive_pack }, { "reflog", cmd_reflog, RUN_SETUP }, + { "refs", cmd_refs, RUN_SETUP }, { "remote", cmd_remote, RUN_SETUP }, { "remote-ext", cmd_remote_ext, NO_PARSEOPT }, { "remote-fd", cmd_remote_fd, NO_PARSEOPT }, { "repack", cmd_repack, RUN_SETUP }, { "replace", cmd_replace, RUN_SETUP }, + { "replay", cmd_replay, RUN_SETUP }, { "rerere", cmd_rerere, RUN_SETUP }, { "reset", cmd_reset, RUN_SETUP }, { "restore", cmd_restore, RUN_SETUP | NEED_WORK_TREE }, @@ -681,47 +696,57 @@ void load_builtin_commands(const char *prefix, struct cmdnames *cmds) } #ifdef STRIP_EXTENSION -static void strip_extension(const char **argv) +static void strip_extension(struct strvec *args) { size_t len; - if (strip_suffix(argv[0], STRIP_EXTENSION, &len)) - argv[0] = xmemdupz(argv[0], len); + if (strip_suffix(args->v[0], STRIP_EXTENSION, &len)) { + char *stripped = xmemdupz(args->v[0], len); + strvec_replace(args, 0, stripped); + free(stripped); + } } #else #define strip_extension(cmd) #endif -static void handle_builtin(int argc, const char **argv) +static void handle_builtin(struct strvec *args) { - struct strvec args = STRVEC_INIT; const char *cmd; struct cmd_struct *builtin; - strip_extension(argv); - cmd = argv[0]; + strip_extension(args); + cmd = args->v[0]; /* Turn "git cmd --help" into "git help --exclude-guides cmd" */ - if (argc > 1 && !strcmp(argv[1], "--help")) { - int i; + if (args->nr > 1 && !strcmp(args->v[1], "--help")) { + const char *exclude_guides_arg[] = { "--exclude-guides" }; + + strvec_replace(args, 1, args->v[0]); + strvec_replace(args, 0, "help"); + cmd = "help"; + strvec_splice(args, 2, 0, exclude_guides_arg, + ARRAY_SIZE(exclude_guides_arg)); + } - argv[1] = argv[0]; - argv[0] = cmd = "help"; + builtin = get_builtin(cmd); + if (builtin) { + const char **argv_copy = NULL; + int ret; - for (i = 0; i < argc; i++) { - strvec_push(&args, argv[i]); - if (!i) - strvec_push(&args, "--exclude-guides"); - } + /* + * `run_builtin()` will modify the argv array, so we need to + * create a shallow copy such that we can free all of its + * strings. + */ + if (args->nr) + DUP_ARRAY(argv_copy, args->v, args->nr + 1); - argc++; - argv = args.v; + ret = run_builtin(builtin, args->nr, argv_copy, the_repository); + strvec_clear(args); + free(argv_copy); + exit(ret); } - - builtin = get_builtin(cmd); - if (builtin) - exit(run_builtin(builtin, argc, argv)); - strvec_clear(&args); } static void execv_dashed_external(const char **argv) @@ -767,10 +792,10 @@ static void execv_dashed_external(const char **argv) exit(128); } -static int run_argv(int *argcp, const char ***argv) +static int run_argv(struct strvec *args) { int done_alias = 0; - struct string_list cmd_list = STRING_LIST_INIT_NODUP; + struct string_list cmd_list = STRING_LIST_INIT_DUP; struct string_list_item *seen; while (1) { @@ -784,8 +809,8 @@ static int run_argv(int *argcp, const char ***argv) * process. */ if (!done_alias) - handle_builtin(*argcp, *argv); - else if (get_builtin(**argv)) { + handle_builtin(args); + else if (get_builtin(args->v[0])) { struct child_process cmd = CHILD_PROCESS_INIT; int i; @@ -801,8 +826,8 @@ static int run_argv(int *argcp, const char ***argv) commit_pager_choice(); strvec_push(&cmd.args, "git"); - for (i = 0; i < *argcp; i++) - strvec_push(&cmd.args, (*argv)[i]); + for (i = 0; i < args->nr; i++) + strvec_push(&cmd.args, args->v[i]); trace_argv_printf(cmd.args.v, "trace: exec:"); @@ -817,13 +842,13 @@ static int run_argv(int *argcp, const char ***argv) i = run_command(&cmd); if (i >= 0 || errno != ENOENT) exit(i); - die("could not execute builtin %s", **argv); + die("could not execute builtin %s", args->v[0]); } /* .. then try the external ones */ - execv_dashed_external(*argv); + execv_dashed_external(args->v); - seen = unsorted_string_list_lookup(&cmd_list, *argv[0]); + seen = unsorted_string_list_lookup(&cmd_list, args->v[0]); if (seen) { int i; struct strbuf sb = STRBUF_INIT; @@ -840,14 +865,14 @@ static int run_argv(int *argcp, const char ***argv) " not terminate:%s"), cmd_list.items[0].string, sb.buf); } - string_list_append(&cmd_list, *argv[0]); + string_list_append(&cmd_list, args->v[0]); /* * It could be an alias -- this works around the insanity * of overriding "git log" with "git show" by having * alias.log = show */ - if (!handle_alias(argcp, argv)) + if (!handle_alias(args)) break; done_alias = 1; } @@ -859,6 +884,7 @@ static int run_argv(int *argcp, const char ***argv) int cmd_main(int argc, const char **argv) { + struct strvec args = STRVEC_INIT; const char *cmd; int done_help = 0; @@ -884,8 +910,10 @@ int cmd_main(int argc, const char **argv) * that one cannot handle it. */ if (skip_prefix(cmd, "git-", &cmd)) { - argv[0] = cmd; - handle_builtin(argc, argv); + strvec_push(&args, cmd); + strvec_pushv(&args, argv + 1); + handle_builtin(&args); + strvec_clear(&args); die(_("cannot handle %s as a builtin"), cmd); } @@ -918,25 +946,34 @@ int cmd_main(int argc, const char **argv) */ setup_path(); + for (size_t i = 0; i < argc; i++) + strvec_push(&args, argv[i]); + while (1) { - int was_alias = run_argv(&argc, &argv); + int was_alias = run_argv(&args); if (errno != ENOENT) break; if (was_alias) { fprintf(stderr, _("expansion of alias '%s' failed; " "'%s' is not a git command\n"), - cmd, argv[0]); + cmd, args.v[0]); + strvec_clear(&args); exit(1); } if (!done_help) { - cmd = argv[0] = help_unknown_cmd(cmd); + char *assumed = help_unknown_cmd(cmd); + strvec_replace(&args, 0, assumed); + free(assumed); + cmd = args.v[0]; done_help = 1; - } else + } else { break; + } } fprintf(stderr, _("failed to run command '%s': %s\n"), cmd, strerror(errno)); + strvec_clear(&args); return 1; } |