Merge branch 'ds/mergies-with-sparse-index'
Various mergy operations have been prepared to work efficiently with the sparse index. * ds/mergies-with-sparse-index: sparse-index: integrate with cherry-pick and rebase sequencer: ensure full index if not ORT strategy t1092: add cherry-pick, rebase tests merge-ort: expand only for out-of-cone conflicts merge: make sparse-aware with ORT diff: ignore sparse paths in diffstat
This commit is contained in:
commit
a16dd13740
@ -1276,6 +1276,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage_with_options(builtin_merge_usage, builtin_merge_options);
|
||||
|
||||
prepare_repo_settings(the_repository);
|
||||
the_repository->settings.command_requires_full_index = 0;
|
||||
|
||||
/*
|
||||
* Check if we are _not_ on a detached HEAD, i.e. if there is a
|
||||
* current branch.
|
||||
|
@ -560,6 +560,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
|
||||
|
||||
prepare_repo_settings(the_repository);
|
||||
the_repository->settings.command_requires_full_index = 0;
|
||||
|
||||
if (!is_null_oid(&squash_onto))
|
||||
opts.squash_onto = &squash_onto;
|
||||
|
||||
@ -1431,6 +1434,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
||||
usage_with_options(builtin_rebase_usage,
|
||||
builtin_rebase_options);
|
||||
|
||||
prepare_repo_settings(the_repository);
|
||||
the_repository->settings.command_requires_full_index = 0;
|
||||
|
||||
options.allow_empty_message = 1;
|
||||
git_config(rebase_config, &options);
|
||||
/* options.gpg_sign_opt will be either "-S" or NULL */
|
||||
|
@ -136,6 +136,9 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
|
||||
PARSE_OPT_KEEP_ARGV0 |
|
||||
PARSE_OPT_KEEP_UNKNOWN);
|
||||
|
||||
prepare_repo_settings(the_repository);
|
||||
the_repository->settings.command_requires_full_index = 0;
|
||||
|
||||
/* implies allow_empty */
|
||||
if (opts->keep_redundant_commits)
|
||||
opts->allow_empty = 1;
|
||||
|
8
diff.c
8
diff.c
@ -26,6 +26,7 @@
|
||||
#include "parse-options.h"
|
||||
#include "help.h"
|
||||
#include "promisor-remote.h"
|
||||
#include "dir.h"
|
||||
|
||||
#ifdef NO_FAST_WORKING_DIRECTORY
|
||||
#define FAST_WORKING_DIRECTORY 0
|
||||
@ -3907,6 +3908,13 @@ static int reuse_worktree_file(struct index_state *istate,
|
||||
if (!want_file && would_convert_to_git(istate, name))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If this path does not match our sparse-checkout definition,
|
||||
* then the file will not be in the working directory.
|
||||
*/
|
||||
if (!path_in_sparse_checkout(name, istate))
|
||||
return 0;
|
||||
|
||||
len = strlen(name);
|
||||
pos = index_name_pos(istate, name, len);
|
||||
if (pos < 0)
|
||||
|
15
merge-ort.c
15
merge-ort.c
@ -4074,6 +4074,21 @@ static int record_conflicted_index_entries(struct merge_options *opt)
|
||||
if (strmap_empty(&opt->priv->conflicted))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We are in a conflicted state. These conflicts might be inside
|
||||
* sparse-directory entries, so check if any entries are outside
|
||||
* of the sparse-checkout cone preemptively.
|
||||
*
|
||||
* We set original_cache_nr below, but that might change if
|
||||
* index_name_pos() calls ask for paths within sparse directories.
|
||||
*/
|
||||
strmap_for_each_entry(&opt->priv->conflicted, &iter, e) {
|
||||
if (!path_in_sparse_checkout(e->key, index)) {
|
||||
ensure_full_index(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If any entries have skip_worktree set, we'll have to check 'em out */
|
||||
state.force = 1;
|
||||
state.quiet = 1;
|
||||
|
@ -3747,6 +3747,9 @@ int merge_recursive(struct merge_options *opt,
|
||||
assert(opt->ancestor == NULL ||
|
||||
!strcmp(opt->ancestor, "constructed merge base"));
|
||||
|
||||
prepare_repo_settings(opt->repo);
|
||||
opt->repo->settings.command_requires_full_index = 1;
|
||||
|
||||
if (merge_start(opt, repo_get_commit_tree(opt->repo, h1)))
|
||||
return -1;
|
||||
clean = merge_recursive_internal(opt, h1, h2, merge_bases, result);
|
||||
|
@ -664,6 +664,7 @@ static int do_recursive_merge(struct repository *r,
|
||||
merge_switch_to_result(&o, head_tree, &result, 1, show_output);
|
||||
clean = result.clean;
|
||||
} else {
|
||||
ensure_full_index(r->index);
|
||||
clean = merge_trees(&o, head_tree, next_tree, base_tree);
|
||||
if (is_rebase_i(opts) && clean <= 0)
|
||||
fputs(o.obuf.buf, stdout);
|
||||
@ -2359,6 +2360,7 @@ static int read_and_refresh_cache(struct repository *r,
|
||||
_(action_name(opts)));
|
||||
}
|
||||
refresh_index(r->index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
|
||||
|
||||
if (index_fd >= 0) {
|
||||
if (write_locked_index(r->index, &index_lock,
|
||||
COMMIT_LOCK | SKIP_IF_UNCHANGED)) {
|
||||
@ -2366,6 +2368,13 @@ static int read_and_refresh_cache(struct repository *r,
|
||||
_(action_name(opts)));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are resolving merges in any way other than "ort", then
|
||||
* expand the sparse index.
|
||||
*/
|
||||
if (opts->strategy && strcmp(opts->strategy, "ort"))
|
||||
ensure_full_index(r->index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ test_expect_success 'setup' '
|
||||
git checkout -b base &&
|
||||
for dir in folder1 folder2 deep
|
||||
do
|
||||
git checkout -b update-$dir &&
|
||||
git checkout -b update-$dir base &&
|
||||
echo "updated $dir" >$dir/a &&
|
||||
git commit -a -m "update $dir" || return 1
|
||||
done &&
|
||||
@ -481,14 +481,17 @@ test_expect_success 'checkout and reset (mixed) [sparse]' '
|
||||
test_sparse_match git reset update-folder2
|
||||
'
|
||||
|
||||
test_expect_success 'merge' '
|
||||
test_expect_success 'merge, cherry-pick, and rebase' '
|
||||
init_repos &&
|
||||
|
||||
test_all_match git checkout -b merge update-deep &&
|
||||
test_all_match git merge -m "folder1" update-folder1 &&
|
||||
test_all_match git rev-parse HEAD^{tree} &&
|
||||
test_all_match git merge -m "folder2" update-folder2 &&
|
||||
test_all_match git rev-parse HEAD^{tree}
|
||||
for OPERATION in "merge -m merge" cherry-pick rebase
|
||||
do
|
||||
test_all_match git checkout -B temp update-deep &&
|
||||
test_all_match git $OPERATION update-folder1 &&
|
||||
test_all_match git rev-parse HEAD^{tree} &&
|
||||
test_all_match git $OPERATION update-folder2 &&
|
||||
test_all_match git rev-parse HEAD^{tree} || return 1
|
||||
done
|
||||
'
|
||||
|
||||
# NEEDSWORK: This test is documenting current behavior, but that
|
||||
@ -524,6 +527,38 @@ test_expect_success 'merge with conflict outside cone' '
|
||||
test_all_match git rev-parse HEAD^{tree}
|
||||
'
|
||||
|
||||
test_expect_success 'cherry-pick/rebase with conflict outside cone' '
|
||||
init_repos &&
|
||||
|
||||
for OPERATION in cherry-pick rebase
|
||||
do
|
||||
test_all_match git checkout -B tip &&
|
||||
test_all_match git reset --hard merge-left &&
|
||||
test_all_match git status --porcelain=v2 &&
|
||||
test_all_match test_must_fail git $OPERATION merge-right &&
|
||||
test_all_match git status --porcelain=v2 &&
|
||||
|
||||
# Resolve the conflict in different ways:
|
||||
# 1. Revert to the base
|
||||
test_all_match git checkout base -- deep/deeper2/a &&
|
||||
test_all_match git status --porcelain=v2 &&
|
||||
|
||||
# 2. Add the file with conflict markers
|
||||
test_all_match git add folder1/a &&
|
||||
test_all_match git status --porcelain=v2 &&
|
||||
|
||||
# 3. Rename the file to another sparse filename and
|
||||
# accept conflict markers as resolved content.
|
||||
run_on_all mv folder2/a folder2/z &&
|
||||
test_all_match git add folder2 &&
|
||||
test_all_match git status --porcelain=v2 &&
|
||||
|
||||
test_all_match git $OPERATION --continue &&
|
||||
test_all_match git status --porcelain=v2 &&
|
||||
test_all_match git rev-parse HEAD^{tree} || return 1
|
||||
done
|
||||
'
|
||||
|
||||
test_expect_success 'merge with outside renames' '
|
||||
init_repos &&
|
||||
|
||||
@ -617,8 +652,17 @@ test_expect_success 'sparse-index is expanded and converted back' '
|
||||
ensure_not_expanded () {
|
||||
rm -f trace2.txt &&
|
||||
echo >>sparse-index/untracked.txt &&
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
|
||||
git -C sparse-index "$@" &&
|
||||
|
||||
if test "$1" = "!"
|
||||
then
|
||||
shift &&
|
||||
test_must_fail env \
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
|
||||
git -C sparse-index "$@" || return 1
|
||||
else
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
|
||||
git -C sparse-index "$@" || return 1
|
||||
fi &&
|
||||
test_region ! index ensure_full_index trace2.txt
|
||||
}
|
||||
|
||||
@ -647,7 +691,35 @@ test_expect_success 'sparse-index is not expanded' '
|
||||
echo >>sparse-index/extra.txt &&
|
||||
ensure_not_expanded add extra.txt &&
|
||||
echo >>sparse-index/untracked.txt &&
|
||||
ensure_not_expanded add .
|
||||
ensure_not_expanded add . &&
|
||||
|
||||
ensure_not_expanded checkout -f update-deep &&
|
||||
test_config -C sparse-index pull.twohead ort &&
|
||||
(
|
||||
sane_unset GIT_TEST_MERGE_ALGORITHM &&
|
||||
for OPERATION in "merge -m merge" cherry-pick rebase
|
||||
do
|
||||
ensure_not_expanded merge -m merge update-folder1 &&
|
||||
ensure_not_expanded merge -m merge update-folder2 || return 1
|
||||
done
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'sparse-index is not expanded: merge conflict in cone' '
|
||||
init_repos &&
|
||||
|
||||
for side in right left
|
||||
do
|
||||
git -C sparse-index checkout -b expand-$side base &&
|
||||
echo $side >sparse-index/deep/a &&
|
||||
git -C sparse-index commit -a -m "$side" || return 1
|
||||
done &&
|
||||
|
||||
(
|
||||
sane_unset GIT_TEST_MERGE_ALGORITHM &&
|
||||
git -C sparse-index config pull.twohead ort &&
|
||||
ensure_not_expanded ! merge -m merged expand-right
|
||||
)
|
||||
'
|
||||
|
||||
# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
|
||||
|
Loading…
Reference in New Issue
Block a user