summaryrefslogtreecommitdiff
path: root/git.c
diff options
context:
space:
mode:
Diffstat (limited to 'git.c')
-rw-r--r--git.c177
1 files changed, 107 insertions, 70 deletions
diff --git a/git.c b/git.c
index c67e44dd82..46b3c740c5 100644
--- a/git.c
+++ b/git.c
@@ -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;
}