From 9f00bb7e6d1b71716e29b99623bd520033d6fd68 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 57f780163755d841903a23c76d37089c0bef9077 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 6016c9179c55882a76897021f0b515416c8a3230 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' '