sparse-checkout: toggle sparse index from builtin
The sparse index extension is used to signal that index writes should be in sparse mode. This was only updated using GIT_TEST_SPARSE_INDEX=1. Add a '--[no-]sparse-index' option to 'git sparse-checkout init' that specifies if the sparse index should be used. It also updates the index to use the correct format, either way. Add a warning in the documentation that the use of a repository extension might reduce compatibility with third-party tools. 'git sparse-checkout init' already sets extension.worktreeConfig, which places most sparse-checkout users outside of the scope of most third-party tools. Update t1092-sparse-checkout-compatibility.sh to use this CLI instead of GIT_TEST_SPARSE_INDEX=1. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
58300f4743
commit
122ba1f7b5
@ -45,6 +45,20 @@ To avoid interfering with other worktrees, it first enables the
|
|||||||
When `--cone` is provided, the `core.sparseCheckoutCone` setting is
|
When `--cone` is provided, the `core.sparseCheckoutCone` setting is
|
||||||
also set, allowing for better performance with a limited set of
|
also set, allowing for better performance with a limited set of
|
||||||
patterns (see 'CONE PATTERN SET' below).
|
patterns (see 'CONE PATTERN SET' below).
|
||||||
|
+
|
||||||
|
Use the `--[no-]sparse-index` option to toggle the use of the sparse
|
||||||
|
index format. This reduces the size of the index to be more closely
|
||||||
|
aligned with your sparse-checkout definition. This can have significant
|
||||||
|
performance advantages for commands such as `git status` or `git add`.
|
||||||
|
This feature is still experimental. Some commands might be slower with
|
||||||
|
a sparse index until they are properly integrated with the feature.
|
||||||
|
+
|
||||||
|
**WARNING:** Using a sparse index requires modifying the index in a way
|
||||||
|
that is not completely understood by external tools. If you have trouble
|
||||||
|
with this compatibility, then run `git sparse-checkout init --no-sparse-index`
|
||||||
|
to rewrite your index to not be sparse. Older versions of Git will not
|
||||||
|
understand the sparse directory entries index extension and may fail to
|
||||||
|
interact with your repository until it is disabled.
|
||||||
|
|
||||||
'set'::
|
'set'::
|
||||||
Write a set of patterns to the sparse-checkout file, as given as
|
Write a set of patterns to the sparse-checkout file, as given as
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "unpack-trees.h"
|
#include "unpack-trees.h"
|
||||||
#include "wt-status.h"
|
#include "wt-status.h"
|
||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
|
#include "sparse-index.h"
|
||||||
|
|
||||||
static const char *empty_base = "";
|
static const char *empty_base = "";
|
||||||
|
|
||||||
@ -283,12 +284,13 @@ static int set_config(enum sparse_checkout_mode mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char const * const builtin_sparse_checkout_init_usage[] = {
|
static char const * const builtin_sparse_checkout_init_usage[] = {
|
||||||
N_("git sparse-checkout init [--cone]"),
|
N_("git sparse-checkout init [--cone] [--[no-]sparse-index]"),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct sparse_checkout_init_opts {
|
static struct sparse_checkout_init_opts {
|
||||||
int cone_mode;
|
int cone_mode;
|
||||||
|
int sparse_index;
|
||||||
} init_opts;
|
} init_opts;
|
||||||
|
|
||||||
static int sparse_checkout_init(int argc, const char **argv)
|
static int sparse_checkout_init(int argc, const char **argv)
|
||||||
@ -303,11 +305,15 @@ static int sparse_checkout_init(int argc, const char **argv)
|
|||||||
static struct option builtin_sparse_checkout_init_options[] = {
|
static struct option builtin_sparse_checkout_init_options[] = {
|
||||||
OPT_BOOL(0, "cone", &init_opts.cone_mode,
|
OPT_BOOL(0, "cone", &init_opts.cone_mode,
|
||||||
N_("initialize the sparse-checkout in cone mode")),
|
N_("initialize the sparse-checkout in cone mode")),
|
||||||
|
OPT_BOOL(0, "sparse-index", &init_opts.sparse_index,
|
||||||
|
N_("toggle the use of a sparse index")),
|
||||||
OPT_END(),
|
OPT_END(),
|
||||||
};
|
};
|
||||||
|
|
||||||
repo_read_index(the_repository);
|
repo_read_index(the_repository);
|
||||||
|
|
||||||
|
init_opts.sparse_index = -1;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, NULL,
|
argc = parse_options(argc, argv, NULL,
|
||||||
builtin_sparse_checkout_init_options,
|
builtin_sparse_checkout_init_options,
|
||||||
builtin_sparse_checkout_init_usage, 0);
|
builtin_sparse_checkout_init_usage, 0);
|
||||||
@ -326,6 +332,15 @@ static int sparse_checkout_init(int argc, const char **argv)
|
|||||||
sparse_filename = get_sparse_checkout_filename();
|
sparse_filename = get_sparse_checkout_filename();
|
||||||
res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL);
|
res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL);
|
||||||
|
|
||||||
|
if (init_opts.sparse_index >= 0) {
|
||||||
|
if (set_sparse_index_config(the_repository, init_opts.sparse_index) < 0)
|
||||||
|
die(_("failed to modify sparse-index config"));
|
||||||
|
|
||||||
|
/* force an index rewrite */
|
||||||
|
repo_read_index(the_repository);
|
||||||
|
the_repository->index->updated_workdir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we already have a sparse-checkout file, use it. */
|
/* If we already have a sparse-checkout file, use it. */
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
free(sparse_filename);
|
free(sparse_filename);
|
||||||
|
@ -102,21 +102,32 @@ static int convert_to_sparse_rec(struct index_state *istate,
|
|||||||
return num_converted - start_converted;
|
return num_converted - start_converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int enable_sparse_index(struct repository *repo)
|
static int set_index_sparse_config(struct repository *repo, int enable)
|
||||||
{
|
{
|
||||||
const char *config_path = repo_git_path(repo, "config.worktree");
|
int res;
|
||||||
|
char *config_path = repo_git_path(repo, "config.worktree");
|
||||||
git_config_set_in_file_gently(config_path,
|
res = git_config_set_in_file_gently(config_path,
|
||||||
"index.sparse",
|
"index.sparse",
|
||||||
"true");
|
enable ? "true" : NULL);
|
||||||
|
free(config_path);
|
||||||
|
|
||||||
prepare_repo_settings(repo);
|
prepare_repo_settings(repo);
|
||||||
repo->settings.sparse_index = 1;
|
repo->settings.sparse_index = 1;
|
||||||
return 0;
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_sparse_index_config(struct repository *repo, int enable)
|
||||||
|
{
|
||||||
|
int res = set_index_sparse_config(repo, enable);
|
||||||
|
|
||||||
|
prepare_repo_settings(repo);
|
||||||
|
repo->settings.sparse_index = enable;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int convert_to_sparse(struct index_state *istate)
|
int convert_to_sparse(struct index_state *istate)
|
||||||
{
|
{
|
||||||
|
int test_env;
|
||||||
if (istate->split_index || istate->sparse_index ||
|
if (istate->split_index || istate->sparse_index ||
|
||||||
!core_apply_sparse_checkout || !core_sparse_checkout_cone)
|
!core_apply_sparse_checkout || !core_sparse_checkout_cone)
|
||||||
return 0;
|
return 0;
|
||||||
@ -128,11 +139,9 @@ int convert_to_sparse(struct index_state *istate)
|
|||||||
* The GIT_TEST_SPARSE_INDEX environment variable triggers the
|
* The GIT_TEST_SPARSE_INDEX environment variable triggers the
|
||||||
* index.sparse config variable to be on.
|
* index.sparse config variable to be on.
|
||||||
*/
|
*/
|
||||||
if (git_env_bool("GIT_TEST_SPARSE_INDEX", 0)) {
|
test_env = git_env_bool("GIT_TEST_SPARSE_INDEX", -1);
|
||||||
int err = enable_sparse_index(istate->repo);
|
if (test_env >= 0)
|
||||||
if (err < 0)
|
set_sparse_index_config(istate->repo, test_env);
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only convert to sparse if index.sparse is set.
|
* Only convert to sparse if index.sparse is set.
|
||||||
|
@ -5,4 +5,7 @@ struct index_state;
|
|||||||
void ensure_full_index(struct index_state *istate);
|
void ensure_full_index(struct index_state *istate);
|
||||||
int convert_to_sparse(struct index_state *istate);
|
int convert_to_sparse(struct index_state *istate);
|
||||||
|
|
||||||
|
struct repository;
|
||||||
|
int set_sparse_index_config(struct repository *repo, int enable);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ test_description='compare full workdir to sparse workdir'
|
|||||||
# So, disable the check until that integration is complete.
|
# So, disable the check until that integration is complete.
|
||||||
GIT_TEST_CHECK_CACHE_TREE=0
|
GIT_TEST_CHECK_CACHE_TREE=0
|
||||||
GIT_TEST_SPLIT_INDEX=0
|
GIT_TEST_SPLIT_INDEX=0
|
||||||
|
GIT_TEST_SPARSE_INDEX=
|
||||||
|
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
@ -100,25 +101,26 @@ init_repos () {
|
|||||||
# initialize sparse-checkout definitions
|
# initialize sparse-checkout definitions
|
||||||
git -C sparse-checkout sparse-checkout init --cone &&
|
git -C sparse-checkout sparse-checkout init --cone &&
|
||||||
git -C sparse-checkout sparse-checkout set deep &&
|
git -C sparse-checkout sparse-checkout set deep &&
|
||||||
GIT_TEST_SPARSE_INDEX=1 git -C sparse-index sparse-checkout init --cone &&
|
git -C sparse-index sparse-checkout init --cone --sparse-index &&
|
||||||
GIT_TEST_SPARSE_INDEX=1 git -C sparse-index sparse-checkout set deep
|
test_cmp_config -C sparse-index true index.sparse &&
|
||||||
|
git -C sparse-index sparse-checkout set deep
|
||||||
}
|
}
|
||||||
|
|
||||||
run_on_sparse () {
|
run_on_sparse () {
|
||||||
(
|
(
|
||||||
cd sparse-checkout &&
|
cd sparse-checkout &&
|
||||||
GIT_TEST_SPARSE_INDEX=0 "$@" >../sparse-checkout-out 2>../sparse-checkout-err
|
"$@" >../sparse-checkout-out 2>../sparse-checkout-err
|
||||||
) &&
|
) &&
|
||||||
(
|
(
|
||||||
cd sparse-index &&
|
cd sparse-index &&
|
||||||
GIT_TEST_SPARSE_INDEX=1 "$@" >../sparse-index-out 2>../sparse-index-err
|
"$@" >../sparse-index-out 2>../sparse-index-err
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
run_on_all () {
|
run_on_all () {
|
||||||
(
|
(
|
||||||
cd full-checkout &&
|
cd full-checkout &&
|
||||||
GIT_TEST_SPARSE_INDEX=0 "$@" >../full-checkout-out 2>../full-checkout-err
|
"$@" >../full-checkout-out 2>../full-checkout-err
|
||||||
) &&
|
) &&
|
||||||
run_on_sparse "$@"
|
run_on_sparse "$@"
|
||||||
}
|
}
|
||||||
@ -148,7 +150,7 @@ test_expect_success 'sparse-index contents' '
|
|||||||
|| return 1
|
|| return 1
|
||||||
done &&
|
done &&
|
||||||
|
|
||||||
GIT_TEST_SPARSE_INDEX=1 git -C sparse-index sparse-checkout set folder1 &&
|
git -C sparse-index sparse-checkout set folder1 &&
|
||||||
|
|
||||||
test-tool -C sparse-index read-cache --table >cache &&
|
test-tool -C sparse-index read-cache --table >cache &&
|
||||||
for dir in deep folder2 x
|
for dir in deep folder2 x
|
||||||
@ -158,7 +160,7 @@ test_expect_success 'sparse-index contents' '
|
|||||||
|| return 1
|
|| return 1
|
||||||
done &&
|
done &&
|
||||||
|
|
||||||
GIT_TEST_SPARSE_INDEX=1 git -C sparse-index sparse-checkout set deep/deeper1 &&
|
git -C sparse-index sparse-checkout set deep/deeper1 &&
|
||||||
|
|
||||||
test-tool -C sparse-index read-cache --table >cache &&
|
test-tool -C sparse-index read-cache --table >cache &&
|
||||||
for dir in deep/deeper2 folder1 folder2 x
|
for dir in deep/deeper2 folder1 folder2 x
|
||||||
@ -166,7 +168,14 @@ test_expect_success 'sparse-index contents' '
|
|||||||
TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
|
TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
|
||||||
grep "040000 tree $TREE $dir/" cache \
|
grep "040000 tree $TREE $dir/" cache \
|
||||||
|| return 1
|
|| return 1
|
||||||
done
|
done &&
|
||||||
|
|
||||||
|
# Disabling the sparse-index removes tree entries with full ones
|
||||||
|
git -C sparse-index sparse-checkout init --no-sparse-index &&
|
||||||
|
|
||||||
|
test-tool -C sparse-index read-cache --table >cache &&
|
||||||
|
! grep "040000 tree" cache &&
|
||||||
|
test_sparse_match test-tool read-cache --table
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'expanded in-memory index matches full index' '
|
test_expect_success 'expanded in-memory index matches full index' '
|
||||||
@ -396,9 +405,6 @@ test_expect_success 'submodule handling' '
|
|||||||
test_expect_success 'sparse-index is expanded and converted back' '
|
test_expect_success 'sparse-index is expanded and converted back' '
|
||||||
init_repos &&
|
init_repos &&
|
||||||
|
|
||||||
(
|
|
||||||
GIT_TEST_SPARSE_INDEX=1 &&
|
|
||||||
export GIT_TEST_SPARSE_INDEX &&
|
|
||||||
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
|
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
|
||||||
git -C sparse-index -c core.fsmonitor="" reset --hard &&
|
git -C sparse-index -c core.fsmonitor="" reset --hard &&
|
||||||
test_region index convert_to_sparse trace2.txt &&
|
test_region index convert_to_sparse trace2.txt &&
|
||||||
@ -408,7 +414,6 @@ test_expect_success 'sparse-index is expanded and converted back' '
|
|||||||
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
|
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
|
||||||
git -C sparse-index -c core.fsmonitor="" status -uno &&
|
git -C sparse-index -c core.fsmonitor="" status -uno &&
|
||||||
test_region index ensure_full_index trace2.txt
|
test_region index ensure_full_index trace2.txt
|
||||||
)
|
|
||||||
'
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
x
Reference in New Issue
Block a user