diff --git a/builtin/am.c b/builtin/am.c index b6be1f1cb11e47..f4682b8e959f8d 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -1613,7 +1613,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa if (state->quiet) o.verbosity = 0; - if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { + if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, merge_recursive, &result)) { repo_rerere(the_repository, state->allow_rerere_autoupdate); free(their_tree_name); return error(_("Failed to merge in the changes.")); diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index a4bfd8fc51d6b2..58964676be9b35 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -81,7 +81,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) if (o.verbosity >= 3) printf(_("Merging %s with %s\n"), o.branch1, o.branch2); - failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result); + failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, merge_recursive, &result); free(better1); free(better2); diff --git a/builtin/stash.c b/builtin/stash.c index e3051e9c407f6e..5044720175602a 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -7,6 +7,7 @@ #include "cache-tree.h" #include "unpack-trees.h" #include "merge-recursive.h" +#include "merge-ort-wrappers.h" #include "strvec.h" #include "run-command.h" #include "dir.h" @@ -554,7 +555,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, bases[0] = &info->b_tree; ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases, - &result); + merge_ort_recursive, &result); if (ret) { rerere(0); @@ -1790,6 +1791,9 @@ int cmd_stash(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, git_stash_usage, PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH); + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + index_file = get_index_file(); strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file, (uintmax_t)pid); diff --git a/merge-ort.c b/merge-ort.c index 58038094836afa..d302f31753e754 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4684,7 +4684,8 @@ void merge_incore_recursive(struct merge_options *opt, trace2_region_enter("merge", "incore_recursive", opt->repo); /* We set the ancestor label based on the merge_bases */ - assert(opt->ancestor == NULL); + assert(opt->ancestor == NULL || + !strcmp(opt->ancestor, "constructed merge base")); trace2_region_enter("merge", "merge_start", opt->repo); merge_start(opt, result); diff --git a/merge-recursive.c b/merge-recursive.c index 593eab87910899..c108c69f385357 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -3799,6 +3799,7 @@ int merge_recursive_generic(struct merge_options *opt, const struct object_id *merge, int num_merge_bases, const struct object_id **merge_bases, + recursive_merge_fn_t merge_fn, struct commit **result) { int clean; @@ -3822,8 +3823,7 @@ int merge_recursive_generic(struct merge_options *opt, } repo_hold_locked_index(opt->repo, &lock, LOCK_DIE_ON_ERROR); - clean = merge_recursive(opt, head_commit, next_commit, ca, - result); + clean = merge_fn(opt, head_commit, next_commit, ca, result); if (clean < 0) { rollback_lock_file(&lock); return clean; diff --git a/merge-recursive.h b/merge-recursive.h index 0795a1d3ec1809..6436ddcdca9d49 100644 --- a/merge-recursive.h +++ b/merge-recursive.h @@ -51,6 +51,12 @@ struct merge_options { struct merge_options_internal *priv; }; +typedef int (*recursive_merge_fn_t)(struct merge_options *opt, + struct commit *h1, + struct commit *h2, + struct commit_list *merge_bases, + struct commit **result); + void init_merge_options(struct merge_options *opt, struct repository *repo); /* parse the option in s and update the relevant field of opt */ @@ -103,7 +109,7 @@ int merge_recursive(struct merge_options *opt, /* * merge_recursive_generic can operate on trees instead of commits, by - * wrapping the trees into virtual commits, and calling merge_recursive(). + * wrapping the trees into virtual commits, and calling the provided merge_fn. * It also writes out the in-memory index to disk if the merge is successful. * * Outputs: @@ -118,6 +124,7 @@ int merge_recursive_generic(struct merge_options *opt, const struct object_id *merge, int num_merge_bases, const struct object_id **merge_bases, + recursive_merge_fn_t merge_fn, struct commit **result); #endif diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh index 5da8dd2c9baf66..4babe0b4ad4772 100755 --- a/t/perf/p2000-sparse-operations.sh +++ b/t/perf/p2000-sparse-operations.sh @@ -106,6 +106,7 @@ test_perf_on_all () { } test_perf_on_all git status +test_perf_on_all 'git stash && git stash pop' test_perf_on_all git add -A test_perf_on_all git add . test_perf_on_all git commit -a -m A diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 125d978112dee0..9b2259a06c54e6 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1258,6 +1258,19 @@ test_expect_success 'sparse-index is not expanded' ' echo >>sparse-index/untracked.txt && ensure_not_expanded add . && + echo >>sparse-index/a && + ensure_not_expanded stash && + ensure_not_expanded stash list && + ensure_not_expanded stash show stash@{0} && + ensure_not_expanded stash apply stash@{0} && + ensure_not_expanded stash drop stash@{0} && + + ensure_not_expanded stash create && + oid=$(git -C sparse-index stash create) && + ensure_not_expanded stash store -m "test" $oid && + ensure_not_expanded reset --hard && + ensure_not_expanded stash pop && + ensure_not_expanded checkout-index -f a && ensure_not_expanded checkout-index -f --all && for ref in update-deep update-folder1 update-folder2 update-deep