1#include "builtin.h"
2#include "config.h"
3#include "parse-options.h"
4#include "refs.h"
5#include "lockfile.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"
11#include "dir.h"
12#include "rerere.h"
13#include "revision.h"
14#include "log-tree.h"
15#include "diffcore.h"
16
17#define INCLUDE_ALL_FILES 2
18
19static const char * const git_stash_helper_usage[] = {
20 N_("git stash--helper list [<options>]"),
21 N_("git stash--helper show [<options>] [<stash>]"),
22 N_("git stash--helper drop [-q|--quiet] [<stash>]"),
23 N_("git stash--helper ( pop | apply ) [--index] [-q|--quiet] [<stash>]"),
24 N_("git stash--helper branch <branchname> [<stash>]"),
25 N_("git stash--helper clear"),
26 N_("git stash--helper [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
27 " [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
28 " [--] [<pathspec>...]]"),
29 NULL
30};
31
32static const char * const git_stash_helper_list_usage[] = {
33 N_("git stash--helper list [<options>]"),
34 NULL
35};
36
37static const char * const git_stash_helper_show_usage[] = {
38 N_("git stash--helper show [<options>] [<stash>]"),
39 NULL
40};
41
42static const char * const git_stash_helper_drop_usage[] = {
43 N_("git stash--helper drop [-q|--quiet] [<stash>]"),
44 NULL
45};
46
47static const char * const git_stash_helper_pop_usage[] = {
48 N_("git stash--helper pop [--index] [-q|--quiet] [<stash>]"),
49 NULL
50};
51
52static const char * const git_stash_helper_apply_usage[] = {
53 N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
54 NULL
55};
56
57static const char * const git_stash_helper_branch_usage[] = {
58 N_("git stash--helper branch <branchname> [<stash>]"),
59 NULL
60};
61
62static const char * const git_stash_helper_clear_usage[] = {
63 N_("git stash--helper clear"),
64 NULL
65};
66
67static const char * const git_stash_helper_store_usage[] = {
68 N_("git stash--helper store [-m|--message <message>] [-q|--quiet] <commit>"),
69 NULL
70};
71
72static const char * const git_stash_helper_create_usage[] = {
73 N_("git stash--helper create [<message>]"),
74 NULL
75};
76
77static const char * const git_stash_helper_push_usage[] = {
78 N_("git stash--helper [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
79 " [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
80 " [--] [<pathspec>...]]"),
81 NULL
82};
83
84static const char *ref_stash = "refs/stash";
85static struct strbuf stash_index_path = STRBUF_INIT;
86
87/*
88 * w_commit is set to the commit containing the working tree
89 * b_commit is set to the base commit
90 * i_commit is set to the commit containing the index tree
91 * u_commit is set to the commit containing the untracked files tree
92 * w_tree is set to the working tree
93 * b_tree is set to the base tree
94 * i_tree is set to the index tree
95 * u_tree is set to the untracked files tree
96 */
97struct stash_info {
98 struct object_id w_commit;
99 struct object_id b_commit;
100 struct object_id i_commit;
101 struct object_id u_commit;
102 struct object_id w_tree;
103 struct object_id b_tree;
104 struct object_id i_tree;
105 struct object_id u_tree;
106 struct strbuf revision;
107 int is_stash_ref;
108 int has_u;
109};
110
111static void free_stash_info(struct stash_info *info)
112{
113 strbuf_release(&info->revision);
114}
115
116static void assert_stash_like(struct stash_info *info, const char *revision)
117{
118 if (get_oidf(&info->b_commit, "%s^1", revision) ||
119 get_oidf(&info->w_tree, "%s:", revision) ||
120 get_oidf(&info->b_tree, "%s^1:", revision) ||
121 get_oidf(&info->i_tree, "%s^2:", revision))
122 die(_("'%s' is not a stash-like commit"), revision);
123}
124
125static int get_stash_info(struct stash_info *info, int argc, const char **argv)
126{
127 int ret;
128 char *end_of_rev;
129 char *expanded_ref;
130 const char *revision;
131 const char *commit = NULL;
132 struct object_id dummy;
133 struct strbuf symbolic = STRBUF_INIT;
134
135 if (argc > 1) {
136 int i;
137 struct strbuf refs_msg = STRBUF_INIT;
138
139 for (i = 0; i < argc; i++)
140 strbuf_addf(&refs_msg, " '%s'", argv[i]);
141
142 fprintf_ln(stderr, _("Too many revisions specified:%s"),
143 refs_msg.buf);
144 strbuf_release(&refs_msg);
145
146 return -1;
147 }
148
149 if (argc == 1)
150 commit = argv[0];
151
152 strbuf_init(&info->revision, 0);
153 if (!commit) {
154 if (!ref_exists(ref_stash)) {
155 free_stash_info(info);
156 fprintf_ln(stderr, _("No stash entries found."));
157 return -1;
158 }
159
160 strbuf_addf(&info->revision, "%s@{0}", ref_stash);
161 } else if (strspn(commit, "0123456789") == strlen(commit)) {
162 strbuf_addf(&info->revision, "%s@{%s}", ref_stash, commit);
163 } else {
164 strbuf_addstr(&info->revision, commit);
165 }
166
167 revision = info->revision.buf;
168
169 if (get_oid(revision, &info->w_commit)) {
170 error(_("%s is not a valid reference"), revision);
171 free_stash_info(info);
172 return -1;
173 }
174
175 assert_stash_like(info, revision);
176
177 info->has_u = !get_oidf(&info->u_tree, "%s^3:", revision);
178
179 end_of_rev = strchrnul(revision, '@');
180 strbuf_add(&symbolic, revision, end_of_rev - revision);
181
182 ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref);
183 strbuf_release(&symbolic);
184 switch (ret) {
185 case 0: /* Not found, but valid ref */
186 info->is_stash_ref = 0;
187 break;
188 case 1:
189 info->is_stash_ref = !strcmp(expanded_ref, ref_stash);
190 break;
191 default: /* Invalid or ambiguous */
192 free_stash_info(info);
193 }
194
195 free(expanded_ref);
196 return !(ret == 0 || ret == 1);
197}
198
199static int do_clear_stash(void)
200{
201 struct object_id obj;
202 if (get_oid(ref_stash, &obj))
203 return 0;
204
205 return delete_ref(NULL, ref_stash, &obj, 0);
206}
207
208static int clear_stash(int argc, const char **argv, const char *prefix)
209{
210 struct option options[] = {
211 OPT_END()
212 };
213
214 argc = parse_options(argc, argv, prefix, options,
215 git_stash_helper_clear_usage,
216 PARSE_OPT_STOP_AT_NON_OPTION);
217
218 if (argc)
219 return error(_("git stash clear with parameters is "
220 "unimplemented"));
221
222 return do_clear_stash();
223}
224
225static int reset_tree(struct object_id *i_tree, int update, int reset)
226{
227 int nr_trees = 1;
228 struct unpack_trees_options opts;
229 struct tree_desc t[MAX_UNPACK_TREES];
230 struct tree *tree;
231 struct lock_file lock_file = LOCK_INIT;
232
233 read_cache_preload(NULL);
234 if (refresh_cache(REFRESH_QUIET))
235 return -1;
236
237 hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
238
239 memset(&opts, 0, sizeof(opts));
240
241 tree = parse_tree_indirect(i_tree);
242 if (parse_tree(tree))
243 return -1;
244
245 init_tree_desc(t, tree->buffer, tree->size);
246
247 opts.head_idx = 1;
248 opts.src_index = &the_index;
249 opts.dst_index = &the_index;
250 opts.merge = 1;
251 opts.reset = reset;
252 opts.update = update;
253 opts.fn = oneway_merge;
254
255 if (unpack_trees(nr_trees, t, &opts))
256 return -1;
257
258 if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
259 return error(_("unable to write new index file"));
260
261 return 0;
262}
263
264static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit)
265{
266 struct child_process cp = CHILD_PROCESS_INIT;
267 const char *w_commit_hex = oid_to_hex(w_commit);
268
269 /*
270 * Diff-tree would not be very hard to replace with a native function,
271 * however it should be done together with apply_cached.
272 */
273 cp.git_cmd = 1;
274 argv_array_pushl(&cp.args, "diff-tree", "--binary", NULL);
275 argv_array_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
276
277 return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
278}
279
280static int apply_cached(struct strbuf *out)
281{
282 struct child_process cp = CHILD_PROCESS_INIT;
283
284 /*
285 * Apply currently only reads either from stdin or a file, thus
286 * apply_all_patches would have to be updated to optionally take a
287 * buffer.
288 */
289 cp.git_cmd = 1;
290 argv_array_pushl(&cp.args, "apply", "--cached", NULL);
291 return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
292}
293
294static int reset_head(void)
295{
296 struct child_process cp = CHILD_PROCESS_INIT;
297
298 /*
299 * Reset is overall quite simple, however there is no current public
300 * API for resetting.
301 */
302 cp.git_cmd = 1;
303 argv_array_push(&cp.args, "reset");
304
305 return run_command(&cp);
306}
307
308static void add_diff_to_buf(struct diff_queue_struct *q,
309 struct diff_options *options,
310 void *data)
311{
312 int i;
313
314 for (i = 0; i < q->nr; i++) {
315 strbuf_addstr(data, q->queue[i]->one->path);
316
317 /* NUL-terminate: will be fed to update-index -z */
318 strbuf_addch(data, '\0');
319 }
320}
321
322static int get_newly_staged(struct strbuf *out, struct object_id *c_tree)
323{
324 struct child_process cp = CHILD_PROCESS_INIT;
325 const char *c_tree_hex = oid_to_hex(c_tree);
326
327 /*
328 * diff-index is very similar to diff-tree above, and should be
329 * converted together with update_index.
330 */
331 cp.git_cmd = 1;
332 argv_array_pushl(&cp.args, "diff-index", "--cached", "--name-only",
333 "--diff-filter=A", NULL);
334 argv_array_push(&cp.args, c_tree_hex);
335 return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
336}
337
338static int update_index(struct strbuf *out)
339{
340 struct child_process cp = CHILD_PROCESS_INIT;
341
342 /*
343 * Update-index is very complicated and may need to have a public
344 * function exposed in order to remove this forking.
345 */
346 cp.git_cmd = 1;
347 argv_array_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
348 return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
349}
350
351static int restore_untracked(struct object_id *u_tree)
352{
353 int res;
354 struct child_process cp = CHILD_PROCESS_INIT;
355
356 /*
357 * We need to run restore files from a given index, but without
358 * affecting the current index, so we use GIT_INDEX_FILE with
359 * run_command to fork processes that will not interfere.
360 */
361 cp.git_cmd = 1;
362 argv_array_push(&cp.args, "read-tree");
363 argv_array_push(&cp.args, oid_to_hex(u_tree));
364 argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
365 stash_index_path.buf);
366 if (run_command(&cp)) {
367 remove_path(stash_index_path.buf);
368 return -1;
369 }
370
371 child_process_init(&cp);
372 cp.git_cmd = 1;
373 argv_array_pushl(&cp.args, "checkout-index", "--all", NULL);
374 argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
375 stash_index_path.buf);
376
377 res = run_command(&cp);
378 remove_path(stash_index_path.buf);
379 return res;
380}
381
382static int do_apply_stash(const char *prefix, struct stash_info *info,
383 int index, int quiet)
384{
385 int ret;
386 int has_index = index;
387 struct merge_options o;
388 struct object_id c_tree;
389 struct object_id index_tree;
390 struct commit *result;
391 const struct object_id *bases[1];
392
393 read_cache_preload(NULL);
394 if (refresh_cache(REFRESH_QUIET))
395 return -1;
396
397 if (write_cache_as_tree(&c_tree, 0, NULL))
398 return error(_("cannot apply a stash in the middle of a merge"));
399
400 if (index) {
401 if (oideq(&info->b_tree, &info->i_tree) ||
402 oideq(&c_tree, &info->i_tree)) {
403 has_index = 0;
404 } else {
405 struct strbuf out = STRBUF_INIT;
406
407 if (diff_tree_binary(&out, &info->w_commit)) {
408 strbuf_release(&out);
409 return error(_("could not generate diff %s^!."),
410 oid_to_hex(&info->w_commit));
411 }
412
413 ret = apply_cached(&out);
414 strbuf_release(&out);
415 if (ret)
416 return error(_("conflicts in index."
417 "Try without --index."));
418
419 discard_cache();
420 read_cache();
421 if (write_cache_as_tree(&index_tree, 0, NULL))
422 return error(_("could not save index tree"));
423
424 reset_head();
425 }
426 }
427
428 if (info->has_u && restore_untracked(&info->u_tree))
429 return error(_("could not restore untracked files from stash"));
430
431 init_merge_options(&o);
432
433 o.branch1 = "Updated upstream";
434 o.branch2 = "Stashed changes";
435
436 if (oideq(&info->b_tree, &c_tree))
437 o.branch1 = "Version stash was based on";
438
439 if (quiet)
440 o.verbosity = 0;
441
442 if (o.verbosity >= 3)
443 printf_ln(_("Merging %s with %s"), o.branch1, o.branch2);
444
445 bases[0] = &info->b_tree;
446
447 ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases,
448 &result);
449 if (ret) {
450 rerere(0);
451
452 if (index)
453 fprintf_ln(stderr, _("Index was not unstashed."));
454
455 return ret;
456 }
457
458 if (has_index) {
459 if (reset_tree(&index_tree, 0, 0))
460 return -1;
461 } else {
462 struct strbuf out = STRBUF_INIT;
463
464 if (get_newly_staged(&out, &c_tree)) {
465 strbuf_release(&out);
466 return -1;
467 }
468
469 if (reset_tree(&c_tree, 0, 1)) {
470 strbuf_release(&out);
471 return -1;
472 }
473
474 ret = update_index(&out);
475 strbuf_release(&out);
476 if (ret)
477 return -1;
478
479 discard_cache();
480 }
481
482 if (quiet) {
483 if (refresh_cache(REFRESH_QUIET))
484 warning("could not refresh index");
485 } else {
486 struct child_process cp = CHILD_PROCESS_INIT;
487
488 /*
489 * Status is quite simple and could be replaced with calls to
490 * wt_status in the future, but it adds complexities which may
491 * require more tests.
492 */
493 cp.git_cmd = 1;
494 cp.dir = prefix;
495 argv_array_push(&cp.args, "status");
496 run_command(&cp);
497 }
498
499 return 0;
500}
501
502static int apply_stash(int argc, const char **argv, const char *prefix)
503{
504 int ret;
505 int quiet = 0;
506 int index = 0;
507 struct stash_info info;
508 struct option options[] = {
509 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
510 OPT_BOOL(0, "index", &index,
511 N_("attempt to recreate the index")),
512 OPT_END()
513 };
514
515 argc = parse_options(argc, argv, prefix, options,
516 git_stash_helper_apply_usage, 0);
517
518 if (get_stash_info(&info, argc, argv))
519 return -1;
520
521 ret = do_apply_stash(prefix, &info, index, quiet);
522 free_stash_info(&info);
523 return ret;
524}
525
526static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet)
527{
528 int ret;
529 struct child_process cp_reflog = CHILD_PROCESS_INIT;
530 struct child_process cp = CHILD_PROCESS_INIT;
531
532 /*
533 * reflog does not provide a simple function for deleting refs. One will
534 * need to be added to avoid implementing too much reflog code here
535 */
536
537 cp_reflog.git_cmd = 1;
538 argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
539 "--rewrite", NULL);
540 argv_array_push(&cp_reflog.args, info->revision.buf);
541 ret = run_command(&cp_reflog);
542 if (!ret) {
543 if (!quiet)
544 printf_ln(_("Dropped %s (%s)"), info->revision.buf,
545 oid_to_hex(&info->w_commit));
546 } else {
547 return error(_("%s: Could not drop stash entry"),
548 info->revision.buf);
549 }
550
551 /*
552 * This could easily be replaced by get_oid, but currently it will throw
553 * a fatal error when a reflog is empty, which we can not recover from.
554 */
555 cp.git_cmd = 1;
556 /* Even though --quiet is specified, rev-parse still outputs the hash */
557 cp.no_stdout = 1;
558 argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
559 argv_array_pushf(&cp.args, "%s@{0}", ref_stash);
560 ret = run_command(&cp);
561
562 /* do_clear_stash if we just dropped the last stash entry */
563 if (ret)
564 do_clear_stash();
565
566 return 0;
567}
568
569static void assert_stash_ref(struct stash_info *info)
570{
571 if (!info->is_stash_ref) {
572 error(_("'%s' is not a stash reference"), info->revision.buf);
573 free_stash_info(info);
574 exit(1);
575 }
576}
577
578static int drop_stash(int argc, const char **argv, const char *prefix)
579{
580 int ret;
581 int quiet = 0;
582 struct stash_info info;
583 struct option options[] = {
584 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
585 OPT_END()
586 };
587
588 argc = parse_options(argc, argv, prefix, options,
589 git_stash_helper_drop_usage, 0);
590
591 if (get_stash_info(&info, argc, argv))
592 return -1;
593
594 assert_stash_ref(&info);
595
596 ret = do_drop_stash(prefix, &info, quiet);
597 free_stash_info(&info);
598 return ret;
599}
600
601static int pop_stash(int argc, const char **argv, const char *prefix)
602{
603 int ret;
604 int index = 0;
605 int quiet = 0;
606 struct stash_info info;
607 struct option options[] = {
608 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
609 OPT_BOOL(0, "index", &index,
610 N_("attempt to recreate the index")),
611 OPT_END()
612 };
613
614 argc = parse_options(argc, argv, prefix, options,
615 git_stash_helper_pop_usage, 0);
616
617 if (get_stash_info(&info, argc, argv))
618 return -1;
619
620 assert_stash_ref(&info);
621 if ((ret = do_apply_stash(prefix, &info, index, quiet)))
622 printf_ln(_("The stash entry is kept in case "
623 "you need it again."));
624 else
625 ret = do_drop_stash(prefix, &info, quiet);
626
627 free_stash_info(&info);
628 return ret;
629}
630
631static int branch_stash(int argc, const char **argv, const char *prefix)
632{
633 int ret;
634 const char *branch = NULL;
635 struct stash_info info;
636 struct child_process cp = CHILD_PROCESS_INIT;
637 struct option options[] = {
638 OPT_END()
639 };
640
641 argc = parse_options(argc, argv, prefix, options,
642 git_stash_helper_branch_usage, 0);
643
644 if (!argc) {
645 fprintf_ln(stderr, _("No branch name specified"));
646 return -1;
647 }
648
649 branch = argv[0];
650
651 if (get_stash_info(&info, argc - 1, argv + 1))
652 return -1;
653
654 cp.git_cmd = 1;
655 argv_array_pushl(&cp.args, "checkout", "-b", NULL);
656 argv_array_push(&cp.args, branch);
657 argv_array_push(&cp.args, oid_to_hex(&info.b_commit));
658 ret = run_command(&cp);
659 if (!ret)
660 ret = do_apply_stash(prefix, &info, 1, 0);
661 if (!ret && info.is_stash_ref)
662 ret = do_drop_stash(prefix, &info, 0);
663
664 free_stash_info(&info);
665
666 return ret;
667}
668
669static int list_stash(int argc, const char **argv, const char *prefix)
670{
671 struct child_process cp = CHILD_PROCESS_INIT;
672 struct option options[] = {
673 OPT_END()
674 };
675
676 argc = parse_options(argc, argv, prefix, options,
677 git_stash_helper_list_usage,
678 PARSE_OPT_KEEP_UNKNOWN);
679
680 if (!ref_exists(ref_stash))
681 return 0;
682
683 cp.git_cmd = 1;
684 argv_array_pushl(&cp.args, "log", "--format=%gd: %gs", "-g",
685 "--first-parent", "-m", NULL);
686 argv_array_pushv(&cp.args, argv);
687 argv_array_push(&cp.args, ref_stash);
688 argv_array_push(&cp.args, "--");
689 return run_command(&cp);
690}
691
692static int show_stat = 1;
693static int show_patch;
694
695static int git_stash_config(const char *var, const char *value, void *cb)
696{
697 if (!strcmp(var, "stash.showstat")) {
698 show_stat = git_config_bool(var, value);
699 return 0;
700 }
701 if (!strcmp(var, "stash.showpatch")) {
702 show_patch = git_config_bool(var, value);
703 return 0;
704 }
705 return git_default_config(var, value, cb);
706}
707
708static int show_stash(int argc, const char **argv, const char *prefix)
709{
710 int i;
711 int opts = 0;
712 int ret = 0;
713 struct stash_info info;
714 struct rev_info rev;
715 struct argv_array stash_args = ARGV_ARRAY_INIT;
716 struct option options[] = {
717 OPT_END()
718 };
719
720 init_diff_ui_defaults();
721 git_config(git_diff_ui_config, NULL);
722 init_revisions(&rev, prefix);
723
724 for (i = 1; i < argc; i++) {
725 if (argv[i][0] != '-')
726 argv_array_push(&stash_args, argv[i]);
727 else
728 opts++;
729 }
730
731 ret = get_stash_info(&info, stash_args.argc, stash_args.argv);
732 argv_array_clear(&stash_args);
733 if (ret)
734 return -1;
735
736 /*
737 * The config settings are applied only if there are not passed
738 * any options.
739 */
740 if (!opts) {
741 git_config(git_stash_config, NULL);
742 if (show_stat)
743 rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
744
745 if (show_patch)
746 rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
747
748 if (!show_stat && !show_patch) {
749 free_stash_info(&info);
750 return 0;
751 }
752 }
753
754 argc = setup_revisions(argc, argv, &rev, NULL);
755 if (argc > 1) {
756 free_stash_info(&info);
757 usage_with_options(git_stash_helper_show_usage, options);
758 }
759
760 rev.diffopt.flags.recursive = 1;
761 setup_diff_pager(&rev.diffopt);
762 diff_tree_oid(&info.b_commit, &info.w_commit, "", &rev.diffopt);
763 log_tree_diff_flush(&rev);
764
765 free_stash_info(&info);
766 return diff_result_code(&rev.diffopt, 0);
767}
768
769static int do_store_stash(const struct object_id *w_commit, const char *stash_msg,
770 int quiet)
771{
772 if (!stash_msg)
773 stash_msg = "Created via \"git stash store\".";
774
775 if (update_ref(stash_msg, ref_stash, w_commit, NULL,
776 REF_FORCE_CREATE_REFLOG,
777 quiet ? UPDATE_REFS_QUIET_ON_ERR :
778 UPDATE_REFS_MSG_ON_ERR)) {
779 if (!quiet) {
780 fprintf_ln(stderr, _("Cannot update %s with %s"),
781 ref_stash, oid_to_hex(w_commit));
782 }
783 return -1;
784 }
785
786 return 0;
787}
788
789static int store_stash(int argc, const char **argv, const char *prefix)
790{
791 int quiet = 0;
792 const char *stash_msg = NULL;
793 struct object_id obj;
794 struct object_context dummy;
795 struct option options[] = {
796 OPT__QUIET(&quiet, N_("be quiet")),
797 OPT_STRING('m', "message", &stash_msg, "message",
798 N_("stash message")),
799 OPT_END()
800 };
801
802 argc = parse_options(argc, argv, prefix, options,
803 git_stash_helper_store_usage,
804 PARSE_OPT_KEEP_UNKNOWN);
805
806 if (argc != 1) {
807 if (!quiet)
808 fprintf_ln(stderr, _("\"git stash store\" requires one "
809 "<commit> argument"));
810 return -1;
811 }
812
813 if (get_oid_with_context(argv[0], quiet ? GET_OID_QUIETLY : 0, &obj,
814 &dummy)) {
815 if (!quiet)
816 fprintf_ln(stderr, _("Cannot update %s with %s"),
817 ref_stash, argv[0]);
818 return -1;
819 }
820
821 return do_store_stash(&obj, stash_msg, quiet);
822}
823
824static void add_pathspecs(struct argv_array *args,
825 struct pathspec ps) {
826 int i;
827
828 for (i = 0; i < ps.nr; i++)
829 argv_array_push(args, ps.items[i].match);
830}
831
832/*
833 * `untracked_files` will be filled with the names of untracked files.
834 * The return value is:
835 *
836 * = 0 if there are not any untracked files
837 * > 0 if there are untracked files
838 */
839static int get_untracked_files(struct pathspec ps, int include_untracked,
840 struct strbuf *untracked_files)
841{
842 int i;
843 int max_len;
844 int found = 0;
845 char *seen;
846 struct dir_struct dir;
847
848 memset(&dir, 0, sizeof(dir));
849 if (include_untracked != INCLUDE_ALL_FILES)
850 setup_standard_excludes(&dir);
851
852 seen = xcalloc(ps.nr, 1);
853
854 max_len = fill_directory(&dir, the_repository->index, &ps);
855 for (i = 0; i < dir.nr; i++) {
856 struct dir_entry *ent = dir.entries[i];
857 if (dir_path_match(&the_index, ent, &ps, max_len, seen)) {
858 found++;
859 strbuf_addstr(untracked_files, ent->name);
860 /* NUL-terminate: will be fed to update-index -z */
861 strbuf_addch(untracked_files, '\0');
862 }
863 free(ent);
864 }
865
866 free(seen);
867 free(dir.entries);
868 free(dir.ignored);
869 clear_directory(&dir);
870 return found;
871}
872
873/*
874 * The return value of `check_changes()` can be:
875 *
876 * < 0 if there was an error
877 * = 0 if there are no changes.
878 * > 0 if there are changes.
879 */
880static int check_changes(struct pathspec ps, int include_untracked)
881{
882 int result;
883 struct rev_info rev;
884 struct object_id dummy;
885 struct strbuf out = STRBUF_INIT;
886
887 /* No initial commit. */
888 if (get_oid("HEAD", &dummy))
889 return -1;
890
891 if (read_cache() < 0)
892 return -1;
893
894 init_revisions(&rev, NULL);
895 rev.prune_data = ps;
896
897 rev.diffopt.flags.quick = 1;
898 rev.diffopt.flags.ignore_submodules = 1;
899 rev.abbrev = 0;
900
901 add_head_to_pending(&rev);
902 diff_setup_done(&rev.diffopt);
903
904 result = run_diff_index(&rev, 1);
905 if (diff_result_code(&rev.diffopt, result))
906 return 1;
907
908 object_array_clear(&rev.pending);
909 result = run_diff_files(&rev, 0);
910 if (diff_result_code(&rev.diffopt, result))
911 return 1;
912
913 if (include_untracked && get_untracked_files(ps, include_untracked,
914 &out)) {
915 strbuf_release(&out);
916 return 1;
917 }
918
919 strbuf_release(&out);
920 return 0;
921}
922
923static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
924 struct strbuf files)
925{
926 int ret = 0;
927 struct strbuf untracked_msg = STRBUF_INIT;
928 struct strbuf out = STRBUF_INIT;
929 struct child_process cp_upd_index = CHILD_PROCESS_INIT;
930 struct child_process cp_write_tree = CHILD_PROCESS_INIT;
931
932 cp_upd_index.git_cmd = 1;
933 argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
934 "--remove", "--stdin", NULL);
935 argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
936 stash_index_path.buf);
937
938 strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf);
939 if (pipe_command(&cp_upd_index, files.buf, files.len, NULL, 0,
940 NULL, 0)) {
941 ret = -1;
942 goto done;
943 }
944
945 cp_write_tree.git_cmd = 1;
946 argv_array_push(&cp_write_tree.args, "write-tree");
947 argv_array_pushf(&cp_write_tree.env_array, "GIT_INDEX_FILE=%s",
948 stash_index_path.buf);
949 if (pipe_command(&cp_write_tree, NULL, 0, &out, 0,NULL, 0)) {
950 ret = -1;
951 goto done;
952 }
953 get_oid_hex(out.buf, &info->u_tree);
954
955 if (commit_tree(untracked_msg.buf, untracked_msg.len,
956 &info->u_tree, NULL, &info->u_commit, NULL, NULL)) {
957 ret = -1;
958 goto done;
959 }
960
961done:
962 strbuf_release(&untracked_msg);
963 strbuf_release(&out);
964 remove_path(stash_index_path.buf);
965 return ret;
966}
967
968static int stash_patch(struct stash_info *info, struct pathspec ps,
969 struct strbuf *out_patch)
970{
971 int ret = 0;
972 struct strbuf out = STRBUF_INIT;
973 struct child_process cp_read_tree = CHILD_PROCESS_INIT;
974 struct child_process cp_add_i = CHILD_PROCESS_INIT;
975 struct child_process cp_write_tree = CHILD_PROCESS_INIT;
976 struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
977
978 remove_path(stash_index_path.buf);
979
980 cp_read_tree.git_cmd = 1;
981 argv_array_pushl(&cp_read_tree.args, "read-tree", "HEAD", NULL);
982 argv_array_pushf(&cp_read_tree.env_array, "GIT_INDEX_FILE=%s",
983 stash_index_path.buf);
984 if (run_command(&cp_read_tree)) {
985 ret = -1;
986 goto done;
987 }
988
989 /* Find out what the user wants. */
990 cp_add_i.git_cmd = 1;
991 argv_array_pushl(&cp_add_i.args, "add--interactive", "--patch=stash",
992 "--", NULL);
993 add_pathspecs(&cp_add_i.args, ps);
994 argv_array_pushf(&cp_add_i.env_array, "GIT_INDEX_FILE=%s",
995 stash_index_path.buf);
996 if (run_command(&cp_add_i)) {
997 ret = -1;
998 goto done;
999 }
1000
1001 /* State of the working tree. */
1002 cp_write_tree.git_cmd = 1;
1003 argv_array_push(&cp_write_tree.args, "write-tree");
1004 argv_array_pushf(&cp_write_tree.env_array, "GIT_INDEX_FILE=%s",
1005 stash_index_path.buf);
1006 if (pipe_command(&cp_write_tree, NULL, 0, &out, 0,NULL, 0)) {
1007 ret = -1;
1008 goto done;
1009 }
1010
1011 get_oid_hex(out.buf, &info->w_tree);
1012
1013 cp_diff_tree.git_cmd = 1;
1014 argv_array_pushl(&cp_diff_tree.args, "diff-tree", "-p", "HEAD",
1015 oid_to_hex(&info->w_tree), "--", NULL);
1016 if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
1017 ret = -1;
1018 goto done;
1019 }
1020
1021 if (!out_patch->len) {
1022 fprintf_ln(stderr, _("No changes selected"));
1023 ret = 1;
1024 }
1025
1026done:
1027 strbuf_release(&out);
1028 remove_path(stash_index_path.buf);
1029 return ret;
1030}
1031
1032static int stash_working_tree(struct stash_info *info, struct pathspec ps)
1033{
1034 int ret = 0;
1035 struct rev_info rev;
1036 struct child_process cp_upd_index = CHILD_PROCESS_INIT;
1037 struct child_process cp_write_tree = CHILD_PROCESS_INIT;
1038 struct strbuf out = STRBUF_INIT;
1039 struct strbuf diff_output = STRBUF_INIT;
1040
1041 init_revisions(&rev, NULL);
1042
1043 set_alternate_index_output(stash_index_path.buf);
1044 if (reset_tree(&info->i_tree, 0, 0)) {
1045 ret = -1;
1046 goto done;
1047 }
1048 set_alternate_index_output(NULL);
1049
1050 rev.prune_data = ps;
1051 rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
1052 rev.diffopt.format_callback = add_diff_to_buf;
1053 rev.diffopt.format_callback_data = &diff_output;
1054
1055 if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
1056 ret = -1;
1057 goto done;
1058 }
1059
1060 add_pending_object(&rev, parse_object(the_repository, &info->b_commit),
1061 "");
1062 if (run_diff_index(&rev, 0)) {
1063 ret = -1;
1064 goto done;
1065 }
1066
1067 cp_upd_index.git_cmd = 1;
1068 argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
1069 "--remove", "--stdin", NULL);
1070 argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
1071 stash_index_path.buf);
1072
1073 if (pipe_command(&cp_upd_index, diff_output.buf, diff_output.len,
1074 NULL, 0, NULL, 0)) {
1075 ret = -1;
1076 goto done;
1077 }
1078
1079 cp_write_tree.git_cmd = 1;
1080 argv_array_push(&cp_write_tree.args, "write-tree");
1081 argv_array_pushf(&cp_write_tree.env_array, "GIT_INDEX_FILE=%s",
1082 stash_index_path.buf);
1083 if (pipe_command(&cp_write_tree, NULL, 0, &out, 0,NULL, 0)) {
1084 ret = -1;
1085 goto done;
1086 }
1087
1088 get_oid_hex(out.buf, &info->w_tree);
1089
1090done:
1091 UNLEAK(rev);
1092 strbuf_release(&out);
1093 object_array_clear(&rev.pending);
1094 strbuf_release(&diff_output);
1095 remove_path(stash_index_path.buf);
1096 return ret;
1097}
1098
1099static int do_create_stash(struct pathspec ps, struct strbuf *stash_msg_buf,
1100 int include_untracked, int patch_mode,
1101 struct stash_info *info, struct strbuf *patch)
1102{
1103 int ret = 0;
1104 int flags = 0;
1105 int untracked_commit_option = 0;
1106 const char *head_short_sha1 = NULL;
1107 const char *branch_ref = NULL;
1108 const char *branch_name = "(no branch)";
1109 struct commit *head_commit = NULL;
1110 struct commit_list *parents = NULL;
1111 struct strbuf msg = STRBUF_INIT;
1112 struct strbuf commit_tree_label = STRBUF_INIT;
1113 struct strbuf untracked_files = STRBUF_INIT;
1114
1115 prepare_fallback_ident("git stash", "git@stash");
1116
1117 read_cache_preload(NULL);
1118 refresh_cache(REFRESH_QUIET);
1119
1120 if (get_oid("HEAD", &info->b_commit)) {
1121 fprintf_ln(stderr, _("You do not have the initial commit yet"));
1122 ret = -1;
1123 goto done;
1124 } else {
1125 head_commit = lookup_commit(the_repository, &info->b_commit);
1126 }
1127
1128 if (!check_changes(ps, include_untracked)) {
1129 ret = 1;
1130 goto done;
1131 }
1132
1133 branch_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
1134 if (flags & REF_ISSYMREF)
1135 branch_name = strrchr(branch_ref, '/') + 1;
1136 head_short_sha1 = find_unique_abbrev(&head_commit->object.oid,
1137 DEFAULT_ABBREV);
1138 strbuf_addf(&msg, "%s: %s ", branch_name, head_short_sha1);
1139 pp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg);
1140
1141 strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf);
1142 commit_list_insert(head_commit, &parents);
1143 if (write_cache_as_tree(&info->i_tree, 0, NULL) ||
1144 commit_tree(commit_tree_label.buf, commit_tree_label.len,
1145 &info->i_tree, parents, &info->i_commit, NULL, NULL)) {
1146 fprintf_ln(stderr, _("Cannot save the current index state"));
1147 ret = -1;
1148 goto done;
1149 }
1150
1151 if (include_untracked && get_untracked_files(ps, include_untracked,
1152 &untracked_files)) {
1153 if (save_untracked_files(info, &msg, untracked_files)) {
1154 fprintf_ln(stderr, _("Cannot save "
1155 "the untracked files"));
1156 ret = -1;
1157 goto done;
1158 }
1159 untracked_commit_option = 1;
1160 }
1161 if (patch_mode) {
1162 ret = stash_patch(info, ps, patch);
1163 if (ret < 0) {
1164 fprintf_ln(stderr, _("Cannot save the current "
1165 "worktree state"));
1166 goto done;
1167 } else if (ret > 0) {
1168 goto done;
1169 }
1170 } else {
1171 if (stash_working_tree(info, ps)) {
1172 fprintf_ln(stderr, _("Cannot save the current "
1173 "worktree state"));
1174 ret = -1;
1175 goto done;
1176 }
1177 }
1178
1179 if (!stash_msg_buf->len)
1180 strbuf_addf(stash_msg_buf, "WIP on %s", msg.buf);
1181 else
1182 strbuf_insertf(stash_msg_buf, 0, "On %s: ", branch_name);
1183
1184 /*
1185 * `parents` will be empty after calling `commit_tree()`, so there is
1186 * no need to call `free_commit_list()`
1187 */
1188 parents = NULL;
1189 if (untracked_commit_option)
1190 commit_list_insert(lookup_commit(the_repository,
1191 &info->u_commit),
1192 &parents);
1193 commit_list_insert(lookup_commit(the_repository, &info->i_commit),
1194 &parents);
1195 commit_list_insert(head_commit, &parents);
1196
1197 if (commit_tree(stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,
1198 parents, &info->w_commit, NULL, NULL)) {
1199 fprintf_ln(stderr, _("Cannot record working tree state"));
1200 ret = -1;
1201 goto done;
1202 }
1203
1204done:
1205 strbuf_release(&commit_tree_label);
1206 strbuf_release(&msg);
1207 strbuf_release(&untracked_files);
1208 return ret;
1209}
1210
1211static int create_stash(int argc, const char **argv, const char *prefix)
1212{
1213 int include_untracked = 0;
1214 int ret = 0;
1215 const char *stash_msg = NULL;
1216 struct strbuf stash_msg_buf = STRBUF_INIT;
1217 struct stash_info info;
1218 struct pathspec ps;
1219 struct option options[] = {
1220 OPT_BOOL('u', "include-untracked", &include_untracked,
1221 N_("include untracked files in stash")),
1222 OPT_STRING('m', "message", &stash_msg, N_("message"),
1223 N_("stash message")),
1224 OPT_END()
1225 };
1226
1227 argc = parse_options(argc, argv, prefix, options,
1228 git_stash_helper_create_usage,
1229 0);
1230
1231 memset(&ps, 0, sizeof(ps));
1232 strbuf_addstr(&stash_msg_buf, stash_msg);
1233 ret = do_create_stash(ps, &stash_msg_buf, include_untracked, 0, &info,
1234 NULL);
1235 if (!ret)
1236 printf_ln("%s", oid_to_hex(&info.w_commit));
1237
1238 strbuf_release(&stash_msg_buf);
1239
1240 /*
1241 * ret can be 1 if there were no changes. In this case, we should
1242 * not error out.
1243 */
1244 return ret < 0;
1245}
1246
1247static int do_push_stash(struct pathspec ps, const char *stash_msg, int quiet,
1248 int keep_index, int patch_mode, int include_untracked)
1249{
1250 int ret = 0;
1251 struct stash_info info;
1252 struct strbuf patch = STRBUF_INIT;
1253 struct strbuf stash_msg_buf = STRBUF_INIT;
1254
1255 if (patch_mode && keep_index == -1)
1256 keep_index = 1;
1257
1258 if (patch_mode && include_untracked) {
1259 fprintf_ln(stderr, _("Can't use --patch and --include-untracked"
1260 " or --all at the same time"));
1261 ret = -1;
1262 goto done;
1263 }
1264
1265 read_cache_preload(NULL);
1266 if (!include_untracked && ps.nr) {
1267 int i;
1268 char *ps_matched = xcalloc(ps.nr, 1);
1269
1270 for (i = 0; i < active_nr; i++)
1271 ce_path_match(&the_index, active_cache[i], &ps,
1272 ps_matched);
1273
1274 if (report_path_error(ps_matched, &ps, NULL)) {
1275 fprintf_ln(stderr, _("Did you forget to 'git add'?"));
1276 ret = -1;
1277 free(ps_matched);
1278 goto done;
1279 }
1280 free(ps_matched);
1281 }
1282
1283 if (refresh_cache(REFRESH_QUIET)) {
1284 ret = -1;
1285 goto done;
1286 }
1287
1288 if (!check_changes(ps, include_untracked)) {
1289 if (!quiet)
1290 printf_ln(_("No local changes to save"));
1291 goto done;
1292 }
1293
1294 if (!reflog_exists(ref_stash) && do_clear_stash()) {
1295 ret = -1;
1296 fprintf_ln(stderr, _("Cannot initialize stash"));
1297 goto done;
1298 }
1299
1300 if (stash_msg)
1301 strbuf_addstr(&stash_msg_buf, stash_msg);
1302 if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode,
1303 &info, &patch)) {
1304 ret = -1;
1305 goto done;
1306 }
1307
1308 if (do_store_stash(&info.w_commit, stash_msg_buf.buf, 1)) {
1309 ret = -1;
1310 fprintf_ln(stderr, _("Cannot save the current status"));
1311 goto done;
1312 }
1313
1314 printf_ln(_("Saved working directory and index state %s"),
1315 stash_msg_buf.buf);
1316
1317 if (!patch_mode) {
1318 if (include_untracked && !ps.nr) {
1319 struct child_process cp = CHILD_PROCESS_INIT;
1320
1321 cp.git_cmd = 1;
1322 argv_array_pushl(&cp.args, "clean", "--force",
1323 "--quiet", "-d", NULL);
1324 if (include_untracked == INCLUDE_ALL_FILES)
1325 argv_array_push(&cp.args, "-x");
1326 if (run_command(&cp)) {
1327 ret = -1;
1328 goto done;
1329 }
1330 }
1331 discard_cache();
1332 if (ps.nr) {
1333 struct child_process cp_add = CHILD_PROCESS_INIT;
1334 struct child_process cp_diff = CHILD_PROCESS_INIT;
1335 struct child_process cp_apply = CHILD_PROCESS_INIT;
1336 struct strbuf out = STRBUF_INIT;
1337
1338 cp_add.git_cmd = 1;
1339 argv_array_push(&cp_add.args, "add");
1340 if (!include_untracked)
1341 argv_array_push(&cp_add.args, "-u");
1342 if (include_untracked == INCLUDE_ALL_FILES)
1343 argv_array_push(&cp_add.args, "--force");
1344 argv_array_push(&cp_add.args, "--");
1345 add_pathspecs(&cp_add.args, ps);
1346 if (run_command(&cp_add)) {
1347 ret = -1;
1348 goto done;
1349 }
1350
1351 cp_diff.git_cmd = 1;
1352 argv_array_pushl(&cp_diff.args, "diff-index", "-p",
1353 "--cached", "--binary", "HEAD", "--",
1354 NULL);
1355 add_pathspecs(&cp_diff.args, ps);
1356 if (pipe_command(&cp_diff, NULL, 0, &out, 0, NULL, 0)) {
1357 ret = -1;
1358 goto done;
1359 }
1360
1361 cp_apply.git_cmd = 1;
1362 argv_array_pushl(&cp_apply.args, "apply", "--index",
1363 "-R", NULL);
1364 if (pipe_command(&cp_apply, out.buf, out.len, NULL, 0,
1365 NULL, 0)) {
1366 ret = -1;
1367 goto done;
1368 }
1369 } else {
1370 struct child_process cp = CHILD_PROCESS_INIT;
1371 cp.git_cmd = 1;
1372 argv_array_pushl(&cp.args, "reset", "--hard", "-q",
1373 NULL);
1374 if (run_command(&cp)) {
1375 ret = -1;
1376 goto done;
1377 }
1378 }
1379
1380 if (keep_index == 1 && !is_null_oid(&info.i_tree)) {
1381 struct child_process cp_ls = CHILD_PROCESS_INIT;
1382 struct child_process cp_checkout = CHILD_PROCESS_INIT;
1383 struct strbuf out = STRBUF_INIT;
1384
1385 if (reset_tree(&info.i_tree, 0, 1)) {
1386 ret = -1;
1387 goto done;
1388 }
1389
1390 cp_ls.git_cmd = 1;
1391 argv_array_pushl(&cp_ls.args, "ls-files", "-z",
1392 "--modified", "--", NULL);
1393
1394 add_pathspecs(&cp_ls.args, ps);
1395 if (pipe_command(&cp_ls, NULL, 0, &out, 0, NULL, 0)) {
1396 ret = -1;
1397 goto done;
1398 }
1399
1400 cp_checkout.git_cmd = 1;
1401 argv_array_pushl(&cp_checkout.args, "checkout-index",
1402 "-z", "--force", "--stdin", NULL);
1403 if (pipe_command(&cp_checkout, out.buf, out.len, NULL,
1404 0, NULL, 0)) {
1405 ret = -1;
1406 goto done;
1407 }
1408 }
1409 goto done;
1410 } else {
1411 struct child_process cp = CHILD_PROCESS_INIT;
1412
1413 cp.git_cmd = 1;
1414 argv_array_pushl(&cp.args, "apply", "-R", NULL);
1415
1416 if (pipe_command(&cp, patch.buf, patch.len, NULL, 0, NULL, 0)) {
1417 fprintf_ln(stderr, _("Cannot remove worktree changes"));
1418 ret = -1;
1419 goto done;
1420 }
1421
1422 if (keep_index < 1) {
1423 struct child_process cp = CHILD_PROCESS_INIT;
1424
1425 cp.git_cmd = 1;
1426 argv_array_pushl(&cp.args, "reset", "-q", "--", NULL);
1427 add_pathspecs(&cp.args, ps);
1428 if (run_command(&cp)) {
1429 ret = -1;
1430 goto done;
1431 }
1432 }
1433 goto done;
1434 }
1435
1436done:
1437 strbuf_release(&stash_msg_buf);
1438 return ret;
1439}
1440
1441static int push_stash(int argc, const char **argv, const char *prefix)
1442{
1443 int keep_index = -1;
1444 int patch_mode = 0;
1445 int include_untracked = 0;
1446 int quiet = 0;
1447 const char *stash_msg = NULL;
1448 struct pathspec ps;
1449 struct option options[] = {
1450 OPT_BOOL('k', "keep-index", &keep_index,
1451 N_("keep index")),
1452 OPT_BOOL('p', "patch", &patch_mode,
1453 N_("stash in patch mode")),
1454 OPT__QUIET(&quiet, N_("quiet mode")),
1455 OPT_BOOL('u', "include-untracked", &include_untracked,
1456 N_("include untracked files in stash")),
1457 OPT_SET_INT('a', "all", &include_untracked,
1458 N_("include ignore files"), 2),
1459 OPT_STRING('m', "message", &stash_msg, N_("message"),
1460 N_("stash message")),
1461 OPT_END()
1462 };
1463
1464 argc = parse_options(argc, argv, prefix, options,
1465 git_stash_helper_push_usage,
1466 0);
1467
1468 parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL, prefix, argv);
1469 return do_push_stash(ps, stash_msg, quiet, keep_index, patch_mode,
1470 include_untracked);
1471}
1472
1473int cmd_stash__helper(int argc, const char **argv, const char *prefix)
1474{
1475 pid_t pid = getpid();
1476 const char *index_file;
1477
1478 struct option options[] = {
1479 OPT_END()
1480 };
1481
1482 git_config(git_diff_basic_config, NULL);
1483
1484 argc = parse_options(argc, argv, prefix, options, git_stash_helper_usage,
1485 PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH);
1486
1487 index_file = get_index_file();
1488 strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file,
1489 (uintmax_t)pid);
1490
1491 if (argc < 1)
1492 usage_with_options(git_stash_helper_usage, options);
1493 if (!strcmp(argv[0], "apply"))
1494 return !!apply_stash(argc, argv, prefix);
1495 else if (!strcmp(argv[0], "clear"))
1496 return !!clear_stash(argc, argv, prefix);
1497 else if (!strcmp(argv[0], "drop"))
1498 return !!drop_stash(argc, argv, prefix);
1499 else if (!strcmp(argv[0], "pop"))
1500 return !!pop_stash(argc, argv, prefix);
1501 else if (!strcmp(argv[0], "branch"))
1502 return !!branch_stash(argc, argv, prefix);
1503 else if (!strcmp(argv[0], "list"))
1504 return !!list_stash(argc, argv, prefix);
1505 else if (!strcmp(argv[0], "show"))
1506 return !!show_stash(argc, argv, prefix);
1507 else if (!strcmp(argv[0], "store"))
1508 return !!store_stash(argc, argv, prefix);
1509 else if (!strcmp(argv[0], "create"))
1510 return !!create_stash(argc, argv, prefix);
1511 else if (!strcmp(argv[0], "push"))
1512 return !!push_stash(argc, argv, prefix);
1513
1514 usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
1515 git_stash_helper_usage, options);
1516}