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"
16 static const char * const git_stash_helper_usage[] = {
17 N_("git stash--helper list [<options>]"),
18 N_("git stash--helper show [<options>] [<stash>]"),
19 N_("git stash--helper drop [-q|--quiet] [<stash>]"),
20 N_("git stash--helper ( pop | apply ) [--index] [-q|--quiet] [<stash>]"),
21 N_("git stash--helper branch <branchname> [<stash>]"),
22 N_("git stash--helper clear"),
26 static const char * const git_stash_helper_list_usage[] = {
27 N_("git stash--helper list [<options>]"),
31 static const char * const git_stash_helper_show_usage[] = {
32 N_("git stash--helper show [<options>] [<stash>]"),
36 static const char * const git_stash_helper_drop_usage[] = {
37 N_("git stash--helper drop [-q|--quiet] [<stash>]"),
41 static const char * const git_stash_helper_pop_usage[] = {
42 N_("git stash--helper pop [--index] [-q|--quiet] [<stash>]"),
46 static const char * const git_stash_helper_apply_usage[] = {
47 N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
51 static const char * const git_stash_helper_branch_usage[] = {
52 N_("git stash--helper branch <branchname> [<stash>]"),
56 static const char * const git_stash_helper_clear_usage[] = {
57 N_("git stash--helper clear"),
61 static const char *ref_stash = "refs/stash";
62 static struct strbuf stash_index_path = STRBUF_INIT;
65 * w_commit is set to the commit containing the working tree
66 * b_commit is set to the base commit
67 * i_commit is set to the commit containing the index tree
68 * u_commit is set to the commit containing the untracked files tree
69 * w_tree is set to the working tree
70 * b_tree is set to the base tree
71 * i_tree is set to the index tree
72 * u_tree is set to the untracked files tree
75 struct object_id w_commit;
76 struct object_id b_commit;
77 struct object_id i_commit;
78 struct object_id u_commit;
79 struct object_id w_tree;
80 struct object_id b_tree;
81 struct object_id i_tree;
82 struct object_id u_tree;
83 struct strbuf revision;
88 static void free_stash_info(struct stash_info *info)
90 strbuf_release(&info->revision);
93 static void assert_stash_like(struct stash_info *info, const char *revision)
95 if (get_oidf(&info->b_commit, "%s^1", revision) ||
96 get_oidf(&info->w_tree, "%s:", revision) ||
97 get_oidf(&info->b_tree, "%s^1:", revision) ||
98 get_oidf(&info->i_tree, "%s^2:", revision))
99 die(_("'%s' is not a stash-like commit"), revision);
102 static int get_stash_info(struct stash_info *info, int argc, const char **argv)
107 const char *revision;
108 const char *commit = NULL;
109 struct object_id dummy;
110 struct strbuf symbolic = STRBUF_INIT;
114 struct strbuf refs_msg = STRBUF_INIT;
116 for (i = 0; i < argc; i++)
117 strbuf_addf(&refs_msg, " '%s'", argv[i]);
119 fprintf_ln(stderr, _("Too many revisions specified:%s"),
121 strbuf_release(&refs_msg);
129 strbuf_init(&info->revision, 0);
131 if (!ref_exists(ref_stash)) {
132 free_stash_info(info);
133 fprintf_ln(stderr, _("No stash entries found."));
137 strbuf_addf(&info->revision, "%s@{0}", ref_stash);
138 } else if (strspn(commit, "0123456789") == strlen(commit)) {
139 strbuf_addf(&info->revision, "%s@{%s}", ref_stash, commit);
141 strbuf_addstr(&info->revision, commit);
144 revision = info->revision.buf;
146 if (get_oid(revision, &info->w_commit)) {
147 error(_("%s is not a valid reference"), revision);
148 free_stash_info(info);
152 assert_stash_like(info, revision);
154 info->has_u = !get_oidf(&info->u_tree, "%s^3:", revision);
156 end_of_rev = strchrnul(revision, '@');
157 strbuf_add(&symbolic, revision, end_of_rev - revision);
159 ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref);
160 strbuf_release(&symbolic);
162 case 0: /* Not found, but valid ref */
163 info->is_stash_ref = 0;
166 info->is_stash_ref = !strcmp(expanded_ref, ref_stash);
168 default: /* Invalid or ambiguous */
169 free_stash_info(info);
173 return !(ret == 0 || ret == 1);
176 static int do_clear_stash(void)
178 struct object_id obj;
179 if (get_oid(ref_stash, &obj))
182 return delete_ref(NULL, ref_stash, &obj, 0);
185 static int clear_stash(int argc, const char **argv, const char *prefix)
187 struct option options[] = {
191 argc = parse_options(argc, argv, prefix, options,
192 git_stash_helper_clear_usage,
193 PARSE_OPT_STOP_AT_NON_OPTION);
196 return error(_("git stash clear with parameters is "
199 return do_clear_stash();
202 static int reset_tree(struct object_id *i_tree, int update, int reset)
205 struct unpack_trees_options opts;
206 struct tree_desc t[MAX_UNPACK_TREES];
208 struct lock_file lock_file = LOCK_INIT;
210 read_cache_preload(NULL);
211 if (refresh_cache(REFRESH_QUIET))
214 hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
216 memset(&opts, 0, sizeof(opts));
218 tree = parse_tree_indirect(i_tree);
219 if (parse_tree(tree))
222 init_tree_desc(t, tree->buffer, tree->size);
225 opts.src_index = &the_index;
226 opts.dst_index = &the_index;
229 opts.update = update;
230 opts.fn = oneway_merge;
232 if (unpack_trees(nr_trees, t, &opts))
235 if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
236 return error(_("unable to write new index file"));
241 static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit)
243 struct child_process cp = CHILD_PROCESS_INIT;
244 const char *w_commit_hex = oid_to_hex(w_commit);
247 * Diff-tree would not be very hard to replace with a native function,
248 * however it should be done together with apply_cached.
251 argv_array_pushl(&cp.args, "diff-tree", "--binary", NULL);
252 argv_array_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
254 return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
257 static int apply_cached(struct strbuf *out)
259 struct child_process cp = CHILD_PROCESS_INIT;
262 * Apply currently only reads either from stdin or a file, thus
263 * apply_all_patches would have to be updated to optionally take a
267 argv_array_pushl(&cp.args, "apply", "--cached", NULL);
268 return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
271 static int reset_head(void)
273 struct child_process cp = CHILD_PROCESS_INIT;
276 * Reset is overall quite simple, however there is no current public
280 argv_array_push(&cp.args, "reset");
282 return run_command(&cp);
285 static int get_newly_staged(struct strbuf *out, struct object_id *c_tree)
287 struct child_process cp = CHILD_PROCESS_INIT;
288 const char *c_tree_hex = oid_to_hex(c_tree);
291 * diff-index is very similar to diff-tree above, and should be
292 * converted together with update_index.
295 argv_array_pushl(&cp.args, "diff-index", "--cached", "--name-only",
296 "--diff-filter=A", NULL);
297 argv_array_push(&cp.args, c_tree_hex);
298 return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
301 static int update_index(struct strbuf *out)
303 struct child_process cp = CHILD_PROCESS_INIT;
306 * Update-index is very complicated and may need to have a public
307 * function exposed in order to remove this forking.
310 argv_array_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
311 return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
314 static int restore_untracked(struct object_id *u_tree)
317 struct child_process cp = CHILD_PROCESS_INIT;
320 * We need to run restore files from a given index, but without
321 * affecting the current index, so we use GIT_INDEX_FILE with
322 * run_command to fork processes that will not interfere.
325 argv_array_push(&cp.args, "read-tree");
326 argv_array_push(&cp.args, oid_to_hex(u_tree));
327 argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
328 stash_index_path.buf);
329 if (run_command(&cp)) {
330 remove_path(stash_index_path.buf);
334 child_process_init(&cp);
336 argv_array_pushl(&cp.args, "checkout-index", "--all", NULL);
337 argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
338 stash_index_path.buf);
340 res = run_command(&cp);
341 remove_path(stash_index_path.buf);
345 static int do_apply_stash(const char *prefix, struct stash_info *info,
346 int index, int quiet)
349 int has_index = index;
350 struct merge_options o;
351 struct object_id c_tree;
352 struct object_id index_tree;
353 struct commit *result;
354 const struct object_id *bases[1];
356 read_cache_preload(NULL);
357 if (refresh_cache(REFRESH_QUIET))
360 if (write_cache_as_tree(&c_tree, 0, NULL))
361 return error(_("cannot apply a stash in the middle of a merge"));
364 if (oideq(&info->b_tree, &info->i_tree) ||
365 oideq(&c_tree, &info->i_tree)) {
368 struct strbuf out = STRBUF_INIT;
370 if (diff_tree_binary(&out, &info->w_commit)) {
371 strbuf_release(&out);
372 return error(_("could not generate diff %s^!."),
373 oid_to_hex(&info->w_commit));
376 ret = apply_cached(&out);
377 strbuf_release(&out);
379 return error(_("conflicts in index."
380 "Try without --index."));
384 if (write_cache_as_tree(&index_tree, 0, NULL))
385 return error(_("could not save index tree"));
391 if (info->has_u && restore_untracked(&info->u_tree))
392 return error(_("could not restore untracked files from stash"));
394 init_merge_options(&o);
396 o.branch1 = "Updated upstream";
397 o.branch2 = "Stashed changes";
399 if (oideq(&info->b_tree, &c_tree))
400 o.branch1 = "Version stash was based on";
405 if (o.verbosity >= 3)
406 printf_ln(_("Merging %s with %s"), o.branch1, o.branch2);
408 bases[0] = &info->b_tree;
410 ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases,
416 fprintf_ln(stderr, _("Index was not unstashed."));
422 if (reset_tree(&index_tree, 0, 0))
425 struct strbuf out = STRBUF_INIT;
427 if (get_newly_staged(&out, &c_tree)) {
428 strbuf_release(&out);
432 if (reset_tree(&c_tree, 0, 1)) {
433 strbuf_release(&out);
437 ret = update_index(&out);
438 strbuf_release(&out);
446 if (refresh_cache(REFRESH_QUIET))
447 warning("could not refresh index");
449 struct child_process cp = CHILD_PROCESS_INIT;
452 * Status is quite simple and could be replaced with calls to
453 * wt_status in the future, but it adds complexities which may
454 * require more tests.
458 argv_array_push(&cp.args, "status");
465 static int apply_stash(int argc, const char **argv, const char *prefix)
470 struct stash_info info;
471 struct option options[] = {
472 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
473 OPT_BOOL(0, "index", &index,
474 N_("attempt to recreate the index")),
478 argc = parse_options(argc, argv, prefix, options,
479 git_stash_helper_apply_usage, 0);
481 if (get_stash_info(&info, argc, argv))
484 ret = do_apply_stash(prefix, &info, index, quiet);
485 free_stash_info(&info);
489 static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet)
492 struct child_process cp_reflog = CHILD_PROCESS_INIT;
493 struct child_process cp = CHILD_PROCESS_INIT;
496 * reflog does not provide a simple function for deleting refs. One will
497 * need to be added to avoid implementing too much reflog code here
500 cp_reflog.git_cmd = 1;
501 argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
503 argv_array_push(&cp_reflog.args, info->revision.buf);
504 ret = run_command(&cp_reflog);
507 printf_ln(_("Dropped %s (%s)"), info->revision.buf,
508 oid_to_hex(&info->w_commit));
510 return error(_("%s: Could not drop stash entry"),
515 * This could easily be replaced by get_oid, but currently it will throw
516 * a fatal error when a reflog is empty, which we can not recover from.
519 /* Even though --quiet is specified, rev-parse still outputs the hash */
521 argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
522 argv_array_pushf(&cp.args, "%s@{0}", ref_stash);
523 ret = run_command(&cp);
525 /* do_clear_stash if we just dropped the last stash entry */
532 static void assert_stash_ref(struct stash_info *info)
534 if (!info->is_stash_ref) {
535 error(_("'%s' is not a stash reference"), info->revision.buf);
536 free_stash_info(info);
541 static int drop_stash(int argc, const char **argv, const char *prefix)
545 struct stash_info info;
546 struct option options[] = {
547 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
551 argc = parse_options(argc, argv, prefix, options,
552 git_stash_helper_drop_usage, 0);
554 if (get_stash_info(&info, argc, argv))
557 assert_stash_ref(&info);
559 ret = do_drop_stash(prefix, &info, quiet);
560 free_stash_info(&info);
564 static int pop_stash(int argc, const char **argv, const char *prefix)
569 struct stash_info info;
570 struct option options[] = {
571 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
572 OPT_BOOL(0, "index", &index,
573 N_("attempt to recreate the index")),
577 argc = parse_options(argc, argv, prefix, options,
578 git_stash_helper_pop_usage, 0);
580 if (get_stash_info(&info, argc, argv))
583 assert_stash_ref(&info);
584 if ((ret = do_apply_stash(prefix, &info, index, quiet)))
585 printf_ln(_("The stash entry is kept in case "
586 "you need it again."));
588 ret = do_drop_stash(prefix, &info, quiet);
590 free_stash_info(&info);
594 static int branch_stash(int argc, const char **argv, const char *prefix)
597 const char *branch = NULL;
598 struct stash_info info;
599 struct child_process cp = CHILD_PROCESS_INIT;
600 struct option options[] = {
604 argc = parse_options(argc, argv, prefix, options,
605 git_stash_helper_branch_usage, 0);
608 fprintf_ln(stderr, _("No branch name specified"));
614 if (get_stash_info(&info, argc - 1, argv + 1))
618 argv_array_pushl(&cp.args, "checkout", "-b", NULL);
619 argv_array_push(&cp.args, branch);
620 argv_array_push(&cp.args, oid_to_hex(&info.b_commit));
621 ret = run_command(&cp);
623 ret = do_apply_stash(prefix, &info, 1, 0);
624 if (!ret && info.is_stash_ref)
625 ret = do_drop_stash(prefix, &info, 0);
627 free_stash_info(&info);
632 static int list_stash(int argc, const char **argv, const char *prefix)
634 struct child_process cp = CHILD_PROCESS_INIT;
635 struct option options[] = {
639 argc = parse_options(argc, argv, prefix, options,
640 git_stash_helper_list_usage,
641 PARSE_OPT_KEEP_UNKNOWN);
643 if (!ref_exists(ref_stash))
647 argv_array_pushl(&cp.args, "log", "--format=%gd: %gs", "-g",
648 "--first-parent", "-m", NULL);
649 argv_array_pushv(&cp.args, argv);
650 argv_array_push(&cp.args, ref_stash);
651 argv_array_push(&cp.args, "--");
652 return run_command(&cp);
655 static int show_stat = 1;
656 static int show_patch;
658 static int git_stash_config(const char *var, const char *value, void *cb)
660 if (!strcmp(var, "stash.showstat")) {
661 show_stat = git_config_bool(var, value);
664 if (!strcmp(var, "stash.showpatch")) {
665 show_patch = git_config_bool(var, value);
668 return git_default_config(var, value, cb);
671 static int show_stash(int argc, const char **argv, const char *prefix)
676 struct stash_info info;
678 struct argv_array stash_args = ARGV_ARRAY_INIT;
679 struct option options[] = {
683 init_diff_ui_defaults();
684 git_config(git_diff_ui_config, NULL);
685 init_revisions(&rev, prefix);
687 for (i = 1; i < argc; i++) {
688 if (argv[i][0] != '-')
689 argv_array_push(&stash_args, argv[i]);
694 ret = get_stash_info(&info, stash_args.argc, stash_args.argv);
695 argv_array_clear(&stash_args);
700 * The config settings are applied only if there are not passed
704 git_config(git_stash_config, NULL);
706 rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
709 rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
711 if (!show_stat && !show_patch) {
712 free_stash_info(&info);
717 argc = setup_revisions(argc, argv, &rev, NULL);
719 free_stash_info(&info);
720 usage_with_options(git_stash_helper_show_usage, options);
723 rev.diffopt.flags.recursive = 1;
724 setup_diff_pager(&rev.diffopt);
725 diff_tree_oid(&info.b_commit, &info.w_commit, "", &rev.diffopt);
726 log_tree_diff_flush(&rev);
728 free_stash_info(&info);
729 return diff_result_code(&rev.diffopt, 0);
732 int cmd_stash__helper(int argc, const char **argv, const char *prefix)
734 pid_t pid = getpid();
735 const char *index_file;
737 struct option options[] = {
741 git_config(git_default_config, NULL);
743 argc = parse_options(argc, argv, prefix, options, git_stash_helper_usage,
744 PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH);
746 index_file = get_index_file();
747 strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file,
751 usage_with_options(git_stash_helper_usage, options);
752 if (!strcmp(argv[0], "apply"))
753 return !!apply_stash(argc, argv, prefix);
754 else if (!strcmp(argv[0], "clear"))
755 return !!clear_stash(argc, argv, prefix);
756 else if (!strcmp(argv[0], "drop"))
757 return !!drop_stash(argc, argv, prefix);
758 else if (!strcmp(argv[0], "pop"))
759 return !!pop_stash(argc, argv, prefix);
760 else if (!strcmp(argv[0], "branch"))
761 return !!branch_stash(argc, argv, prefix);
762 else if (!strcmp(argv[0], "list"))
763 return !!list_stash(argc, argv, prefix);
764 else if (!strcmp(argv[0], "show"))
765 return !!show_stash(argc, argv, prefix);
767 usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
768 git_stash_helper_usage, options);