763a5ffd25c8229e59d69ac938db72a8ea11d5e6
   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 * const git_stash_helper_store_usage[] = {
  62        N_("git stash--helper store [-m|--message <message>] [-q|--quiet] <commit>"),
  63        NULL
  64};
  65
  66static const char *ref_stash = "refs/stash";
  67static struct strbuf stash_index_path = STRBUF_INIT;
  68
  69/*
  70 * w_commit is set to the commit containing the working tree
  71 * b_commit is set to the base commit
  72 * i_commit is set to the commit containing the index tree
  73 * u_commit is set to the commit containing the untracked files tree
  74 * w_tree is set to the working tree
  75 * b_tree is set to the base tree
  76 * i_tree is set to the index tree
  77 * u_tree is set to the untracked files tree
  78 */
  79struct stash_info {
  80        struct object_id w_commit;
  81        struct object_id b_commit;
  82        struct object_id i_commit;
  83        struct object_id u_commit;
  84        struct object_id w_tree;
  85        struct object_id b_tree;
  86        struct object_id i_tree;
  87        struct object_id u_tree;
  88        struct strbuf revision;
  89        int is_stash_ref;
  90        int has_u;
  91};
  92
  93static void free_stash_info(struct stash_info *info)
  94{
  95        strbuf_release(&info->revision);
  96}
  97
  98static void assert_stash_like(struct stash_info *info, const char *revision)
  99{
 100        if (get_oidf(&info->b_commit, "%s^1", revision) ||
 101            get_oidf(&info->w_tree, "%s:", revision) ||
 102            get_oidf(&info->b_tree, "%s^1:", revision) ||
 103            get_oidf(&info->i_tree, "%s^2:", revision))
 104                die(_("'%s' is not a stash-like commit"), revision);
 105}
 106
 107static int get_stash_info(struct stash_info *info, int argc, const char **argv)
 108{
 109        int ret;
 110        char *end_of_rev;
 111        char *expanded_ref;
 112        const char *revision;
 113        const char *commit = NULL;
 114        struct object_id dummy;
 115        struct strbuf symbolic = STRBUF_INIT;
 116
 117        if (argc > 1) {
 118                int i;
 119                struct strbuf refs_msg = STRBUF_INIT;
 120
 121                for (i = 0; i < argc; i++)
 122                        strbuf_addf(&refs_msg, " '%s'", argv[i]);
 123
 124                fprintf_ln(stderr, _("Too many revisions specified:%s"),
 125                           refs_msg.buf);
 126                strbuf_release(&refs_msg);
 127
 128                return -1;
 129        }
 130
 131        if (argc == 1)
 132                commit = argv[0];
 133
 134        strbuf_init(&info->revision, 0);
 135        if (!commit) {
 136                if (!ref_exists(ref_stash)) {
 137                        free_stash_info(info);
 138                        fprintf_ln(stderr, _("No stash entries found."));
 139                        return -1;
 140                }
 141
 142                strbuf_addf(&info->revision, "%s@{0}", ref_stash);
 143        } else if (strspn(commit, "0123456789") == strlen(commit)) {
 144                strbuf_addf(&info->revision, "%s@{%s}", ref_stash, commit);
 145        } else {
 146                strbuf_addstr(&info->revision, commit);
 147        }
 148
 149        revision = info->revision.buf;
 150
 151        if (get_oid(revision, &info->w_commit)) {
 152                error(_("%s is not a valid reference"), revision);
 153                free_stash_info(info);
 154                return -1;
 155        }
 156
 157        assert_stash_like(info, revision);
 158
 159        info->has_u = !get_oidf(&info->u_tree, "%s^3:", revision);
 160
 161        end_of_rev = strchrnul(revision, '@');
 162        strbuf_add(&symbolic, revision, end_of_rev - revision);
 163
 164        ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref);
 165        strbuf_release(&symbolic);
 166        switch (ret) {
 167        case 0: /* Not found, but valid ref */
 168                info->is_stash_ref = 0;
 169                break;
 170        case 1:
 171                info->is_stash_ref = !strcmp(expanded_ref, ref_stash);
 172                break;
 173        default: /* Invalid or ambiguous */
 174                free_stash_info(info);
 175        }
 176
 177        free(expanded_ref);
 178        return !(ret == 0 || ret == 1);
 179}
 180
 181static int do_clear_stash(void)
 182{
 183        struct object_id obj;
 184        if (get_oid(ref_stash, &obj))
 185                return 0;
 186
 187        return delete_ref(NULL, ref_stash, &obj, 0);
 188}
 189
 190static int clear_stash(int argc, const char **argv, const char *prefix)
 191{
 192        struct option options[] = {
 193                OPT_END()
 194        };
 195
 196        argc = parse_options(argc, argv, prefix, options,
 197                             git_stash_helper_clear_usage,
 198                             PARSE_OPT_STOP_AT_NON_OPTION);
 199
 200        if (argc)
 201                return error(_("git stash clear with parameters is "
 202                               "unimplemented"));
 203
 204        return do_clear_stash();
 205}
 206
 207static int reset_tree(struct object_id *i_tree, int update, int reset)
 208{
 209        int nr_trees = 1;
 210        struct unpack_trees_options opts;
 211        struct tree_desc t[MAX_UNPACK_TREES];
 212        struct tree *tree;
 213        struct lock_file lock_file = LOCK_INIT;
 214
 215        read_cache_preload(NULL);
 216        if (refresh_cache(REFRESH_QUIET))
 217                return -1;
 218
 219        hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
 220
 221        memset(&opts, 0, sizeof(opts));
 222
 223        tree = parse_tree_indirect(i_tree);
 224        if (parse_tree(tree))
 225                return -1;
 226
 227        init_tree_desc(t, tree->buffer, tree->size);
 228
 229        opts.head_idx = 1;
 230        opts.src_index = &the_index;
 231        opts.dst_index = &the_index;
 232        opts.merge = 1;
 233        opts.reset = reset;
 234        opts.update = update;
 235        opts.fn = oneway_merge;
 236
 237        if (unpack_trees(nr_trees, t, &opts))
 238                return -1;
 239
 240        if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
 241                return error(_("unable to write new index file"));
 242
 243        return 0;
 244}
 245
 246static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit)
 247{
 248        struct child_process cp = CHILD_PROCESS_INIT;
 249        const char *w_commit_hex = oid_to_hex(w_commit);
 250
 251        /*
 252         * Diff-tree would not be very hard to replace with a native function,
 253         * however it should be done together with apply_cached.
 254         */
 255        cp.git_cmd = 1;
 256        argv_array_pushl(&cp.args, "diff-tree", "--binary", NULL);
 257        argv_array_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
 258
 259        return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
 260}
 261
 262static int apply_cached(struct strbuf *out)
 263{
 264        struct child_process cp = CHILD_PROCESS_INIT;
 265
 266        /*
 267         * Apply currently only reads either from stdin or a file, thus
 268         * apply_all_patches would have to be updated to optionally take a
 269         * buffer.
 270         */
 271        cp.git_cmd = 1;
 272        argv_array_pushl(&cp.args, "apply", "--cached", NULL);
 273        return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
 274}
 275
 276static int reset_head(void)
 277{
 278        struct child_process cp = CHILD_PROCESS_INIT;
 279
 280        /*
 281         * Reset is overall quite simple, however there is no current public
 282         * API for resetting.
 283         */
 284        cp.git_cmd = 1;
 285        argv_array_push(&cp.args, "reset");
 286
 287        return run_command(&cp);
 288}
 289
 290static int get_newly_staged(struct strbuf *out, struct object_id *c_tree)
 291{
 292        struct child_process cp = CHILD_PROCESS_INIT;
 293        const char *c_tree_hex = oid_to_hex(c_tree);
 294
 295        /*
 296         * diff-index is very similar to diff-tree above, and should be
 297         * converted together with update_index.
 298         */
 299        cp.git_cmd = 1;
 300        argv_array_pushl(&cp.args, "diff-index", "--cached", "--name-only",
 301                         "--diff-filter=A", NULL);
 302        argv_array_push(&cp.args, c_tree_hex);
 303        return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
 304}
 305
 306static int update_index(struct strbuf *out)
 307{
 308        struct child_process cp = CHILD_PROCESS_INIT;
 309
 310        /*
 311         * Update-index is very complicated and may need to have a public
 312         * function exposed in order to remove this forking.
 313         */
 314        cp.git_cmd = 1;
 315        argv_array_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
 316        return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
 317}
 318
 319static int restore_untracked(struct object_id *u_tree)
 320{
 321        int res;
 322        struct child_process cp = CHILD_PROCESS_INIT;
 323
 324        /*
 325         * We need to run restore files from a given index, but without
 326         * affecting the current index, so we use GIT_INDEX_FILE with
 327         * run_command to fork processes that will not interfere.
 328         */
 329        cp.git_cmd = 1;
 330        argv_array_push(&cp.args, "read-tree");
 331        argv_array_push(&cp.args, oid_to_hex(u_tree));
 332        argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
 333                         stash_index_path.buf);
 334        if (run_command(&cp)) {
 335                remove_path(stash_index_path.buf);
 336                return -1;
 337        }
 338
 339        child_process_init(&cp);
 340        cp.git_cmd = 1;
 341        argv_array_pushl(&cp.args, "checkout-index", "--all", NULL);
 342        argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
 343                         stash_index_path.buf);
 344
 345        res = run_command(&cp);
 346        remove_path(stash_index_path.buf);
 347        return res;
 348}
 349
 350static int do_apply_stash(const char *prefix, struct stash_info *info,
 351                          int index, int quiet)
 352{
 353        int ret;
 354        int has_index = index;
 355        struct merge_options o;
 356        struct object_id c_tree;
 357        struct object_id index_tree;
 358        struct commit *result;
 359        const struct object_id *bases[1];
 360
 361        read_cache_preload(NULL);
 362        if (refresh_cache(REFRESH_QUIET))
 363                return -1;
 364
 365        if (write_cache_as_tree(&c_tree, 0, NULL))
 366                return error(_("cannot apply a stash in the middle of a merge"));
 367
 368        if (index) {
 369                if (oideq(&info->b_tree, &info->i_tree) ||
 370                    oideq(&c_tree, &info->i_tree)) {
 371                        has_index = 0;
 372                } else {
 373                        struct strbuf out = STRBUF_INIT;
 374
 375                        if (diff_tree_binary(&out, &info->w_commit)) {
 376                                strbuf_release(&out);
 377                                return error(_("could not generate diff %s^!."),
 378                                             oid_to_hex(&info->w_commit));
 379                        }
 380
 381                        ret = apply_cached(&out);
 382                        strbuf_release(&out);
 383                        if (ret)
 384                                return error(_("conflicts in index."
 385                                               "Try without --index."));
 386
 387                        discard_cache();
 388                        read_cache();
 389                        if (write_cache_as_tree(&index_tree, 0, NULL))
 390                                return error(_("could not save index tree"));
 391
 392                        reset_head();
 393                }
 394        }
 395
 396        if (info->has_u && restore_untracked(&info->u_tree))
 397                return error(_("could not restore untracked files from stash"));
 398
 399        init_merge_options(&o);
 400
 401        o.branch1 = "Updated upstream";
 402        o.branch2 = "Stashed changes";
 403
 404        if (oideq(&info->b_tree, &c_tree))
 405                o.branch1 = "Version stash was based on";
 406
 407        if (quiet)
 408                o.verbosity = 0;
 409
 410        if (o.verbosity >= 3)
 411                printf_ln(_("Merging %s with %s"), o.branch1, o.branch2);
 412
 413        bases[0] = &info->b_tree;
 414
 415        ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases,
 416                                      &result);
 417        if (ret) {
 418                rerere(0);
 419
 420                if (index)
 421                        fprintf_ln(stderr, _("Index was not unstashed."));
 422
 423                return ret;
 424        }
 425
 426        if (has_index) {
 427                if (reset_tree(&index_tree, 0, 0))
 428                        return -1;
 429        } else {
 430                struct strbuf out = STRBUF_INIT;
 431
 432                if (get_newly_staged(&out, &c_tree)) {
 433                        strbuf_release(&out);
 434                        return -1;
 435                }
 436
 437                if (reset_tree(&c_tree, 0, 1)) {
 438                        strbuf_release(&out);
 439                        return -1;
 440                }
 441
 442                ret = update_index(&out);
 443                strbuf_release(&out);
 444                if (ret)
 445                        return -1;
 446
 447                discard_cache();
 448        }
 449
 450        if (quiet) {
 451                if (refresh_cache(REFRESH_QUIET))
 452                        warning("could not refresh index");
 453        } else {
 454                struct child_process cp = CHILD_PROCESS_INIT;
 455
 456                /*
 457                 * Status is quite simple and could be replaced with calls to
 458                 * wt_status in the future, but it adds complexities which may
 459                 * require more tests.
 460                 */
 461                cp.git_cmd = 1;
 462                cp.dir = prefix;
 463                argv_array_push(&cp.args, "status");
 464                run_command(&cp);
 465        }
 466
 467        return 0;
 468}
 469
 470static int apply_stash(int argc, const char **argv, const char *prefix)
 471{
 472        int ret;
 473        int quiet = 0;
 474        int index = 0;
 475        struct stash_info info;
 476        struct option options[] = {
 477                OPT__QUIET(&quiet, N_("be quiet, only report errors")),
 478                OPT_BOOL(0, "index", &index,
 479                         N_("attempt to recreate the index")),
 480                OPT_END()
 481        };
 482
 483        argc = parse_options(argc, argv, prefix, options,
 484                             git_stash_helper_apply_usage, 0);
 485
 486        if (get_stash_info(&info, argc, argv))
 487                return -1;
 488
 489        ret = do_apply_stash(prefix, &info, index, quiet);
 490        free_stash_info(&info);
 491        return ret;
 492}
 493
 494static int do_drop_stash(const char *prefix, struct stash_info *info, int quiet)
 495{
 496        int ret;
 497        struct child_process cp_reflog = CHILD_PROCESS_INIT;
 498        struct child_process cp = CHILD_PROCESS_INIT;
 499
 500        /*
 501         * reflog does not provide a simple function for deleting refs. One will
 502         * need to be added to avoid implementing too much reflog code here
 503         */
 504
 505        cp_reflog.git_cmd = 1;
 506        argv_array_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
 507                         "--rewrite", NULL);
 508        argv_array_push(&cp_reflog.args, info->revision.buf);
 509        ret = run_command(&cp_reflog);
 510        if (!ret) {
 511                if (!quiet)
 512                        printf_ln(_("Dropped %s (%s)"), info->revision.buf,
 513                                  oid_to_hex(&info->w_commit));
 514        } else {
 515                return error(_("%s: Could not drop stash entry"),
 516                             info->revision.buf);
 517        }
 518
 519        /*
 520         * This could easily be replaced by get_oid, but currently it will throw
 521         * a fatal error when a reflog is empty, which we can not recover from.
 522         */
 523        cp.git_cmd = 1;
 524        /* Even though --quiet is specified, rev-parse still outputs the hash */
 525        cp.no_stdout = 1;
 526        argv_array_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
 527        argv_array_pushf(&cp.args, "%s@{0}", ref_stash);
 528        ret = run_command(&cp);
 529
 530        /* do_clear_stash if we just dropped the last stash entry */
 531        if (ret)
 532                do_clear_stash();
 533
 534        return 0;
 535}
 536
 537static void assert_stash_ref(struct stash_info *info)
 538{
 539        if (!info->is_stash_ref) {
 540                error(_("'%s' is not a stash reference"), info->revision.buf);
 541                free_stash_info(info);
 542                exit(1);
 543        }
 544}
 545
 546static int drop_stash(int argc, const char **argv, const char *prefix)
 547{
 548        int ret;
 549        int quiet = 0;
 550        struct stash_info info;
 551        struct option options[] = {
 552                OPT__QUIET(&quiet, N_("be quiet, only report errors")),
 553                OPT_END()
 554        };
 555
 556        argc = parse_options(argc, argv, prefix, options,
 557                             git_stash_helper_drop_usage, 0);
 558
 559        if (get_stash_info(&info, argc, argv))
 560                return -1;
 561
 562        assert_stash_ref(&info);
 563
 564        ret = do_drop_stash(prefix, &info, quiet);
 565        free_stash_info(&info);
 566        return ret;
 567}
 568
 569static int pop_stash(int argc, const char **argv, const char *prefix)
 570{
 571        int ret;
 572        int index = 0;
 573        int quiet = 0;
 574        struct stash_info info;
 575        struct option options[] = {
 576                OPT__QUIET(&quiet, N_("be quiet, only report errors")),
 577                OPT_BOOL(0, "index", &index,
 578                         N_("attempt to recreate the index")),
 579                OPT_END()
 580        };
 581
 582        argc = parse_options(argc, argv, prefix, options,
 583                             git_stash_helper_pop_usage, 0);
 584
 585        if (get_stash_info(&info, argc, argv))
 586                return -1;
 587
 588        assert_stash_ref(&info);
 589        if ((ret = do_apply_stash(prefix, &info, index, quiet)))
 590                printf_ln(_("The stash entry is kept in case "
 591                            "you need it again."));
 592        else
 593                ret = do_drop_stash(prefix, &info, quiet);
 594
 595        free_stash_info(&info);
 596        return ret;
 597}
 598
 599static int branch_stash(int argc, const char **argv, const char *prefix)
 600{
 601        int ret;
 602        const char *branch = NULL;
 603        struct stash_info info;
 604        struct child_process cp = CHILD_PROCESS_INIT;
 605        struct option options[] = {
 606                OPT_END()
 607        };
 608
 609        argc = parse_options(argc, argv, prefix, options,
 610                             git_stash_helper_branch_usage, 0);
 611
 612        if (!argc) {
 613                fprintf_ln(stderr, _("No branch name specified"));
 614                return -1;
 615        }
 616
 617        branch = argv[0];
 618
 619        if (get_stash_info(&info, argc - 1, argv + 1))
 620                return -1;
 621
 622        cp.git_cmd = 1;
 623        argv_array_pushl(&cp.args, "checkout", "-b", NULL);
 624        argv_array_push(&cp.args, branch);
 625        argv_array_push(&cp.args, oid_to_hex(&info.b_commit));
 626        ret = run_command(&cp);
 627        if (!ret)
 628                ret = do_apply_stash(prefix, &info, 1, 0);
 629        if (!ret && info.is_stash_ref)
 630                ret = do_drop_stash(prefix, &info, 0);
 631
 632        free_stash_info(&info);
 633
 634        return ret;
 635}
 636
 637static int list_stash(int argc, const char **argv, const char *prefix)
 638{
 639        struct child_process cp = CHILD_PROCESS_INIT;
 640        struct option options[] = {
 641                OPT_END()
 642        };
 643
 644        argc = parse_options(argc, argv, prefix, options,
 645                             git_stash_helper_list_usage,
 646                             PARSE_OPT_KEEP_UNKNOWN);
 647
 648        if (!ref_exists(ref_stash))
 649                return 0;
 650
 651        cp.git_cmd = 1;
 652        argv_array_pushl(&cp.args, "log", "--format=%gd: %gs", "-g",
 653                         "--first-parent", "-m", NULL);
 654        argv_array_pushv(&cp.args, argv);
 655        argv_array_push(&cp.args, ref_stash);
 656        argv_array_push(&cp.args, "--");
 657        return run_command(&cp);
 658}
 659
 660static int show_stat = 1;
 661static int show_patch;
 662
 663static int git_stash_config(const char *var, const char *value, void *cb)
 664{
 665        if (!strcmp(var, "stash.showstat")) {
 666                show_stat = git_config_bool(var, value);
 667                return 0;
 668        }
 669        if (!strcmp(var, "stash.showpatch")) {
 670                show_patch = git_config_bool(var, value);
 671                return 0;
 672        }
 673        return git_default_config(var, value, cb);
 674}
 675
 676static int show_stash(int argc, const char **argv, const char *prefix)
 677{
 678        int i;
 679        int opts = 0;
 680        int ret = 0;
 681        struct stash_info info;
 682        struct rev_info rev;
 683        struct argv_array stash_args = ARGV_ARRAY_INIT;
 684        struct option options[] = {
 685                OPT_END()
 686        };
 687
 688        init_diff_ui_defaults();
 689        git_config(git_diff_ui_config, NULL);
 690        init_revisions(&rev, prefix);
 691
 692        for (i = 1; i < argc; i++) {
 693                if (argv[i][0] != '-')
 694                        argv_array_push(&stash_args, argv[i]);
 695                else
 696                        opts++;
 697        }
 698
 699        ret = get_stash_info(&info, stash_args.argc, stash_args.argv);
 700        argv_array_clear(&stash_args);
 701        if (ret)
 702                return -1;
 703
 704        /*
 705         * The config settings are applied only if there are not passed
 706         * any options.
 707         */
 708        if (!opts) {
 709                git_config(git_stash_config, NULL);
 710                if (show_stat)
 711                        rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
 712
 713                if (show_patch)
 714                        rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
 715
 716                if (!show_stat && !show_patch) {
 717                        free_stash_info(&info);
 718                        return 0;
 719                }
 720        }
 721
 722        argc = setup_revisions(argc, argv, &rev, NULL);
 723        if (argc > 1) {
 724                free_stash_info(&info);
 725                usage_with_options(git_stash_helper_show_usage, options);
 726        }
 727
 728        rev.diffopt.flags.recursive = 1;
 729        setup_diff_pager(&rev.diffopt);
 730        diff_tree_oid(&info.b_commit, &info.w_commit, "", &rev.diffopt);
 731        log_tree_diff_flush(&rev);
 732
 733        free_stash_info(&info);
 734        return diff_result_code(&rev.diffopt, 0);
 735}
 736
 737static int do_store_stash(const struct object_id *w_commit, const char *stash_msg,
 738                          int quiet)
 739{
 740        if (!stash_msg)
 741                stash_msg = "Created via \"git stash store\".";
 742
 743        if (update_ref(stash_msg, ref_stash, w_commit, NULL,
 744                       REF_FORCE_CREATE_REFLOG,
 745                       quiet ? UPDATE_REFS_QUIET_ON_ERR :
 746                       UPDATE_REFS_MSG_ON_ERR)) {
 747                if (!quiet) {
 748                        fprintf_ln(stderr, _("Cannot update %s with %s"),
 749                                   ref_stash, oid_to_hex(w_commit));
 750                }
 751                return -1;
 752        }
 753
 754        return 0;
 755}
 756
 757static int store_stash(int argc, const char **argv, const char *prefix)
 758{
 759        int quiet = 0;
 760        const char *stash_msg = NULL;
 761        struct object_id obj;
 762        struct object_context dummy;
 763        struct option options[] = {
 764                OPT__QUIET(&quiet, N_("be quiet")),
 765                OPT_STRING('m', "message", &stash_msg, "message",
 766                           N_("stash message")),
 767                OPT_END()
 768        };
 769
 770        argc = parse_options(argc, argv, prefix, options,
 771                             git_stash_helper_store_usage,
 772                             PARSE_OPT_KEEP_UNKNOWN);
 773
 774        if (argc != 1) {
 775                if (!quiet)
 776                        fprintf_ln(stderr, _("\"git stash store\" requires one "
 777                                             "<commit> argument"));
 778                return -1;
 779        }
 780
 781        if (get_oid_with_context(argv[0], quiet ? GET_OID_QUIETLY : 0, &obj,
 782                                 &dummy)) {
 783                if (!quiet)
 784                        fprintf_ln(stderr, _("Cannot update %s with %s"),
 785                                             ref_stash, argv[0]);
 786                return -1;
 787        }
 788
 789        return do_store_stash(&obj, stash_msg, quiet);
 790}
 791
 792int cmd_stash__helper(int argc, const char **argv, const char *prefix)
 793{
 794        pid_t pid = getpid();
 795        const char *index_file;
 796
 797        struct option options[] = {
 798                OPT_END()
 799        };
 800
 801        git_config(git_default_config, NULL);
 802
 803        argc = parse_options(argc, argv, prefix, options, git_stash_helper_usage,
 804                             PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH);
 805
 806        index_file = get_index_file();
 807        strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file,
 808                    (uintmax_t)pid);
 809
 810        if (argc < 1)
 811                usage_with_options(git_stash_helper_usage, options);
 812        if (!strcmp(argv[0], "apply"))
 813                return !!apply_stash(argc, argv, prefix);
 814        else if (!strcmp(argv[0], "clear"))
 815                return !!clear_stash(argc, argv, prefix);
 816        else if (!strcmp(argv[0], "drop"))
 817                return !!drop_stash(argc, argv, prefix);
 818        else if (!strcmp(argv[0], "pop"))
 819                return !!pop_stash(argc, argv, prefix);
 820        else if (!strcmp(argv[0], "branch"))
 821                return !!branch_stash(argc, argv, prefix);
 822        else if (!strcmp(argv[0], "list"))
 823                return !!list_stash(argc, argv, prefix);
 824        else if (!strcmp(argv[0], "show"))
 825                return !!show_stash(argc, argv, prefix);
 826        else if (!strcmp(argv[0], "store"))
 827                return !!store_stash(argc, argv, prefix);
 828
 829        usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
 830                      git_stash_helper_usage, options);
 831}