3 #include "parse-options.h"
6 #include "cache-tree.h"
7 #include "unpack-trees.h"
8 #include "merge-recursive.h"
9 #include "argv-array.h"
10 #include "run-command.h"
14 static const char * const git_stash_helper_usage
[] = {
15 N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
19 static const char * const git_stash_helper_apply_usage
[] = {
20 N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
24 static const char *ref_stash
= "refs/stash";
25 static struct strbuf stash_index_path
= STRBUF_INIT
;
28 * w_commit is set to the commit containing the working tree
29 * b_commit is set to the base commit
30 * i_commit is set to the commit containing the index tree
31 * u_commit is set to the commit containing the untracked files tree
32 * w_tree is set to the working tree
33 * b_tree is set to the base tree
34 * i_tree is set to the index tree
35 * u_tree is set to the untracked files tree
38 struct object_id w_commit
;
39 struct object_id b_commit
;
40 struct object_id i_commit
;
41 struct object_id u_commit
;
42 struct object_id w_tree
;
43 struct object_id b_tree
;
44 struct object_id i_tree
;
45 struct object_id u_tree
;
46 struct strbuf revision
;
51 static void free_stash_info(struct stash_info
*info
)
53 strbuf_release(&info
->revision
);
56 static void assert_stash_like(struct stash_info
*info
, const char *revision
)
58 if (get_oidf(&info
->b_commit
, "%s^1", revision
) ||
59 get_oidf(&info
->w_tree
, "%s:", revision
) ||
60 get_oidf(&info
->b_tree
, "%s^1:", revision
) ||
61 get_oidf(&info
->i_tree
, "%s^2:", revision
))
62 die(_("'%s' is not a stash-like commit"), revision
);
65 static int get_stash_info(struct stash_info
*info
, int argc
, const char **argv
)
71 const char *commit
= NULL
;
72 struct object_id dummy
;
73 struct strbuf symbolic
= STRBUF_INIT
;
77 struct strbuf refs_msg
= STRBUF_INIT
;
79 for (i
= 0; i
< argc
; i
++)
80 strbuf_addf(&refs_msg
, " '%s'", argv
[i
]);
82 fprintf_ln(stderr
, _("Too many revisions specified:%s"),
84 strbuf_release(&refs_msg
);
92 strbuf_init(&info
->revision
, 0);
94 if (!ref_exists(ref_stash
)) {
95 free_stash_info(info
);
96 fprintf_ln(stderr
, _("No stash entries found."));
100 strbuf_addf(&info
->revision
, "%s@{0}", ref_stash
);
101 } else if (strspn(commit
, "0123456789") == strlen(commit
)) {
102 strbuf_addf(&info
->revision
, "%s@{%s}", ref_stash
, commit
);
104 strbuf_addstr(&info
->revision
, commit
);
107 revision
= info
->revision
.buf
;
109 if (get_oid(revision
, &info
->w_commit
)) {
110 error(_("%s is not a valid reference"), revision
);
111 free_stash_info(info
);
115 assert_stash_like(info
, revision
);
117 info
->has_u
= !get_oidf(&info
->u_tree
, "%s^3:", revision
);
119 end_of_rev
= strchrnul(revision
, '@');
120 strbuf_add(&symbolic
, revision
, end_of_rev
- revision
);
122 ret
= dwim_ref(symbolic
.buf
, symbolic
.len
, &dummy
, &expanded_ref
);
123 strbuf_release(&symbolic
);
125 case 0: /* Not found, but valid ref */
126 info
->is_stash_ref
= 0;
129 info
->is_stash_ref
= !strcmp(expanded_ref
, ref_stash
);
131 default: /* Invalid or ambiguous */
132 free_stash_info(info
);
136 return !(ret
== 0 || ret
== 1);
139 static int reset_tree(struct object_id
*i_tree
, int update
, int reset
)
142 struct unpack_trees_options opts
;
143 struct tree_desc t
[MAX_UNPACK_TREES
];
145 struct lock_file lock_file
= LOCK_INIT
;
147 read_cache_preload(NULL
);
148 if (refresh_cache(REFRESH_QUIET
))
151 hold_locked_index(&lock_file
, LOCK_DIE_ON_ERROR
);
153 memset(&opts
, 0, sizeof(opts
));
155 tree
= parse_tree_indirect(i_tree
);
156 if (parse_tree(tree
))
159 init_tree_desc(t
, tree
->buffer
, tree
->size
);
162 opts
.src_index
= &the_index
;
163 opts
.dst_index
= &the_index
;
166 opts
.update
= update
;
167 opts
.fn
= oneway_merge
;
169 if (unpack_trees(nr_trees
, t
, &opts
))
172 if (write_locked_index(&the_index
, &lock_file
, COMMIT_LOCK
))
173 return error(_("unable to write new index file"));
178 static int diff_tree_binary(struct strbuf
*out
, struct object_id
*w_commit
)
180 struct child_process cp
= CHILD_PROCESS_INIT
;
181 const char *w_commit_hex
= oid_to_hex(w_commit
);
184 * Diff-tree would not be very hard to replace with a native function,
185 * however it should be done together with apply_cached.
188 argv_array_pushl(&cp
.args
, "diff-tree", "--binary", NULL
);
189 argv_array_pushf(&cp
.args
, "%s^2^..%s^2", w_commit_hex
, w_commit_hex
);
191 return pipe_command(&cp
, NULL
, 0, out
, 0, NULL
, 0);
194 static int apply_cached(struct strbuf
*out
)
196 struct child_process cp
= CHILD_PROCESS_INIT
;
199 * Apply currently only reads either from stdin or a file, thus
200 * apply_all_patches would have to be updated to optionally take a
204 argv_array_pushl(&cp
.args
, "apply", "--cached", NULL
);
205 return pipe_command(&cp
, out
->buf
, out
->len
, NULL
, 0, NULL
, 0);
208 static int reset_head(void)
210 struct child_process cp
= CHILD_PROCESS_INIT
;
213 * Reset is overall quite simple, however there is no current public
217 argv_array_push(&cp
.args
, "reset");
219 return run_command(&cp
);
222 static int get_newly_staged(struct strbuf
*out
, struct object_id
*c_tree
)
224 struct child_process cp
= CHILD_PROCESS_INIT
;
225 const char *c_tree_hex
= oid_to_hex(c_tree
);
228 * diff-index is very similar to diff-tree above, and should be
229 * converted together with update_index.
232 argv_array_pushl(&cp
.args
, "diff-index", "--cached", "--name-only",
233 "--diff-filter=A", NULL
);
234 argv_array_push(&cp
.args
, c_tree_hex
);
235 return pipe_command(&cp
, NULL
, 0, out
, 0, NULL
, 0);
238 static int update_index(struct strbuf
*out
)
240 struct child_process cp
= CHILD_PROCESS_INIT
;
243 * Update-index is very complicated and may need to have a public
244 * function exposed in order to remove this forking.
247 argv_array_pushl(&cp
.args
, "update-index", "--add", "--stdin", NULL
);
248 return pipe_command(&cp
, out
->buf
, out
->len
, NULL
, 0, NULL
, 0);
251 static int restore_untracked(struct object_id
*u_tree
)
254 struct child_process cp
= CHILD_PROCESS_INIT
;
257 * We need to run restore files from a given index, but without
258 * affecting the current index, so we use GIT_INDEX_FILE with
259 * run_command to fork processes that will not interfere.
262 argv_array_push(&cp
.args
, "read-tree");
263 argv_array_push(&cp
.args
, oid_to_hex(u_tree
));
264 argv_array_pushf(&cp
.env_array
, "GIT_INDEX_FILE=%s",
265 stash_index_path
.buf
);
266 if (run_command(&cp
)) {
267 remove_path(stash_index_path
.buf
);
271 child_process_init(&cp
);
273 argv_array_pushl(&cp
.args
, "checkout-index", "--all", NULL
);
274 argv_array_pushf(&cp
.env_array
, "GIT_INDEX_FILE=%s",
275 stash_index_path
.buf
);
277 res
= run_command(&cp
);
278 remove_path(stash_index_path
.buf
);
282 static int do_apply_stash(const char *prefix
, struct stash_info
*info
,
283 int index
, int quiet
)
286 int has_index
= index
;
287 struct merge_options o
;
288 struct object_id c_tree
;
289 struct object_id index_tree
;
290 struct commit
*result
;
291 const struct object_id
*bases
[1];
293 read_cache_preload(NULL
);
294 if (refresh_cache(REFRESH_QUIET
))
297 if (write_cache_as_tree(&c_tree
, 0, NULL
))
298 return error(_("cannot apply a stash in the middle of a merge"));
301 if (oideq(&info
->b_tree
, &info
->i_tree
) ||
302 oideq(&c_tree
, &info
->i_tree
)) {
305 struct strbuf out
= STRBUF_INIT
;
307 if (diff_tree_binary(&out
, &info
->w_commit
)) {
308 strbuf_release(&out
);
309 return error(_("could not generate diff %s^!."),
310 oid_to_hex(&info
->w_commit
));
313 ret
= apply_cached(&out
);
314 strbuf_release(&out
);
316 return error(_("conflicts in index."
317 "Try without --index."));
321 if (write_cache_as_tree(&index_tree
, 0, NULL
))
322 return error(_("could not save index tree"));
328 if (info
->has_u
&& restore_untracked(&info
->u_tree
))
329 return error(_("could not restore untracked files from stash"));
331 init_merge_options(&o
);
333 o
.branch1
= "Updated upstream";
334 o
.branch2
= "Stashed changes";
336 if (oideq(&info
->b_tree
, &c_tree
))
337 o
.branch1
= "Version stash was based on";
342 if (o
.verbosity
>= 3)
343 printf_ln(_("Merging %s with %s"), o
.branch1
, o
.branch2
);
345 bases
[0] = &info
->b_tree
;
347 ret
= merge_recursive_generic(&o
, &c_tree
, &info
->w_tree
, 1, bases
,
353 fprintf_ln(stderr
, _("Index was not unstashed."));
359 if (reset_tree(&index_tree
, 0, 0))
362 struct strbuf out
= STRBUF_INIT
;
364 if (get_newly_staged(&out
, &c_tree
)) {
365 strbuf_release(&out
);
369 if (reset_tree(&c_tree
, 0, 1)) {
370 strbuf_release(&out
);
374 ret
= update_index(&out
);
375 strbuf_release(&out
);
383 if (refresh_cache(REFRESH_QUIET
))
384 warning("could not refresh index");
386 struct child_process cp
= CHILD_PROCESS_INIT
;
389 * Status is quite simple and could be replaced with calls to
390 * wt_status in the future, but it adds complexities which may
391 * require more tests.
395 argv_array_push(&cp
.args
, "status");
402 static int apply_stash(int argc
, const char **argv
, const char *prefix
)
407 struct stash_info info
;
408 struct option options
[] = {
409 OPT__QUIET(&quiet
, N_("be quiet, only report errors")),
410 OPT_BOOL(0, "index", &index
,
411 N_("attempt to recreate the index")),
415 argc
= parse_options(argc
, argv
, prefix
, options
,
416 git_stash_helper_apply_usage
, 0);
418 if (get_stash_info(&info
, argc
, argv
))
421 ret
= do_apply_stash(prefix
, &info
, index
, quiet
);
422 free_stash_info(&info
);
426 int cmd_stash__helper(int argc
, const char **argv
, const char *prefix
)
428 pid_t pid
= getpid();
429 const char *index_file
;
431 struct option options
[] = {
435 git_config(git_default_config
, NULL
);
437 argc
= parse_options(argc
, argv
, prefix
, options
, git_stash_helper_usage
,
438 PARSE_OPT_KEEP_UNKNOWN
| PARSE_OPT_KEEP_DASHDASH
);
440 index_file
= get_index_file();
441 strbuf_addf(&stash_index_path
, "%s.stash.%" PRIuMAX
, index_file
,
445 usage_with_options(git_stash_helper_usage
, options
);
446 if (!strcmp(argv
[0], "apply"))
447 return !!apply_stash(argc
, argv
, prefix
);
449 usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv
[0]),
450 git_stash_helper_usage
, options
);