Skip to content

Commit

Permalink
diff: enable and test the sparse index
Browse files Browse the repository at this point in the history
Enable the sparse index within the 'git diff' command. Its implementation
already safely integrates with the sparse index because it shares code with
the 'git status' and 'git checkout' commands that were already integrated.
The most interesting thing to do is to add tests that verify that 'git diff'
behaves correctly when the sparse index is enabled. These cases are:

1. The index is not expanded for 'diff' and 'diff --staged'
2. 'diff' and 'diff --staged' behave the same in full checkout, sparse
checkout, and sparse index repositories in the following partially-staged
scenarios (i.e. the index, HEAD, and working directory differ at a given
path):
    1. Path is within sparse-checkout cone
    2. Path is outside sparse-checkout cone
    3. A merge conflict exists for paths outside sparse-checkout cone

The `p2000` tests demonstrate an ~30% execution time reduction for 'git
diff' an ~75% execution time reduction for 'git diff --staged' using a
sparse index:

Test                                      before  after
-------------------------------------------------------------
2000.30: git diff (full-v3)               0.37    0.36 -2.7%
2000.31: git diff (full-v4)               0.36    0.35 -2.8%
2000.32: git diff (sparse-v3)             0.46    0.30 -34.8%
2000.33: git diff (sparse-v4)             0.43    0.31 -27.9%
2000.34: git diff --staged (full-v3)      0.08    0.08 +0.0%
2000.35: git diff --staged (full-v4)      0.08    0.08 +0.0%
2000.36: git diff --staged (sparse-v3)    0.17    0.04 -76.5%
2000.37: git diff --staged (sparse-v4)    0.16    0.04 -75.0%

Co-authored-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Lessley Dennington <lessleydennington@gmail.com>
  • Loading branch information
ldennington and derrickstolee committed Oct 13, 2021
1 parent 57049e8 commit 92046ac
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
3 changes: 3 additions & 0 deletions builtin/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@ int cmd_diff(int argc, const char **argv, const char *prefix)

prefix = setup_git_directory_gently(&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
Expand Down
2 changes: 2 additions & 0 deletions t/perf/p2000-sparse-operations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,7 @@ 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 --staged

test_done
42 changes: 42 additions & 0 deletions t/t1092-sparse-checkout-compatibility.sh
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,43 @@ test_expect_success 'diff --staged' '
test_all_match git diff --staged
'

test_expect_success 'diff partially-staged' '
init_repos &&
write_script edit-contents <<-\EOF &&
echo text >>$1
EOF
# Add file within cone
test_all_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 --staged &&
# Add file outside cone
test_all_match git reset --hard &&
run_on_all mkdir newdirectory &&
run_on_all ../edit-contents newdirectory/testfile &&
test_all_match git sparse-checkout set newdirectory &&
test_all_match git add newdirectory/testfile &&
run_on_all ../edit-contents newdirectory/testfile &&
test_all_match git sparse-checkout set &&
test_all_match git diff &&
test_all_match git diff --staged &&
# Merge conflict outside cone
test_all_match 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 --staged
'

# NEEDSWORK: sparse-checkout behaves differently from full-checkout when
# running this test with 'df-conflict-2' after 'df-conflict-1'.
test_expect_success 'diff with renames and conflicts' '
Expand Down Expand Up @@ -800,6 +837,11 @@ test_expect_success 'sparse-index is not expanded' '
# Wildcard identifies only full sparse directories, no index expansion
ensure_not_expanded reset deepest -- folder\* &&
echo a test change >>sparse-index/README.md &&
ensure_not_expanded diff &&
git -C sparse-index add README.md &&
ensure_not_expanded diff --staged &&
ensure_not_expanded checkout -f update-deep &&
test_config -C sparse-index pull.twohead ort &&
(
Expand Down

0 comments on commit 92046ac

Please sign in to comment.