Skip to content

Commit 49fdd51

Browse files
derrickstoleegitster
authored andcommitted
add: skip tracked paths outside sparse-checkout cone
When 'git add' adds a tracked file that is outside of the sparse-checkout cone, it checks the SKIP_WORKTREE bit to see if the file exists outside of the sparse-checkout cone. This is usually correct, except in the case of a merge conflict outside of the cone. Modify add_pathspec_matched_against_index() to be more careful about paths by checking the sparse-checkout patterns in addition to the SKIP_WORKTREE bit. This causes 'git add' to no longer allow files outside of the cone that removed the SKIP_WORKTREE bit due to a merge conflict. With only this change, users will only be able to add the file after adding the file to the sparse-checkout cone. A later change will allow users to force adding even though the file is outside of the sparse-checkout cone. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 105e8b0 commit 49fdd51

File tree

5 files changed

+34
-10
lines changed

5 files changed

+34
-10
lines changed

builtin/add.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ static void update_callback(struct diff_queue_struct *q,
9494
for (i = 0; i < q->nr; i++) {
9595
struct diff_filepair *p = q->queue[i];
9696
const char *path = p->one->path;
97+
98+
if (!path_in_sparse_checkout(path, &the_index))
99+
continue;
100+
97101
switch (fix_unmerged_status(p, data)) {
98102
default:
99103
die(_("unexpected diff status %c"), p->status);

pathspec.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ void add_pathspec_matches_against_index(const struct pathspec *pathspec,
3939
return;
4040
for (i = 0; i < istate->cache_nr; i++) {
4141
const struct cache_entry *ce = istate->cache[i];
42-
if (sw_action == PS_IGNORE_SKIP_WORKTREE && ce_skip_worktree(ce))
42+
if (sw_action == PS_IGNORE_SKIP_WORKTREE &&
43+
(ce_skip_worktree(ce) || !path_in_sparse_checkout(ce->name, istate)))
4344
continue;
4445
ce_path_match(istate, ce, pathspec, seen);
4546
}
@@ -70,7 +71,7 @@ char *find_pathspecs_matching_skip_worktree(const struct pathspec *pathspec)
7071

7172
for (i = 0; i < istate->cache_nr; i++) {
7273
struct cache_entry *ce = istate->cache[i];
73-
if (ce_skip_worktree(ce))
74+
if (ce_skip_worktree(ce) || !path_in_sparse_checkout(ce->name, istate))
7475
ce_path_match(istate, ce, pathspec, seen);
7576
}
7677

t/t1091-sparse-checkout-builtin.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged stat
406406
git -C unmerged sparse-checkout disable
407407
'
408408

409-
test_expect_success 'sparse-checkout reapply' '
409+
test_expect_failure 'sparse-checkout reapply' '
410410
git clone repo tweak &&
411411
412412
echo dirty >tweak/deep/deeper2/a &&
@@ -438,6 +438,8 @@ test_expect_success 'sparse-checkout reapply' '
438438
test_i18ngrep "warning.*The following paths are unmerged" err &&
439439
test_path_is_file tweak/folder1/a &&
440440
441+
# NEEDSWORK: We are asking to update a file outside of the
442+
# sparse-checkout cone, but this is no longer allowed.
441443
git -C tweak add folder1/a &&
442444
git -C tweak sparse-checkout reapply 2>err &&
443445
test_must_be_empty err &&

t/t1092-sparse-checkout-compatibility.sh

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -546,10 +546,9 @@ test_expect_failure 'merge with conflict outside cone' '
546546
test_all_match git status --porcelain=v2 &&
547547
548548
# 2. Add the file with conflict markers
549-
# NEEDSWORK: Even though the merge conflict removed the
550-
# SKIP_WORKTREE bit from the index entry for folder1/a, we should
551-
# warn that this is a problematic add.
552-
test_all_match git add folder1/a &&
549+
test_sparse_match test_must_fail git add folder1/a &&
550+
grep "Disable or modify the sparsity rules" sparse-checkout-err &&
551+
test_sparse_unstaged folder1/a &&
553552
test_all_match git status --porcelain=v2 &&
554553
555554
# 3. Rename the file to another sparse filename and
@@ -558,7 +557,9 @@ test_expect_failure 'merge with conflict outside cone' '
558557
# NEEDSWORK: This mode now fails, because folder2/z is
559558
# outside of the sparse-checkout cone and does not match an
560559
# existing index entry with the SKIP_WORKTREE bit cleared.
561-
test_all_match git add folder2 &&
560+
test_sparse_match test_must_fail git add folder2 &&
561+
grep "Disable or modify the sparsity rules" sparse-checkout-err &&
562+
test_sparse_unstaged folder2/z &&
562563
test_all_match git status --porcelain=v2 &&
563564
564565
test_all_match git merge --continue &&
@@ -586,7 +587,9 @@ test_expect_failure 'cherry-pick/rebase with conflict outside cone' '
586587
# NEEDSWORK: Even though the merge conflict removed the
587588
# SKIP_WORKTREE bit from the index entry for folder1/a, we should
588589
# warn that this is a problematic add.
589-
test_all_match git add folder1/a &&
590+
test_sparse_match test_must_fail git add folder1/a &&
591+
grep "Disable or modify the sparsity rules" sparse-checkout-err &&
592+
test_sparse_unstaged folder1/a &&
590593
test_all_match git status --porcelain=v2 &&
591594
592595
# 3. Rename the file to another sparse filename and
@@ -595,7 +598,9 @@ test_expect_failure 'cherry-pick/rebase with conflict outside cone' '
595598
# outside of the sparse-checkout cone and does not match an
596599
# existing index entry with the SKIP_WORKTREE bit cleared.
597600
run_on_all mv folder2/a folder2/z &&
598-
test_all_match git add folder2 &&
601+
test_sparse_match test_must_fail git add folder2 &&
602+
grep "Disable or modify the sparsity rules" sparse-checkout-err &&
603+
test_sparse_unstaged folder2/z &&
599604
test_all_match git status --porcelain=v2 &&
600605
601606
test_all_match git $OPERATION --continue &&

t/t3705-add-sparse-checkout.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ test_expect_success 'do not warn when pathspec matches dense entries' '
158158
git ls-files --error-unmatch dense_entry
159159
'
160160

161+
test_expect_success 'git add fails outside of sparse-checkout definition' '
162+
test_when_finished git sparse-checkout disable &&
163+
test_commit a &&
164+
git sparse-checkout init &&
165+
git sparse-checkout set a &&
166+
echo >>sparse_entry &&
167+
168+
git update-index --no-skip-worktree sparse_entry &&
169+
test_must_fail git add sparse_entry &&
170+
test_sparse_entry_unstaged
171+
'
172+
161173
test_expect_success 'add obeys advice.updateSparsePath' '
162174
setup_sparse_entry &&
163175
test_must_fail git -c advice.updateSparsePath=false add sparse_entry 2>stderr &&

0 commit comments

Comments
 (0)