untracked-cache: write index when populating empty untracked cache

It is expected that an empty/unpopulated untracked cache structure can be written to the index - by update-index, or by a "git status" call that sees the untracked cache should be enabled and is not, but is running with options that make the untracked cache non-applicable in that run (eg a pathspec). Currently, if that happens, then subsequent "git status" calls end up populating the untracked cache, but not writing the index (not saving their work) - so the performance outcome is almost identical to the cache being altogether disabled. This continues until the index gets written with the untracked cache populated, for some *other* reason, such as a working tree change. Detect the condition where an empty untracked cache exists in the index and we will collect the list of untracked paths, and queue an index write under that condition, so that the collected untracked paths can be written out to the untracked cache extension in the index. This change depends on previous fixes to t7519 for the "ignore .git changes when invalidating UNTR" test case to pass - before this fix, the test never actually did anything as it was not set up correctly. Signed-off-by: Tao Klerks <tao@klerks.biz> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Tao Klerks committed Feb 27, 2022 at 21:57 UTC 317956d91239e86b26ce95735451698b042dbe5d
1 file changed +7 -3
dir.c
+7 -3
@@ -2781,7 +2781,8 @@ void remove_untracked_cache(struct index_state *istate)
2781
2782 static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *dir,
2783 int base_len,
2784 - const struct pathspec *pathspec)
2784 + const struct pathspec *pathspec,
2785 + struct index_state *istate)
2786 {
2787 struct untracked_cache_dir *root;
2788 static int untracked_cache_disabled = -1;
@@ -2845,8 +2846,11 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
2846 return NULL;
2847 }
2848
2848 - if (!dir->untracked->root)
2849 + if (!dir->untracked->root) {
2850 + /* Untracked cache existed but is not initialized; fix that */
2851 FLEX_ALLOC_STR(dir->untracked->root, name, "");
2852 + istate->cache_changed |= UNTRACKED_CHANGED;
2853 + }
2854
2855 /* Validate $GIT_DIR/info/exclude and core.excludesfile */
2856 root = dir->untracked->root;
@@ -2916,7 +2920,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
2920 return dir->nr;
2921 }
2922
2919 - untracked = validate_untracked_cache(dir, len, pathspec);
2923 + untracked = validate_untracked_cache(dir, len, pathspec, istate);
2924 if (!untracked)
2925 /*
2926 * make sure untracked cache code path is disabled,