]> git.ipfire.org Git - thirdparty/git.git/commitdiff
git add: make -p/-i aware of sparse index
authorDerrick Stolee <stolee@gmail.com>
Fri, 16 May 2025 14:55:28 +0000 (14:55 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 16 May 2025 19:01:51 +0000 (12:01 -0700)
It is slow to expand a sparse index in-memory due to parsing of trees.
We aim to minimize that performance cost when possible. 'git add -p'
uses 'git apply' child processes to modify the index, but still there
are some expansions that occur.

It turns out that control flows out of cmd_add() in the interactive
cases before the lines that confirm that the builtin is integrated with
the sparse index.

Moving that integration point earlier in cmd_add() allows 'git add -i'
and 'git add -p' to operate without expanding a sparse index to a full
one.

Add test cases that confirm that these interactive add options work with
the sparse index.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/add.c
t/t1092-sparse-checkout-compatibility.sh

index 78dfb265776724109f4a8b93a419c32667979954..b96360dc5cf96d21d2ccb92666bdf038495396e8 100644 (file)
@@ -391,6 +391,10 @@ int cmd_add(int argc,
 
        argc = parse_options(argc, argv, prefix, builtin_add_options,
                          builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
+
+       prepare_repo_settings(repo);
+       repo->settings.command_requires_full_index = 0;
+
        if (patch_interactive)
                add_interactive = 1;
        if (add_interactive) {
@@ -427,9 +431,6 @@ int cmd_add(int argc,
        add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
        require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
 
-       prepare_repo_settings(repo);
-       repo->settings.command_requires_full_index = 0;
-
        repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR);
 
        /*
index fa2472010d8abbca945ebd8795bde8a6b2d38d91..f47cf8fa7fdfab5a82e4953809467e00e62549fc 100755 (executable)
@@ -384,6 +384,38 @@ test_expect_success 'add, commit, checkout' '
        test_all_match git checkout -
 '
 
+test_expect_success 'git add -p' '
+       init_repos &&
+
+       write_script edit-contents <<-\EOF &&
+       echo text >>$1
+       EOF
+
+       # Does not expand when edits are within sparse checkout.
+       run_on_all ../edit-contents deep/a &&
+       run_on_all ../edit-contents deep/deeper1/a &&
+
+       test_write_lines y n >in &&
+       run_on_all git add -p <in &&
+       test_all_match git status --porcelain=v2 &&
+       test_all_match git reset &&
+
+       test_write_lines u 1 "" q >in &&
+       run_on_all git add -i <in &&
+       test_all_match git status --porcelain=v2 &&
+       test_all_match git reset --hard &&
+
+       run_on_sparse mkdir -p folder1 &&
+       run_on_all ../edit-contents folder1/a &&
+       test_write_lines y n y >in &&
+       run_on_all git add -p <in &&
+       test_sparse_match git status --porcelain=v2 &&
+       test_sparse_match git reset &&
+       test_write_lines u 2 3 "" q >in &&
+       run_on_all git add -i <in &&
+       test_sparse_match git status --porcelain=v2
+'
+
 test_expect_success 'deep changes during checkout' '
        init_repos &&
 
@@ -2400,6 +2432,34 @@ test_expect_success 'sparse-index is not expanded: git apply' '
        ensure_expanded apply --cached ../patch-outside
 '
 
+test_expect_success 'sparse-index is not expanded: git add -p' '
+       init_repos &&
+
+       # Does not expand when edits are within sparse checkout.
+       echo "new content" >sparse-index/deep/a &&
+       echo "new content" >sparse-index/deep/deeper1/a &&
+       test_write_lines y n >in &&
+       ensure_not_expanded add -p <in &&
+       git -C sparse-index reset &&
+       ensure_not_expanded add -i <in &&
+
+       # -p does expand when edits are outside sparse checkout.
+       mkdir -p sparse-index/folder1 &&
+       echo "new content" >sparse-index/folder1/a &&
+       test_write_lines y n y >in &&
+       ensure_expanded add -p <in &&
+
+       # Fully reset the index.
+       git -C sparse-index reset --hard &&
+       git -C sparse-index sparse-checkout reapply &&
+
+       # -i does expand when edits are outside sparse checkout.
+       mkdir -p sparse-index/folder1 &&
+       echo "new content" >sparse-index/folder1/a &&
+       test_write_lines u 2 3 "" q >in &&
+       ensure_expanded add -i <in
+'
+
 test_expect_success 'advice.sparseIndexExpanded' '
        init_repos &&