4028b643141e1f808f92dd5740e486e05bb7c401
   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
  16static 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
  26static const char * const git_stash_helper_list_usage[] = {
  27        N_("git stash--helper list [<options>]"),
  28        NULL
  29};
  30
  31static const char * const git_stash_helper_show_usage[] = {
  32        N_("git stash--helper show [<options>] [<stash>]"),
  33        NULL
  34};
  35
  36static const char * const git_stash_helper_drop_usage[] = {
  37        N_("git stash--helper drop [-q|--quiet] [<stash>]"),
  38        NULL
  39};
  40
  41static const char * const git_stash_helper_pop_usage[] = {
  42        N_("git stash--helper pop [--index] [-q|--quiet] [<stash>]"),
  43        NULL
  44};
  45
  46static const char * const git_stash_helper_apply_usage[] = {
  47        N_("git stash--helper apply [--index] [-q|--quiet] [<stash>]"),
  48        NULL
  49};
  50
  51static const char * const git_stash_helper_branch_usage[] = {
  52        N_("git stash--helper branch <branchname> [<stash>]"),
  53        NULL
  54};
  55
  56static const char * const git_stash_helper_clear_usage[] = {
  57        N_("git stash--helper clear"),
  58        NULL
  59};
  60
  61static const char *ref_stash = "refs/stash";
  62static 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 */
  74struct 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
  88static void free_stash_info(struct stash_info *info)
  89{
  90        strbuf_release(&info->revision);
  91}
  92
  93static 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
 102static 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
 176static 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
 185static 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
 202static 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
 241static 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
 257static 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
 271static 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
 285static 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
 301static 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
 314static 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
 345static 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
 465static 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
 489static 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
 532static 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
 541static 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
 564static 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
 594static 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
 632static 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
 655static int show_stat = 1;
 656static int show_patch;
 657
 658static 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
 671static 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
 732int 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}