Merge branch 'tg/stash-keep-index-with-removed-paths'
authorJunio C Hamano <gitster@pobox.com>
Thu, 25 Jul 2019 20:59:23 +0000 (13:59 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 25 Jul 2019 20:59:23 +0000 (13:59 -0700)
"git stash --keep-index" did not work correctly on paths that have
been removed, which has been fixed.

* tg/stash-keep-index-with-removed-paths:
stash: fix handling removed files with --keep-index

1  2 
builtin/stash.c
t/t3903-stash.sh
diff --combined builtin/stash.c
index fde6397caa16326912087215383506026d00ab79,251120b92405af986838792cba5e5351018ad6c7..b5a301f24d7a5f8b0a5f7d51703ca4cf38e2109c
@@@ -713,11 -713,11 +713,11 @@@ static int git_stash_config(const char 
  static int show_stash(int argc, const char **argv, const char *prefix)
  {
        int i;
 -      int opts = 0;
        int ret = 0;
        struct stash_info info;
        struct rev_info rev;
        struct argv_array stash_args = ARGV_ARRAY_INIT;
 +      struct argv_array revision_args = ARGV_ARRAY_INIT;
        struct option options[] = {
                OPT_END()
        };
        git_config(git_diff_ui_config, NULL);
        init_revisions(&rev, prefix);
  
 +      argv_array_push(&revision_args, argv[0]);
        for (i = 1; i < argc; i++) {
                if (argv[i][0] != '-')
                        argv_array_push(&stash_args, argv[i]);
                else
 -                      opts++;
 +                      argv_array_push(&revision_args, argv[i]);
        }
  
        ret = get_stash_info(&info, stash_args.argc, stash_args.argv);
         * The config settings are applied only if there are not passed
         * any options.
         */
 -      if (!opts) {
 +      if (revision_args.argc == 1) {
                git_config(git_stash_config, NULL);
                if (show_stat)
                        rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
                }
        }
  
 -      argc = setup_revisions(argc, argv, &rev, NULL);
 +      argc = setup_revisions(revision_args.argc, revision_args.argv, &rev, NULL);
        if (argc > 1) {
                free_stash_info(&info);
                usage_with_options(git_stash_show_usage, options);
@@@ -1391,30 -1390,16 +1391,16 @@@ static int do_push_stash(const struct p
                }
  
                if (keep_index == 1 && !is_null_oid(&info.i_tree)) {
-                       struct child_process cp_ls = CHILD_PROCESS_INIT;
-                       struct child_process cp_checkout = CHILD_PROCESS_INIT;
-                       struct strbuf out = STRBUF_INIT;
-                       if (reset_tree(&info.i_tree, 0, 1)) {
-                               ret = -1;
-                               goto done;
-                       }
-                       cp_ls.git_cmd = 1;
-                       argv_array_pushl(&cp_ls.args, "ls-files", "-z",
-                                        "--modified", "--", NULL);
-                       add_pathspecs(&cp_ls.args, ps);
-                       if (pipe_command(&cp_ls, NULL, 0, &out, 0, NULL, 0)) {
-                               ret = -1;
-                               goto done;
-                       }
+                       struct child_process cp = CHILD_PROCESS_INIT;
  
-                       cp_checkout.git_cmd = 1;
-                       argv_array_pushl(&cp_checkout.args, "checkout-index",
-                                        "-z", "--force", "--stdin", NULL);
-                       if (pipe_command(&cp_checkout, out.buf, out.len, NULL,
-                                        0, NULL, 0)) {
+                       cp.git_cmd = 1;
+                       argv_array_pushl(&cp.args, "checkout", "--no-overlay",
+                                        oid_to_hex(&info.i_tree), "--", NULL);
+                       if (!ps->nr)
+                               argv_array_push(&cp.args, ":/");
+                       else
+                               add_pathspecs(&cp.args, ps);
+                       if (run_command(&cp)) {
                                ret = -1;
                                goto done;
                        }
diff --combined t/t3903-stash.sh
index b22e671608119d37dd73bf6b0df41ce62e1a26f9,151cd497be88f2612d44614929841cc3bb3d1219..b8e337893f3e1e505da94b0c3f0b743ece622f10
@@@ -708,24 -708,6 +708,24 @@@ test_expect_success 'invalid ref of th
        git stash drop
  '
  
 +test_expect_success 'valid ref of the form "n", n < N' '
 +      git stash clear &&
 +      echo bar5 >file &&
 +      echo bar6 >file2 &&
 +      git add file2 &&
 +      git stash &&
 +      git stash show 0 &&
 +      git stash branch tmp 0 &&
 +      git checkout master &&
 +      git stash &&
 +      git stash apply 0 &&
 +      git reset --hard &&
 +      git stash pop 0 &&
 +      git stash &&
 +      git stash drop 0 &&
 +      test_must_fail git stash drop
 +'
 +
  test_expect_success 'branch: do not drop the stash if the branch exists' '
        git stash clear &&
        echo foo >file &&
@@@ -1234,4 -1216,11 +1234,11 @@@ test_expect_success 'stash works when u
        )
  '
  
+ test_expect_success 'stash --keep-index with file deleted in index does not resurrect it on disk' '
+       test_commit to-remove to-remove &&
+       git rm to-remove &&
+       git stash --keep-index &&
+       test_path_is_missing to-remove
+ '
  test_done