`apply_all_patches()` does not provide a method to apply patches
from strbuf. Because of this, this commit introduces a new
function `apply_patch_from_buf()` which applies a patch from buf.
It works by saving the strbuf as a file. This way we can call
`apply_all_patches()`. Before returning, the created file is
removed.
---
 builtin/stash.c | 61 +++++++++++++++++++++++++++----------------------
 1 file changed, 34 insertions(+), 27 deletions(-)

diff --git a/builtin/stash.c b/builtin/stash.c
index 46e76a34e..74eda822c 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -13,6 +13,7 @@
 #include "revision.h"
 #include "log-tree.h"
 #include "diffcore.h"
+#include "apply.h"
 
 static const char * const git_stash_usage[] = {
        N_("git stash list [<options>]"),
@@ -277,10 +278,6 @@ static int diff_tree_binary(struct strbuf *out, struct 
object_id *w_commit)
        struct child_process cp = CHILD_PROCESS_INIT;
        const char *w_commit_hex = oid_to_hex(w_commit);
 
-       /*
-        * Diff-tree would not be very hard to replace with a native function,
-        * however it should be done together with apply_cached.
-        */
        cp.git_cmd = 1;
        argv_array_pushl(&cp.args, "diff-tree", "--binary", NULL);
        argv_array_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
@@ -288,18 +285,36 @@ static int diff_tree_binary(struct strbuf *out, struct 
object_id *w_commit)
        return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
 }
 
-static int apply_cached(struct strbuf *out)
+static int apply_patch_from_buf(struct strbuf *patch, int cached, int reverse,
+                               int check_index)
 {
-       struct child_process cp = CHILD_PROCESS_INIT;
+       int ret = 0;
+       struct apply_state state;
+       struct argv_array args = ARGV_ARRAY_INIT;
+       const char *patch_path = ".git/stash_patch.patch";
+       FILE *patch_file;
 
-       /*
-        * Apply currently only reads either from stdin or a file, thus
-        * apply_all_patches would have to be updated to optionally take a
-        * buffer.
-        */
-       cp.git_cmd = 1;
-       argv_array_pushl(&cp.args, "apply", "--cached", NULL);
-       return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
+       if (init_apply_state(&state, NULL))
+               return -1;
+
+       state.cached = cached;
+       state.apply_in_reverse = reverse;
+       state.check_index = check_index;
+       if (state.cached)
+               state.check_index = 1;
+       if (state.check_index)
+               state.unsafe_paths = 0;
+
+       patch_file = fopen(patch_path, "w");
+       strbuf_write(patch, patch_file);
+       fclose(patch_file);
+
+       argv_array_push(&args, patch_path);
+       ret = apply_all_patches(&state, args.argc, args.argv, 0);
+
+       remove_path(patch_path);
+       clear_apply_state(&state);
+       return ret;
 }
 
 static int reset_head(const char *prefix)
@@ -418,7 +433,7 @@ static int do_apply_stash(const char *prefix, struct 
stash_info *info,
                                return -1;
                        }
 
-                       ret = apply_cached(&out);
+                       ret = apply_patch_from_buf(&out, 1, 0, 0);
                        strbuf_release(&out);
                        if (ret)
                                return -1;
@@ -1341,7 +1356,6 @@ static int do_push_stash(int argc, const char **argv, 
const char *prefix,
                        int i;
                        struct child_process cp1 = CHILD_PROCESS_INIT;
                        struct child_process cp2 = CHILD_PROCESS_INIT;
-                       struct child_process cp3 = CHILD_PROCESS_INIT;
                        struct strbuf out = STRBUF_INIT;
 
                        cp1.git_cmd = 1;
@@ -1365,11 +1379,9 @@ static int do_push_stash(int argc, const char **argv, 
const char *prefix,
                        if (pipe_command(&cp2, NULL, 0, &out, 0, NULL, 0))
                                return -1;
 
-                       cp3.git_cmd = 1;
-                       argv_array_pushl(&cp3.args, "apply", "--index", "-R",
-                                        NULL);
-                       if (pipe_command(&cp3, out.buf, out.len, NULL, 0, NULL,
-                                        0))
+                       discard_cache();
+                       read_cache();
+                       if (apply_patch_from_buf(&out, 0, 1, 1))
                                return -1;
                } else {
                        struct child_process cp = CHILD_PROCESS_INIT;
@@ -1405,12 +1417,7 @@ static int do_push_stash(int argc, const char **argv, 
const char *prefix,
                                return -1;
                }
        } else {
-               struct child_process cp = CHILD_PROCESS_INIT;
-
-               cp.git_cmd = 1;
-               argv_array_pushl(&cp.args, "apply", "-R", NULL);
-
-               if (pipe_command(&cp, patch.buf, patch.len, NULL, 0, NULL, 0)) {
+               if (apply_patch_from_buf(&patch, 0, 1, 0)) {
                        if (!quiet)
                                fprintf_ln(stderr, "Cannot remove worktree 
changes");
                        return -1;
-- 
2.18.0.573.g56500d98f

Reply via email to