]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/add.c: replace run_command() with direct apply_all_patches() call
authorGatla Vishweshwar Reddy <gatlavishweshwarreddy26@gmail.com>
Sat, 11 Jul 2026 06:06:15 +0000 (11:36 +0530)
committerJunio C Hamano <gitster@pobox.com>
Sat, 11 Jul 2026 21:12:39 +0000 (14:12 -0700)
When the user runs "git add -e", the diff of the working tree changes
is written to a temporary file, opened in an editor, and then applied
back to the index. The application step is done by spawning a child
process running "git apply --recount --cached <file>", which is an
unnecessary subprocess since the apply machinery is available as a
native C API.

Replace the run_command() call with a direct call to apply_all_patches()
using an initialized apply_state with the cached and recount options set
appropriately. This avoids the overhead of forking a subprocess, keeps
the operation within the same process, and makes the intent of the code
clearer to the reader.

Remove the now-unused includes of "run-command.h" and "strvec.h" since
no other code in this file requires them after this change.

Signed-off-by: Gatla Vishweshwar Reddy <gatlavishweshwarreddy26@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/add.c
t/t3702-add-edit.sh

index c859f665199efa91897472e6eab7e8d7ae983fc6..20a86a16114191839e459688c334f812c722a0f8 100644 (file)
@@ -13,7 +13,6 @@
 #include "dir.h"
 #include "gettext.h"
 #include "pathspec.h"
-#include "run-command.h"
 #include "object-file.h"
 #include "odb.h"
 #include "odb/transaction.h"
@@ -23,9 +22,9 @@
 #include "diff.h"
 #include "read-cache.h"
 #include "revision.h"
-#include "strvec.h"
 #include "submodule.h"
 #include "add-interactive.h"
+#include "apply.h"
 
 static const char * const builtin_add_usage[] = {
        N_("git add [<options>] [--] <pathspec>..."),
@@ -187,7 +186,8 @@ static int edit_patch(struct repository *repo,
                      const char *prefix)
 {
        char *file = repo_git_path(repo, "ADD_EDIT.patch");
-       struct child_process child = CHILD_PROCESS_INIT;
+       struct apply_state state;
+       const char *apply_argv[2];
        struct rev_info rev;
        int out;
        struct stat st;
@@ -217,11 +217,16 @@ static int edit_patch(struct repository *repo,
        if (!st.st_size)
                die(_("empty patch. aborted"));
 
-       child.git_cmd = 1;
-       strvec_pushl(&child.args, "apply", "--recount", "--cached", file,
-                    NULL);
-       if (run_command(&child))
+       apply_argv[0] = file;
+       apply_argv[1] = NULL;
+       if (init_apply_state(&state, repo, NULL))
+               die(_("could not initialize apply state"));
+       state.cached = 1;
+       if (check_apply_state(&state, 0))
+               die(_("could not check apply state"));
+       if (apply_all_patches(&state, 1, apply_argv, APPLY_OPT_RECOUNT))
                die(_("could not apply '%s'"), file);
+       clear_apply_state(&state);
 
        unlink(file);
        free(file);
index 8bacacbac6807c1ddab20aeca87ac34dbdd05bfb..f6285640051e5995189507e545269ec35e43b93d 100755 (executable)
@@ -124,5 +124,15 @@ test_expect_success 'add -e notices editor failure' '
        test_must_fail env GIT_EDITOR=false git add -e &&
        test_expect_code 1 git diff --exit-code
 '
+test_expect_success 'add -e works from a subdirectory' '
+       git reset --hard &&
+       echo change >>file &&
+       mkdir -p subdir &&
+       (
+               cd subdir &&
+               GIT_EDITOR=cat git add -e ../file
+       ) &&
+       git diff --cached | grep -q "^+change"
+'
 
 test_done