stash: convert show to builtin
[git] / builtin / stash--helper.c
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
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"),
23         NULL
24 };
25
26 static const char * const git_stash_helper_list_usage[] = {
27         N_("git stash--helper list [<options>]"),
28         NULL
29 };
30
31 static const char * const git_stash_helper_show_usage[] = {
32         N_("git stash--helper show [<options>] [<stash>]"),
33         NULL
34 };
35
36 static const char * const git_stash_helper_drop_usage[] = {
37         N_("git stash--helper drop [-q|--quiet] [<stash>]"),
38         NULL
39 };
40
41 static const char * const git_stash_helper_pop_usage[] = {
42         N_("git stash--helper pop [--index] [-q|--quiet] [<stash>]"),
43         NULL
44 };
45
46 static const char * const git_stash_helper_apply_usage[] = {
47         N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
48         NULL
49 };
50
51 static const char * const git_stash_helper_branch_usage[] = {
52         N_("git stash--helper branch <branchname> [<stash>]"),
53         NULL
54 };
55
56 static const char * const git_stash_helper_clear_usage[] = {
57         N_("git stash--helper clear"),
58         NULL
59 };
60
61 static const char *ref_stash = "refs/stash";
62 static struct strbuf stash_index_path = STRBUF_INIT;
63
64 /*
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
73  */
74 struct stash_info {
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;
84         int is_stash_ref;
85         int has_u;
86 };
87
88 static void free_stash_info(struct stash_info *info)
89 {
90         strbuf_release(&info->revision);
91 }
92
93 static void assert_stash_like(struct stash_info *info, const char *revision)
94 {
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);
100 }
101
102 static int get_stash_info(struct stash_info *info, int argc, const char **argv)
103 {
104         int ret;
105         char *end_of_rev;
106         char *expanded_ref;
107         const char *revision;
108         const char *commit = NULL;
109         struct object_id dummy;
110         struct strbuf symbolic = STRBUF_INIT;
111
112         if (argc > 1) {
113                 int i;
114                 struct strbuf refs_msg = STRBUF_INIT;
115
116                 for (i = 0; i < argc; i++)
117                         strbuf_addf(&refs_msg, " '%s'", argv[i]);
118
119                 fprintf_ln(stderr, _("Too many revisions specified:%s"),
120                            refs_msg.buf);
121                 strbuf_release(&refs_msg);
122
123                 return -1;
124         }
125
126         if (argc == 1)
127                 commit = argv[0];
128
129         strbuf_init(&info->revision, 0);
130         if (!commit) {
131                 if (!ref_exists(ref_stash)) {
132                         free_stash_info(info);
133                         fprintf_ln(stderr, _("No stash entries found."));
134                         return -1;
135                 }
136
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);
140         } else {
141                 strbuf_addstr(&info->revision, commit);
142         }
143
144         revision = info->revision.buf;
145
146         if (get_oid(revision, &info->w_commit)) {
147                 error(_("%s is not a valid reference"), revision);
148                 free_stash_info(info);
149                 return -1;
150         }
151
152         assert_stash_like(info, revision);
153
154         info->has_u = !get_oidf(&info->u_tree, "%s^3:", revision);
155
156         end_of_rev = strchrnul(revision, '@');
157         strbuf_add(&symbolic, revision, end_of_rev - revision);
158
159         ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref);
160         strbuf_release(&symbolic);
161         switch (ret) {
162         case 0: /* Not found, but valid ref */
163                 info->is_stash_ref = 0;
164                 break;
165         case 1:
166                 info->is_stash_ref = !strcmp(expanded_ref, ref_stash);
167                 break;
168         default: /* Invalid or ambiguous */
169                 free_stash_info(info);
170         }
171
172         free(expanded_ref);
173         return !(ret == 0 || ret == 1);
174 }
175
176 static int do_clear_stash(void)
177 {
178         struct object_id obj;
179         if (get_oid(ref_stash, &obj))
180                 return 0;
181
182         return delete_ref(NULL, ref_stash, &obj, 0);
183 }
184
185 static int clear_stash(int argc, const char **argv, const char *prefix)
186 {
187         struct option options[] = {
188                 OPT_END()
189         };
190
191         argc = parse_options(argc, argv, prefix, options,
192                              git_stash_helper_clear_usage,
193                              PARSE_OPT_STOP_AT_NON_OPTION);
194
195         if (argc)
196                 return error(_("git stash clear with parameters is "
197                                "unimplemented"));
198
199         return do_clear_stash();
200 }
201
202 static int reset_tree(struct object_id *i_tree, int update, int reset)
203 {
204         int nr_trees = 1;
205         struct unpack_trees_options opts;
206         struct tree_desc t[MAX_UNPACK_TREES];
207         struct tree *tree;
208         struct lock_file lock_file = LOCK_INIT;
209
210         read_cache_preload(NULL);
211         if (refresh_cache(REFRESH_QUIET))
212                 return -1;
213
214         hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
215
216         memset(&opts, 0, sizeof(opts));
217
218         tree = parse_tree_indirect(i_tree);
219         if (parse_tree(tree))
220                 return -1;
221
222         init_tree_desc(t, tree->buffer, tree->size);
223
224         opts.head_idx = 1;
225         opts.src_index = &the_index;
226         opts.dst_index = &the_index;
227         opts.merge = 1;
228         opts.reset = reset;
229         opts.update = update;
230         opts.fn = oneway_merge;
231
232         if (unpack_trees(nr_trees, t, &opts))
233                 return -1;
234
235         if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
236                 return error(_("unable to write new index file"));
237
238         return 0;
239 }
240
241 static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit)
242 {
243         struct child_process cp = CHILD_PROCESS_INIT;
244         const char *w_commit_hex = oid_to_hex(w_commit);
245
246         /*
247          * Diff-tree would not be very hard to replace with a native function,
248          * however it should be done together with apply_cached.
249          */
250         cp.git_cmd = 1;
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);
253
254         return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
255 }
256
257 static int apply_cached(struct strbuf *out)
258 {
259         struct child_process cp = CHILD_PROCESS_INIT;
260
261         /*
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
264          * buffer.
265          */
266         cp.git_cmd = 1;
267         argv_array_pushl(&cp.args, "apply", "--cached", NULL);
268         return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
269 }
270
271 static int reset_head(void)
272 {
273         struct child_process cp = CHILD_PROCESS_INIT;
274
275         /*
276          * Reset is overall quite simple, however there is no current public
277          * API for resetting.
278          */
279         cp.git_cmd = 1;
280         argv_array_push(&cp.args, "reset");
281
282         return run_command(&cp);
283 }
284
285 static int get_newly_staged(struct strbuf *out, struct object_id *c_tree)
286 {
287         struct child_process cp = CHILD_PROCESS_INIT;
288         const char *c_tree_hex = oid_to_hex(c_tree);
289
290         /*
291          * diff-index is very similar to diff-tree above, and should be
292          * converted together with update_index.
293          */
294         cp.git_cmd = 1;
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);
299 }
300
301 static int update_index(struct strbuf *out)
302 {
303         struct child_process cp = CHILD_PROCESS_INIT;
304
305         /*
306          * Update-index is very complicated and may need to have a public
307          * function exposed in order to remove this forking.
308          */
309         cp.git_cmd = 1;
310         argv_array_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
311         return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
312 }
313
314 static int restore_untracked(struct object_id *u_tree)
315 {
316         int res;
317         struct child_process cp = CHILD_PROCESS_INIT;
318
319         /*
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.
323          */
324         cp.git_cmd = 1;
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);
331                 return -1;
332         }
333
334         child_process_init(&cp);
335         cp.git_cmd = 1;
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);
339
340         res = run_command(&cp);
341         remove_path(stash_index_path.buf);
342         return res;
343 }
344
345 static int do_apply_stash(const char *prefix, struct stash_info *info,
346                           int index, int quiet)
347 {
348         int ret;
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];
355
356         read_cache_preload(NULL);
357         if (refresh_cache(REFRESH_QUIET))
358                 return -1;
359
360         if (write_cache_as_tree(&c_tree, 0, NULL))
361                 return error(_("cannot apply a stash in the middle of a merge"));
362
363         if (index) {
364                 if (oideq(&info->b_tree, &info->i_tree) ||
365                     oideq(&c_tree, &info->i_tree)) {
366                         has_index = 0;
367                 } else {
368                         struct strbuf out = STRBUF_INIT;
369
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));
374                         }
375
376                         ret = apply_cached(&out);
377                         strbuf_release(&out);
378                         if (ret)
379                                 return error(_("conflicts in index."
380                                                "Try without --index."));
381
382                         discard_cache();
383                         read_cache();
384                         if (write_cache_as_tree(&index_tree, 0, NULL))
385                                 return error(_("could not save index tree"));
386
387                         reset_head();
388                 }
389         }
390
391         if (info->has_u && restore_untracked(&info->u_tree))
392                 return error(_("could not restore untracked files from stash"));
393
394         init_merge_options(&o);
395
396         o.branch1 = "Updated upstream";
397         o.branch2 = "Stashed changes";
398
399         if (oideq(&info->b_tree, &c_tree))
400                 o.branch1 = "Version stash was based on";
401
402         if (quiet)
403                 o.verbosity = 0;
404
405         if (o.verbosity >= 3)
406                 printf_ln(_("Merging %s with %s"), o.branch1, o.branch2);
407
408         bases[0] = &info->b_tree;
409
410         ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases,
411                                       &result);
412         if (ret) {
413                 rerere(0);
414
415                 if (index)
416                         fprintf_ln(stderr, _("Index was not unstashed."));
417
418                 return ret;
419         }
420
421         if (has_index) {
422                 if (reset_tree(&index_tree, 0, 0))
423                         return -1;
424         } else {
425                 struct strbuf out = STRBUF_INIT;
426
427                 if (get_newly_staged(&out, &c_tree)) {
428                         strbuf_release(&out);
429                         return -1;
430                 }
431
432                 if (reset_tree(&c_tree, 0, 1)) {
433                         strbuf_release(&out);
434                         return -1;
435                 }
436
437                 ret = update_index(&out);
438                 strbuf_release(&out);
439                 if (ret)
440                         return -1;
441
442                 discard_cache();
443         }
444
445         if (quiet) {
446                 if (refresh_cache(REFRESH_QUIET))
447                         warning("could not refresh index");
448         } else {
449                 struct child_process cp = CHILD_PROCESS_INIT;
450
451                 /*
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.
455                  */
456                 cp.git_cmd = 1;
457                 cp.dir = prefix;
458                 argv_array_push(&cp.args, "status");
459                 run_command(&cp);
460         }
461
462         return 0;
463 }
464
465 static int apply_stash(int argc, const char **argv, const char *prefix)
466 {
467         int ret;
468         int quiet = 0;
469         int index = 0;
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")),
475                 OPT_END()
476         };
477
478         argc = parse_options(argc, argv, prefix, options,
479                              git_stash_helper_apply_usage, 0);
480
481         if (get_stash_info(&info, argc, argv))
482                 return -1;
483
484         ret = do_apply_stash(prefix, &info, index, quiet);
485         free_stash_info(&info);
486         return ret;
487 }
488
489 static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet)
490 {
491         int ret;
492         struct child_process cp_reflog = CHILD_PROCESS_INIT;
493         struct child_process cp = CHILD_PROCESS_INIT;
494
495         /*
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
498          */
499
500         cp_reflog.git_cmd = 1;
501         argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
502                          "--rewrite", NULL);
503         argv_array_push(&cp_reflog.args, info->revision.buf);
504         ret = run_command(&cp_reflog);
505         if (!ret) {
506                 if (!quiet)
507                         printf_ln(_("Dropped %s (%s)"), info->revision.buf,
508                                   oid_to_hex(&info->w_commit));
509         } else {
510                 return error(_("%s: Could not drop stash entry"),
511                              info->revision.buf);
512         }
513
514         /*
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.
517          */
518         cp.git_cmd = 1;
519         /* Even though --quiet is specified, rev-parse still outputs the hash */
520         cp.no_stdout = 1;
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);
524
525         /* do_clear_stash if we just dropped the last stash entry */
526         if (ret)
527                 do_clear_stash();
528
529         return 0;
530 }
531
532 static void assert_stash_ref(struct stash_info *info)
533 {
534         if (!info->is_stash_ref) {
535                 error(_("'%s' is not a stash reference"), info->revision.buf);
536                 free_stash_info(info);
537                 exit(1);
538         }
539 }
540
541 static int drop_stash(int argc, const char **argv, const char *prefix)
542 {
543         int ret;
544         int quiet = 0;
545         struct stash_info info;
546         struct option options[] = {
547                 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
548                 OPT_END()
549         };
550
551         argc = parse_options(argc, argv, prefix, options,
552                              git_stash_helper_drop_usage, 0);
553
554         if (get_stash_info(&info, argc, argv))
555                 return -1;
556
557         assert_stash_ref(&info);
558
559         ret = do_drop_stash(prefix, &info, quiet);
560         free_stash_info(&info);
561         return ret;
562 }
563
564 static int pop_stash(int argc, const char **argv, const char *prefix)
565 {
566         int ret;
567         int index = 0;
568         int quiet = 0;
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")),
574                 OPT_END()
575         };
576
577         argc = parse_options(argc, argv, prefix, options,
578                              git_stash_helper_pop_usage, 0);
579
580         if (get_stash_info(&info, argc, argv))
581                 return -1;
582
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."));
587         else
588                 ret = do_drop_stash(prefix, &info, quiet);
589
590         free_stash_info(&info);
591         return ret;
592 }
593
594 static int branch_stash(int argc, const char **argv, const char *prefix)
595 {
596         int ret;
597         const char *branch = NULL;
598         struct stash_info info;
599         struct child_process cp = CHILD_PROCESS_INIT;
600         struct option options[] = {
601                 OPT_END()
602         };
603
604         argc = parse_options(argc, argv, prefix, options,
605                              git_stash_helper_branch_usage, 0);
606
607         if (!argc) {
608                 fprintf_ln(stderr, _("No branch name specified"));
609                 return -1;
610         }
611
612         branch = argv[0];
613
614         if (get_stash_info(&info, argc - 1, argv + 1))
615                 return -1;
616
617         cp.git_cmd = 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);
622         if (!ret)
623                 ret = do_apply_stash(prefix, &info, 1, 0);
624         if (!ret && info.is_stash_ref)
625                 ret = do_drop_stash(prefix, &info, 0);
626
627         free_stash_info(&info);
628
629         return ret;
630 }
631
632 static int list_stash(int argc, const char **argv, const char *prefix)
633 {
634         struct child_process cp = CHILD_PROCESS_INIT;
635         struct option options[] = {
636                 OPT_END()
637         };
638
639         argc = parse_options(argc, argv, prefix, options,
640                              git_stash_helper_list_usage,
641                              PARSE_OPT_KEEP_UNKNOWN);
642
643         if (!ref_exists(ref_stash))
644                 return 0;
645
646         cp.git_cmd = 1;
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);
653 }
654
655 static int show_stat = 1;
656 static int show_patch;
657
658 static int git_stash_config(const char *var, const char *value, void *cb)
659 {
660         if (!strcmp(var, "stash.showstat")) {
661                 show_stat = git_config_bool(var, value);
662                 return 0;
663         }
664         if (!strcmp(var, "stash.showpatch")) {
665                 show_patch = git_config_bool(var, value);
666                 return 0;
667         }
668         return git_default_config(var, value, cb);
669 }
670
671 static int show_stash(int argc, const char **argv, const char *prefix)
672 {
673         int i;
674         int opts = 0;
675         int ret = 0;
676         struct stash_info info;
677         struct rev_info rev;
678         struct argv_array stash_args = ARGV_ARRAY_INIT;
679         struct option options[] = {
680                 OPT_END()
681         };
682
683         init_diff_ui_defaults();
684         git_config(git_diff_ui_config, NULL);
685         init_revisions(&rev, prefix);
686
687         for (i = 1; i < argc; i++) {
688                 if (argv[i][0] != '-')
689                         argv_array_push(&stash_args, argv[i]);
690                 else
691                         opts++;
692         }
693
694         ret = get_stash_info(&info, stash_args.argc, stash_args.argv);
695         argv_array_clear(&stash_args);
696         if (ret)
697                 return -1;
698
699         /*
700          * The config settings are applied only if there are not passed
701          * any options.
702          */
703         if (!opts) {
704                 git_config(git_stash_config, NULL);
705                 if (show_stat)
706                         rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
707
708                 if (show_patch)
709                         rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
710
711                 if (!show_stat && !show_patch) {
712                         free_stash_info(&info);
713                         return 0;
714                 }
715         }
716
717         argc = setup_revisions(argc, argv, &rev, NULL);
718         if (argc > 1) {
719                 free_stash_info(&info);
720                 usage_with_options(git_stash_helper_show_usage, options);
721         }
722
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);
727
728         free_stash_info(&info);
729         return diff_result_code(&rev.diffopt, 0);
730 }
731
732 int cmd_stash__helper(int argc, const char **argv, const char *prefix)
733 {
734         pid_t pid = getpid();
735         const char *index_file;
736
737         struct option options[] = {
738                 OPT_END()
739         };
740
741         git_config(git_default_config, NULL);
742
743         argc = parse_options(argc, argv, prefix, options, git_stash_helper_usage,
744                              PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH);
745
746         index_file = get_index_file();
747         strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file,
748                     (uintmax_t)pid);
749
750         if (argc < 1)
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);
766
767         usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
768                       git_stash_helper_usage, options);
769 }