Skip to content

Commit e9331c4

Browse files
committed
sparse-index: make mixed reset sparse-aware
Due to the introduction of sparse directory entries in the `diff_cache` execution (used internally by `reset --mixed`), explicit `change` and `add_remove` functions are specified for merging of the interior contents of those sparse directories. Additionally, to handle cases in which `reset --mixed` must merge files nested multiple levels deep in directories outside the sparse checkout cone, the `recursive` diff option is added. Signed-off-by: Victoria Dye <[email protected]>
1 parent 9a65b6a commit e9331c4

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

builtin/reset.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,44 @@ static int read_from_tree(const struct pathspec *pathspec,
195195
int intent_to_add)
196196
{
197197
struct diff_options opt;
198+
unsigned int i;
199+
char *skip_worktree_seen = NULL;
198200

199201
memset(&opt, 0, sizeof(opt));
200202
copy_pathspec(&opt.pathspec, pathspec);
201203
opt.output_format = DIFF_FORMAT_CALLBACK;
202204
opt.format_callback = update_index_from_diff;
203205
opt.format_callback_data = &intent_to_add;
204206
opt.flags.override_submodule_config = 1;
207+
opt.flags.recursive = 1;
205208
opt.repo = the_repository;
209+
opt.change = diff_change;
210+
opt.add_remove = diff_addremove;
211+
212+
/*
213+
* When pathspec is given for resetting a cone-mode sparse checkout, it may
214+
* identify entries that are nested in sparse directories, in which case the
215+
* index should be expanded. For the sake of efficiency, this check is
216+
* overly-cautious: anything with a wildcard or a magic prefix requires
217+
* expansion, as well as literal paths that aren't in the sparse checkout
218+
* definition AND don't match any directory in the index.
219+
*/
220+
if (pathspec->nr && the_index.sparse_index) {
221+
if (pathspec->magic || pathspec->has_wildcard) {
222+
ensure_full_index(&the_index);
223+
} else {
224+
for (i = 0; i < pathspec->nr; i++) {
225+
if (!path_in_cone_modesparse_checkout(pathspec->items[i].original, &the_index) &&
226+
!matches_skip_worktree(pathspec, i, &skip_worktree_seen)) {
227+
ensure_full_index(&the_index);
228+
break;
229+
}
230+
}
231+
}
232+
}
233+
234+
free(skip_worktree_seen);
206235

207-
ensure_full_index(&the_index);
208236
if (do_diff_cache(tree_oid, &opt))
209237
return 1;
210238
diffcore_std(&opt);

t/t1092-sparse-checkout-compatibility.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ test_expect_success 'reset with sparse directory pathspec outside definition' '
569569
test_all_match git status --porcelain=v2
570570
'
571571

572-
test_expect_success 'reset with file pathspec outside sparse definition' '
572+
test_expect_success 'reset with pathspec match in sparse directory' '
573573
init_repos &&
574574
575575
test_all_match git checkout -b reset-test update-deep &&
@@ -802,14 +802,25 @@ test_expect_success 'sparse-index is not expanded' '
802802
for ref in update-deep update-folder1 update-folder2 update-deep
803803
do
804804
echo >>sparse-index/README.md &&
805+
ensure_not_expanded reset --mixed $ref
805806
ensure_not_expanded reset --hard $ref
806807
done &&
807808
808809
ensure_not_expanded reset --hard update-deep &&
809810
ensure_not_expanded reset --keep base &&
810811
ensure_not_expanded reset --merge update-deep &&
811-
ensure_not_expanded reset --hard &&
812812
813+
ensure_not_expanded reset base -- deep/a &&
814+
ensure_not_expanded reset base -- nonexistent-file &&
815+
ensure_not_expanded reset deepest -- deep &&
816+
817+
# Although folder1 is outside the sparse definition, it exists as a
818+
# directory entry in the index, so it will be reset without needing to
819+
# expand the full index.
820+
ensure_not_expanded reset --hard update-folder1 &&
821+
ensure_not_expanded reset base -- folder1 &&
822+
823+
ensure_not_expanded reset --hard update-deep &&
813824
ensure_not_expanded checkout -f update-deep &&
814825
(
815826
sane_unset GIT_TEST_MERGE_ALGORITHM &&

0 commit comments

Comments
 (0)