untracked-cache: support sparse checkout

Remove a check that would disable the untracked cache for sparse checkouts. Add tests that ensure that the untracked cache works with sparse checkouts -- specifically considering the case that a file foo/bar is checked out, but foo/.gitignore is not. Signed-off-by: David Turner <dturner@twopensource.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Turner committed Jul 31, 2015 at 13:35 UTC 7687252f3f7def11a862a0fd118c531ee630bd05
2 files changed +122 -14
dir.c
+3 -14
@@ -1078,10 +1078,9 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
1078 (!untracked || !untracked->valid ||
1079 /*
1080 * .. and .gitignore does not exist before
1081 - * (i.e. null exclude_sha1 and skip_worktree is
1082 - * not set). Then we can skip loading .gitignore,
1083 - * which would result in ENOENT anyway.
1084 - * skip_worktree is taken care in read_directory()
1081 + * (i.e. null exclude_sha1). Then we can skip
1082 + * loading .gitignore, which would result in
1083 + * ENOENT anyway.
1084 */
1085 !is_null_sha1(untracked->exclude_sha1))) {
1086 /*
@@ -1880,7 +1879,6 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
1879 const struct pathspec *pathspec)
1880 {
1881 struct untracked_cache_dir *root;
1883 - int i;
1882
1883 if (!dir->untracked || getenv("GIT_DISABLE_UNTRACKED_CACHE"))
1884 return NULL;
@@ -1932,15 +1930,6 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
1930 if (dir->exclude_list_group[EXC_CMDL].nr)
1931 return NULL;
1932
1935 - /*
1936 - * An optimization in prep_exclude() does not play well with
1937 - * CE_SKIP_WORKTREE. It's a rare case anyway, if a single
1938 - * entry has that bit set, disable the whole untracked cache.
1939 - */
1940 - for (i = 0; i < active_nr; i++)
1941 - if (ce_skip_worktree(active_cache[i]))
1942 - return NULL;
1943 -
1933 if (!ident_in_untracked(dir->untracked)) {
1934 warning(_("Untracked cache is disabled on this system."));
1935 return NULL;
t/t7063-status-untracked-cache.sh
+119
@@ -354,4 +354,123 @@ EOF
354 test_cmp ../expect ../actual
355 '
356
357 +test_expect_success 'set up for sparse checkout testing' '
358 + echo two >done/.gitignore &&
359 + echo three >>done/.gitignore &&
360 + echo two >done/two &&
361 + git add -f done/two done/.gitignore &&
362 + git commit -m "first commit"
363 +'
364 +
365 +test_expect_success 'status after commit' '
366 + : >../trace &&
367 + GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
368 + git status --porcelain >../actual &&
369 + cat >../status.expect <<EOF &&
370 +?? .gitignore
371 +?? dtwo/
372 +EOF
373 + test_cmp ../status.expect ../actual &&
374 + cat >../trace.expect <<EOF &&
375 +node creation: 0
376 +gitignore invalidation: 0
377 +directory invalidation: 0
378 +opendir: 1
379 +EOF
380 + test_cmp ../trace.expect ../trace
381 +'
382 +
383 +test_expect_success 'untracked cache correct after commit' '
384 + test-dump-untracked-cache >../actual &&
385 + cat >../expect <<EOF &&
386 +info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
387 +core.excludesfile 0000000000000000000000000000000000000000
388 +exclude_per_dir .gitignore
389 +flags 00000006
390 +/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
391 +.gitignore
392 +dtwo/
393 +/done/ 0000000000000000000000000000000000000000 recurse valid
394 +/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
395 +/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
396 +two
397 +EOF
398 + test_cmp ../expect ../actual
399 +'
400 +
401 +test_expect_success 'set up sparse checkout' '
402 + echo "done/[a-z]*" >.git/info/sparse-checkout &&
403 + test_config core.sparsecheckout true &&
404 + git checkout master &&
405 + git update-index --untracked-cache &&
406 + git status --porcelain >/dev/null && # prime the cache
407 + test_path_is_missing done/.gitignore &&
408 + test_path_is_file done/one
409 +'
410 +
411 +test_expect_success 'create files, some of which are gitignored' '
412 + echo three >done/three && # three is gitignored
413 + echo four >done/four && # four is gitignored at a higher level
414 + echo five >done/five # five is not gitignored
415 +'
416 +
417 +test_expect_success 'test sparse status with untracked cache' '
418 + : >../trace &&
419 + avoid_racy &&
420 + GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
421 + git status --porcelain >../status.actual &&
422 + cat >../status.expect <<EOF &&
423 +?? .gitignore
424 +?? done/five
425 +?? dtwo/
426 +EOF
427 + test_cmp ../status.expect ../status.actual &&
428 + cat >../trace.expect <<EOF &&
429 +node creation: 0
430 +gitignore invalidation: 1
431 +directory invalidation: 2
432 +opendir: 2
433 +EOF
434 + test_cmp ../trace.expect ../trace
435 +'
436 +
437 +test_expect_success 'untracked cache correct after status' '
438 + test-dump-untracked-cache >../actual &&
439 + cat >../expect <<EOF &&
440 +info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
441 +core.excludesfile 0000000000000000000000000000000000000000
442 +exclude_per_dir .gitignore
443 +flags 00000006
444 +/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
445 +.gitignore
446 +dtwo/
447 +/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
448 +five
449 +/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
450 +/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
451 +two
452 +EOF
453 + test_cmp ../expect ../actual
454 +'
455 +
456 +test_expect_success 'test sparse status again with untracked cache' '
457 + avoid_racy &&
458 + : >../trace &&
459 + GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
460 + git status --porcelain >../status.actual &&
461 + cat >../status.expect <<EOF &&
462 +?? .gitignore
463 +?? done/five
464 +?? dtwo/
465 +EOF
466 + test_cmp ../status.expect ../status.actual &&
467 + cat >../trace.expect <<EOF &&
468 +node creation: 0
469 +gitignore invalidation: 0
470 +directory invalidation: 0
471 +opendir: 0
472 +EOF
473 + test_cmp ../trace.expect ../trace
474 +'
475 +
476 test_done