Skip to content

Commit 68fb83b

Browse files
committed
Merge branch 'mt/fix-add-rm-with-sparse-index'
Fix-up to a topic already merged to 'master'. * mt/fix-add-rm-with-sparse-index: add, rm, mv: fix bug that prevents the update of non-sparse dirs
2 parents 7b3fd03 + 20141e3 commit 68fb83b

File tree

4 files changed

+96
-11
lines changed

4 files changed

+96
-11
lines changed

dir.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,8 +1504,9 @@ static int path_in_sparse_checkout_1(const char *path,
15041504
struct index_state *istate,
15051505
int require_cone_mode)
15061506
{
1507-
const char *base;
15081507
int dtype = DT_REG;
1508+
enum pattern_match_result match = UNDECIDED;
1509+
const char *end, *slash;
15091510

15101511
/*
15111512
* We default to accepting a path if there are no patterns or
@@ -1516,11 +1517,27 @@ static int path_in_sparse_checkout_1(const char *path,
15161517
!istate->sparse_checkout_patterns->use_cone_patterns))
15171518
return 1;
15181519

1519-
base = strrchr(path, '/');
1520-
return path_matches_pattern_list(path, strlen(path), base ? base + 1 : path,
1521-
&dtype,
1522-
istate->sparse_checkout_patterns,
1523-
istate) > 0;
1520+
/*
1521+
* If UNDECIDED, use the match from the parent dir (recursively), or
1522+
* fall back to NOT_MATCHED at the topmost level. Note that cone mode
1523+
* never returns UNDECIDED, so we will execute only one iteration in
1524+
* this case.
1525+
*/
1526+
for (end = path + strlen(path);
1527+
end > path && match == UNDECIDED;
1528+
end = slash) {
1529+
1530+
for (slash = end - 1; slash > path && *slash != '/'; slash--)
1531+
; /* do nothing */
1532+
1533+
match = path_matches_pattern_list(path, end - path,
1534+
slash > path ? slash + 1 : path, &dtype,
1535+
istate->sparse_checkout_patterns, istate);
1536+
1537+
/* We are going to match the parent dir now */
1538+
dtype = DT_DIR;
1539+
}
1540+
return match > 0;
15241541
}
15251542

15261543
int path_in_sparse_checkout(const char *path,

t/t3602-rm-sparse-checkout.sh

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,20 @@ done
4040
test_expect_success 'recursive rm does not remove sparse entries' '
4141
git reset --hard &&
4242
git sparse-checkout set sub/dir &&
43-
test_must_fail git rm -r sub &&
44-
git rm --sparse -r sub &&
43+
git rm -r sub &&
4544
git status --porcelain -uno >actual &&
4645
cat >expected <<-\EOF &&
46+
D sub/dir/e
47+
EOF
48+
test_cmp expected actual &&
49+
50+
git rm --sparse -r sub &&
51+
git status --porcelain -uno >actual2 &&
52+
cat >expected2 <<-\EOF &&
4753
D sub/d
4854
D sub/dir/e
4955
EOF
50-
test_cmp expected actual
56+
test_cmp expected2 actual2
5157
'
5258

5359
test_expect_success 'recursive rm --sparse removes sparse entries' '
@@ -105,4 +111,29 @@ test_expect_success 'refuse to rm a non-skip-worktree path outside sparse cone'
105111
test_path_is_missing b
106112
'
107113

114+
test_expect_success 'can remove files from non-sparse dir' '
115+
git reset --hard &&
116+
git sparse-checkout disable &&
117+
mkdir -p w x/y &&
118+
test_commit w/f &&
119+
test_commit x/y/f &&
120+
121+
git sparse-checkout set w !/x y/ &&
122+
git rm w/f.t x/y/f.t 2>stderr &&
123+
test_must_be_empty stderr
124+
'
125+
126+
test_expect_success 'refuse to remove non-skip-worktree file from sparse dir' '
127+
git reset --hard &&
128+
git sparse-checkout disable &&
129+
mkdir -p x/y/z &&
130+
test_commit x/y/z/f &&
131+
git sparse-checkout set !/x y/ !x/y/z &&
132+
133+
git update-index --no-skip-worktree x/y/z/f.t &&
134+
test_must_fail git rm x/y/z/f.t 2>stderr &&
135+
echo x/y/z/f.t | cat sparse_error_header - sparse_hint >expect &&
136+
test_cmp expect stderr
137+
'
138+
108139
test_done

t/t3705-add-sparse-checkout.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,21 @@ test_expect_success 'add allows sparse entries with --sparse' '
214214
test_must_be_empty stderr
215215
'
216216

217+
test_expect_success 'can add files from non-sparse dir' '
218+
git sparse-checkout set w !/x y/ &&
219+
mkdir -p w x/y &&
220+
touch w/f x/y/f &&
221+
git add w/f x/y/f 2>stderr &&
222+
test_must_be_empty stderr
223+
'
224+
225+
test_expect_success 'refuse to add non-skip-worktree file from sparse dir' '
226+
git sparse-checkout set !/x y/ !x/y/z &&
227+
mkdir -p x/y/z &&
228+
touch x/y/z/f &&
229+
test_must_fail git add x/y/z/f 2>stderr &&
230+
echo x/y/z/f | cat sparse_error_header - sparse_hint >expect &&
231+
test_cmp expect stderr
232+
'
233+
217234
test_done

t/t7002-mv-sparse-checkout.sh

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,6 @@ test_expect_success 'recursive mv refuses to move (possible) sparse' '
143143
cat >>expect <<-\EOF &&
144144
sub/d
145145
sub2/d
146-
sub/dir/e
147-
sub2/dir/e
148146
sub/dir2/e
149147
sub2/dir2/e
150148
EOF
@@ -186,4 +184,26 @@ test_expect_success 'recursive mv refuses to move sparse' '
186184
git reset --hard HEAD~1
187185
'
188186

187+
test_expect_success 'can move files to non-sparse dir' '
188+
git reset --hard &&
189+
git sparse-checkout init --no-cone &&
190+
git sparse-checkout set a b c w !/x y/ &&
191+
mkdir -p w x/y &&
192+
193+
git mv a w/new-a 2>stderr &&
194+
git mv b x/y/new-b 2>stderr &&
195+
test_must_be_empty stderr
196+
'
197+
198+
test_expect_success 'refuse to move file to non-skip-worktree sparse path' '
199+
git reset --hard &&
200+
git sparse-checkout init --no-cone &&
201+
git sparse-checkout set a !/x y/ !x/y/z &&
202+
mkdir -p x/y/z &&
203+
204+
test_must_fail git mv a x/y/z/new-a 2>stderr &&
205+
echo x/y/z/new-a | cat sparse_error_header - sparse_hint >expect &&
206+
test_cmp expect stderr
207+
'
208+
189209
test_done

0 commit comments

Comments
 (0)