From 0a6bb1dd9a0df6ac9d68149eae53e357ea031d99 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 b28bdbfb859250..9588d48912bd65 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1969,6 +1969,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 b8fb94365beca6e07677e737d6dc25e46adab481 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 c8821aba88ec9d6180f9f7780420eabc58aeaf1a 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 cfe21a8faeebf9..ac85de21f0ea8f 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1354,6 +1354,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 && @@ -1622,28 +1625,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' '