aboutsummaryrefslogtreecommitdiffstats
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/add.c4
-rw-r--r--builtin/am.c22
-rw-r--r--builtin/bisect.c (renamed from builtin/bisect--helper.c)174
-rw-r--r--builtin/branch.c6
-rw-r--r--builtin/bugreport.c9
-rw-r--r--builtin/bundle.c9
-rw-r--r--builtin/cat-file.c28
-rw-r--r--builtin/check-attr.c35
-rw-r--r--builtin/checkout.c6
-rw-r--r--builtin/clone.c21
-rw-r--r--builtin/commit.c13
-rw-r--r--builtin/config.c42
-rw-r--r--builtin/diff.c2
-rw-r--r--builtin/difftool.c4
-rw-r--r--builtin/env--helper.c100
-rw-r--r--builtin/fast-export.c2
-rw-r--r--builtin/fetch.c1
-rw-r--r--builtin/fsmonitor--daemon.c6
-rw-r--r--builtin/hash-object.c1
-rw-r--r--builtin/log.c14
-rw-r--r--builtin/ls-files.c1
-rw-r--r--builtin/ls-tree.c268
-rw-r--r--builtin/merge-tree.c67
-rw-r--r--builtin/merge.c5
-rw-r--r--builtin/pack-objects.c29
-rw-r--r--builtin/range-diff.c2
-rw-r--r--builtin/read-tree.c1
-rw-r--r--builtin/rebase.c126
-rw-r--r--builtin/remote-ext.c6
-rw-r--r--builtin/remote-fd.c2
-rw-r--r--builtin/repack.c2
-rw-r--r--builtin/rerere.c2
-rw-r--r--builtin/reset.c5
-rw-r--r--builtin/rev-parse.c1
-rw-r--r--builtin/revert.c4
-rw-r--r--builtin/rm.c2
-rw-r--r--builtin/sparse-checkout.c1
-rw-r--r--builtin/stash.c18
-rw-r--r--builtin/submodule--helper.c94
-rw-r--r--builtin/unpack-file.c1
-rw-r--r--builtin/var.c33
-rw-r--r--builtin/worktree.c9
42 files changed, 644 insertions, 534 deletions
diff --git a/builtin/add.c b/builtin/add.c
index 76277df326..0c60402267 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -88,7 +88,7 @@ static int fix_unmerged_status(struct diff_filepair *p,
}
static void update_callback(struct diff_queue_struct *q,
- struct diff_options *opt, void *cbdata)
+ struct diff_options *opt UNUSED, void *cbdata)
{
int i;
struct update_callback_data *data = cbdata;
@@ -695,6 +695,6 @@ finish:
die(_("Unable to write new index file"));
dir_clear(&dir);
- UNLEAK(pathspec);
+ clear_pathspec(&pathspec);
return exit_status;
}
diff --git a/builtin/am.c b/builtin/am.c
index 30c9b3a9cd..82a41cbfc4 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -117,6 +117,7 @@ struct am_state {
/* various operating modes and command line options */
int interactive;
+ int no_verify;
int threeway;
int quiet;
int signoff; /* enum signoff_type */
@@ -472,10 +473,12 @@ static void am_destroy(const struct am_state *state)
*/
static int run_applypatch_msg_hook(struct am_state *state)
{
- int ret;
+ int ret = 0;
assert(state->msg);
- ret = run_hooks_l("applypatch-msg", am_path(state, "final-commit"), NULL);
+
+ if (!state->no_verify)
+ ret = run_hooks_l("applypatch-msg", am_path(state, "final-commit"), NULL);
if (!ret) {
FREE_AND_NULL(state->msg);
@@ -1476,6 +1479,7 @@ static int run_apply(const struct am_state *state, const char *index_file)
int res, opts_left;
int force_apply = 0;
int options = 0;
+ const char **apply_argv;
if (init_apply_state(&apply_state, the_repository, NULL))
BUG("init_apply_state() failed");
@@ -1483,7 +1487,14 @@ static int run_apply(const struct am_state *state, const char *index_file)
strvec_push(&apply_opts, "apply");
strvec_pushv(&apply_opts, state->git_apply_opts.v);
- opts_left = apply_parse_options(apply_opts.nr, apply_opts.v,
+ /*
+ * Build a copy that apply_parse_options() can rearrange.
+ * apply_opts.v keeps referencing the allocated strings for
+ * strvec_clear() to release.
+ */
+ DUP_ARRAY(apply_argv, apply_opts.v, apply_opts.nr);
+
+ opts_left = apply_parse_options(apply_opts.nr, apply_argv,
&apply_state, &force_apply, &options,
NULL);
@@ -1513,6 +1524,7 @@ static int run_apply(const struct am_state *state, const char *index_file)
strvec_clear(&apply_paths);
strvec_clear(&apply_opts);
clear_apply_state(&apply_state);
+ free(apply_argv);
if (res)
return res;
@@ -1640,7 +1652,7 @@ static void do_commit(const struct am_state *state)
const char *reflog_msg, *author, *committer = NULL;
struct strbuf sb = STRBUF_INIT;
- if (run_hooks("pre-applypatch"))
+ if (!state->no_verify && run_hooks("pre-applypatch"))
exit(1);
if (write_cache_as_tree(&tree, 0, NULL))
@@ -2330,6 +2342,8 @@ int cmd_am(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_BOOL('i', "interactive", &state.interactive,
N_("run interactively")),
+ OPT_BOOL('n', "no-verify", &state.no_verify,
+ N_("bypass pre-applypatch and applypatch-msg hooks")),
OPT_HIDDEN_BOOL('b', "binary", &binary,
N_("historical option -- no-op")),
OPT_BOOL('3', "3way", &state.threeway,
diff --git a/builtin/bisect--helper.c b/builtin/bisect.c
index 6e41cbdb2d..7301740267 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect.c
@@ -15,23 +15,44 @@ static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK")
static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
-static GIT_PATH_FUNC(git_path_head_name, "head-name")
static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
-static const char * const git_bisect_helper_usage[] = {
- N_("git bisect--helper --bisect-reset [<commit>]"),
- "git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]",
- N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
- " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
- "git bisect--helper --bisect-next",
- N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
- N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
- N_("git bisect--helper --bisect-replay <filename>"),
- N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
- "git bisect--helper --bisect-visualize",
- N_("git bisect--helper --bisect-run <cmd>..."),
+#define BUILTIN_GIT_BISECT_START_USAGE \
+ N_("git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]" \
+ " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--]" \
+ " [<pathspec>...]")
+#define BUILTIN_GIT_BISECT_STATE_USAGE \
+ N_("git bisect (good|bad) [<rev>...]")
+#define BUILTIN_GIT_BISECT_TERMS_USAGE \
+ "git bisect terms [--term-good | --term-bad]"
+#define BUILTIN_GIT_BISECT_SKIP_USAGE \
+ N_("git bisect skip [(<rev>|<range>)...]")
+#define BUILTIN_GIT_BISECT_NEXT_USAGE \
+ "git bisect next"
+#define BUILTIN_GIT_BISECT_RESET_USAGE \
+ N_("git bisect reset [<commit>]")
+#define BUILTIN_GIT_BISECT_VISUALIZE_USAGE \
+ "git bisect visualize"
+#define BUILTIN_GIT_BISECT_REPLAY_USAGE \
+ N_("git bisect replay <logfile>")
+#define BUILTIN_GIT_BISECT_LOG_USAGE \
+ "git bisect log"
+#define BUILTIN_GIT_BISECT_RUN_USAGE \
+ N_("git bisect run <cmd>...")
+
+static const char * const git_bisect_usage[] = {
+ BUILTIN_GIT_BISECT_START_USAGE,
+ BUILTIN_GIT_BISECT_STATE_USAGE,
+ BUILTIN_GIT_BISECT_TERMS_USAGE,
+ BUILTIN_GIT_BISECT_SKIP_USAGE,
+ BUILTIN_GIT_BISECT_NEXT_USAGE,
+ BUILTIN_GIT_BISECT_RESET_USAGE,
+ BUILTIN_GIT_BISECT_VISUALIZE_USAGE,
+ BUILTIN_GIT_BISECT_REPLAY_USAGE,
+ BUILTIN_GIT_BISECT_LOG_USAGE,
+ BUILTIN_GIT_BISECT_RUN_USAGE,
NULL
};
@@ -656,7 +677,8 @@ static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char
return bisect_next(terms, prefix);
}
-static enum bisect_error bisect_start(struct bisect_terms *terms, const char **argv, int argc)
+static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
+ const char **argv)
{
int no_checkout = 0;
int first_parent_only = 0;
@@ -785,13 +807,6 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, const char **a
strbuf_addstr(&start_head, oid_to_hex(&head_oid));
} else if (!get_oid(head, &head_oid) &&
skip_prefix(head, "refs/heads/", &head)) {
- /*
- * This error message should only be triggered by
- * cogito usage, and cogito users should understand
- * it relates to cg-seek.
- */
- if (!is_empty_or_missing_file(git_path_head_name()))
- return error(_("won't bisect on cg-seek'ed tree"));
strbuf_addstr(&start_head, head);
} else {
return error(_("bad HEAD - strange symbolic ref"));
@@ -886,13 +901,13 @@ static int bisect_autostart(struct bisect_terms *terms)
yesno = git_prompt(_("Do you want me to do it for you "
"[Y/n]? "), PROMPT_ECHO);
res = tolower(*yesno) == 'n' ?
- -1 : bisect_start(terms, empty_strvec, 0);
+ -1 : bisect_start(terms, 0, empty_strvec);
return res;
}
-static enum bisect_error bisect_state(struct bisect_terms *terms, const char **argv,
- int argc)
+static enum bisect_error bisect_state(struct bisect_terms *terms, int argc,
+ const char **argv)
{
const char *state;
int i, verify_expected = 1;
@@ -1011,7 +1026,7 @@ static int process_replay_line(struct bisect_terms *terms, struct strbuf *line)
struct strvec argv = STRVEC_INIT;
int res;
sq_dequote_to_strvec(rev, &argv);
- res = bisect_start(terms, argv.v, argv.nr);
+ res = bisect_start(terms, argv.nr, argv.v);
strvec_clear(&argv);
return res;
}
@@ -1061,7 +1076,8 @@ static enum bisect_error bisect_replay(struct bisect_terms *terms, const char *f
return bisect_auto_next(terms, NULL);
}
-static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **argv, int argc)
+static enum bisect_error bisect_skip(struct bisect_terms *terms, int argc,
+ const char **argv)
{
int i;
enum bisect_error res;
@@ -1091,13 +1107,14 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **ar
strvec_push(&argv_state, argv[i]);
}
}
- res = bisect_state(terms, argv_state.v, argv_state.nr);
+ res = bisect_state(terms, argv_state.nr, argv_state.v);
strvec_clear(&argv_state);
return res;
}
-static int bisect_visualize(struct bisect_terms *terms, const char **argv, int argc)
+static int bisect_visualize(struct bisect_terms *terms, int argc,
+ const char **argv)
{
struct child_process cmd = CHILD_PROCESS_INIT;
struct strbuf sb = STRBUF_INIT;
@@ -1180,7 +1197,7 @@ static int verify_good(const struct bisect_terms *terms, const char *command)
return rc;
}
-static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
+static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
{
int res = BISECT_OK;
struct strbuf command = STRBUF_INIT;
@@ -1191,13 +1208,13 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
if (bisect_next_check(terms, NULL))
return BISECT_FAILED;
- if (argc)
- sq_quote_argv(&command, argv);
- else {
+ if (!argc) {
error(_("bisect run failed: no command provided."));
return BISECT_FAILED;
}
+ sq_quote_argv(&command, argv);
+ strbuf_ltrim(&command);
while (1) {
res = do_bisect_run(command.buf);
@@ -1211,8 +1228,8 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
if (is_first_run && (res == 126 || res == 127)) {
int rc = verify_good(terms, command.buf);
is_first_run = 0;
- if (rc < 0) {
- error(_("unable to verify '%s' on good"
+ if (rc < 0 || 128 <= rc) {
+ error(_("unable to verify %s on good"
" revision"), command.buf);
res = BISECT_FAILED;
break;
@@ -1227,7 +1244,7 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
if (res < 0 || 128 <= res) {
error(_("bisect run failed: exit code %d from"
- " '%s' is < 0 or >= 128"), res, command.buf);
+ " %s is < 0 or >= 128"), res, command.buf);
break;
}
@@ -1249,7 +1266,7 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
saved_stdout = dup(1);
dup2(temporary_stdout_fd, 1);
- res = bisect_state(terms, &new_state, 1);
+ res = bisect_state(terms, 1, &new_state);
fflush(stdout);
dup2(saved_stdout, 1);
@@ -1261,14 +1278,14 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
if (res == BISECT_ONLY_SKIPPED_LEFT)
error(_("bisect run cannot continue any more"));
else if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) {
- printf(_("bisect run success"));
+ puts(_("bisect run success"));
res = BISECT_OK;
} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
- printf(_("bisect found first bad commit"));
+ puts(_("bisect found first bad commit"));
res = BISECT_OK;
} else if (res) {
- error(_("bisect run failed: 'git bisect--helper --bisect-state"
- " %s' exited with error code %d"), new_state, res);
+ error(_("bisect run failed: 'git bisect %s'"
+ " exited with error code %d"), new_state, res);
} else {
continue;
}
@@ -1282,7 +1299,8 @@ static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
static int cmd_bisect__reset(int argc, const char **argv, const char *prefix UNUSED)
{
if (argc > 1)
- return error(_("--bisect-reset requires either no argument or a commit"));
+ return error(_("'%s' requires either no argument or a commit"),
+ "git bisect reset");
return bisect_reset(argc ? argv[0] : NULL);
}
@@ -1292,7 +1310,8 @@ static int cmd_bisect__terms(int argc, const char **argv, const char *prefix UNU
struct bisect_terms terms = { 0 };
if (argc > 1)
- return error(_("--bisect-terms requires 0 or 1 argument"));
+ return error(_("'%s' requires 0 or 1 argument"),
+ "git bisect terms");
res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);
free_terms(&terms);
return res;
@@ -1304,7 +1323,7 @@ static int cmd_bisect__start(int argc, const char **argv, const char *prefix UNU
struct bisect_terms terms = { 0 };
set_terms(&terms, "bad", "good");
- res = bisect_start(&terms, argv, argc);
+ res = bisect_start(&terms, argc, argv);
free_terms(&terms);
return res;
}
@@ -1315,29 +1334,16 @@ static int cmd_bisect__next(int argc, const char **argv UNUSED, const char *pref
struct bisect_terms terms = { 0 };
if (argc)
- return error(_("--bisect-next requires 0 arguments"));
+ return error(_("'%s' requires 0 arguments"),
+ "git bisect next");
get_terms(&terms);
res = bisect_next(&terms, prefix);
free_terms(&terms);
return res;
}
-static int cmd_bisect__state(int argc, const char **argv, const char *prefix UNUSED)
-{
- int res;
- struct bisect_terms terms = { 0 };
-
- set_terms(&terms, "bad", "good");
- get_terms(&terms);
- res = bisect_state(&terms, argv, argc);
- free_terms(&terms);
- return res;
-}
-
-static int cmd_bisect__log(int argc, const char **argv UNUSED, const char *prefix UNUSED)
+static int cmd_bisect__log(int argc UNUSED, const char **argv UNUSED, const char *prefix UNUSED)
{
- if (argc)
- return error(_("--bisect-log requires 0 arguments"));
return bisect_log();
}
@@ -1361,7 +1367,7 @@ static int cmd_bisect__skip(int argc, const char **argv, const char *prefix UNUS
set_terms(&terms, "bad", "good");
get_terms(&terms);
- res = bisect_skip(&terms, argv, argc);
+ res = bisect_skip(&terms, argc, argv);
free_terms(&terms);
return res;
}
@@ -1372,7 +1378,7 @@ static int cmd_bisect__visualize(int argc, const char **argv, const char *prefix
struct bisect_terms terms = { 0 };
get_terms(&terms);
- res = bisect_visualize(&terms, argv, argc);
+ res = bisect_visualize(&terms, argc, argv);
free_terms(&terms);
return res;
}
@@ -1383,14 +1389,14 @@ static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSE
struct bisect_terms terms = { 0 };
if (!argc)
- return error(_("bisect run failed: no command provided."));
+ return error(_("'%s' failed: no command provided."), "git bisect run");
get_terms(&terms);
- res = bisect_run(&terms, argv, argc);
+ res = bisect_run(&terms, argc, argv);
free_terms(&terms);
return res;
}
-int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
+int cmd_bisect(int argc, const char **argv, const char *prefix)
{
int res = 0;
parse_opt_subcommand_fn *fn = NULL;
@@ -1399,7 +1405,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
OPT_SUBCOMMAND("terms", &fn, cmd_bisect__terms),
OPT_SUBCOMMAND("start", &fn, cmd_bisect__start),
OPT_SUBCOMMAND("next", &fn, cmd_bisect__next),
- OPT_SUBCOMMAND("state", &fn, cmd_bisect__state),
OPT_SUBCOMMAND("log", &fn, cmd_bisect__log),
OPT_SUBCOMMAND("replay", &fn, cmd_bisect__replay),
OPT_SUBCOMMAND("skip", &fn, cmd_bisect__skip),
@@ -1408,22 +1413,27 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
OPT_SUBCOMMAND("run", &fn, cmd_bisect__run),
OPT_END()
};
- argc = parse_options(argc, argv, prefix, options,
- git_bisect_helper_usage, 0);
-
- if (!fn)
- usage_with_options(git_bisect_helper_usage, options);
- argc--;
- argv++;
-
- res = fn(argc, argv, prefix);
-
- /*
- * Handle early success
- * From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all
- */
- if ((res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) || (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND))
- res = BISECT_OK;
+ argc = parse_options(argc, argv, prefix, options, git_bisect_usage,
+ PARSE_OPT_SUBCOMMAND_OPTIONAL);
+
+ if (!fn) {
+ struct bisect_terms terms = { 0 };
+
+ if (!argc)
+ usage_msg_opt(_("need a command"), git_bisect_usage, options);
+
+ set_terms(&terms, "bad", "good");
+ get_terms(&terms);
+ if (check_and_set_terms(&terms, argv[0]))
+ usage_msg_optf(_("unknown command: '%s'"), git_bisect_usage,
+ options, argv[0]);
+ res = bisect_state(&terms, argc, argv);
+ free_terms(&terms);
+ } else {
+ argc--;
+ argv++;
+ res = fn(argc, argv, prefix);
+ }
- return -res;
+ return is_bisect_success(res) ? 0 : -res;
}
diff --git a/builtin/branch.c b/builtin/branch.c
index 9470c980c1..f63fd45edb 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -581,13 +581,13 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
strbuf_release(&logmsg);
strbuf_addf(&oldsection, "branch.%s", interpreted_oldname);
- strbuf_release(&oldref);
strbuf_addf(&newsection, "branch.%s", interpreted_newname);
- strbuf_release(&newref);
if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
die(_("Branch is renamed, but update of config-file failed"));
- if (copy && strcmp(oldname, newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
+ if (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
die(_("Branch is copied, but update of config-file failed"));
+ strbuf_release(&oldref);
+ strbuf_release(&newref);
strbuf_release(&oldsection);
strbuf_release(&newsection);
}
diff --git a/builtin/bugreport.c b/builtin/bugreport.c
index 96052541cb..5bc254be80 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -106,6 +106,7 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
const char *user_relative_path = NULL;
char *prefixed_filename;
size_t output_path_len;
+ int ret;
const struct option bugreport_options[] = {
OPT_CALLBACK_F(0, "diagnose", &diagnose, N_("mode"),
@@ -182,7 +183,9 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
user_relative_path);
free(prefixed_filename);
- UNLEAK(buffer);
- UNLEAK(report_path);
- return !!launch_editor(report_path.buf, NULL, NULL);
+ strbuf_release(&buffer);
+
+ ret = !!launch_editor(report_path.buf, NULL, NULL);
+ strbuf_release(&report_path);
+ return ret;
}
diff --git a/builtin/bundle.c b/builtin/bundle.c
index c12c09f854..acceef6200 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -55,13 +55,12 @@ static int parse_options_cmd_bundle(int argc,
const char * const usagestr[],
const struct option options[],
char **bundle_file) {
- int newargc;
- newargc = parse_options(argc, argv, NULL, options, usagestr,
+ argc = parse_options(argc, argv, NULL, options, usagestr,
PARSE_OPT_STOP_AT_NON_OPTION);
- if (argc < 1)
- usage_with_options(usagestr, options);
+ if (!argc)
+ usage_msg_opt(_("need a <file> argument"), usagestr, options);
*bundle_file = prefix_filename(prefix, argv[0]);
- return newargc;
+ return argc;
}
static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index b3be58b1fb..cc17635e76 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -132,8 +132,21 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
case 's':
oi.sizep = &size;
+
+ if (use_mailmap) {
+ oi.typep = &type;
+ oi.contentp = (void**)&buf;
+ }
+
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
die("git cat-file: could not get object info");
+
+ if (use_mailmap && (type == OBJ_COMMIT || type == OBJ_TAG)) {
+ size_t s = size;
+ buf = replace_idents_using_mailmap(buf, &s);
+ size = cast_size_t_to_ulong(s);
+ }
+
printf("%"PRIuMAX"\n", (uintmax_t)size);
ret = 0;
goto cleanup;
@@ -431,6 +444,9 @@ static void batch_object_write(const char *obj_name,
if (!data->skip_object_info) {
int ret;
+ if (use_mailmap)
+ data->info.typep = &data->type;
+
if (pack)
ret = packed_object_info(the_repository, pack, offset,
&data->info);
@@ -444,6 +460,18 @@ static void batch_object_write(const char *obj_name,
fflush(stdout);
return;
}
+
+ if (use_mailmap && (data->type == OBJ_COMMIT || data->type == OBJ_TAG)) {
+ size_t s = data->size;
+ char *buf = NULL;
+
+ buf = repo_read_object_file(the_repository, &data->oid, &data->type,
+ &data->size);
+ buf = replace_idents_using_mailmap(buf, &s);
+ data->size = cast_size_t_to_ulong(s);
+
+ free(buf);
+ }
}
strbuf_reset(scratch);
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 0fef10eb6b..d7a40e674c 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -9,9 +9,10 @@
static int all_attrs;
static int cached_attrs;
static int stdin_paths;
+static char *source;
static const char * const check_attr_usage[] = {
-N_("git check-attr [-a | --all | <attr>...] [--] <pathname>..."),
-N_("git check-attr --stdin [-z] [-a | --all | <attr>...]"),
+N_("git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] <pathname>..."),
+N_("git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]"),
NULL
};
@@ -23,6 +24,7 @@ static const struct option check_attr_options[] = {
OPT_BOOL(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
OPT_BOOL('z', NULL, &nul_term_line,
N_("terminate input and output records by a NUL character")),
+ OPT_STRING(0, "source", &source, N_("<tree-ish>"), N_("which tree-ish to check attributes at")),
OPT_END()
};
@@ -55,27 +57,26 @@ static void output_attr(struct attr_check *check, const char *file)
}
}
-static void check_attr(const char *prefix,
- struct attr_check *check,
- int collect_all,
+static void check_attr(const char *prefix, struct attr_check *check,
+ const struct object_id *tree_oid, int collect_all,
const char *file)
+
{
char *full_path =
prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
if (collect_all) {
- git_all_attrs(&the_index, full_path, check);
+ git_all_attrs(&the_index, tree_oid, full_path, check);
} else {
- git_check_attr(&the_index, full_path, check);
+ git_check_attr(&the_index, tree_oid, full_path, check);
}
output_attr(check, file);
free(full_path);
}
-static void check_attr_stdin_paths(const char *prefix,
- struct attr_check *check,
- int collect_all)
+static void check_attr_stdin_paths(const char *prefix, struct attr_check *check,
+ const struct object_id *tree_oid, int collect_all)
{
struct strbuf buf = STRBUF_INIT;
struct strbuf unquoted = STRBUF_INIT;
@@ -89,7 +90,7 @@ static void check_attr_stdin_paths(const char *prefix,
die("line is badly quoted");
strbuf_swap(&buf, &unquoted);
}
- check_attr(prefix, check, collect_all, buf.buf);
+ check_attr(prefix, check, tree_oid, collect_all, buf.buf);
maybe_flush_or_die(stdout, "attribute to stdout");
}
strbuf_release(&buf);
@@ -105,6 +106,8 @@ static NORETURN void error_with_usage(const char *msg)
int cmd_check_attr(int argc, const char **argv, const char *prefix)
{
struct attr_check *check;
+ struct object_id *tree_oid = NULL;
+ struct object_id initialized_oid;
int cnt, i, doubledash, filei;
if (!is_bare_repository())
@@ -176,11 +179,17 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
}
}
+ if (source) {
+ if (repo_get_oid_tree(the_repository, source, &initialized_oid))
+ die("%s: not a valid tree-ish source", source);
+ tree_oid = &initialized_oid;
+ }
+
if (stdin_paths)
- check_attr_stdin_paths(prefix, check, all_attrs);
+ check_attr_stdin_paths(prefix, check, tree_oid, all_attrs);
else {
for (i = filei; i < argc; i++)
- check_attr(prefix, check, all_attrs, argv[i]);
+ check_attr(prefix, check, tree_oid, all_attrs, argv[i]);
maybe_flush_or_die(stdout, "attribute to stdout");
}
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 3fa29a08ee..5963e1b74b 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -232,7 +232,7 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
pos++;
}
if (!overlay_mode) {
- unlink_entry(ce);
+ unlink_entry(ce, NULL);
return 0;
}
if (stage == 2)
@@ -1270,7 +1270,7 @@ static int parse_branchname_arg(int argc, const char **argv,
* between A and B, A...B names that merge base.
*
* (b) If <something> is _not_ a commit, either "--" is present
- * or <something> is not a path, no -t or -b was given, and
+ * or <something> is not a path, no -t or -b was given,
* and there is a tracking branch whose name is <something>
* in one and only one remote (or if the branch exists on the
* remote named in checkout.defaultRemote), then this is a
@@ -1471,6 +1471,8 @@ static void die_if_some_operation_in_progress(void)
"or \"git worktree add\"."));
if (state.bisect_in_progress)
warning(_("you are switching branch while bisecting"));
+
+ wt_status_state_free_buffers(&state);
}
static int checkout_branch(struct checkout_opts *opts,
diff --git a/builtin/clone.c b/builtin/clone.c
index f518bb2dc1..5453ba5277 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1271,6 +1271,27 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (refs)
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
+ if (!bundle_uri) {
+ /*
+ * Populate transport->got_remote_bundle_uri and
+ * transport->bundle_uri. We might get nothing.
+ */
+ transport_get_remote_bundle_uri(transport);
+
+ if (transport->bundles &&
+ hashmap_get_size(&transport->bundles->bundles)) {
+ /* At this point, we need the_repository to match the cloned repo. */
+ if (repo_init(the_repository, git_dir, work_tree))
+ warning(_("failed to initialize the repo, skipping bundle URI"));
+ else if (fetch_bundle_list(the_repository,
+ transport->bundles))
+ warning(_("failed to fetch advertised bundles"));
+ } else {
+ clear_bundle_list(transport->bundles);
+ FREE_AND_NULL(transport->bundles);
+ }
+ }
+
if (mapped_refs) {
int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
diff --git a/builtin/commit.c b/builtin/commit.c
index 06b1330346..44b763d7cd 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -991,8 +991,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
struct object_id oid;
const char *parent = "HEAD";
- if (!active_nr && read_cache() < 0)
- die(_("Cannot read index"));
+ if (!active_nr) {
+ discard_cache();
+ if (read_cache() < 0)
+ die(_("Cannot read index"));
+ }
if (amend)
parent = "HEAD^1";
@@ -1875,8 +1878,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
apply_autostash(git_path_merge_autostash(the_repository));
cleanup:
- UNLEAK(author_ident);
- UNLEAK(err);
- UNLEAK(sb);
+ strbuf_release(&author_ident);
+ strbuf_release(&err);
+ strbuf_release(&sb);
return ret;
}
diff --git a/builtin/config.c b/builtin/config.c
index 753e5fac29..060cf9f3e0 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -639,8 +639,9 @@ static char *default_user_config(void)
int cmd_config(int argc, const char **argv, const char *prefix)
{
int nongit = !startup_info->have_repository;
- char *value;
+ char *value = NULL;
int flags = 0;
+ int ret = 0;
given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
@@ -856,44 +857,38 @@ int cmd_config(int argc, const char **argv, const char *prefix)
free(config_file);
}
else if (actions == ACTION_SET) {
- int ret;
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
- UNLEAK(value);
ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
if (ret == CONFIG_NOTHING_SET)
error(_("cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."), argv[0]);
- return ret;
}
else if (actions == ACTION_SET_ALL) {
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
- UNLEAK(value);
- return git_config_set_multivar_in_file_gently(given_config_source.file,
- argv[0], value, argv[2],
- flags);
+ ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+ argv[0], value, argv[2],
+ flags);
}
else if (actions == ACTION_ADD) {
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
- UNLEAK(value);
- return git_config_set_multivar_in_file_gently(given_config_source.file,
- argv[0], value,
- CONFIG_REGEX_NONE,
- flags);
+ ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+ argv[0], value,
+ CONFIG_REGEX_NONE,
+ flags);
}
else if (actions == ACTION_REPLACE_ALL) {
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1]);
- UNLEAK(value);
- return git_config_set_multivar_in_file_gently(given_config_source.file,
- argv[0], value, argv[2],
- flags | CONFIG_FLAGS_MULTI_REPLACE);
+ ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+ argv[0], value, argv[2],
+ flags | CONFIG_FLAGS_MULTI_REPLACE);
}
else if (actions == ACTION_GET) {
check_argc(argc, 1, 2);
@@ -934,26 +929,28 @@ int cmd_config(int argc, const char **argv, const char *prefix)
flags | CONFIG_FLAGS_MULTI_REPLACE);
}
else if (actions == ACTION_RENAME_SECTION) {
- int ret;
check_write();
check_argc(argc, 2, 2);
ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], argv[1]);
if (ret < 0)
return ret;
- if (ret == 0)
+ else if (!ret)
die(_("no such section: %s"), argv[0]);
+ else
+ ret = 0;
}
else if (actions == ACTION_REMOVE_SECTION) {
- int ret;
check_write();
check_argc(argc, 1, 1);
ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], NULL);
if (ret < 0)
return ret;
- if (ret == 0)
+ else if (!ret)
die(_("no such section: %s"), argv[0]);
+ else
+ ret = 0;
}
else if (actions == ACTION_GET_COLOR) {
check_argc(argc, 1, 2);
@@ -966,5 +963,6 @@ int cmd_config(int argc, const char **argv, const char *prefix)
return get_colorbool(argv[0], argc == 2);
}
- return 0;
+ free(value);
+ return ret;
}
diff --git a/builtin/diff.c b/builtin/diff.c
index 163f2c6a87..26f1e532c6 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -612,7 +612,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
if (1 < rev.diffopt.skip_stat_unmatch)
refresh_index_quietly();
release_revisions(&rev);
- UNLEAK(ent);
+ object_array_clear(&ent);
UNLEAK(blob);
return result;
}
diff --git a/builtin/difftool.c b/builtin/difftool.c
index d9b76226f6..dbbfb19f19 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -361,7 +361,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct hashmap symlinks2 = HASHMAP_INIT(pair_cmp, NULL);
struct hashmap_iter iter;
struct pair_entry *entry;
- struct index_state wtindex;
+ struct index_state wtindex = INDEX_STATE_INIT(the_repository);
struct checkout lstate, rstate;
int err = 0;
struct child_process cmd = CHILD_PROCESS_INIT;
@@ -387,8 +387,6 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
mkdir(ldir.buf, 0700);
mkdir(rdir.buf, 0700);
- memset(&wtindex, 0, sizeof(wtindex));
-
memset(&lstate, 0, sizeof(lstate));
lstate.base_dir = lbase_dir = xstrdup(ldir.buf);
lstate.base_dir_len = ldir.len;
diff --git a/builtin/env--helper.c b/builtin/env--helper.c
deleted file mode 100644
index ea04c16636..0000000000
--- a/builtin/env--helper.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "parse-options.h"
-
-static char const * const env__helper_usage[] = {
- N_("git env--helper --type=[bool|ulong] <options> <env-var>"),
- NULL
-};
-
-enum cmdmode {
- ENV_HELPER_TYPE_BOOL = 1,
- ENV_HELPER_TYPE_ULONG
-};
-
-static int option_parse_type(const struct option *opt, const char *arg,
- int unset)
-{
- enum cmdmode *cmdmode = opt->value;
-
- BUG_ON_OPT_NEG(unset);
-
- if (!strcmp(arg, "bool"))
- *cmdmode = ENV_HELPER_TYPE_BOOL;
- else if (!strcmp(arg, "ulong"))
- *cmdmode = ENV_HELPER_TYPE_ULONG;
- else
- die(_("unrecognized --type argument, %s"), arg);
-
- return 0;
-}
-
-int cmd_env__helper(int argc, const char **argv, const char *prefix)
-{
- int exit_code = 0;
- const char *env_variable = NULL;
- const char *env_default = NULL;
- int ret;
- int ret_int, default_int;
- unsigned long ret_ulong, default_ulong;
- enum cmdmode cmdmode = 0;
- struct option opts[] = {
- OPT_CALLBACK_F(0, "type", &cmdmode, N_("type"),
- N_("value is given this type"), PARSE_OPT_NONEG,
- option_parse_type),
- OPT_STRING(0, "default", &env_default, N_("value"),
- N_("default for git_env_*(...) to fall back on")),
- OPT_BOOL(0, "exit-code", &exit_code,
- N_("be quiet only use git_env_*() value as exit code")),
- OPT_END(),
- };
-
- argc = parse_options(argc, argv, prefix, opts, env__helper_usage,
- PARSE_OPT_KEEP_UNKNOWN_OPT);
- if (env_default && !*env_default)
- usage_with_options(env__helper_usage, opts);
- if (!cmdmode)
- usage_with_options(env__helper_usage, opts);
- if (argc != 1)
- usage_with_options(env__helper_usage, opts);
- env_variable = argv[0];
-
- switch (cmdmode) {
- case ENV_HELPER_TYPE_BOOL:
- if (env_default) {
- default_int = git_parse_maybe_bool(env_default);
- if (default_int == -1) {
- error(_("option `--default' expects a boolean value with `--type=bool`, not `%s`"),
- env_default);
- usage_with_options(env__helper_usage, opts);
- }
- } else {
- default_int = 0;
- }
- ret_int = git_env_bool(env_variable, default_int);
- if (!exit_code)
- puts(ret_int ? "true" : "false");
- ret = ret_int;
- break;
- case ENV_HELPER_TYPE_ULONG:
- if (env_default) {
- if (!git_parse_ulong(env_default, &default_ulong)) {
- error(_("option `--default' expects an unsigned long value with `--type=ulong`, not `%s`"),
- env_default);
- usage_with_options(env__helper_usage, opts);
- }
- } else {
- default_ulong = 0;
- }
- ret_ulong = git_env_ulong(env_variable, default_ulong);
- if (!exit_code)
- printf("%lu\n", ret_ulong);
- ret = ret_ulong;
- break;
- default:
- BUG("unknown <type> value");
- break;
- }
-
- return !ret;
-}
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 3b3314e7b2..39a890fc00 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -409,7 +409,7 @@ static const char *anonymize_oid(const char *oid_hex)
}
static void show_filemodify(struct diff_queue_struct *q,
- struct diff_options *options, void *data)
+ struct diff_options *options UNUSED, void *data)
{
int i;
struct string_list *changed = data;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 7378cafeec..12978622d5 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -2228,6 +2228,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
argv++;
}
}
+ string_list_remove_duplicates(&list, 0);
if (negotiate_only) {
struct oidset acked_commits = OIDSET_INIT;
diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
index 6f30a4f93a..0feef8caf6 100644
--- a/builtin/fsmonitor--daemon.c
+++ b/builtin/fsmonitor--daemon.c
@@ -710,6 +710,7 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
"fsmonitor: unsupported V1 protocol '%s'"),
command);
do_trivial = 1;
+ do_cookie = 1;
} else {
/* We have "builtin:*" */
@@ -719,6 +720,7 @@ static int do_handle_client(struct fsmonitor_daemon_state *state,
"fsmonitor: invalid V2 protocol token '%s'",
command);
do_trivial = 1;
+ do_cookie = 1;
} else {
/*
@@ -1209,7 +1211,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
* events.
*/
if (pthread_create(&state->listener_thread, NULL,
- fsm_listen__thread_proc, state) < 0) {
+ fsm_listen__thread_proc, state)) {
ipc_server_stop_async(state->ipc_server_data);
err = error(_("could not start fsmonitor listener thread"));
goto cleanup;
@@ -1220,7 +1222,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
* Start the health thread to watch over our process.
*/
if (pthread_create(&state->health_thread, NULL,
- fsm_health__thread_proc, state) < 0) {
+ fsm_health__thread_proc, state)) {
ipc_server_stop_async(state->ipc_server_data);
err = error(_("could not start fsmonitor health thread"));
goto cleanup;
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index b506381502..44db83f07f 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -27,6 +27,7 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig
else
ret = write_object_file_literally(buf.buf, buf.len, type, oid,
flags);
+ close(fd);
strbuf_release(&buf);
return ret;
}
diff --git a/builtin/log.c b/builtin/log.c
index 89447a5083..04412dd9c9 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -52,6 +52,7 @@ static int decoration_style;
static int decoration_given;
static int use_mailmap_config = 1;
static unsigned int force_in_body_from;
+static int stdout_mboxrd;
static const char *fmt_patch_subject_prefix = "PATCH";
static int fmt_patch_name_max = FORMAT_PATCH_NAME_MAX_DEFAULT;
static const char *fmt_pretty;
@@ -1077,6 +1078,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
cover_from_description_mode = parse_cover_from_description(value);
return 0;
}
+ if (!strcmp(var, "format.mboxrd")) {
+ stdout_mboxrd = git_config_bool(var, value);
+ return 0;
+ }
return git_log_config(var, value, cb);
}
@@ -1870,6 +1875,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
struct strbuf rdiff1 = STRBUF_INIT;
struct strbuf rdiff2 = STRBUF_INIT;
struct strbuf rdiff_title = STRBUF_INIT;
+ struct strbuf sprefix = STRBUF_INIT;
int creation_factor = -1;
const struct option builtin_format_patch_options[] = {
@@ -2010,12 +2016,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
if (reroll_count) {
- struct strbuf sprefix = STRBUF_INIT;
-
strbuf_addf(&sprefix, "%s v%s",
rev.subject_prefix, reroll_count);
rev.reroll_count = reroll_count;
- rev.subject_prefix = strbuf_detach(&sprefix, NULL);
+ rev.subject_prefix = sprefix.buf;
}
for (i = 0; i < extra_hdr.nr; i++) {
@@ -2105,6 +2109,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.diffopt.close_file, "--output",
!!output_directory, "--output-directory");
+ if (use_stdout && stdout_mboxrd)
+ rev.commit_format = CMIT_FMT_MBOXRD;
+
if (use_stdout) {
setup_pager();
} else if (!rev.diffopt.close_file) {
@@ -2376,6 +2383,7 @@ done:
strbuf_release(&rdiff1);
strbuf_release(&rdiff2);
strbuf_release(&rdiff_title);
+ strbuf_release(&sprefix);
free(to_free);
if (rev.ref_message_ids)
string_list_clear(rev.ref_message_ids, 0);
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 4cf8a23648..a03b559eca 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -613,6 +613,7 @@ void overlay_tree_on_index(struct index_state *istate,
if (!fn)
fn = read_one_entry_quick;
err = read_tree(the_repository, tree, &pathspec, fn, istate);
+ clear_pathspec(&pathspec);
if (err)
die("unable to read tree entries %s", tree_name);
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index c3ea09281a..8cc8c995df 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -14,37 +14,11 @@
#include "parse-options.h"
#include "pathspec.h"
-static int line_termination = '\n';
-#define LS_RECURSIVE 1
-#define LS_TREE_ONLY (1 << 1)
-#define LS_SHOW_TREES (1 << 2)
-static int abbrev;
-static int ls_options;
-static struct pathspec pathspec;
-static int chomp_prefix;
-static const char *ls_tree_prefix;
-static const char *format;
-struct show_tree_data {
- unsigned mode;
- enum object_type type;
- const struct object_id *oid;
- const char *pathname;
- struct strbuf *base;
-};
-
-static const char * const ls_tree_usage[] = {
+static const char * const ls_tree_usage[] = {
N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
NULL
};
-static enum ls_tree_cmdmode {
- MODE_DEFAULT = 0,
- MODE_LONG,
- MODE_NAME_ONLY,
- MODE_NAME_STATUS,
- MODE_OBJECT_ONLY,
-} cmdmode;
-
static void expand_objectsize(struct strbuf *line, const struct object_id *oid,
const enum object_type type, unsigned int padded)
{
@@ -64,10 +38,34 @@ static void expand_objectsize(struct strbuf *line, const struct object_id *oid,
}
}
+struct ls_tree_options {
+ unsigned null_termination:1;
+ int abbrev;
+ enum ls_tree_path_options {
+ LS_RECURSIVE = 1 << 0,
+ LS_TREE_ONLY = 1 << 1,
+ LS_SHOW_TREES = 1 << 2,
+ } ls_options;
+ struct pathspec pathspec;
+ int chomp_prefix;
+ const char *ls_tree_prefix;
+ const char *format;
+};
+
+struct show_tree_data {
+ struct ls_tree_options *options;
+ unsigned mode;
+ enum object_type type;
+ const struct object_id *oid;
+ const char *pathname;
+ struct strbuf *base;
+};
+
static size_t expand_show_tree(struct strbuf *sb, const char *start,
void *context)
{
struct show_tree_data *data = context;
+ struct ls_tree_options *options = data->options;
const char *end;
const char *p;
unsigned int errlen;
@@ -92,18 +90,18 @@ static size_t expand_show_tree(struct strbuf *sb, const char *start,
} else if (skip_prefix(start, "(objectsize)", &p)) {
expand_objectsize(sb, data->oid, data->type, 0);
} else if (skip_prefix(start, "(objectname)", &p)) {
- strbuf_add_unique_abbrev(sb, data->oid, abbrev);
+ strbuf_add_unique_abbrev(sb, data->oid, options->abbrev);
} else if (skip_prefix(start, "(path)", &p)) {
const char *name = data->base->buf;
- const char *prefix = chomp_prefix ? ls_tree_prefix : NULL;
- struct strbuf quoted = STRBUF_INIT;
+ const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL;
struct strbuf sbuf = STRBUF_INIT;
+ size_t baselen = data->base->len;
+
strbuf_addstr(data->base, data->pathname);
name = relative_path(data->base->buf, prefix, &sbuf);
- quote_c_style(name, &quoted, NULL, 0);
- strbuf_addbuf(sb, &quoted);
+ quote_c_style(name, sb, NULL, 0);
+ strbuf_setlen(data->base, baselen);
strbuf_release(&sbuf);
- strbuf_release(&quoted);
} else {
errlen = (unsigned long)len;
die(_("bad ls-tree format: %%%.*s"), errlen, start);
@@ -111,18 +109,19 @@ static size_t expand_show_tree(struct strbuf *sb, const char *start,
return len;
}
-static int show_recursive(const char *base, size_t baselen, const char *pathname)
+static int show_recursive(struct ls_tree_options *options, const char *base,
+ size_t baselen, const char *pathname)
{
int i;
- if (ls_options & LS_RECURSIVE)
+ if (options->ls_options & LS_RECURSIVE)
return 1;
- if (!pathspec.nr)
+ if (!options->pathspec.nr)
return 0;
- for (i = 0; i < pathspec.nr; i++) {
- const char *spec = pathspec.items[i].match;
+ for (i = 0; i < options->pathspec.nr; i++) {
+ const char *spec = options->pathspec.items[i].match;
size_t len, speclen;
if (strncmp(base, spec, baselen))
@@ -142,14 +141,14 @@ static int show_recursive(const char *base, size_t baselen, const char *pathname
}
static int show_tree_fmt(const struct object_id *oid, struct strbuf *base,
- const char *pathname, unsigned mode, void *context UNUSED)
+ const char *pathname, unsigned mode, void *context)
{
- size_t baselen;
+ struct ls_tree_options *options = context;
int recurse = 0;
struct strbuf sb = STRBUF_INIT;
enum object_type type = object_type(mode);
-
- struct show_tree_data data = {
+ struct show_tree_data cb_data = {
+ .options = options,
.mode = mode,
.type = type,
.oid = oid,
@@ -157,94 +156,100 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base,
.base = base,
};
- if (type == OBJ_TREE && show_recursive(base->buf, base->len, pathname))
+ if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname))
recurse = READ_TREE_RECURSIVE;
- if (type == OBJ_TREE && recurse && !(ls_options & LS_SHOW_TREES))
+ if (type == OBJ_TREE && recurse && !(options->ls_options & LS_SHOW_TREES))
return recurse;
- if (type == OBJ_BLOB && (ls_options & LS_TREE_ONLY))
+ if (type == OBJ_BLOB && (options->ls_options & LS_TREE_ONLY))
return 0;
- baselen = base->len;
- strbuf_expand(&sb, format, expand_show_tree, &data);
- strbuf_addch(&sb, line_termination);
+ strbuf_expand(&sb, options->format, expand_show_tree, &cb_data);
+ strbuf_addch(&sb, options->null_termination ? '\0' : '\n');
fwrite(sb.buf, sb.len, 1, stdout);
strbuf_release(&sb);
- strbuf_setlen(base, baselen);
return recurse;
}
-static int show_tree_common(struct show_tree_data *data, int *recurse,
- const struct object_id *oid, struct strbuf *base,
- const char *pathname, unsigned mode)
+static int show_tree_common(struct ls_tree_options *options, int *recurse,
+ struct strbuf *base, const char *pathname,
+ enum object_type type)
{
- enum object_type type = object_type(mode);
int ret = -1;
-
*recurse = 0;
- data->mode = mode;
- data->type = type;
- data->oid = oid;
- data->pathname = pathname;
- data->base = base;
if (type == OBJ_BLOB) {
- if (ls_options & LS_TREE_ONLY)
+ if (options->ls_options & LS_TREE_ONLY)
ret = 0;
} else if (type == OBJ_TREE &&
- show_recursive(base->buf, base->len, pathname)) {
+ show_recursive(options, base->buf, base->len, pathname)) {
*recurse = READ_TREE_RECURSIVE;
- if (!(ls_options & LS_SHOW_TREES))
+ if (!(options->ls_options & LS_SHOW_TREES))
ret = *recurse;
}
return ret;
}
-static void show_tree_common_default_long(struct strbuf *base,
+static void show_tree_common_default_long(struct ls_tree_options *options,
+ struct strbuf *base,
const char *pathname,
const size_t baselen)
{
+ const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL;
+
strbuf_addstr(base, pathname);
- write_name_quoted_relative(base->buf,
- chomp_prefix ? ls_tree_prefix : NULL, stdout,
- line_termination);
+
+ if (options->null_termination) {
+ struct strbuf sb = STRBUF_INIT;
+ const char *name = relative_path(base->buf, prefix, &sb);
+
+ fputs(name, stdout);
+ fputc('\0', stdout);
+
+ strbuf_release(&sb);
+ } else {
+ write_name_quoted_relative(base->buf, prefix, stdout, '\n');
+ }
+
strbuf_setlen(base, baselen);
}
static int show_tree_default(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode,
- void *context UNUSED)
+ void *context)
{
+ struct ls_tree_options *options = context;
int early;
int recurse;
- struct show_tree_data data = { 0 };
+ enum object_type type = object_type(mode);
- early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
+ early = show_tree_common(options, &recurse, base, pathname, type);
if (early >= 0)
return early;
- printf("%06o %s %s\t", data.mode, type_name(data.type),
- find_unique_abbrev(data.oid, abbrev));
- show_tree_common_default_long(base, pathname, data.base->len);
+ printf("%06o %s %s\t", mode, type_name(object_type(mode)),
+ find_unique_abbrev(oid, options->abbrev));
+ show_tree_common_default_long(options, base, pathname, base->len);
return recurse;
}
static int show_tree_long(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode,
- void *context UNUSED)
+ void *context)
{
+ struct ls_tree_options *options = context;
int early;
int recurse;
- struct show_tree_data data = { 0 };
char size_text[24];
+ enum object_type type = object_type(mode);
- early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
+ early = show_tree_common(options, &recurse, base, pathname, type);
if (early >= 0)
return early;
- if (data.type == OBJ_BLOB) {
+ if (type == OBJ_BLOB) {
unsigned long size;
- if (oid_object_info(the_repository, data.oid, &size) == OBJ_BAD)
+ if (oid_object_info(the_repository, oid, &size) == OBJ_BAD)
xsnprintf(size_text, sizeof(size_text), "BAD");
else
xsnprintf(size_text, sizeof(size_text),
@@ -253,49 +258,76 @@ static int show_tree_long(const struct object_id *oid, struct strbuf *base,
xsnprintf(size_text, sizeof(size_text), "-");
}
- printf("%06o %s %s %7s\t", data.mode, type_name(data.type),
- find_unique_abbrev(data.oid, abbrev), size_text);
- show_tree_common_default_long(base, pathname, data.base->len);
+ printf("%06o %s %s %7s\t", mode, type_name(type),
+ find_unique_abbrev(oid, options->abbrev), size_text);
+ show_tree_common_default_long(options, base, pathname, base->len);
return recurse;
}
static int show_tree_name_only(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode,
- void *context UNUSED)
+ void *context)
{
+ struct ls_tree_options *options = context;
int early;
int recurse;
const size_t baselen = base->len;
- struct show_tree_data data = { 0 };
+ enum object_type type = object_type(mode);
+ const char *prefix;
- early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
+ early = show_tree_common(options, &recurse, base, pathname, type);
if (early >= 0)
return early;
+ prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL;
strbuf_addstr(base, pathname);
- write_name_quoted_relative(base->buf,
- chomp_prefix ? ls_tree_prefix : NULL,
- stdout, line_termination);
+ if (options->null_termination) {
+ struct strbuf sb = STRBUF_INIT;
+ const char *name = relative_path(base->buf, prefix, &sb);
+
+ fputs(name, stdout);
+ fputc('\0', stdout);
+
+ strbuf_release(&sb);
+ } else {
+ write_name_quoted_relative(base->buf, prefix, stdout, '\n');
+ }
strbuf_setlen(base, baselen);
return recurse;
}
static int show_tree_object(const struct object_id *oid, struct strbuf *base,
const char *pathname, unsigned mode,
- void *context UNUSED)
+ void *context)
{
+ struct ls_tree_options *options = context;
int early;
int recurse;
- struct show_tree_data data = { 0 };
+ enum object_type type = object_type(mode);
+ const char *str;
- early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
+ early = show_tree_common(options, &recurse, base, pathname, type);
if (early >= 0)
return early;
- printf("%s%c", find_unique_abbrev(oid, abbrev), line_termination);
+ str = find_unique_abbrev(oid, options->abbrev);
+ if (options->null_termination) {
+ fputs(str, stdout);
+ fputc('\0', stdout);
+ } else {
+ puts(str);
+ }
return recurse;
}
+enum ls_tree_cmdmode {
+ MODE_DEFAULT = 0,
+ MODE_LONG,
+ MODE_NAME_ONLY,
+ MODE_NAME_STATUS,
+ MODE_OBJECT_ONLY,
+};
+
struct ls_tree_cmdmode_to_fmt {
enum ls_tree_cmdmode mode;
const char *const fmt;
@@ -335,15 +367,18 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
struct tree *tree;
int i, full_tree = 0;
read_tree_fn_t fn = NULL;
+ enum ls_tree_cmdmode cmdmode = MODE_DEFAULT;
+ int null_termination = 0;
+ struct ls_tree_options options = { 0 };
const struct option ls_tree_options[] = {
- OPT_BIT('d', NULL, &ls_options, N_("only show trees"),
+ OPT_BIT('d', NULL, &options.ls_options, N_("only show trees"),
LS_TREE_ONLY),
- OPT_BIT('r', NULL, &ls_options, N_("recurse into subtrees"),
+ OPT_BIT('r', NULL, &options.ls_options, N_("recurse into subtrees"),
LS_RECURSIVE),
- OPT_BIT('t', NULL, &ls_options, N_("show trees when recursing"),
+ OPT_BIT('t', NULL, &options.ls_options, N_("show trees when recursing"),
LS_SHOW_TREES),
- OPT_SET_INT('z', NULL, &line_termination,
- N_("terminate entries with NUL byte"), 0),
+ OPT_BOOL('z', NULL, &null_termination,
+ N_("terminate entries with NUL byte")),
OPT_CMDMODE('l', "long", &cmdmode, N_("include object size"),
MODE_LONG),
OPT_CMDMODE(0, "name-only", &cmdmode, N_("list only filenames"),
@@ -352,29 +387,32 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
MODE_NAME_STATUS),
OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"),
MODE_OBJECT_ONLY),
- OPT_SET_INT(0, "full-name", &chomp_prefix,
+ OPT_SET_INT(0, "full-name", &options.chomp_prefix,
N_("use full path names"), 0),
OPT_BOOL(0, "full-tree", &full_tree,
N_("list entire tree; not just current directory "
"(implies --full-name)")),
- OPT_STRING_F(0, "format", &format, N_("format"),
+ OPT_STRING_F(0, "format", &options.format, N_("format"),
N_("format to use for the output"),
PARSE_OPT_NONEG),
- OPT__ABBREV(&abbrev),
+ OPT__ABBREV(&options.abbrev),
OPT_END()
};
struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format;
+ int ret;
git_config(git_default_config, NULL);
- ls_tree_prefix = prefix;
+ options.ls_tree_prefix = prefix;
if (prefix)
- chomp_prefix = strlen(prefix);
+ options.chomp_prefix = strlen(prefix);
argc = parse_options(argc, argv, prefix, ls_tree_options,
ls_tree_usage, 0);
+ options.null_termination = null_termination;
+
if (full_tree) {
- ls_tree_prefix = prefix = NULL;
- chomp_prefix = 0;
+ options.ls_tree_prefix = prefix = NULL;
+ options.chomp_prefix = 0;
}
/*
* We wanted to detect conflicts between --name-only and
@@ -386,10 +424,10 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
/* -d -r should imply -t, but -d by itself should not have to. */
if ( (LS_TREE_ONLY|LS_RECURSIVE) ==
- ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options))
- ls_options |= LS_SHOW_TREES;
+ ((LS_TREE_ONLY|LS_RECURSIVE) & options.ls_options))
+ options.ls_options |= LS_SHOW_TREES;
- if (format && cmdmode)
+ if (options.format && cmdmode)
usage_msg_opt(
_("--format can't be combined with other format-altering options"),
ls_tree_usage, ls_tree_options);
@@ -404,13 +442,13 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
* cannot be lifted until it is converted to use
* match_pathspec() or tree_entry_interesting()
*/
- parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC &
- ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
+ parse_pathspec(&options.pathspec, PATHSPEC_ALL_MAGIC &
+ ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
PATHSPEC_PREFER_CWD,
prefix, argv + 1);
- for (i = 0; i < pathspec.nr; i++)
- pathspec.items[i].nowildcard_len = pathspec.items[i].len;
- pathspec.has_wildcard = 0;
+ for (i = 0; i < options.pathspec.nr; i++)
+ options.pathspec.items[i].nowildcard_len = options.pathspec.items[i].len;
+ options.pathspec.has_wildcard = 0;
tree = parse_tree_indirect(&oid);
if (!tree)
die("not a tree object");
@@ -420,11 +458,11 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
*/
while (m2f) {
if (!m2f->fmt) {
- fn = format ? show_tree_fmt : show_tree_default;
- } else if (format && !strcmp(format, m2f->fmt)) {
+ fn = options.format ? show_tree_fmt : show_tree_default;
+ } else if (options.format && !strcmp(options.format, m2f->fmt)) {
cmdmode = m2f->mode;
fn = m2f->fn;
- } else if (!format && cmdmode == m2f->mode) {
+ } else if (!options.format && cmdmode == m2f->mode) {
fn = m2f->fn;
} else {
m2f++;
@@ -433,5 +471,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
break;
}
- return !!read_tree(the_repository, tree, &pathspec, fn, NULL);
+ ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options);
+ clear_pathspec(&options.pathspec);
+ return ret;
}
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index e3767087bb..828dc81c42 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -3,6 +3,7 @@
#include "tree-walk.h"
#include "xdiff-interface.h"
#include "help.h"
+#include "commit.h"
#include "commit-reach.h"
#include "merge-ort.h"
#include "object-store.h"
@@ -98,7 +99,7 @@ static void *origin(struct merge_list *entry, unsigned long *size)
return NULL;
}
-static int show_outf(void *priv_, mmbuffer_t *mb, int nbuf)
+static int show_outf(void *priv UNUSED, mmbuffer_t *mb, int nbuf)
{
int i;
for (i = 0; i < nbuf; i++)
@@ -406,6 +407,7 @@ struct merge_tree_options {
};
static int real_merge(struct merge_tree_options *o,
+ const char *merge_base,
const char *branch1, const char *branch2,
const char *prefix)
{
@@ -432,16 +434,31 @@ static int real_merge(struct merge_tree_options *o,
opt.branch1 = branch1;
opt.branch2 = branch2;
- /*
- * Get the merge bases, in reverse order; see comment above
- * merge_incore_recursive in merge-ort.h
- */
- merge_bases = get_merge_bases(parent1, parent2);
- if (!merge_bases && !o->allow_unrelated_histories)
- die(_("refusing to merge unrelated histories"));
- merge_bases = reverse_commit_list(merge_bases);
+ if (merge_base) {
+ struct commit *base_commit;
+ struct tree *base_tree, *parent1_tree, *parent2_tree;
+
+ base_commit = lookup_commit_reference_by_name(merge_base);
+ if (!base_commit)
+ die(_("could not lookup commit %s"), merge_base);
+
+ opt.ancestor = merge_base;
+ base_tree = get_commit_tree(base_commit);
+ parent1_tree = get_commit_tree(parent1);
+ parent2_tree = get_commit_tree(parent2);
+ merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result);
+ } else {
+ /*
+ * Get the merge bases, in reverse order; see comment above
+ * merge_incore_recursive in merge-ort.h
+ */
+ merge_bases = get_merge_bases(parent1, parent2);
+ if (!merge_bases && !o->allow_unrelated_histories)
+ die(_("refusing to merge unrelated histories"));
+ merge_bases = reverse_commit_list(merge_bases);
+ merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result);
+ }
- merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result);
if (result.clean < 0)
die(_("failure to merge"));
@@ -487,6 +504,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
struct merge_tree_options o = { .show_messages = -1 };
int expected_remaining_argc;
int original_argc;
+ const char *merge_base = NULL;
const char * const merge_tree_usage[] = {
N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"),
@@ -515,6 +533,10 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
&o.use_stdin,
N_("perform multiple merges, one per line of input"),
PARSE_OPT_NONEG),
+ OPT_STRING(0, "merge-base",
+ &merge_base,
+ N_("commit"),
+ N_("specify a merge-base for the merge")),
OPT_END()
};
@@ -529,16 +551,35 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
if (o.mode == MODE_TRIVIAL)
die(_("--trivial-merge is incompatible with all other options"));
+ if (merge_base)
+ die(_("--merge-base is incompatible with --stdin"));
line_termination = '\0';
while (strbuf_getline_lf(&buf, stdin) != EOF) {
struct strbuf **split;
int result;
+ const char *input_merge_base = NULL;
split = strbuf_split(&buf, ' ');
- if (!split[0] || !split[1] || split[2])
+ if (!split[0] || !split[1])
die(_("malformed input line: '%s'."), buf.buf);
strbuf_rtrim(split[0]);
- result = real_merge(&o, split[0]->buf, split[1]->buf, prefix);
+ strbuf_rtrim(split[1]);
+
+ /* parse the merge-base */
+ if (!strcmp(split[1]->buf, "--")) {
+ input_merge_base = split[0]->buf;
+ }
+
+ if (input_merge_base && split[2] && split[3] && !split[4]) {
+ strbuf_rtrim(split[2]);
+ strbuf_rtrim(split[3]);
+ result = real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
+ } else if (!input_merge_base && !split[2]) {
+ result = real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
+ } else {
+ die(_("malformed input line: '%s'."), buf.buf);
+ }
+
if (result < 0)
die(_("merging cannot continue; got unclean result of %d"), result);
strbuf_list_free(split);
@@ -581,7 +622,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
/* Do the relevant type of merge */
if (o.mode == MODE_REAL)
- return real_merge(&o, argv[0], argv[1], prefix);
+ return real_merge(&o, merge_base, argv[0], argv[1], prefix);
else
return trivial_merge(argv[0], argv[1], argv[2]);
}
diff --git a/builtin/merge.c b/builtin/merge.c
index dd474371a2..74de2ebd2b 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -188,7 +188,7 @@ static struct strategy *get_strategy(const char *name)
for (i = 0; i < main_cmds.cnt; i++) {
int j, found = 0;
struct cmdname *ent = main_cmds.names[i];
- for (j = 0; j < ARRAY_SIZE(all_strategy); j++)
+ for (j = 0; !found && j < ARRAY_SIZE(all_strategy); j++)
if (!strncmp(ent->name, all_strategy[j].name, ent->len)
&& !all_strategy[j].name[ent->len])
found = 1;
@@ -776,7 +776,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
}
static void count_diff_files(struct diff_queue_struct *q,
- struct diff_options *opt, void *data)
+ struct diff_options *opt UNUSED, void *data)
{
int *count = data;
@@ -1789,5 +1789,6 @@ done:
}
strbuf_release(&buf);
free(branch_to_free);
+ discard_index(&the_index);
return ret;
}
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 573d0b20b7..cabace4abb 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1318,7 +1318,7 @@ static int no_try_delta(const char *path)
if (!check)
check = attr_check_initl("delta", NULL);
- git_check_attr(the_repository->index, path, check);
+ git_check_attr(the_repository->index, NULL, path, check);
if (ATTR_FALSE(check->items[0].value))
return 1;
return 0;
@@ -4149,21 +4149,6 @@ static int option_parse_cruft_expiration(const struct option *opt,
return 0;
}
-struct po_filter_data {
- unsigned have_revs:1;
- struct rev_info revs;
-};
-
-static struct list_objects_filter_options *po_filter_revs_init(void *value)
-{
- struct po_filter_data *data = value;
-
- repo_init_revisions(the_repository, &data->revs, NULL);
- data->have_revs = 1;
-
- return &data->revs.filter;
-}
-
int cmd_pack_objects(int argc, const char **argv, const char *prefix)
{
int use_internal_rev_list = 0;
@@ -4174,7 +4159,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
int rev_list_index = 0;
int stdin_packs = 0;
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
- struct po_filter_data pfd = { .have_revs = 0 };
+ struct list_objects_filter_options filter_options =
+ LIST_OBJECTS_FILTER_INIT;
struct option pack_objects_options[] = {
OPT_SET_INT('q', "quiet", &progress,
@@ -4265,7 +4251,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
&write_bitmap_index,
N_("write a bitmap index if possible"),
WRITE_BITMAP_QUIET, PARSE_OPT_HIDDEN),
- OPT_PARSE_LIST_OBJECTS_FILTER_INIT(&pfd, po_filter_revs_init),
+ OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
OPT_CALLBACK_F(0, "missing", NULL, N_("action"),
N_("handling for missing objects"), PARSE_OPT_NONEG,
option_parse_missing_action),
@@ -4385,7 +4371,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
if (!rev_list_all || !rev_list_reflog || !rev_list_index)
unpack_unreachable_expiration = 0;
- if (pfd.have_revs && pfd.revs.filter.choice) {
+ if (filter_options.choice) {
if (!pack_to_stdout)
die(_("cannot use --filter without --stdout"));
if (stdin_packs)
@@ -4472,13 +4458,11 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
read_cruft_objects();
} else if (!use_internal_rev_list) {
read_object_list_from_stdin();
- } else if (pfd.have_revs) {
- get_object_list(&pfd.revs, rp.nr, rp.v);
- release_revisions(&pfd.revs);
} else {
struct rev_info revs;
repo_init_revisions(the_repository, &revs, NULL);
+ list_objects_filter_copy(&revs.filter, &filter_options);
get_object_list(&revs, rp.nr, rp.v);
release_revisions(&revs);
}
@@ -4513,6 +4497,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
reuse_packfile_objects);
cleanup:
+ list_objects_filter_release(&filter_options);
strvec_clear(&rp);
return 0;
diff --git a/builtin/range-diff.c b/builtin/range-diff.c
index e2a74efb42..aecfae12d3 100644
--- a/builtin/range-diff.c
+++ b/builtin/range-diff.c
@@ -47,7 +47,7 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
repo_diff_setup(the_repository, &diffopt);
- options = parse_options_concat(range_diff_options, diffopt.parseopts);
+ options = add_diff_options(range_diff_options, &diffopt);
argc = parse_options(argc, argv, prefix, options,
builtin_range_diff_usage, PARSE_OPT_KEEP_DASHDASH);
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index f702f9d47b..3ce7541783 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -114,6 +114,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
int prefix_set = 0;
struct lock_file lock_file = LOCK_INIT;
const struct option read_tree_options[] = {
+ OPT__SUPER_PREFIX(&opts.super_prefix),
OPT_CALLBACK_F(0, "index-output", NULL, N_("file"),
N_("write resulting index to <file>"),
PARSE_OPT_NONEG, index_output_cb),
diff --git a/builtin/rebase.c b/builtin/rebase.c
index b22768ca5b..7171be40ee 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -113,7 +113,7 @@ struct rebase_options {
int autostash;
int committer_date_is_author_date;
int ignore_date;
- char *cmd;
+ struct string_list exec;
int allow_empty_message;
int rebase_merges, rebase_cousins;
char *strategy, *strategy_opts;
@@ -122,6 +122,8 @@ struct rebase_options {
int reapply_cherry_picks;
int fork_point;
int update_refs;
+ int config_autosquash;
+ int config_update_refs;
};
#define REBASE_OPTIONS_INIT { \
@@ -131,8 +133,15 @@ struct rebase_options {
.default_backend = "merge", \
.flags = REBASE_NO_QUIET, \
.git_am_opts = STRVEC_INIT, \
+ .exec = STRING_LIST_INIT_NODUP, \
.git_format_patch_opt = STRBUF_INIT, \
.fork_point = -1, \
+ .reapply_cherry_picks = -1, \
+ .allow_empty_message = 1, \
+ .autosquash = -1, \
+ .config_autosquash = -1, \
+ .update_refs = -1, \
+ .config_update_refs = -1, \
}
static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@@ -243,17 +252,6 @@ static int init_basic_state(struct replay_opts *opts, const char *head_name,
return write_basic_state(opts, head_name, onto, orig_head);
}
-static void split_exec_commands(const char *cmd, struct string_list *commands)
-{
- if (cmd && *cmd) {
- string_list_split(commands, cmd, '\n', -1);
-
- /* rebase.c adds a new line to cmd after every command,
- * so here the last command is always empty */
- string_list_remove_empty_items(commands, 0);
- }
-}
-
static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
{
int ret;
@@ -261,7 +259,6 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
struct strvec make_script_args = STRVEC_INIT;
struct todo_list todo_list = TODO_LIST_INIT;
struct replay_opts replay = get_replay_opts(opts);
- struct string_list commands = STRING_LIST_INIT_DUP;
if (get_revision_ranges(opts->upstream, opts->onto, &opts->orig_head->object.oid,
&revisions, &shortrevisions))
@@ -297,14 +294,12 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
&todo_list))
BUG("unusable todo list");
- split_exec_commands(opts->cmd, &commands);
ret = complete_action(the_repository, &replay, flags,
shortrevisions, opts->onto_name, opts->onto,
- &opts->orig_head->object.oid, &commands,
+ &opts->orig_head->object.oid, &opts->exec,
opts->autosquash, opts->update_refs, &todo_list);
}
- string_list_clear(&commands, 0);
free(revisions);
free(shortrevisions);
todo_list_release(&todo_list);
@@ -789,7 +784,7 @@ static int rebase_config(const char *var, const char *value, void *data)
}
if (!strcmp(var, "rebase.autosquash")) {
- opts->autosquash = git_config_bool(var, value);
+ opts->config_autosquash = git_config_bool(var, value);
return 0;
}
@@ -806,7 +801,7 @@ static int rebase_config(const char *var, const char *value, void *data)
}
if (!strcmp(var, "rebase.updaterefs")) {
- opts->update_refs = git_config_bool(var, value);
+ opts->config_update_refs = git_config_bool(var, value);
return 0;
}
@@ -920,6 +915,9 @@ static int parse_opt_am(const struct option *opt, const char *arg, int unset)
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
+ if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_APPLY)
+ die(_("apply options and merge options cannot be used together"));
+
opts->type = REBASE_APPLY;
return 0;
@@ -933,8 +931,10 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
- if (!is_merge(opts))
- opts->type = REBASE_MERGE;
+ if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_MERGE)
+ die(_("apply options and merge options cannot be used together"));
+
+ opts->type = REBASE_MERGE;
return 0;
}
@@ -948,6 +948,9 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
+ if (opts->type != REBASE_UNSPECIFIED && opts->type != REBASE_MERGE)
+ die(_("apply options and merge options cannot be used together"));
+
opts->type = REBASE_MERGE;
opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
@@ -1032,7 +1035,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
struct object_id branch_base;
int ignore_whitespace = 0;
const char *gpg_sign = NULL;
- struct string_list exec = STRING_LIST_INIT_NODUP;
const char *rebase_merges = NULL;
struct string_list strategy_options = STRING_LIST_INIT_NODUP;
struct object_id squash_onto;
@@ -1127,7 +1129,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
N_("GPG-sign commits"),
PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
OPT_AUTOSTASH(&options.autostash),
- OPT_STRING_LIST('x', "exec", &exec, N_("exec"),
+ OPT_STRING_LIST('x', "exec", &options.exec, N_("exec"),
N_("add exec lines after each commit of the "
"editable list")),
OPT_BOOL_F(0, "allow-empty-message",
@@ -1164,8 +1166,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
- options.reapply_cherry_picks = -1;
- options.allow_empty_message = 1;
git_config(rebase_config, &options);
/* options.gpg_sign_opt will be either "-S" or NULL */
gpg_sign = options.gpg_sign_opt ? "" : NULL;
@@ -1230,13 +1230,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.fork_point < 0)
options.fork_point = 0;
}
- /*
- * --keep-base defaults to --reapply-cherry-picks to avoid losing
- * commits when using this option.
- */
- if (options.reapply_cherry_picks < 0)
- options.reapply_cherry_picks = keep_base;
-
if (options.root && options.fork_point > 0)
die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
@@ -1250,7 +1243,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (trace2_is_enabled()) {
if (is_merge(&options))
trace2_cmd_mode("interactive");
- else if (exec.nr)
+ else if (options.exec.nr)
trace2_cmd_mode("interactive-exec");
else
trace2_cmd_mode(action_names[options.action]);
@@ -1322,6 +1315,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (reset_head(the_repository, &ropts) < 0)
die(_("could not move back to %s"),
oid_to_hex(&options.orig_head->object.oid));
+ strbuf_release(&head_msg);
remove_branch_state(the_repository, 0);
ret = finish_rebase(&options);
goto cleanup;
@@ -1377,8 +1371,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
(options.action != ACTION_NONE) ||
- (exec.nr > 0) ||
- options.autosquash) {
+ (options.exec.nr > 0) ||
+ (options.autosquash == -1 && options.config_autosquash == 1) ||
+ options.autosquash == 1) {
allow_preemptive_ff = 0;
}
if (options.committer_date_is_author_date || options.ignore_date)
@@ -1401,8 +1396,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
}
}
- for (i = 0; i < exec.nr; i++)
- if (check_exec_cmd(exec.items[i].string))
+ for (i = 0; i < options.exec.nr; i++)
+ if (check_exec_cmd(options.exec.items[i].string))
exit(1);
if (!(options.flags & REBASE_NO_QUIET))
@@ -1411,27 +1406,34 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.empty != EMPTY_UNSPECIFIED)
imply_merge(&options, "--empty");
- /*
- * --keep-base implements --reapply-cherry-picks by altering upstream so
- * it works with both backends.
- */
- if (options.reapply_cherry_picks && !keep_base)
- imply_merge(&options, "--reapply-cherry-picks");
+ if (options.reapply_cherry_picks < 0)
+ /*
+ * We default to --no-reapply-cherry-picks unless
+ * --keep-base is given; when --keep-base is given, we want
+ * to default to --reapply-cherry-picks.
+ */
+ options.reapply_cherry_picks = keep_base;
+ else if (!keep_base)
+ /*
+ * The apply backend always searches for and drops cherry
+ * picks. This is often not wanted with --keep-base, so
+ * --keep-base allows --reapply-cherry-picks to be
+ * simulated by altering the upstream such that
+ * cherry-picks cannot be detected and thus all commits are
+ * reapplied. Thus, --[no-]reapply-cherry-picks is
+ * supported when --keep-base is specified, but not when
+ * --keep-base is left out.
+ */
+ imply_merge(&options, options.reapply_cherry_picks ?
+ "--reapply-cherry-picks" :
+ "--no-reapply-cherry-picks");
if (gpg_sign)
options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
- if (exec.nr) {
- int i;
-
+ if (options.exec.nr)
imply_merge(&options, "--exec");
- strbuf_reset(&buf);
- for (i = 0; i < exec.nr; i++)
- strbuf_addf(&buf, "exec %s\n", exec.items[i].string);
- options.cmd = xstrdup(buf.buf);
- }
-
if (rebase_merges) {
if (!*rebase_merges)
; /* default mode; do nothing */
@@ -1504,15 +1506,29 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (strcmp(options.git_am_opts.v[i], "-q"))
break;
- if (i >= 0) {
+ if (i >= 0 || options.type == REBASE_APPLY) {
if (is_merge(&options))
die(_("apply options and merge options "
"cannot be used together"));
+ else if (options.autosquash == -1 && options.config_autosquash == 1)
+ die(_("apply options are incompatible with rebase.autosquash. Consider adding --no-autosquash"));
+ else if (options.update_refs == -1 && options.config_update_refs == 1)
+ die(_("apply options are incompatible with rebase.updateRefs. Consider adding --no-update-refs"));
else
options.type = REBASE_APPLY;
}
}
+ if (options.update_refs == 1)
+ imply_merge(&options, "--update-refs");
+ options.update_refs = (options.update_refs >= 0) ? options.update_refs :
+ ((options.config_update_refs >= 0) ? options.config_update_refs : 0);
+
+ if (options.autosquash == 1)
+ imply_merge(&options, "--autosquash");
+ options.autosquash = (options.autosquash >= 0) ? options.autosquash :
+ ((options.config_autosquash >= 0) ? options.config_autosquash : 0);
+
if (options.type == REBASE_UNSPECIFIED) {
if (!strcmp(options.default_backend, "merge"))
imply_merge(&options, "--merge");
@@ -1542,7 +1558,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.empty == EMPTY_UNSPECIFIED) {
if (options.flags & REBASE_INTERACTIVE_EXPLICIT)
options.empty = EMPTY_ASK;
- else if (exec.nr > 0)
+ else if (options.exec.nr > 0)
options.empty = EMPTY_KEEP;
else
options.empty = EMPTY_DROP;
@@ -1828,10 +1844,12 @@ cleanup:
strbuf_release(&revisions);
free(options.reflog_action);
free(options.head_name);
+ strvec_clear(&options.git_am_opts);
free(options.gpg_sign_opt);
- free(options.cmd);
+ string_list_clear(&options.exec, 0);
free(options.strategy);
strbuf_release(&options.git_format_patch_opt);
free(squash_onto_name);
+ string_list_clear(&strategy_options, 0);
return !!ret;
}
diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c
index fd3538d4f0..ee338bf440 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -169,6 +169,8 @@ static int command_loop(const char *child)
while (1) {
size_t i;
+ const char *arg;
+
if (!fgets(buffer, MAXCOMMAND - 1, stdin)) {
if (ferror(stdin))
die("Command input error");
@@ -182,10 +184,10 @@ static int command_loop(const char *child)
if (!strcmp(buffer, "capabilities")) {
printf("*connect\n\n");
fflush(stdout);
- } else if (!strncmp(buffer, "connect ", 8)) {
+ } else if (skip_prefix(buffer, "connect ", &arg)) {
printf("\n");
fflush(stdout);
- return run_child(child, buffer + 8);
+ return run_child(child, arg);
} else {
fprintf(stderr, "Bad command");
return 1;
diff --git a/builtin/remote-fd.c b/builtin/remote-fd.c
index 91dfe07e06..b2a3980b1d 100644
--- a/builtin/remote-fd.c
+++ b/builtin/remote-fd.c
@@ -40,7 +40,7 @@ static void command_loop(int input_fd, int output_fd)
if (!strcmp(buffer, "capabilities")) {
printf("*connect\n\n");
fflush(stdout);
- } else if (!strncmp(buffer, "connect ", 8)) {
+ } else if (starts_with(buffer, "connect ")) {
printf("\n");
fflush(stdout);
if (bidirectional_transfer_loop(input_fd,
diff --git a/builtin/repack.c b/builtin/repack.c
index 65eb1b8bd2..c1402ad038 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -973,6 +973,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
item = string_list_append(&names, line.buf);
item->util = populate_pack_exts(item->string);
}
+ strbuf_release(&line);
fclose(out);
ret = finish_command(&cmd);
if (ret)
@@ -1175,7 +1176,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
string_list_clear(&existing_nonkept_packs, 0);
string_list_clear(&existing_kept_packs, 0);
clear_pack_geometry(geometry);
- strbuf_release(&line);
return 0;
}
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 8b7392d5b4..94ffb8c21a 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -14,7 +14,7 @@ static const char * const rerere_usage[] = {
NULL,
};
-static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
+static int outf(void *dummy UNUSED, mmbuffer_t *ptr, int nbuf)
{
int i;
for (i = 0; i < nbuf; i++)
diff --git a/builtin/reset.c b/builtin/reset.c
index 1fa86edb4c..fea20a9ba0 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -133,7 +133,8 @@ static void print_new_head_line(struct commit *commit)
}
static void update_index_from_diff(struct diff_queue_struct *q,
- struct diff_options *opt, void *data)
+ struct diff_options *opt UNUSED,
+ void *data)
{
int i;
int intent_to_add = *(int *)data;
@@ -485,5 +486,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (!pathspec.nr)
remove_branch_state(the_repository, 0);
+ discard_index(&the_index);
+
return update_ref_status;
}
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 1c344d74a7..e67999e5eb 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -530,6 +530,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
strbuf_addstr(&parsed, " --");
sq_quote_argv(&parsed, argv);
puts(parsed.buf);
+ strbuf_release(&parsed);
return 0;
}
diff --git a/builtin/revert.c b/builtin/revert.c
index 6a9b550a61..f2d86d2a8f 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -221,6 +221,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
opts->strategy = xstrdup_or_null(opts->strategy);
if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM"))
opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
+ free(options);
if (cmd == 'q') {
int ret = sequencer_remove_state(opts);
@@ -261,6 +262,9 @@ int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
opts.action = REPLAY_PICK;
sequencer_init_config(&opts);
res = run_sequencer(argc, argv, &opts);
+ if (opts.revs)
+ release_revisions(opts.revs);
+ free(opts.revs);
if (res < 0)
die(_("cherry-pick failed"));
return res;
diff --git a/builtin/rm.c b/builtin/rm.c
index d4989d4d86..4a4aec0d00 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -86,7 +86,7 @@ static void submodules_absorb_gitdir_if_needed(void)
continue;
if (!submodule_uses_gitfile(name))
- absorb_git_dir_into_superproject(name);
+ absorb_git_dir_into_superproject(name, NULL);
}
}
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 58a22503f0..c373815491 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -217,6 +217,7 @@ static int update_working_directory(struct pattern_list *pl)
o.head_idx = -1;
o.src_index = r->index;
o.dst_index = r->index;
+ index_state_init(&o.result, r);
o.skip_sparse_checkout = 0;
o.pl = pl;
diff --git a/builtin/stash.c b/builtin/stash.c
index 62e36718d3..839569a980 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1137,7 +1137,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
int ret = 0;
struct strbuf untracked_msg = STRBUF_INIT;
struct child_process cp_upd_index = CHILD_PROCESS_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
cp_upd_index.git_cmd = 1;
strvec_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
@@ -1165,7 +1165,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
}
done:
- discard_index(&istate);
+ release_index(&istate);
strbuf_release(&untracked_msg);
remove_path(stash_index_path.buf);
return ret;
@@ -1176,7 +1176,7 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
{
int ret = 0;
struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
if (write_index_as_tree(&info->w_tree, &istate, the_repository->index_file,
0, NULL)) {
@@ -1199,7 +1199,7 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
}
done:
- discard_index(&istate);
+ release_index(&istate);
return ret;
}
@@ -1209,7 +1209,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
int ret = 0;
struct child_process cp_read_tree = CHILD_PROCESS_INIT;
struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
char *old_index_env = NULL, *old_repo_index_file;
remove_path(stash_index_path.buf);
@@ -1260,7 +1260,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
}
done:
- discard_index(&istate);
+ release_index(&istate);
remove_path(stash_index_path.buf);
return ret;
}
@@ -1271,7 +1271,7 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
struct rev_info rev;
struct child_process cp_upd_index = CHILD_PROCESS_INIT;
struct strbuf diff_output = STRBUF_INIT;
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
init_revisions(&rev, NULL);
copy_pathspec(&rev.prune_data, ps);
@@ -1319,7 +1319,7 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
}
done:
- discard_index(&istate);
+ release_index(&istate);
release_revisions(&rev);
strbuf_release(&diff_output);
remove_path(stash_index_path.buf);
@@ -1689,8 +1689,10 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
}
done:
+ strbuf_release(&patch);
free_stash_info(&info);
strbuf_release(&stash_msg_buf);
+ strbuf_release(&untracked_files);
return ret;
}
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 05f2c9bc98..4c173d8b37 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -113,10 +113,9 @@ static char *resolve_relative_url(const char *rel_url, const char *up_path, int
}
/* the result should be freed by the caller. */
-static char *get_submodule_displaypath(const char *path, const char *prefix)
+static char *get_submodule_displaypath(const char *path, const char *prefix,
+ const char *super_prefix)
{
- const char *super_prefix = get_super_prefix();
-
if (prefix && super_prefix) {
BUG("cannot have prefix '%s' and superprefix '%s'",
prefix, super_prefix);
@@ -279,6 +278,7 @@ struct foreach_cb {
int argc;
const char **argv;
const char *prefix;
+ const char *super_prefix;
int quiet;
int recursive;
};
@@ -294,7 +294,8 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
struct child_process cp = CHILD_PROCESS_INIT;
char *displaypath;
- displaypath = get_submodule_displaypath(path, info->prefix);
+ displaypath = get_submodule_displaypath(path, info->prefix,
+ info->super_prefix);
sub = submodule_from_path(the_repository, null_oid(), path);
@@ -364,10 +365,10 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
cpr.dir = path;
prepare_submodule_repo_env(&cpr.env);
- strvec_pushl(&cpr.args, "--super-prefix", NULL);
- strvec_pushf(&cpr.args, "%s/", displaypath);
strvec_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
NULL);
+ strvec_pushl(&cpr.args, "--super-prefix", NULL);
+ strvec_pushf(&cpr.args, "%s/", displaypath);
if (info->quiet)
strvec_push(&cpr.args, "--quiet");
@@ -391,6 +392,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
struct option module_foreach_options[] = {
+ OPT__SUPER_PREFIX(&info.super_prefix),
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
OPT_BOOL(0, "recursive", &info.recursive,
N_("recurse into nested submodules")),
@@ -435,11 +437,13 @@ static int starts_with_dot_dot_slash(const char *const path)
struct init_cb {
const char *prefix;
+ const char *super_prefix;
unsigned int flags;
};
#define INIT_CB_INIT { 0 }
static void init_submodule(const char *path, const char *prefix,
+ const char *super_prefix,
unsigned int flags)
{
const struct submodule *sub;
@@ -447,7 +451,7 @@ static void init_submodule(const char *path, const char *prefix,
const char *upd;
char *url = NULL, *displaypath;
- displaypath = get_submodule_displaypath(path, prefix);
+ displaypath = get_submodule_displaypath(path, prefix, super_prefix);
sub = submodule_from_path(the_repository, null_oid(), path);
@@ -523,7 +527,8 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
{
struct init_cb *info = cb_data;
- init_submodule(list_item->name, info->prefix, info->flags);
+ init_submodule(list_item->name, info->prefix, info->super_prefix,
+ info->flags);
}
static int module_init(int argc, const char **argv, const char *prefix)
@@ -570,6 +575,7 @@ cleanup:
struct status_cb {
const char *prefix;
+ const char *super_prefix;
unsigned int flags;
};
#define STATUS_CB_INIT { 0 }
@@ -608,7 +614,7 @@ static int handle_submodule_head_ref(const char *refname UNUSED,
static void status_submodule(const char *path, const struct object_id *ce_oid,
unsigned int ce_flags, const char *prefix,
- unsigned int flags)
+ const char *super_prefix, unsigned int flags)
{
char *displaypath;
struct strvec diff_files_args = STRVEC_INIT;
@@ -624,7 +630,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
die(_("no submodule mapping found in .gitmodules for path '%s'"),
path);
- displaypath = get_submodule_displaypath(path, prefix);
+ displaypath = get_submodule_displaypath(path, prefix, super_prefix);
if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {
print_status(flags, 'U', path, null_oid(), displaypath);
@@ -682,10 +688,10 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
cpr.dir = path;
prepare_submodule_repo_env(&cpr.env);
- strvec_push(&cpr.args, "--super-prefix");
- strvec_pushf(&cpr.args, "%s/", displaypath);
strvec_pushl(&cpr.args, "submodule--helper", "status",
"--recursive", NULL);
+ strvec_push(&cpr.args, "--super-prefix");
+ strvec_pushf(&cpr.args, "%s/", displaypath);
if (flags & OPT_CACHED)
strvec_push(&cpr.args, "--cached");
@@ -709,7 +715,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
struct status_cb *info = cb_data;
status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
- info->prefix, info->flags);
+ info->prefix, info->super_prefix, info->flags);
}
static int module_status(int argc, const char **argv, const char *prefix)
@@ -719,6 +725,7 @@ static int module_status(int argc, const char **argv, const char *prefix)
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
struct option module_status_options[] = {
+ OPT__SUPER_PREFIX(&info.super_prefix),
OPT__QUIET(&quiet, N_("suppress submodule status output")),
OPT_BIT(0, "cached", &info.flags, N_("use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
@@ -787,6 +794,7 @@ struct summary_cb {
int argc;
const char **argv;
const char *prefix;
+ const char *super_prefix;
unsigned int cached: 1;
unsigned int for_status: 1;
unsigned int files: 1;
@@ -948,7 +956,8 @@ static void generate_submodule_summary(struct summary_cb *info,
dst_abbrev = xstrndup(oid_to_hex(&p->oid_dst), 7);
}
- displaypath = get_submodule_displaypath(p->sm_path, info->prefix);
+ displaypath = get_submodule_displaypath(p->sm_path, info->prefix,
+ info->super_prefix);
if (!missing_src && !missing_dst) {
struct child_process cp_rev_list = CHILD_PROCESS_INIT;
@@ -1043,7 +1052,7 @@ static void prepare_submodule_summary(struct summary_cb *info,
}
static void submodule_summary_callback(struct diff_queue_struct *q,
- struct diff_options *options,
+ struct diff_options *options UNUSED,
void *data)
{
int i;
@@ -1203,12 +1212,13 @@ static int module_summary(int argc, const char **argv, const char *prefix)
struct sync_cb {
const char *prefix;
+ const char *super_prefix;
unsigned int flags;
};
#define SYNC_CB_INIT { 0 }
static void sync_submodule(const char *path, const char *prefix,
- unsigned int flags)
+ const char *super_prefix, unsigned int flags)
{
const struct submodule *sub;
char *remote_key = NULL;
@@ -1239,7 +1249,7 @@ static void sync_submodule(const char *path, const char *prefix,
super_config_url = xstrdup("");
}
- displaypath = get_submodule_displaypath(path, prefix);
+ displaypath = get_submodule_displaypath(path, prefix, super_prefix);
if (!(flags & OPT_QUIET))
printf(_("Synchronizing submodule url for '%s'\n"),
@@ -1276,10 +1286,11 @@ static void sync_submodule(const char *path, const char *prefix,
cpr.dir = path;
prepare_submodule_repo_env(&cpr.env);
- strvec_push(&cpr.args, "--super-prefix");
- strvec_pushf(&cpr.args, "%s/", displaypath);
strvec_pushl(&cpr.args, "submodule--helper", "sync",
"--recursive", NULL);
+ strvec_push(&cpr.args, "--super-prefix");
+ strvec_pushf(&cpr.args, "%s/", displaypath);
+
if (flags & OPT_QUIET)
strvec_push(&cpr.args, "--quiet");
@@ -1302,7 +1313,8 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
{
struct sync_cb *info = cb_data;
- sync_submodule(list_item->name, info->prefix, info->flags);
+ sync_submodule(list_item->name, info->prefix, info->super_prefix,
+ info->flags);
}
static int module_sync(int argc, const char **argv, const char *prefix)
@@ -1313,6 +1325,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
int quiet = 0;
int recursive = 0;
struct option module_sync_options[] = {
+ OPT__SUPER_PREFIX(&info.super_prefix),
OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
OPT_BOOL(0, "recursive", &recursive,
N_("recurse into nested submodules")),
@@ -1365,7 +1378,7 @@ static void deinit_submodule(const char *path, const char *prefix,
if (!sub || !sub->name)
goto cleanup;
- displaypath = get_submodule_displaypath(path, prefix);
+ displaypath = get_submodule_displaypath(path, prefix, NULL);
/* remove the submodule work tree (unless the user already did it) */
if (is_directory(path)) {
@@ -1379,7 +1392,7 @@ static void deinit_submodule(const char *path, const char *prefix,
".git file by using absorbgitdirs."),
displaypath);
- absorb_git_dir_into_superproject(path);
+ absorb_git_dir_into_superproject(path, NULL);
}
@@ -1883,6 +1896,7 @@ static void submodule_update_clone_release(struct submodule_update_clone *suc)
struct update_data {
const char *prefix;
+ const char *super_prefix;
char *displaypath;
enum submodule_update_type update_default;
struct object_id suboid;
@@ -1958,7 +1972,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
enum submodule_update_type update_type;
char *key;
const struct update_data *ud = suc->update_data;
- char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
+ char *displaypath = get_submodule_displaypath(ce->name, ud->prefix,
+ ud->super_prefix);
struct strbuf sb = STRBUF_INIT;
int needs_cloning = 0;
int need_free_url = 0;
@@ -2438,11 +2453,11 @@ static void update_data_to_args(const struct update_data *update_data,
{
enum submodule_update_type update_type = update_data->update_default;
+ strvec_pushl(args, "submodule--helper", "update", "--recursive", NULL);
if (update_data->displaypath) {
strvec_push(args, "--super-prefix");
strvec_pushf(args, "%s/", update_data->displaypath);
}
- strvec_pushl(args, "submodule--helper", "update", "--recursive", NULL);
strvec_pushf(args, "--jobs=%d", update_data->max_jobs);
if (update_data->quiet)
strvec_push(args, "--quiet");
@@ -2608,7 +2623,8 @@ static int update_submodules(struct update_data *update_data)
goto fail;
update_data->displaypath = get_submodule_displaypath(
- update_data->sm_path, update_data->prefix);
+ update_data->sm_path, update_data->prefix,
+ update_data->super_prefix);
code = update_submodule(update_data);
FREE_AND_NULL(update_data->displaypath);
fail:
@@ -2634,6 +2650,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
LIST_OBJECTS_FILTER_INIT;
int ret;
struct option module_update_options[] = {
+ OPT__SUPER_PREFIX(&opt.super_prefix),
OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
OPT_BOOL(0, "init", &opt.init,
N_("initialize uninitialized submodules before update")),
@@ -2730,6 +2747,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
module_list_active(&list);
info.prefix = opt.prefix;
+ info.super_prefix = opt.super_prefix;
if (opt.quiet)
info.flags |= OPT_QUIET;
@@ -2828,7 +2846,9 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
int i;
struct pathspec pathspec = { 0 };
struct module_list list = MODULE_LIST_INIT;
+ const char *super_prefix = NULL;
struct option embed_gitdir_options[] = {
+ OPT__SUPER_PREFIX(&super_prefix),
OPT_END()
};
const char *const git_submodule_helper_usage[] = {
@@ -2844,7 +2864,8 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
goto cleanup;
for (i = 0; i < list.nr; i++)
- absorb_git_dir_into_superproject(list.entries[i]->name);
+ absorb_git_dir_into_superproject(list.entries[i]->name,
+ super_prefix);
ret = 0;
cleanup:
@@ -2876,7 +2897,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix)
config_name = xstrfmt("submodule.%s.url", path);
config_set_in_gitmodules_file_gently(config_name, newurl);
- sync_submodule(path, prefix, quiet ? OPT_QUIET : 0);
+ sync_submodule(path, prefix, NULL, quiet ? OPT_QUIET : 0);
free(config_name);
@@ -3198,9 +3219,8 @@ static void die_on_index_match(const char *path, int force)
ensure_full_index(&the_index);
/*
- * Since there is only one pathspec, we just need
- * need to check ps_matched[0] to know if a cache
- * entry matched.
+ * Since there is only one pathspec, we just need to
+ * check ps_matched[0] to know if a cache entry matched.
*/
for (i = 0; i < the_index.cache_nr; i++) {
ce_path_match(&the_index, the_index.cache[i], &ps,
@@ -3353,8 +3373,6 @@ cleanup:
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
{
- const char *cmd = argv[0];
- const char *subcmd;
parse_opt_subcommand_fn *fn = NULL;
const char *const usage[] = {
N_("git submodule--helper <command>"),
@@ -3378,18 +3396,6 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
OPT_END()
};
argc = parse_options(argc, argv, prefix, options, usage, 0);
- subcmd = argv[0];
-
- if (strcmp(subcmd, "clone") && strcmp(subcmd, "update") &&
- strcmp(subcmd, "foreach") && strcmp(subcmd, "status") &&
- strcmp(subcmd, "sync") && strcmp(subcmd, "absorbgitdirs") &&
- get_super_prefix())
- /*
- * xstrfmt() rather than "%s %s" to keep the translated
- * string identical to git.c's.
- */
- die(_("%s doesn't support --super-prefix"),
- xstrfmt("'%s %s'", cmd, subcmd));
return fn(argc, argv, prefix);
}
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index 9e8119dd35..88de32b7d7 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -19,6 +19,7 @@ static char *create_temp_file(struct object_id *oid)
if (write_in_full(fd, buf, size) < 0)
die_errno("unable to write temp-file");
close(fd);
+ free(buf);
return path;
}
diff --git a/builtin/var.c b/builtin/var.c
index 491db27429..a80c1df86f 100644
--- a/builtin/var.c
+++ b/builtin/var.c
@@ -11,12 +11,12 @@ static const char var_usage[] = "git var (-l | <variable>)";
static const char *editor(int flag)
{
- const char *pgm = git_editor();
-
- if (!pgm && flag & IDENT_STRICT)
- die("Terminal is dumb, but EDITOR unset");
+ return git_editor();
+}
- return pgm;
+static const char *sequence_editor(int flag)
+{
+ return git_sequence_editor();
}
static const char *pager(int flag)
@@ -41,6 +41,7 @@ static struct git_var git_vars[] = {
{ "GIT_COMMITTER_IDENT", git_committer_info },
{ "GIT_AUTHOR_IDENT", git_author_info },
{ "GIT_EDITOR", editor },
+ { "GIT_SEQUENCE_EDITOR", sequence_editor },
{ "GIT_PAGER", pager },
{ "GIT_DEFAULT_BRANCH", default_branch },
{ "", NULL },
@@ -56,18 +57,15 @@ static void list_vars(void)
printf("%s=%s\n", ptr->name, val);
}
-static const char *read_var(const char *var)
+static const struct git_var *get_git_var(const char *var)
{
struct git_var *ptr;
- const char *val;
- val = NULL;
for (ptr = git_vars; ptr->read; ptr++) {
if (strcmp(var, ptr->name) == 0) {
- val = ptr->read(IDENT_STRICT);
- break;
+ return ptr;
}
}
- return val;
+ return NULL;
}
static int show_config(const char *var, const char *value, void *cb)
@@ -81,7 +79,9 @@ static int show_config(const char *var, const char *value, void *cb)
int cmd_var(int argc, const char **argv, const char *prefix)
{
- const char *val = NULL;
+ const struct git_var *git_var;
+ const char *val;
+
if (argc != 2)
usage(var_usage);
@@ -91,10 +91,15 @@ int cmd_var(int argc, const char **argv, const char *prefix)
return 0;
}
git_config(git_default_config, NULL);
- val = read_var(argv[1]);
- if (!val)
+
+ git_var = get_git_var(argv[1]);
+ if (!git_var)
usage(var_usage);
+ val = git_var->read(IDENT_STRICT);
+ if (!val)
+ return 1;
+
printf("%s\n", val);
return 0;
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 4a24d53be1..f51c40f1e1 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -629,6 +629,7 @@ static int add(int ac, const char **av, const char *prefix)
N_("try to match the new branch name with a remote-tracking branch")),
OPT_END()
};
+ int ret;
memset(&opts, 0, sizeof(opts));
opts.checkout = 1;
@@ -705,9 +706,9 @@ static int add(int ac, const char **av, const char *prefix)
die(_("--[no-]track can only be used if a new branch is created"));
}
- UNLEAK(path);
- UNLEAK(opts);
- return add_worktree(path, branch, &opts);
+ ret = add_worktree(path, branch, &opts);
+ free(path);
+ return ret;
}
static void show_worktree_porcelain(struct worktree *wt, int line_terminator)
@@ -922,7 +923,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix)
static void validate_no_submodules(const struct worktree *wt)
{
- struct index_state istate = { NULL };
+ struct index_state istate = INDEX_STATE_INIT(the_repository);
struct strbuf path = STRBUF_INIT;
int i, found_submodules = 0;