summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2021-12-21 15:03:17 -0800
committerJunio C Hamano <gitster@pobox.com>2021-12-21 15:03:17 -0800
commit8d2c37320bd01bbce4b88365c160bc4a542bee48 (patch)
treed805155422fb863b694eaaeb71967d9667f9e81d
parent3f9d5059c66f45ac75dd701b0798d3891150c1e7 (diff)
parentadd4c864b60766174ad4f74ba7be17e66d61ef16 (diff)
Merge branch 'ld/sparse-diff-blame'
Teach diff and blame to work well with sparse index. * ld/sparse-diff-blame: blame: enable and test the sparse index diff: enable and test the sparse index diff: replace --staged with --cached in t1092 tests repo-settings: prepare_repo_settings only in git repos test-read-cache: set up repo after git directory commit-graph: return if there is no git directory git: ensure correct git directory setup with -h
-rw-r--r--builtin/blame.c3
-rw-r--r--builtin/diff.c5
-rw-r--r--commit-graph.c5
-rw-r--r--git.c39
-rw-r--r--repo-settings.c3
-rwxr-xr-xt/perf/p2000-sparse-operations.sh4
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh109
7 files changed, 131 insertions, 37 deletions
diff --git a/builtin/blame.c b/builtin/blame.c
index f9ee3f8c68..7fafeac408 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -939,6 +939,9 @@ parse_done:
revs.diffopt.flags.follow_renames = 0;
argc = parse_options_end(&ctx);
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+
if (incremental || (output_option & OUTPUT_PORCELAIN)) {
if (show_progress > 0)
die(_("--progress can't be used with --incremental or porcelain formats"));
diff --git a/builtin/diff.c b/builtin/diff.c
index dd8ce688ba..fa4683377e 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -437,6 +437,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
prefix = setup_git_directory_gently(&nongit);
+ if (!nongit) {
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+ }
+
if (!no_index) {
/*
* Treat git diff with at least one path outside of the
diff --git a/commit-graph.c b/commit-graph.c
index 2706683acf..265c010122 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -632,10 +632,13 @@ static int prepare_commit_graph(struct repository *r)
struct object_directory *odb;
/*
+ * Early return if there is no git dir or if the commit graph is
+ * disabled.
+ *
* This must come before the "already attempted?" check below, because
* we want to disable even an already-loaded graph file.
*/
- if (r->commit_graph_disabled)
+ if (!r->gitdir || r->commit_graph_disabled)
return 0;
if (r->objects->commit_graph_attempted)
diff --git a/git.c b/git.c
index 5ff21be21f..7edafd8ecf 100644
--- a/git.c
+++ b/git.c
@@ -421,27 +421,30 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
int status, help;
struct stat st;
const char *prefix;
+ int run_setup = (p->option & (RUN_SETUP | RUN_SETUP_GENTLY));
- prefix = NULL;
help = argc == 2 && !strcmp(argv[1], "-h");
- if (!help) {
- if (p->option & RUN_SETUP)
- prefix = setup_git_directory();
- else if (p->option & RUN_SETUP_GENTLY) {
- int nongit_ok;
- prefix = setup_git_directory_gently(&nongit_ok);
- }
- precompose_argv_prefix(argc, argv, NULL);
- if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY) &&
- !(p->option & DELAY_PAGER_CONFIG))
- use_pager = check_pager_config(p->cmd);
- if (use_pager == -1 && p->option & USE_PAGER)
- use_pager = 1;
-
- if ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) &&
- startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */
- trace_repo_setup(prefix);
+ if (help && (run_setup & RUN_SETUP))
+ /* demote to GENTLY to allow 'git cmd -h' outside repo */
+ run_setup = RUN_SETUP_GENTLY;
+
+ if (run_setup & RUN_SETUP) {
+ prefix = setup_git_directory();
+ } else if (run_setup & RUN_SETUP_GENTLY) {
+ int nongit_ok;
+ prefix = setup_git_directory_gently(&nongit_ok);
+ } else {
+ prefix = NULL;
}
+ precompose_argv_prefix(argc, argv, NULL);
+ if (use_pager == -1 && run_setup &&
+ !(p->option & DELAY_PAGER_CONFIG))
+ use_pager = check_pager_config(p->cmd);
+ if (use_pager == -1 && p->option & USE_PAGER)
+ use_pager = 1;
+ if (run_setup && startup_info->have_repository)
+ /* get_git_dir() may set up repo, avoid that */
+ trace_repo_setup(prefix);
commit_pager_choice();
if (!help && get_super_prefix()) {
diff --git a/repo-settings.c b/repo-settings.c
index b93e91a212..00ca5571a1 100644
--- a/repo-settings.c
+++ b/repo-settings.c
@@ -17,6 +17,9 @@ void prepare_repo_settings(struct repository *r)
char *strval;
int manyfiles;
+ if (!r->gitdir)
+ BUG("Cannot add settings for uninitialized repository");
+
if (r->settings.initialized++)
return;
diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh
index bfd332120c..cb777c74a2 100755
--- a/t/perf/p2000-sparse-operations.sh
+++ b/t/perf/p2000-sparse-operations.sh
@@ -113,5 +113,9 @@ test_perf_on_all git checkout -f -
test_perf_on_all git reset
test_perf_on_all git reset --hard
test_perf_on_all git reset -- does-not-exist
+test_perf_on_all git diff
+test_perf_on_all git diff --cached
+test_perf_on_all git blame $SPARSE_CONE/a
+test_perf_on_all git blame $SPARSE_CONE/f3/a
test_done
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index f8270943aa..49f70a6569 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -415,7 +415,7 @@ test_expect_success 'checkout and reset --hard' '
test_all_match git reset --hard update-folder2
'
-test_expect_success 'diff --staged' '
+test_expect_success 'diff --cached' '
init_repos &&
write_script edit-contents <<-\EOF &&
@@ -424,10 +424,10 @@ test_expect_success 'diff --staged' '
run_on_all ../edit-contents &&
test_all_match git diff &&
- test_all_match git diff --staged &&
+ test_all_match git diff --cached &&
test_all_match git add README.md &&
test_all_match git diff &&
- test_all_match git diff --staged
+ test_all_match git diff --cached
'
# NEEDSWORK: sparse-checkout behaves differently from full-checkout when
@@ -444,8 +444,8 @@ test_expect_success 'diff with renames and conflicts' '
test_all_match git checkout rename-base &&
test_all_match git checkout $branch -- . &&
test_all_match git status --porcelain=v2 &&
- test_all_match git diff --staged --no-renames &&
- test_all_match git diff --staged --find-renames || return 1
+ test_all_match git diff --cached --no-renames &&
+ test_all_match git diff --cached --find-renames || return 1
done
'
@@ -464,8 +464,8 @@ test_expect_success 'diff with directory/file conflicts' '
test_all_match git checkout $branch &&
test_all_match git checkout rename-base -- . &&
test_all_match git status --porcelain=v2 &&
- test_all_match git diff --staged --no-renames &&
- test_all_match git diff --staged --find-renames || return 1
+ test_all_match git diff --cached --no-renames &&
+ test_all_match git diff --cached --find-renames || return 1
done
'
@@ -486,21 +486,36 @@ test_expect_success 'log with pathspec outside sparse definition' '
test_expect_success 'blame with pathspec inside sparse definition' '
init_repos &&
- test_all_match git blame a &&
- test_all_match git blame deep/a &&
- test_all_match git blame deep/deeper1/a &&
- test_all_match git blame deep/deeper1/deepest/a
+ for file in a \
+ deep/a \
+ deep/deeper1/a \
+ deep/deeper1/deepest/a
+ do
+ test_all_match git blame $file
+ done
'
-# TODO: blame currently does not support blaming files outside of the
-# sparse definition. It complains that the file doesn't exist locally.
-test_expect_failure 'blame with pathspec outside sparse definition' '
+# Without a revision specified, blame will error if passed any file that
+# is not present in the working directory (even if the file is tracked).
+# Here we just verify that this is also true with sparse checkouts.
+test_expect_success 'blame with pathspec outside sparse definition' '
init_repos &&
+ test_sparse_match git sparse-checkout set &&
- test_all_match git blame folder1/a &&
- test_all_match git blame folder2/a &&
- test_all_match git blame deep/deeper2/a &&
- test_all_match git blame deep/deeper2/deepest/a
+ for file in a \
+ deep/a \
+ deep/deeper1/a \
+ deep/deeper1/deepest/a
+ do
+ test_sparse_match test_must_fail git blame $file &&
+ cat >expect <<-EOF &&
+ fatal: Cannot lstat '"'"'$file'"'"': No such file or directory
+ EOF
+ # We compare sparse-checkout-err and sparse-index-err in
+ # `test_sparse_match`. Given we know they are the same, we
+ # only check the content of sparse-index-err here.
+ test_cmp expect sparse-index-err
+ done
'
test_expect_success 'checkout and reset (mixed)' '
@@ -936,6 +951,64 @@ test_expect_success 'sparse-index is not expanded: merge conflict in cone' '
)
'
+test_expect_success 'sparse index is not expanded: diff' '
+ init_repos &&
+
+ write_script edit-contents <<-\EOF &&
+ echo text >>$1
+ EOF
+
+ # Add file within cone
+ test_sparse_match git sparse-checkout set deep &&
+ run_on_all ../edit-contents deep/testfile &&
+ test_all_match git add deep/testfile &&
+ run_on_all ../edit-contents deep/testfile &&
+
+ test_all_match git diff &&
+ test_all_match git diff --cached &&
+ ensure_not_expanded diff &&
+ ensure_not_expanded diff --cached &&
+
+ # Add file outside cone
+ test_all_match git reset --hard &&
+ run_on_all mkdir newdirectory &&
+ run_on_all ../edit-contents newdirectory/testfile &&
+ test_sparse_match git sparse-checkout set newdirectory &&
+ test_all_match git add newdirectory/testfile &&
+ run_on_all ../edit-contents newdirectory/testfile &&
+ test_sparse_match git sparse-checkout set &&
+
+ test_all_match git diff &&
+ test_all_match git diff --cached &&
+ ensure_not_expanded diff &&
+ ensure_not_expanded diff --cached &&
+
+ # Merge conflict outside cone
+ # The sparse checkout will report a warning that is not in the
+ # full checkout, so we use `run_on_all` instead of
+ # `test_all_match`
+ run_on_all git reset --hard &&
+ test_all_match git checkout merge-left &&
+ test_all_match test_must_fail git merge merge-right &&
+
+ test_all_match git diff &&
+ test_all_match git diff --cached &&
+ ensure_not_expanded diff &&
+ ensure_not_expanded diff --cached
+'
+
+test_expect_success 'sparse index is not expanded: blame' '
+ init_repos &&
+
+ for file in a \
+ deep/a \
+ deep/deeper1/a \
+ deep/deeper1/deepest/a
+ do
+ ensure_not_expanded blame $file
+ done
+'
+
# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
# in this scenario, but it shouldn't.
test_expect_success 'reset mixed and checkout orphan' '