Git fork

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

+130 -36
+3
builtin/blame.c
··· 939 939 revs.diffopt.flags.follow_renames = 0; 940 940 argc = parse_options_end(&ctx); 941 941 942 + prepare_repo_settings(the_repository); 943 + the_repository->settings.command_requires_full_index = 0; 944 + 942 945 if (incremental || (output_option & OUTPUT_PORCELAIN)) { 943 946 if (show_progress > 0) 944 947 die(_("--progress can't be used with --incremental or porcelain formats"));
+5
builtin/diff.c
··· 437 437 438 438 prefix = setup_git_directory_gently(&nongit); 439 439 440 + if (!nongit) { 441 + prepare_repo_settings(the_repository); 442 + the_repository->settings.command_requires_full_index = 0; 443 + } 444 + 440 445 if (!no_index) { 441 446 /* 442 447 * Treat git diff with at least one path outside of the
+4 -1
commit-graph.c
··· 632 632 struct object_directory *odb; 633 633 634 634 /* 635 + * Early return if there is no git dir or if the commit graph is 636 + * disabled. 637 + * 635 638 * This must come before the "already attempted?" check below, because 636 639 * we want to disable even an already-loaded graph file. 637 640 */ 638 - if (r->commit_graph_disabled) 641 + if (!r->gitdir || r->commit_graph_disabled) 639 642 return 0; 640 643 641 644 if (r->objects->commit_graph_attempted)
+20 -17
git.c
··· 421 421 int status, help; 422 422 struct stat st; 423 423 const char *prefix; 424 + int run_setup = (p->option & (RUN_SETUP | RUN_SETUP_GENTLY)); 424 425 425 - prefix = NULL; 426 426 help = argc == 2 && !strcmp(argv[1], "-h"); 427 - if (!help) { 428 - if (p->option & RUN_SETUP) 429 - prefix = setup_git_directory(); 430 - else if (p->option & RUN_SETUP_GENTLY) { 431 - int nongit_ok; 432 - prefix = setup_git_directory_gently(&nongit_ok); 433 - } 434 - precompose_argv_prefix(argc, argv, NULL); 435 - if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY) && 436 - !(p->option & DELAY_PAGER_CONFIG)) 437 - use_pager = check_pager_config(p->cmd); 438 - if (use_pager == -1 && p->option & USE_PAGER) 439 - use_pager = 1; 427 + if (help && (run_setup & RUN_SETUP)) 428 + /* demote to GENTLY to allow 'git cmd -h' outside repo */ 429 + run_setup = RUN_SETUP_GENTLY; 440 430 441 - if ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) && 442 - startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */ 443 - trace_repo_setup(prefix); 431 + if (run_setup & RUN_SETUP) { 432 + prefix = setup_git_directory(); 433 + } else if (run_setup & RUN_SETUP_GENTLY) { 434 + int nongit_ok; 435 + prefix = setup_git_directory_gently(&nongit_ok); 436 + } else { 437 + prefix = NULL; 444 438 } 439 + precompose_argv_prefix(argc, argv, NULL); 440 + if (use_pager == -1 && run_setup && 441 + !(p->option & DELAY_PAGER_CONFIG)) 442 + use_pager = check_pager_config(p->cmd); 443 + if (use_pager == -1 && p->option & USE_PAGER) 444 + use_pager = 1; 445 + if (run_setup && startup_info->have_repository) 446 + /* get_git_dir() may set up repo, avoid that */ 447 + trace_repo_setup(prefix); 445 448 commit_pager_choice(); 446 449 447 450 if (!help && get_super_prefix()) {
+3
repo-settings.c
··· 17 17 char *strval; 18 18 int manyfiles; 19 19 20 + if (!r->gitdir) 21 + BUG("Cannot add settings for uninitialized repository"); 22 + 20 23 if (r->settings.initialized++) 21 24 return; 22 25
+4
t/perf/p2000-sparse-operations.sh
··· 113 113 test_perf_on_all git reset 114 114 test_perf_on_all git reset --hard 115 115 test_perf_on_all git reset -- does-not-exist 116 + test_perf_on_all git diff 117 + test_perf_on_all git diff --cached 118 + test_perf_on_all git blame $SPARSE_CONE/a 119 + test_perf_on_all git blame $SPARSE_CONE/f3/a 116 120 117 121 test_done
+91 -18
t/t1092-sparse-checkout-compatibility.sh
··· 415 415 test_all_match git reset --hard update-folder2 416 416 ' 417 417 418 - test_expect_success 'diff --staged' ' 418 + test_expect_success 'diff --cached' ' 419 419 init_repos && 420 420 421 421 write_script edit-contents <<-\EOF && ··· 424 424 run_on_all ../edit-contents && 425 425 426 426 test_all_match git diff && 427 - test_all_match git diff --staged && 427 + test_all_match git diff --cached && 428 428 test_all_match git add README.md && 429 429 test_all_match git diff && 430 - test_all_match git diff --staged 430 + test_all_match git diff --cached 431 431 ' 432 432 433 433 # NEEDSWORK: sparse-checkout behaves differently from full-checkout when ··· 444 444 test_all_match git checkout rename-base && 445 445 test_all_match git checkout $branch -- . && 446 446 test_all_match git status --porcelain=v2 && 447 - test_all_match git diff --staged --no-renames && 448 - test_all_match git diff --staged --find-renames || return 1 447 + test_all_match git diff --cached --no-renames && 448 + test_all_match git diff --cached --find-renames || return 1 449 449 done 450 450 ' 451 451 ··· 464 464 test_all_match git checkout $branch && 465 465 test_all_match git checkout rename-base -- . && 466 466 test_all_match git status --porcelain=v2 && 467 - test_all_match git diff --staged --no-renames && 468 - test_all_match git diff --staged --find-renames || return 1 467 + test_all_match git diff --cached --no-renames && 468 + test_all_match git diff --cached --find-renames || return 1 469 469 done 470 470 ' 471 471 ··· 486 486 test_expect_success 'blame with pathspec inside sparse definition' ' 487 487 init_repos && 488 488 489 - test_all_match git blame a && 490 - test_all_match git blame deep/a && 491 - test_all_match git blame deep/deeper1/a && 492 - test_all_match git blame deep/deeper1/deepest/a 489 + for file in a \ 490 + deep/a \ 491 + deep/deeper1/a \ 492 + deep/deeper1/deepest/a 493 + do 494 + test_all_match git blame $file 495 + done 493 496 ' 494 497 495 - # TODO: blame currently does not support blaming files outside of the 496 - # sparse definition. It complains that the file doesn't exist locally. 497 - test_expect_failure 'blame with pathspec outside sparse definition' ' 498 + # Without a revision specified, blame will error if passed any file that 499 + # is not present in the working directory (even if the file is tracked). 500 + # Here we just verify that this is also true with sparse checkouts. 501 + test_expect_success 'blame with pathspec outside sparse definition' ' 498 502 init_repos && 503 + test_sparse_match git sparse-checkout set && 499 504 500 - test_all_match git blame folder1/a && 501 - test_all_match git blame folder2/a && 502 - test_all_match git blame deep/deeper2/a && 503 - test_all_match git blame deep/deeper2/deepest/a 505 + for file in a \ 506 + deep/a \ 507 + deep/deeper1/a \ 508 + deep/deeper1/deepest/a 509 + do 510 + test_sparse_match test_must_fail git blame $file && 511 + cat >expect <<-EOF && 512 + fatal: Cannot lstat '"'"'$file'"'"': No such file or directory 513 + EOF 514 + # We compare sparse-checkout-err and sparse-index-err in 515 + # `test_sparse_match`. Given we know they are the same, we 516 + # only check the content of sparse-index-err here. 517 + test_cmp expect sparse-index-err 518 + done 504 519 ' 505 520 506 521 test_expect_success 'checkout and reset (mixed)' ' ··· 934 949 git -C sparse-index config pull.twohead ort && 935 950 ensure_not_expanded ! merge -m merged expand-right 936 951 ) 952 + ' 953 + 954 + test_expect_success 'sparse index is not expanded: diff' ' 955 + init_repos && 956 + 957 + write_script edit-contents <<-\EOF && 958 + echo text >>$1 959 + EOF 960 + 961 + # Add file within cone 962 + test_sparse_match git sparse-checkout set deep && 963 + run_on_all ../edit-contents deep/testfile && 964 + test_all_match git add deep/testfile && 965 + run_on_all ../edit-contents deep/testfile && 966 + 967 + test_all_match git diff && 968 + test_all_match git diff --cached && 969 + ensure_not_expanded diff && 970 + ensure_not_expanded diff --cached && 971 + 972 + # Add file outside cone 973 + test_all_match git reset --hard && 974 + run_on_all mkdir newdirectory && 975 + run_on_all ../edit-contents newdirectory/testfile && 976 + test_sparse_match git sparse-checkout set newdirectory && 977 + test_all_match git add newdirectory/testfile && 978 + run_on_all ../edit-contents newdirectory/testfile && 979 + test_sparse_match git sparse-checkout set && 980 + 981 + test_all_match git diff && 982 + test_all_match git diff --cached && 983 + ensure_not_expanded diff && 984 + ensure_not_expanded diff --cached && 985 + 986 + # Merge conflict outside cone 987 + # The sparse checkout will report a warning that is not in the 988 + # full checkout, so we use `run_on_all` instead of 989 + # `test_all_match` 990 + run_on_all git reset --hard && 991 + test_all_match git checkout merge-left && 992 + test_all_match test_must_fail git merge merge-right && 993 + 994 + test_all_match git diff && 995 + test_all_match git diff --cached && 996 + ensure_not_expanded diff && 997 + ensure_not_expanded diff --cached 998 + ' 999 + 1000 + test_expect_success 'sparse index is not expanded: blame' ' 1001 + init_repos && 1002 + 1003 + for file in a \ 1004 + deep/a \ 1005 + deep/deeper1/a \ 1006 + deep/deeper1/deepest/a 1007 + do 1008 + ensure_not_expanded blame $file 1009 + done 937 1010 ' 938 1011 939 1012 # NEEDSWORK: a sparse-checkout behaves differently from a full checkout