Skip to content

Commit 36e9f0c

Browse files
committed
Merge branch 'ds/sparse-index-ita-crash' into jch
A crash in the sparse-index collapse code when encountering an invalidated cache-tree node (due to an intent-to-add path) has been fixed by avoiding collapsing such subtrees. * ds/sparse-index-ita-crash: sparse-index: avoid crash on intent-to-add entry outside the cone
2 parents f09e87b + eede1e6 commit 36e9f0c

3 files changed

Lines changed: 82 additions & 1 deletion

File tree

sparse-index.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,17 @@ static int convert_to_sparse_rec(struct index_state *istate,
113113
continue;
114114
}
115115

116+
span = ct->down[pos]->cache_tree->entry_count;
117+
if (span < 0) {
118+
/* cache-tree entry is invalidated, cannot collapse. */
119+
istate->cache[num_converted++] = ce;
120+
i++;
121+
continue;
122+
}
123+
116124
strbuf_setlen(&child_path, 0);
117125
strbuf_add(&child_path, ce->name, slash - ce->name + 1);
118126

119-
span = ct->down[pos]->cache_tree->entry_count;
120127
count = convert_to_sparse_rec(istate,
121128
num_converted, i, i + span,
122129
child_path.buf, child_path.len,

t/t1092-sparse-checkout-compatibility.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,54 @@ test_expect_success 'add, commit, checkout' '
384384
test_all_match git checkout -
385385
'
386386

387+
test_expect_success 'intent-to-add entries outside sparse-checkout' '
388+
init_repos &&
389+
390+
write_script edit-contents <<-\EOF &&
391+
echo text >>$1
392+
EOF
393+
394+
test_sparse_match git sparse-checkout set deep folder1 &&
395+
run_on_sparse mkdir -p folder1 &&
396+
run_on_all ../edit-contents folder1/newita &&
397+
test_sparse_match git add -N folder1/newita &&
398+
399+
test_sparse_match git sparse-checkout set deep &&
400+
test_sparse_match git status --porcelain=v2 &&
401+
test_sparse_match git ls-files --stage
402+
'
403+
404+
test_expect_success 'intent-to-add with --sparse outside sparse-checkout' '
405+
init_repos &&
406+
407+
write_script edit-contents <<-\EOF &&
408+
echo text >>$1
409+
EOF
410+
411+
run_on_all mkdir -p folder1 &&
412+
run_on_all ../edit-contents folder1/newita &&
413+
test_all_match git add --sparse --intent-to-add folder1/newita &&
414+
415+
test_all_match git status --porcelain=v2 &&
416+
test_all_match git ls-files --stage &&
417+
test_all_match git diff --cached --stat &&
418+
419+
# Ensure sparse index stores correct sparse directories and
420+
# intent-to-add path.
421+
git -C sparse-index ls-files --format="%(path)" --sparse >out &&
422+
423+
# These paths should be present in index as-is.
424+
test_grep "^before/\$" out &&
425+
test_grep "^folder1/newita\$" out &&
426+
test_grep "^folder2/\$" out &&
427+
test_grep "^x/\$" out &&
428+
429+
# folder/0/ could theoretically be collapsed to a sparse
430+
# directory entry, but the current implementation avoids the
431+
# reduction because of folder1/newita
432+
test_grep "^folder1/0/0/0\$" out
433+
'
434+
387435
test_expect_success 'git add, checkout, and reset with -p' '
388436
init_repos &&
389437

t/t3705-add-sparse-checkout.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,30 @@ test_expect_success 'refuse to add non-skip-worktree file from sparse dir' '
233233
test_cmp expect stderr
234234
'
235235

236+
test_expect_success 'intent-to-add entry and sparse index' '
237+
test_when_finished "git sparse-checkout disable" &&
238+
test_when_finished "git reset --hard" &&
239+
240+
git sparse-checkout disable &&
241+
mkdir -p in out &&
242+
echo base >in/file &&
243+
echo base >out/file &&
244+
git add in/file out/file &&
245+
git commit -m "in and out directories" &&
246+
247+
# enable sparse-checkout, but with all child directories.
248+
git config index.sparse true &&
249+
git sparse-checkout set in out &&
250+
251+
# create a new path and set intent-to-add bit
252+
echo new >out/newita &&
253+
git add -N out/newita &&
254+
255+
# collapse sparse-checkout, and make sure that the sparse index
256+
# maintains the intent-to-add bit.
257+
git sparse-checkout set in &&
258+
git ls-files --error-unmatch out/newita &&
259+
git status --porcelain
260+
'
261+
236262
test_done

0 commit comments

Comments
 (0)