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
This commit is contained in:
@ -2352,9 +2352,17 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
|
|||||||
|
|
||||||
if (!istate->repo)
|
if (!istate->repo)
|
||||||
istate->repo = the_repository;
|
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);
|
prepare_repo_settings(istate->repo);
|
||||||
if (istate->repo->settings.command_requires_full_index)
|
if (istate->repo->settings.command_requires_full_index)
|
||||||
ensure_full_index(istate);
|
ensure_full_index(istate);
|
||||||
|
else
|
||||||
|
ensure_correct_sparsity(istate);
|
||||||
|
|
||||||
return istate->cache_nr;
|
return istate->cache_nr;
|
||||||
|
|
||||||
|
@ -122,17 +122,17 @@ static int index_has_unmerged_entries(struct index_state *istate)
|
|||||||
return 0;
|
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 (!core_apply_sparse_checkout || !core_sparse_checkout_cone)
|
||||||
if (istate->sparse_index || !istate->cache_nr ||
|
|
||||||
!core_apply_sparse_checkout || !core_sparse_checkout_cone)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!istate->repo)
|
if (!istate->repo)
|
||||||
istate->repo = the_repository;
|
istate->repo = the_repository;
|
||||||
|
|
||||||
if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
|
if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
|
||||||
|
int test_env;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The sparse index is not (yet) integrated with a split index.
|
* The sparse index is not (yet) integrated with a split index.
|
||||||
*/
|
*/
|
||||||
@ -168,6 +168,19 @@ int convert_to_sparse(struct index_state *istate, int flags)
|
|||||||
if (!istate->sparse_checkout_patterns->use_cone_patterns)
|
if (!istate->sparse_checkout_patterns->use_cone_patterns)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convert_to_sparse(struct index_state *istate, int flags)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If the index is already sparse, empty, or otherwise
|
||||||
|
* cannot be converted to sparse, do not convert.
|
||||||
|
*/
|
||||||
|
if (istate->sparse_index || !istate->cache_nr ||
|
||||||
|
!is_sparse_index_allowed(istate, flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NEEDSWORK: If we have unmerged entries, then stay full.
|
* NEEDSWORK: If we have unmerged entries, then stay full.
|
||||||
* Unmerged entries prevent the cache-tree extension from working.
|
* Unmerged entries prevent the cache-tree extension from working.
|
||||||
@ -175,8 +188,10 @@ int convert_to_sparse(struct index_state *istate, int flags)
|
|||||||
if (index_has_unmerged_entries(istate))
|
if (index_has_unmerged_entries(istate))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!cache_tree_fully_valid(istate->cache_tree)) {
|
||||||
/* Clear and recompute the cache-tree */
|
/* Clear and recompute the cache-tree */
|
||||||
cache_tree_free(&istate->cache_tree);
|
cache_tree_free(&istate->cache_tree);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Silently return if there is a problem with the cache tree update,
|
* Silently return if there is a problem with the cache tree update,
|
||||||
* which might just be due to a conflict state in some entry.
|
* which might just be due to a conflict state in some entry.
|
||||||
@ -186,6 +201,7 @@ int convert_to_sparse(struct index_state *istate, int flags)
|
|||||||
*/
|
*/
|
||||||
if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
|
if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
remove_fsmonitor(istate);
|
remove_fsmonitor(istate);
|
||||||
|
|
||||||
@ -313,6 +329,18 @@ void ensure_full_index(struct index_state *istate)
|
|||||||
trace2_region_leave("index", "ensure_full_index", istate->repo);
|
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
|
* This static global helps avoid infinite recursion between
|
||||||
* expand_to_path() and index_file_exists().
|
* expand_to_path() and index_file_exists().
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
struct index_state;
|
struct index_state;
|
||||||
#define SPARSE_INDEX_MEMORY_ONLY (1 << 0)
|
#define SPARSE_INDEX_MEMORY_ONLY (1 << 0)
|
||||||
int convert_to_sparse(struct index_state *istate, int flags);
|
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.
|
* Some places in the codebase expect to search for a specific path.
|
||||||
|
@ -39,8 +39,6 @@ int cmd__read_cache(int argc, const char **argv)
|
|||||||
int table = 0, expand = 0;
|
int table = 0, expand = 0;
|
||||||
|
|
||||||
initialize_the_repository();
|
initialize_the_repository();
|
||||||
prepare_repo_settings(r);
|
|
||||||
r->settings.command_requires_full_index = 0;
|
|
||||||
|
|
||||||
for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
|
for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
|
||||||
if (skip_prefix(*argv, "--print-and-refresh=", &name))
|
if (skip_prefix(*argv, "--print-and-refresh=", &name))
|
||||||
@ -56,6 +54,9 @@ int cmd__read_cache(int argc, const char **argv)
|
|||||||
setup_git_directory();
|
setup_git_directory();
|
||||||
git_config(git_default_config, NULL);
|
git_config(git_default_config, NULL);
|
||||||
|
|
||||||
|
prepare_repo_settings(r);
|
||||||
|
r->settings.command_requires_full_index = 0;
|
||||||
|
|
||||||
for (i = 0; i < cnt; i++) {
|
for (i = 0; i < cnt; i++) {
|
||||||
repo_read_index(r);
|
repo_read_index(r);
|
||||||
|
|
||||||
|
@ -694,6 +694,37 @@ test_expect_success 'sparse-index is expanded and converted back' '
|
|||||||
test_region index ensure_full_index trace2.txt
|
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 () {
|
ensure_not_expanded () {
|
||||||
rm -f trace2.txt &&
|
rm -f trace2.txt &&
|
||||||
echo >>sparse-index/untracked.txt &&
|
echo >>sparse-index/untracked.txt &&
|
||||||
|
Reference in New Issue
Block a user