diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt index fa61241756..0ba8989820 100644 --- a/Documentation/config/advice.txt +++ b/Documentation/config/advice.txt @@ -116,6 +116,10 @@ advice.*:: skippedCherryPicks:: Shown when linkgit:git-rebase[1] skips a commit that has already been cherry-picked onto the upstream branch. + sparseIndexExpanded:: + Shown when a sparse index is expanded to a full index, which is likely + due to an unexpected set of files existing outside of the + sparse-checkout. statusAheadBehind:: Shown when linkgit:git-status[1] computes the ahead/behind counts for a local ref compared to its remote tracking ref, diff --git a/advice.c b/advice.c index 558a46fc0b..6b879d805c 100644 --- a/advice.c +++ b/advice.c @@ -78,6 +78,7 @@ static struct { [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" }, [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" }, [ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" }, + [ADVICE_SPARSE_INDEX_EXPANDED] = { "sparseIndexExpanded" }, [ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning" }, [ADVICE_STATUS_HINTS] = { "statusHints" }, [ADVICE_STATUS_U_OPTION] = { "statusUoption" }, diff --git a/advice.h b/advice.h index 5105d90129..d7466bc0ef 100644 --- a/advice.h +++ b/advice.h @@ -45,6 +45,7 @@ enum advice_type { ADVICE_SEQUENCER_IN_USE, ADVICE_SET_UPSTREAM_FAILURE, ADVICE_SKIPPED_CHERRY_PICKS, + ADVICE_SPARSE_INDEX_EXPANDED, ADVICE_STATUS_AHEAD_BEHIND_WARNING, ADVICE_STATUS_HINTS, ADVICE_STATUS_U_OPTION, diff --git a/sparse-index.c b/sparse-index.c index 9913a6078c..9958656ded 100644 --- a/sparse-index.c +++ b/sparse-index.c @@ -12,6 +12,22 @@ #include "config.h" #include "dir.h" #include "fsmonitor-ll.h" +#include "advice.h" + +/** + * This global is used by expand_index() to determine if we should give the + * advice for advice.sparseIndexExpanded when expanding a sparse index to a full + * one. However, this is sometimes done on purpose, such as in the sparse-checkout + * builtin, even when index.sparse=false. This may be disabled in + * convert_to_sparse(). + */ +static int give_advice_on_expansion = 1; +#define ADVICE_MSG \ + "The sparse index is expanding to a full index, a slow operation.\n" \ + "Your working directory likely has contents that are outside of\n" \ + "your sparse-checkout patterns. Use 'git sparse-checkout list' to\n" \ + "see your sparse-checkout definition and compare it to your working\n" \ + "directory contents. Running 'git clean' may assist in this cleanup." struct modify_index_context { struct index_state *write; @@ -183,6 +199,12 @@ int convert_to_sparse(struct index_state *istate, int flags) !is_sparse_index_allowed(istate, flags)) return 0; + /* + * If we are purposefully collapsing a full index, then don't give + * advice when it is expanded later. + */ + give_advice_on_expansion = 0; + /* * NEEDSWORK: If we have unmerged entries, then stay full. * Unmerged entries prevent the cache-tree extension from working. @@ -328,6 +350,12 @@ void expand_index(struct index_state *istate, struct pattern_list *pl) pl = NULL; } + if (!pl && give_advice_on_expansion) { + give_advice_on_expansion = 0; + advise_if_enabled(ADVICE_SPARSE_INDEX_EXPANDED, + _(ADVICE_MSG)); + } + /* * A NULL pattern set indicates we are expanding a full index, so * we use a special region name that indicates the full expansion. diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 2f1ae5fd3b..a2c0e1b4dc 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -159,7 +159,10 @@ init_repos () { git -C sparse-checkout sparse-checkout set deep && git -C sparse-index sparse-checkout init --cone --sparse-index && test_cmp_config -C sparse-index true index.sparse && - git -C sparse-index sparse-checkout set deep + git -C sparse-index sparse-checkout set deep && + + # Disable this message to keep stderr the same. + git -C sparse-index config advice.sparseIndexExpanded false } init_repos_as_submodules () { @@ -2331,4 +2334,15 @@ test_expect_success 'sparse-index is not expanded: check-attr' ' ensure_not_expanded check-attr -a --cached -- folder1/a ' +test_expect_success 'advice.sparseIndexExpanded' ' + init_repos && + + git -C sparse-index config --unset advice.sparseIndexExpanded && + git -C sparse-index sparse-checkout set deep/deeper1 && + mkdir -p sparse-index/deep/deeper2/deepest && + touch sparse-index/deep/deeper2/deepest/bogus && + git -C sparse-index status 2>err && + grep "The sparse index is expanding to a full index" err +' + test_done