Skip to content

Commit aeabab5

Browse files
Kjetil Barvikgitster
authored andcommitted
lstat_cache(): introduce invalidate_lstat_cache() function
In some cases it could maybe be necessary to say to the cache that "Hey, I deleted/changed the type of this pathname and if you currently have it inside your cache, you should deleted it". This patch introduce a function which support this. Signed-off-by: Kjetil Barvik <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent bad4a54 commit aeabab5

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ extern int checkout_entry(struct cache_entry *ce, const struct checkout *state,
722722
extern int has_symlink_leading_path(int len, const char *name);
723723
extern int has_symlink_or_noent_leading_path(int len, const char *name);
724724
extern int has_dirs_only_path(int len, const char *name, int prefix_len);
725+
extern void invalidate_lstat_cache(int len, const char *name);
725726

726727
extern struct alternate_object_database {
727728
struct alternate_object_database *next;

symlinks.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,30 @@ static struct cache_def {
1212
* Returns the length (on a path component basis) of the longest
1313
* common prefix match of 'name' and the cached path string.
1414
*/
15-
static inline int longest_match_lstat_cache(int len, const char *name)
15+
static inline int longest_match_lstat_cache(int len, const char *name,
16+
int *previous_slash)
1617
{
17-
int max_len, match_len = 0, i = 0;
18+
int max_len, match_len = 0, match_len_prev = 0, i = 0;
1819

1920
max_len = len < cache.len ? len : cache.len;
2021
while (i < max_len && name[i] == cache.path[i]) {
21-
if (name[i] == '/')
22+
if (name[i] == '/') {
23+
match_len_prev = match_len;
2224
match_len = i;
25+
}
2326
i++;
2427
}
2528
/* Is the cached path string a substring of 'name'? */
26-
if (i == cache.len && cache.len < len && name[cache.len] == '/')
29+
if (i == cache.len && cache.len < len && name[cache.len] == '/') {
30+
match_len_prev = match_len;
2731
match_len = cache.len;
2832
/* Is 'name' a substring of the cached path string? */
29-
else if ((i == len && len < cache.len && cache.path[len] == '/') ||
30-
(i == len && len == cache.len))
33+
} else if ((i == len && len < cache.len && cache.path[len] == '/') ||
34+
(i == len && len == cache.len)) {
35+
match_len_prev = match_len;
3136
match_len = len;
37+
}
38+
*previous_slash = match_len_prev;
3239
return match_len;
3340
}
3441

@@ -63,7 +70,7 @@ static inline void reset_lstat_cache(int track_flags, int prefix_len_stat_func)
6370
static int lstat_cache(int len, const char *name,
6471
int track_flags, int prefix_len_stat_func)
6572
{
66-
int match_len, last_slash, last_slash_dir;
73+
int match_len, last_slash, last_slash_dir, previous_slash;
6774
int match_flags, ret_flags, save_flags, max_len, ret;
6875
struct stat st;
6976

@@ -81,7 +88,8 @@ static int lstat_cache(int len, const char *name,
8188
* Check to see if we have a match from the cache for
8289
* the 2 "excluding" path types.
8390
*/
84-
match_len = last_slash = longest_match_lstat_cache(len, name);
91+
match_len = last_slash =
92+
longest_match_lstat_cache(len, name, &previous_slash);
8593
match_flags = cache.flags & track_flags & (FL_NOENT|FL_SYMLINK);
8694
if (match_flags && match_len == cache.len)
8795
return match_flags;
@@ -167,6 +175,26 @@ static int lstat_cache(int len, const char *name,
167175
return ret_flags;
168176
}
169177

178+
/*
179+
* Invalidate the given 'name' from the cache, if 'name' matches
180+
* completely with the cache.
181+
*/
182+
void invalidate_lstat_cache(int len, const char *name)
183+
{
184+
int match_len, previous_slash;
185+
186+
match_len = longest_match_lstat_cache(len, name, &previous_slash);
187+
if (len == match_len) {
188+
if ((cache.track_flags & FL_DIR) && previous_slash > 0) {
189+
cache.path[previous_slash] = '\0';
190+
cache.len = previous_slash;
191+
cache.flags = FL_DIR;
192+
} else
193+
reset_lstat_cache(cache.track_flags,
194+
cache.prefix_len_stat_func);
195+
}
196+
}
197+
170198
#define USE_ONLY_LSTAT 0
171199

172200
/*

0 commit comments

Comments
 (0)