`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