summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2021-12-10 14:35:01 -0800
committerLibravatar Junio C Hamano <gitster@pobox.com>2021-12-10 14:35:01 -0800
commit5396d7b298e9db83e98fb6a552a42a6a59984305 (patch)
tree268a3d472bd5be4ec42da86a026a19a45e856b4f
parentMerge branch 'cw/protocol-v2-doc-fix' (diff)
parentsparse-index: update do_read_index to ensure correct sparsity (diff)
downloadtgif-5396d7b298e9db83e98fb6a552a42a6a59984305.tar.xz
Merge branch 'vd/sparse-sparsity-fix-on-read'
Ensure that the sparseness of the in-core index matches the index.sparse configuration specified by the repository immediately after the on-disk index file is read. * vd/sparse-sparsity-fix-on-read: sparse-index: update do_read_index to ensure correct sparsity sparse-index: add ensure_correct_sparsity function sparse-index: avoid unnecessary cache tree clearing test-read-cache.c: prepare_repo_settings after config init
-rw-r--r--read-cache.c8
-rw-r--r--sparse-index.c58
-rw-r--r--sparse-index.h1
-rw-r--r--t/helper/test-read-cache.c5
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh31
5 files changed, 86 insertions, 17 deletions
diff --git a/read-cache.c b/read-cache.c
index f398659662..d999fff9e4 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2352,9 +2352,17 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
if (!istate->repo)
istate->repo = the_repository;
+
+ /*
+ * If the command explicitly requires a full index, force it
+ * to be full. Otherwise, correct the sparsity based on repository
+ * settings and other properties of the index (if necessary).
+ */
prepare_repo_settings(istate->repo);
if (istate->repo->settings.command_requires_full_index)
ensure_full_index(istate);
+ else
+ ensure_correct_sparsity(istate);
return istate->cache_nr;
diff --git a/sparse-index.c b/sparse-index.c
index 7b7ff79e04..a1d505d50e 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -122,17 +122,17 @@ static int index_has_unmerged_entries(struct index_state *istate)
return 0;
}
-int convert_to_sparse(struct index_state *istate, int flags)
+static int is_sparse_index_allowed(struct index_state *istate, int flags)
{
- int test_env;
- if (istate->sparse_index || !istate->cache_nr ||
- !core_apply_sparse_checkout || !core_sparse_checkout_cone)
+ if (!core_apply_sparse_checkout || !core_sparse_checkout_cone)
return 0;
if (!istate->repo)
istate->repo = the_repository;
if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
+ int test_env;
+
/*
* The sparse index is not (yet) integrated with a split index.
*/
@@ -168,25 +168,41 @@ int convert_to_sparse(struct index_state *istate, int flags)
if (!istate->sparse_checkout_patterns->use_cone_patterns)
return 0;
+ return 1;
+}
+
+int convert_to_sparse(struct index_state *istate, int flags)
+{
/*
- * NEEDSWORK: If we have unmerged entries, then stay full.
- * Unmerged entries prevent the cache-tree extension from working.
+ * If the index is already sparse, empty, or otherwise
+ * cannot be converted to sparse, do not convert.
*/
- if (index_has_unmerged_entries(istate))
+ if (istate->sparse_index || !istate->cache_nr ||
+ !is_sparse_index_allowed(istate, flags))
return 0;
- /* Clear and recompute the cache-tree */
- cache_tree_free(&istate->cache_tree);
/*
- * Silently return if there is a problem with the cache tree update,
- * which might just be due to a conflict state in some entry.
- *
- * This might create new tree objects, so be sure to use
- * WRITE_TREE_MISSING_OK.
+ * NEEDSWORK: If we have unmerged entries, then stay full.
+ * Unmerged entries prevent the cache-tree extension from working.
*/
- if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
+ if (index_has_unmerged_entries(istate))
return 0;
+ if (!cache_tree_fully_valid(istate->cache_tree)) {
+ /* Clear and recompute the cache-tree */
+ cache_tree_free(&istate->cache_tree);
+
+ /*
+ * Silently return if there is a problem with the cache tree update,
+ * which might just be due to a conflict state in some entry.
+ *
+ * This might create new tree objects, so be sure to use
+ * WRITE_TREE_MISSING_OK.
+ */
+ if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
+ return 0;
+ }
+
remove_fsmonitor(istate);
trace2_region_enter("index", "convert_to_sparse", istate->repo);
@@ -313,6 +329,18 @@ void ensure_full_index(struct index_state *istate)
trace2_region_leave("index", "ensure_full_index", istate->repo);
}
+void ensure_correct_sparsity(struct index_state *istate)
+{
+ /*
+ * If the index can be sparse, make it sparse. Otherwise,
+ * ensure the index is full.
+ */
+ if (is_sparse_index_allowed(istate, 0))
+ convert_to_sparse(istate, 0);
+ else
+ ensure_full_index(istate);
+}
+
/*
* This static global helps avoid infinite recursion between
* expand_to_path() and index_file_exists().
diff --git a/sparse-index.h b/sparse-index.h
index 9f3d7bc7fa..656bd835b2 100644
--- a/sparse-index.h
+++ b/sparse-index.h
@@ -4,6 +4,7 @@
struct index_state;
#define SPARSE_INDEX_MEMORY_ONLY (1 << 0)
int convert_to_sparse(struct index_state *istate, int flags);
+void ensure_correct_sparsity(struct index_state *istate);
/*
* Some places in the codebase expect to search for a specific path.
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index b52c174acc..0d9f08931a 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -39,8 +39,6 @@ int cmd__read_cache(int argc, const char **argv)
int table = 0, expand = 0;
initialize_the_repository();
- prepare_repo_settings(r);
- r->settings.command_requires_full_index = 0;
for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
if (skip_prefix(*argv, "--print-and-refresh=", &name))
@@ -56,6 +54,9 @@ int cmd__read_cache(int argc, const char **argv)
setup_git_directory();
git_config(git_default_config, NULL);
+ prepare_repo_settings(r);
+ r->settings.command_requires_full_index = 0;
+
for (i = 0; i < cnt; i++) {
repo_read_index(r);
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 16fbd2c6db..4eaac6a99b 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -694,6 +694,37 @@ test_expect_success 'sparse-index is expanded and converted back' '
test_region index ensure_full_index trace2.txt
'
+test_expect_success 'index.sparse disabled inline uses full index' '
+ init_repos &&
+
+ # When index.sparse is disabled inline with `git status`, the
+ # index is expanded at the beginning of the execution then never
+ # converted back to sparse. It is then written to disk as a full index.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index -c index.sparse=false status &&
+ ! test_region index convert_to_sparse trace2.txt &&
+ test_region index ensure_full_index trace2.txt &&
+
+ # Since index.sparse is set to true at a repo level, the index
+ # is converted from full to sparse when read, then never expanded
+ # over the course of `git status`. It is written to disk as a sparse
+ # index.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index status &&
+ test_region index convert_to_sparse trace2.txt &&
+ ! test_region index ensure_full_index trace2.txt &&
+
+ # Now that the index has been written to disk as sparse, it is not
+ # converted to sparse (or expanded to full) when read by `git status`.
+ rm -f trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
+ git -C sparse-index status &&
+ ! test_region index convert_to_sparse trace2.txt &&
+ ! test_region index ensure_full_index trace2.txt
+'
+
ensure_not_expanded () {
rm -f trace2.txt &&
echo >>sparse-index/untracked.txt &&