diff --git a/builtin/am.c b/builtin/am.c index e9623b8307793f..fbb442ae799d8a 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -23,6 +23,7 @@ #include "lockfile.h" #include "cache-tree.h" #include "refs.h" +#include "repo-settings.h" #include "commit.h" #include "diff.h" #include "unpack-trees.h" @@ -2464,6 +2465,9 @@ int cmd_am(int argc, /* Ensure a valid committer ident can be constructed */ git_committer_info(IDENT_STRICT); + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + if (repo_read_index_preload(the_repository, NULL, 0) < 0) die(_("failed to read the index")); diff --git a/builtin/grep.c b/builtin/grep.c index 6a09571903cd26..d3a6404cc85e39 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -500,6 +500,9 @@ static int grep_submodule(struct grep_opt *opt, * * Note that this list is not exhaustive. */ + prepare_repo_settings(subrepo); + subrepo->settings.command_requires_full_index = 0; + repo_read_gitmodules(subrepo, 0); /* diff --git a/builtin/mv.c b/builtin/mv.c index 948b3306390337..860baa5e2c2260 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -22,11 +22,13 @@ #include "string-list.h" #include "parse-options.h" #include "read-cache-ll.h" +#include "repo-settings.h" #include "setup.h" #include "strvec.h" #include "submodule.h" #include "entry.h" +#include "sparse-index.h" static const char * const builtin_mv_usage[] = { N_("git mv [-v] [-f] [-n] [-k] "), @@ -247,10 +249,16 @@ int cmd_mv(int argc, if (--argc < 1) usage_with_options(builtin_mv_usage, builtin_mv_options); + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR); if (repo_read_index(the_repository) < 0) die(_("index file corrupt")); + if (ignore_sparse) + ensure_full_index(the_repository->index); + internal_prefix_pathspec(&sources, prefix, argv, argc, 0); CALLOC_ARRAY(modes, argc); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 1cc82a134db22e..a40cf7d66bd9b6 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -16,6 +16,7 @@ #include "read-cache.h" #include "setup.h" #include "sparse-index.h" +#include "repo-settings.h" #include "submodule.h" #include "submodule-config.h" #include "string-list.h" @@ -3832,5 +3833,8 @@ int cmd_submodule__helper(int argc, }; argc = parse_options(argc, argv, prefix, options, usage, 0); + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + return fn(argc, argv, prefix, repo); } diff --git a/read-cache.c b/read-cache.c index 21829102ae275e..999ea5defad3e5 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2189,7 +2189,7 @@ static void set_new_index_sparsity(struct index_state *istate) * repo settings. */ prepare_repo_settings(istate->repo); - if (!istate->repo->settings.command_requires_full_index && + if (!repo_settings_get_command_requires_full_index(istate->repo) && is_sparse_index_allowed(istate, 0)) istate->sparse_index = 1; } @@ -2321,7 +2321,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist) * settings and other properties of the index (if necessary). */ prepare_repo_settings(istate->repo); - if (istate->repo->settings.command_requires_full_index) + if (repo_settings_get_command_requires_full_index(istate->repo)) ensure_full_index(istate); else ensure_correct_sparsity(istate); diff --git a/repo-settings.c b/repo-settings.c index 208e09ff17fcee..62122969990bd5 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -1,5 +1,6 @@ #include "git-compat-util.h" #include "config.h" +#include "gettext.h" #include "repo-settings.h" #include "repository.h" #include "midx.h" @@ -131,14 +132,6 @@ void prepare_repo_settings(struct repository *r) die("unknown fetch negotiation algorithm '%s'", strval); } - /* - * This setting guards all index reads to require a full index - * over a sparse index. After suitable guards are placed in the - * codebase around uses of the index, this setting will be - * removed. - */ - r->settings.command_requires_full_index = 1; - if (!repo_config_get_ulong(r, "core.deltabasecachelimit", &ulongval)) r->settings.delta_base_cache_limit = ulongval; @@ -156,6 +149,20 @@ void prepare_repo_settings(struct repository *r) r->settings.packed_git_limit = ulongval; } +int repo_settings_get_command_requires_full_index(struct repository *r) +{ + if (r->settings.command_requires_full_index >= 0) + return r->settings.command_requires_full_index; + + if (git_env_bool("GIT_ALLOW_SPARSE_INDEX_WITHOUT_DECLARATION", 0)) { + r->settings.command_requires_full_index = 1; + return 1; + } + + die(_("BUG: command has not declared sparse-index compatibility\n" + "set GIT_ALLOW_SPARSE_INDEX_WITHOUT_DECLARATION=1 to bypass")); +} + void repo_settings_clear(struct repository *r) { struct repo_settings empty = REPO_SETTINGS_INIT; diff --git a/repo-settings.h b/repo-settings.h index cad9c3f0cc15f3..cc9316b779d3a1 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -72,6 +72,7 @@ struct repo_settings { char *hooks_path; }; #define REPO_SETTINGS_INIT { \ + .command_requires_full_index = -1, \ .shared_repository = -1, \ .index_version = -1, \ .core_untracked_cache = UNTRACKED_CACHE_KEEP, \ @@ -85,6 +86,7 @@ struct repo_settings { void prepare_repo_settings(struct repository *r); void repo_settings_clear(struct repository *r); +int repo_settings_get_command_requires_full_index(struct repository *r); /* Read the value for "core.logAllRefUpdates". */ enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo); diff --git a/repository.c b/repository.c index db57b8308b94e7..6c7f86d1b739c3 100644 --- a/repository.c +++ b/repository.c @@ -465,7 +465,7 @@ int repo_read_index(struct repository *repo) res = read_index_from(repo->index, repo->index_file, repo->gitdir); prepare_repo_settings(repo); - if (repo->settings.command_requires_full_index) + if (repo_settings_get_command_requires_full_index(repo)) ensure_full_index(repo->index); /* diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 8186da5c887c56..bd664628296e9a 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1555,7 +1555,11 @@ test_expect_success 'sparse-index is not expanded' ' ensure_not_expanded merge -m merge update-folder1 && ensure_not_expanded merge -m merge update-folder2 || return 1 done - ) + ) && + + ensure_not_expanded reset --hard && + ensure_not_expanded mv deep/a deep/renamed-a && + ensure_not_expanded mv deep/deeper2 deep/moved-deeper2 ' test_expect_success 'sparse-index is not expanded: merge conflict in cone' ' diff --git a/unpack-trees.c b/unpack-trees.c index 998a1e6dc70cae..33b927747039df 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1906,7 +1906,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options trace2_region_enter("unpack_trees", "unpack_trees", the_repository); prepare_repo_settings(repo); - if (repo->settings.command_requires_full_index) { + if (repo_settings_get_command_requires_full_index(repo)) { ensure_full_index(o->src_index); if (o->dst_index) ensure_full_index(o->dst_index); @@ -1964,7 +1964,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options o->internal.result.fsmonitor_has_run_once = o->src_index->fsmonitor_has_run_once; if (!o->src_index->initialized && - !repo->settings.command_requires_full_index && + !repo_settings_get_command_requires_full_index(repo) && is_sparse_index_allowed(&o->internal.result, 0)) o->internal.result.sparse_index = 1;