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
maint
Junio C Hamano 2021-12-21 15:03:17 -08:00
commit 8d2c37320b
7 changed files with 130 additions and 36 deletions

View File

@ -939,6 +939,9 @@ parse_done:
revs.diffopt.flags.follow_renames = 0; revs.diffopt.flags.follow_renames = 0;
argc = parse_options_end(&ctx); 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 (incremental || (output_option & OUTPUT_PORCELAIN)) {
if (show_progress > 0) if (show_progress > 0)
die(_("--progress can't be used with --incremental or porcelain formats")); die(_("--progress can't be used with --incremental or porcelain formats"));

View File

@ -437,6 +437,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix)


prefix = setup_git_directory_gently(&nongit); prefix = setup_git_directory_gently(&nongit);


if (!nongit) {
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
}

if (!no_index) { if (!no_index) {
/* /*
* Treat git diff with at least one path outside of the * Treat git diff with at least one path outside of the

View File

@ -632,10 +632,13 @@ static int prepare_commit_graph(struct repository *r)
struct object_directory *odb; 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 * This must come before the "already attempted?" check below, because
* we want to disable even an already-loaded graph file. * we want to disable even an already-loaded graph file.
*/ */
if (r->commit_graph_disabled) if (!r->gitdir || r->commit_graph_disabled)
return 0; return 0;


if (r->objects->commit_graph_attempted) if (r->objects->commit_graph_attempted)

37
git.c
View File

@ -421,27 +421,30 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
int status, help; int status, help;
struct stat st; struct stat st;
const char *prefix; const char *prefix;
int run_setup = (p->option & (RUN_SETUP | RUN_SETUP_GENTLY));


prefix = NULL;
help = argc == 2 && !strcmp(argv[1], "-h"); help = argc == 2 && !strcmp(argv[1], "-h");
if (!help) { if (help && (run_setup & RUN_SETUP))
if (p->option & RUN_SETUP) /* demote to GENTLY to allow 'git cmd -h' outside repo */
prefix = setup_git_directory(); run_setup = RUN_SETUP_GENTLY;
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)) && if (run_setup & RUN_SETUP) {
startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */ prefix = setup_git_directory();
trace_repo_setup(prefix); } 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(); commit_pager_choice();


if (!help && get_super_prefix()) { if (!help && get_super_prefix()) {

View File

@ -17,6 +17,9 @@ void prepare_repo_settings(struct repository *r)
char *strval; char *strval;
int manyfiles; int manyfiles;


if (!r->gitdir)
BUG("Cannot add settings for uninitialized repository");

if (r->settings.initialized++) if (r->settings.initialized++)
return; return;



View File

@ -113,5 +113,9 @@ test_perf_on_all git checkout -f -
test_perf_on_all git reset test_perf_on_all git reset
test_perf_on_all git reset --hard test_perf_on_all git reset --hard
test_perf_on_all git reset -- does-not-exist 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 test_done

View File

@ -415,7 +415,7 @@ test_expect_success 'checkout and reset --hard' '
test_all_match git reset --hard update-folder2 test_all_match git reset --hard update-folder2
' '


test_expect_success 'diff --staged' ' test_expect_success 'diff --cached' '
init_repos && init_repos &&


write_script edit-contents <<-\EOF && write_script edit-contents <<-\EOF &&
@ -424,10 +424,10 @@ test_expect_success 'diff --staged' '
run_on_all ../edit-contents && run_on_all ../edit-contents &&


test_all_match git diff && 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 add README.md &&
test_all_match git diff && 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 # 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 rename-base &&
test_all_match git checkout $branch -- . && test_all_match git checkout $branch -- . &&
test_all_match git status --porcelain=v2 && test_all_match git status --porcelain=v2 &&
test_all_match git diff --staged --no-renames && test_all_match git diff --cached --no-renames &&
test_all_match git diff --staged --find-renames || return 1 test_all_match git diff --cached --find-renames || return 1
done done
' '


@ -464,8 +464,8 @@ test_expect_success 'diff with directory/file conflicts' '
test_all_match git checkout $branch && test_all_match git checkout $branch &&
test_all_match git checkout rename-base -- . && test_all_match git checkout rename-base -- . &&
test_all_match git status --porcelain=v2 && test_all_match git status --porcelain=v2 &&
test_all_match git diff --staged --no-renames && test_all_match git diff --cached --no-renames &&
test_all_match git diff --staged --find-renames || return 1 test_all_match git diff --cached --find-renames || return 1
done done
' '


@ -486,21 +486,36 @@ test_expect_success 'log with pathspec outside sparse definition' '
test_expect_success 'blame with pathspec inside sparse definition' ' test_expect_success 'blame with pathspec inside sparse definition' '
init_repos && init_repos &&


test_all_match git blame a && for file in a \
test_all_match git blame deep/a && deep/a \
test_all_match git blame deep/deeper1/a && deep/deeper1/a \
test_all_match git blame deep/deeper1/deepest/a deep/deeper1/deepest/a
do
test_all_match git blame $file
done
' '


# TODO: blame currently does not support blaming files outside of the # Without a revision specified, blame will error if passed any file that
# sparse definition. It complains that the file doesn't exist locally. # is not present in the working directory (even if the file is tracked).
test_expect_failure 'blame with pathspec outside sparse definition' ' # Here we just verify that this is also true with sparse checkouts.
test_expect_success 'blame with pathspec outside sparse definition' '
init_repos && init_repos &&
test_sparse_match git sparse-checkout set &&


test_all_match git blame folder1/a && for file in a \
test_all_match git blame folder2/a && deep/a \
test_all_match git blame deep/deeper2/a && deep/deeper1/a \
test_all_match git blame deep/deeper2/deepest/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)' ' 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 # NEEDSWORK: a sparse-checkout behaves differently from a full checkout
# in this scenario, but it shouldn't. # in this scenario, but it shouldn't.
test_expect_success 'reset mixed and checkout orphan' ' test_expect_success 'reset mixed and checkout orphan' '