Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sparse-index.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/sparse-index.c b/sparse-index.c
index b82648b10e..eed170cd8f 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -341,18 +341,70 @@ void ensure_correct_sparsity(struct index_state *istate)
ensure_full_index(istate);
}
+static int path_found(const char *path, const char **dirname, size_t *dir_len,
+ int *dir_found)
+{
+ struct stat st;
+ char *newdir;
+ char *tmp;
+
+ /*
+ * If dirname corresponds to a directory that doesn't exist, and this
+ * path starts with dirname, then path can't exist.
+ */
+ if (!*dir_found && !memcmp(path, *dirname, *dir_len))
+ return 0;
+
+ /*
+ * If path itself exists, return 1.
+ */
+ if (!lstat(path, &st))
+ return 1;
+
+ /*
+ * Otherwise, path does not exist so we'll return 0...but we'll first
+ * determine some info about its parent directory so we can avoid
+ * lstat calls for future cache entries.
+ */
+ newdir = strrchr(path, '/');
+ if (!newdir)
+ return 0; /* Didn't find a parent dir; just return 0 now. */
+
+ /*
+ * If path starts with directory (which we already lstat'ed and found),
+ * then no need to lstat parent directory again.
+ */
+ if (*dir_found && *dirname && memcmp(path, *dirname, *dir_len))
+ return 0;
+
+ /* Free previous dirname, and cache path's dirname */
+ *dirname = path;
+ *dir_len = newdir - path + 1;
+
+ tmp = xstrndup(path, *dir_len);
+ *dir_found = !lstat(tmp, &st);
+ free(tmp);
+
+ return 0;
+}
+
void clear_skip_worktree_from_present_files(struct index_state *istate)
{
+ const char *last_dirname = NULL;
+ size_t dir_len = 0;
+ int dir_found = 1;
+
int i;
+
if (!core_apply_sparse_checkout)
return;
restart:
for (i = 0; i < istate->cache_nr; i++) {
struct cache_entry *ce = istate->cache[i];
- struct stat st;
- if (ce_skip_worktree(ce) && !lstat(ce->name, &st)) {
+ if (ce_skip_worktree(ce) &&
+ path_found(ce->name, &last_dirname, &dir_len, &dir_found)) {
if (S_ISSPARSEDIR(ce->ce_mode)) {
ensure_full_index(istate);
goto restart;