From 6e34bea30a226d90c9a1571fab0932f2a6dd327d Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Fri, 24 Sep 2021 09:44:19 -0400 Subject: [PATCH 1/3] unpack-trees: expand conditions for sparse result index After `unpack-trees` processing, the index would only be considered "sparse" if it contains any sparse directories. That condition missed the case where the index contains only files inside the sparse checkout definition. By explicitly checking for that condition and setting `sparse_index` accordingly, later processing to ensure the index "remains" full can be avoided. Signed-off-by: Victoria Dye --- unpack-trees.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/unpack-trees.c b/unpack-trees.c index 614e7ee38660f8..7229a4a820de5c 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1961,6 +1961,30 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options } } + /* + * After unpacking trees, the index will be marked "sparse" if any sparse + * directories have been encountered. However, the index may still be + * sparse if there are no sparse directories. To make sure the index is + * marked "sparse" as often as possible, the index is marked sparse if + * all of the following are true: + * - the command in progress allows use of a sparse index + * - the index is not already sparse + * - cone-mode sparse checkout with sparse index is enabled for the repo + * - all index entries are inside of the sparse checkout cone + */ + if (!repo->settings.command_requires_full_index && !o->result.sparse_index && + core_apply_sparse_checkout && core_sparse_checkout_cone && repo->settings.sparse_index) { + o->result.sparse_index = COLLAPSED; + for (i = 0; i < o->result.cache_nr; i++) { + struct cache_entry *ce = o->result.cache[i]; + + if (!path_in_cone_mode_sparse_checkout(ce->name, &o->result)) { + o->result.sparse_index = COMPLETELY_FULL; + break; + } + } + } + ret = check_updates(o, &o->result) ? (-2) : 0; if (o->dst_index) { move_index_extensions(&o->result, o->src_index); From ce00dbe6ae06a81f066bd8a20151c4823154ac7f Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Fri, 24 Sep 2021 09:33:16 -0400 Subject: [PATCH 2/3] checkout-index: perform lazy index expansion for `--sparse` When `--sparse` is specified for `checkout-index` but no sparse directory entries exist outside the sparse checkout definition, the index does not need to be expanded. For this case, moving the index expansion into an explicit check for a sparse directory entry prevents unnecessary expansion. Signed-off-by: Victoria Dye --- builtin/checkout-index.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 4ac566b5e22cb2..63500438468b44 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -128,11 +128,18 @@ static int checkout_all(const char *prefix, int prefix_length, int include_spars int i, errs = 0; struct cache_entry *last_ce = NULL; - if (include_sparse) - ensure_full_index(&the_index); - for (i = 0; i < active_nr ; i++) { struct cache_entry *ce = active_cache[i]; + if (include_sparse && S_ISSPARSEDIR(ce->ce_mode)) { + /* + * If the current entry is a sparse directory (and entries outside the + * sparse checkout definition are included), expand the index and + * continue the loop on the current index position (now pointing to the + * first entry inside the expanded sparse directory). + */ + ensure_full_index(&the_index); + ce = active_cache[i]; + } if (!include_sparse && !path_in_sparse_checkout(ce->name, &the_index)) continue; if (ce_stage(ce) != checkout_stage From f2336dd81f8053a4c4fc382811e3aaec47bc1e21 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Fri, 24 Sep 2021 09:49:46 -0400 Subject: [PATCH 3/3] stash: move sparse index test for `stash -u` Move the test for `git stash -u` into the `sparse-index is not expanded` test because it no longer expands the index (temporary or otherwise) when all stashed files are in the sparse checkout definition. Signed-off-by: Victoria Dye --- t/t1092-sparse-checkout-compatibility.sh | 25 +++--------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 9b450c070a51ac..e623795b0fb979 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1234,6 +1234,9 @@ test_expect_success 'sparse-index is not expanded' ' ensure_not_expanded stash apply stash@{0} && ensure_not_expanded stash drop stash@{0} && + ensure_not_expanded stash -u && + ensure_not_expanded stash pop && + ensure_not_expanded stash create && oid=$(git -C sparse-index stash create) && ensure_not_expanded stash store -m "test" $oid && @@ -1383,28 +1386,6 @@ test_expect_success 'sparse index is not expanded: read-tree' ' ensure_not_expanded read-tree --prefix=deep/deeper2 -u deepest ' -# NEEDSWORK: although the full repository's index is _not_ expanded as part of -# stash, a temporary index, which is _not_ sparse, is created when stashing and -# applying a stash of untracked files. As a result, the test reports that it -# finds an instance of `ensure_full_index`, but it does not carry with it the -# performance implications of expanding the full repository index. -test_expect_success 'sparse index is not expanded: stash -u' ' - init_repos && - - mkdir -p sparse-index/folder1 && - echo >>sparse-index/README.md && - echo >>sparse-index/a && - echo >>sparse-index/folder1/new && - - GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \ - git -C sparse-index stash -u && - test_region index ensure_full_index trace2.txt && - - GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \ - git -C sparse-index stash pop && - test_region index ensure_full_index trace2.txt -' - # NEEDSWORK: similar to `git add`, untracked files outside of the sparse # checkout definition are successfully stashed and unstashed. test_expect_success 'stash -u outside sparse checkout definition' '