aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictoria Dye <vdye@github.com>2022-05-10 23:32:31 +0000
committerJunio C Hamano <gitster@pobox.com>2022-05-10 16:45:12 -0700
commit874cf2a6044462ddba7162730557354a107c3a6d (patch)
tree1cb2b91c060bc837cc9e9ffc6c49f627b539a931
parentread-cache: set sparsity when index is new (diff)
downloadgit-874cf2a6044462ddba7162730557354a107c3a6d.tar.gz
git-874cf2a6044462ddba7162730557354a107c3a6d.zip
stash: apply stash using 'merge_ort_nonrecursive()'
Update 'stash' to use 'merge_ort_nonrecursive()' to apply a stash to the current working tree. When 'git stash apply' was converted from its shell script implementation to a builtin in 8a0fc8d19d (stash: convert apply to builtin, 2019-02-25), 'merge_recursive_generic()' was used to merge a stash into the working tree as part of 'git stash (apply|pop)'. However, with the single merge base used in 'do_apply_stash()', the commit wrapping done by 'merge_recursive_generic()' is not only unnecessary, but misleading (the *real* merge base is labeled "constructed merge base"). Therefore, a non-recursive merge of the working tree, stashed tree, and stash base tree is more appropriate. There are two options for a non-recursive merge-then-update-worktree function: 'merge_trees()' and 'merge_ort_nonrecursive()'. Use 'merge_ort_nonrecursive()' to align with the default merge strategy used by 'git merge' (6a5fb96672 (Change default merge backend from recursive to ort, 2021-08-04)) and, because merge-ort does not operate in-place on the index, avoid unnecessary index expansion. Update tests in 't1092' verifying index expansion for 'git stash' accordingly. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/stash.c30
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh4
2 files changed, 26 insertions, 8 deletions
diff --git a/builtin/stash.c b/builtin/stash.c
index 1bfba53204..3fe549f7d3 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"
@@ -492,13 +493,13 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
static int do_apply_stash(const char *prefix, struct stash_info *info,
int index, int quiet)
{
- int ret;
+ int clean, ret;
int has_index = index;
struct merge_options o;
struct object_id c_tree;
struct object_id index_tree;
- struct commit *result;
- const struct object_id *bases[1];
+ struct tree *head, *merge, *merge_base;
+ struct lock_file lock = LOCK_INIT;
read_cache_preload(NULL);
if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
@@ -541,6 +542,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
o.branch1 = "Updated upstream";
o.branch2 = "Stashed changes";
+ o.ancestor = "Stash base";
if (oideq(&info->b_tree, &c_tree))
o.branch1 = "Version stash was based on";
@@ -551,10 +553,26 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
if (o.verbosity >= 3)
printf_ln(_("Merging %s with %s"), o.branch1, o.branch2);
- bases[0] = &info->b_tree;
+ head = lookup_tree(o.repo, &c_tree);
+ merge = lookup_tree(o.repo, &info->w_tree);
+ merge_base = lookup_tree(o.repo, &info->b_tree);
+
+ repo_hold_locked_index(o.repo, &lock, LOCK_DIE_ON_ERROR);
+ clean = merge_ort_nonrecursive(&o, head, merge, merge_base);
+
+ /*
+ * If 'clean' >= 0, reverse the value for 'ret' so 'ret' is 0 when the
+ * merge was clean, and nonzero if the merge was unclean or encountered
+ * an error.
+ */
+ ret = clean >= 0 ? !clean : clean;
+
+ if (ret < 0)
+ rollback_lock_file(&lock);
+ else if (write_locked_index(o.repo->index, &lock,
+ COMMIT_LOCK | SKIP_IF_UNCHANGED))
+ ret = error(_("could not write index"));
- ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases,
- &result);
if (ret) {
rerere(0);
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 85c6a56f1b..aaf4d880db 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -1385,7 +1385,7 @@ test_expect_success 'sparse-index is not expanded: stash' '
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 apply stash@{0} &&
ensure_not_expanded stash drop stash@{0} &&
echo >>sparse-index/deep/new &&
@@ -1399,7 +1399,7 @@ test_expect_success 'sparse-index is not expanded: stash' '
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 stash pop
'
test_expect_success 'sparse index is not expanded: diff' '