untracked cache: invalidate dirs recursively if .gitignore changes

It's easy to see that if an existing .gitignore changes, its SHA-1 would be different and invalidate_gitignore() is called. If .gitignore is removed, add_excludes() will treat it like an empty .gitignore, which again should invalidate the cached directory data. if .gitignore is added, lookup_untracked() already fills initial .gitignore SHA-1 as "empty file", so again invalidate_gitignore() is called. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Mar 8, 2015 at 17:12 UTC 5ebf79ad4b308c678bd9623dd906c01bb0ab7e0f
1 file changed +17 -1
dir.c
+17 -1
@@ -1011,7 +1011,23 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
1011 add_excludes(el->src, el->src, stk->baselen, el, 1,
1012 untracked ? &sha1_stat : NULL);
1013 }
1014 - if (untracked) {
1014 + /*
1015 + * NEEDSWORK: when untracked cache is enabled, prep_exclude()
1016 + * will first be called in valid_cached_dir() then maybe many
1017 + * times more in last_exclude_matching(). When the cache is
1018 + * used, last_exclude_matching() will not be called and
1019 + * reading .gitignore content will be a waste.
1020 + *
1021 + * So when it's called by valid_cached_dir() and we can get
1022 + * .gitignore SHA-1 from the index (i.e. .gitignore is not
1023 + * modified on work tree), we could delay reading the
1024 + * .gitignore content until we absolutely need it in
1025 + * last_exclude_matching(). Be careful about ignore rule
1026 + * order, though, if you do that.
1027 + */
1028 + if (untracked &&
1029 + hashcmp(sha1_stat.sha1, untracked->exclude_sha1)) {
1030 + invalidate_gitignore(dir->untracked, untracked);
1031 hashcpy(untracked->exclude_sha1, sha1_stat.sha1);
1032 }
1033 dir->exclude_stack = stk;