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