show: integrate with the sparse index

The 'git show' command can take an input to request the state of an object in the index. This can lead to parsing the index in order to load a specific file entry. Without the change presented here, a sparse index would expand to a full one, taking much longer than usual to access a simple file. There is one behavioral change that happens here, though: we now can find a sparse directory entry within the index! Commands that previously failed because we could not find an entry in the worktree or index now succeed because we _do_ find an entry in the index. There might be more work to do to make other situations succeed when looking for an indexed tree, perhaps by looking at or updating the cache-tree extension as needed. These situations include having a full index or asking for a directory that is within the sparse-checkout cone (and hence is not a sparse directory entry in the index). For now, we demonstrate how the sparse index integration is extremely simple for files outside of the cone as well as directories within the cone. A later change will resolve this behavior around sparse directories. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Apr 26, 2022 at 20:43 UTC a37d14422a4edd4f95abbe9532f518127cd3ef69
2 files changed +25 -4
builtin/log.c
+5
@@ -661,6 +661,11 @@ int cmd_show(int argc, const char **argv, const char *prefix)
661 init_log_defaults();
662 git_config(git_log_config, NULL);
663
664 + if (the_repository->gitdir) {
665 + prepare_repo_settings(the_repository);
666 + the_repository->settings.command_requires_full_index = 0;
667 + }
668 +
669 memset(&match_all, 0, sizeof(match_all));
670 repo_init_revisions(the_repository, &rev, prefix);
671 git_config(grep_config, &rev.grep_filter);
t/t1092-sparse-checkout-compatibility.sh
+20 -4
@@ -1159,12 +1159,21 @@ test_expect_success 'show (cached blobs/trees)' '
1159 test_sparse_match git show :folder1/a &&
1160
1161 # Asking "git show" for directories in the index
1162 - # does not work as implemented. The error message is
1163 - # different for a full checkout and a sparse checkout
1164 - # when the directory is outside of the cone.
1162 + # had different behavior depending on the existence
1163 + # of a sparse index.
1164 test_all_match test_must_fail git show :deep/ &&
1165 test_must_fail git -C full-checkout show :folder1/ &&
1167 - test_sparse_match test_must_fail git show :folder1/
1166 + test_must_fail git -C sparse-checkout show :folder1/ &&
1167 +
1168 + git -C sparse-index show :folder1/ >actual &&
1169 + git -C full-checkout show HEAD:folder1 >expect &&
1170 +
1171 + # The output of "git show" includes the way we referenced the
1172 + # objects, so strip that out.
1173 + test_line_count = 4 actual &&
1174 + tail -n 2 actual >actual-trunc &&
1175 + tail -n 2 expect >expect-trunc &&
1176 + test_cmp expect-trunc actual-trunc
1177 '
1178
1179 test_expect_success 'submodule handling' '
@@ -1388,6 +1397,13 @@ test_expect_success 'sparse index is not expanded: diff' '
1397 ensure_not_expanded diff --cached
1398 '
1399
1400 +test_expect_success 'sparse index is not expanded: show' '
1401 + init_repos &&
1402 +
1403 + ensure_not_expanded show :a &&
1404 + ensure_not_expanded show :deep/a
1405 +'
1406 +
1407 test_expect_success 'sparse index is not expanded: update-index' '
1408 init_repos &&
1409