summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
authorLibravatar Derrick Stolee <dstolee@microsoft.com>2021-04-01 01:49:40 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2021-04-14 13:46:30 -0700
commit95e0321c4dbb81eca5dc1c6f96b176b00a0368d7 (patch)
treee4865809318fdd60f9777006278ccdb635e1327d /read-cache.c
parent*: remove 'const' qualifier for struct index_state (diff)
downloadtgif-95e0321c4dbb81eca5dc1c6f96b176b00a0368d7.tar.xz
read-cache: expand on query into sparse-directory entry
Callers to index_name_pos() or index_name_stage_pos() have a specific path in mind. If that happens to be a path with an ancestor being a sparse-directory entry, it can lead to unexpected results. In the case that we did not find the requested path, check to see if the position _before_ the inserted position is a sparse directory entry that matches the initial segment of the input path (including the directory separator at the end of the directory name). If so, then expand the index to be a full index and search again. This expansion will only happen once per index read. Future enhancements could be more careful to expand only the necessary sparse directory entry, but then we would have a special "not fully sparse, but also not fully expanded" mode that could affect writing the index to file. Since this only occurs if a specific file is requested outside of the sparse checkout definition, this is unlikely to be a common situation. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Reviewed-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/read-cache.c b/read-cache.c
index 3ad9457809..3698bc7bf7 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -567,6 +567,27 @@ static int index_name_stage_pos(struct index_state *istate, const char *name, in
}
first = next+1;
}
+
+ if (istate->sparse_index &&
+ first > 0) {
+ /* Note: first <= istate->cache_nr */
+ struct cache_entry *ce = istate->cache[first - 1];
+
+ /*
+ * If we are in a sparse-index _and_ the entry before the
+ * insertion position is a sparse-directory entry that is
+ * an ancestor of 'name', then we need to expand the index
+ * and search again. This will only trigger once, because
+ * thereafter the index is fully expanded.
+ */
+ if (S_ISSPARSEDIR(ce->ce_mode) &&
+ ce_namelen(ce) < namelen &&
+ !strncmp(name, ce->name, ce_namelen(ce))) {
+ ensure_full_index(istate);
+ return index_name_stage_pos(istate, name, namelen, stage);
+ }
+ }
+
return -first-1;
}