]> granicus.if.org Git - git/commitdiff
stash: make sure to write refreshed cache
authorThomas Gummerer <t.gummerer@gmail.com>
Wed, 11 Sep 2019 18:20:27 +0000 (19:20 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 20 Sep 2019 16:58:22 +0000 (09:58 -0700)
When converting stash into C, calls to 'git update-index --refresh'
were replaced with the 'refresh_cache()' function.  That is fine as
long as the index is only needed in-core, and not re-read from disk.

However in many cases we do actually need the refreshed index to be
written to disk, for example 'merge_recursive_generic()' discards the
in-core index before re-reading it from disk, and in the case of 'apply
--quiet', the 'refresh_cache()' we currently have is pointless without
writing the index to disk.

Always write the index after refreshing it to ensure there are no
regressions in this compared to the scripted stash.  In the future we
can consider avoiding the write where possible after making sure none
of the subsequent calls actually need the refreshed cache, and it is
not expected to be refreshed after stash exits or it is written
somewhere else already.

Reported-by: Jeff King <peff@peff.net>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/stash.c
t/t3903-stash.sh

index b5a301f24d7a5f8b0a5f7d51703ca4cf38e2109c..ab30d1e9203b42dec154b4b171f74ba7fec1b6b7 100644 (file)
@@ -396,7 +396,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
        const struct object_id *bases[1];
 
        read_cache_preload(NULL);
-       if (refresh_cache(REFRESH_QUIET))
+       if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
                return -1;
 
        if (write_cache_as_tree(&c_tree, 0, NULL))
@@ -485,7 +485,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
        }
 
        if (quiet) {
-               if (refresh_cache(REFRESH_QUIET))
+               if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
                        warning("could not refresh index");
        } else {
                struct child_process cp = CHILD_PROCESS_INIT;
@@ -1129,7 +1129,10 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
        prepare_fallback_ident("git stash", "git@stash");
 
        read_cache_preload(NULL);
-       refresh_cache(REFRESH_QUIET);
+       if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0) {
+               ret = -1;
+               goto done;
+       }
 
        if (get_oid("HEAD", &info->b_commit)) {
                if (!quiet)
@@ -1290,7 +1293,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
                free(ps_matched);
        }
 
-       if (refresh_cache(REFRESH_QUIET)) {
+       if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) {
                ret = -1;
                goto done;
        }
index b8e337893f3e1e505da94b0c3f0b743ece622f10..392954d6dd9243faa03a9092f21ba9959acdc371 100755 (executable)
@@ -1241,4 +1241,20 @@ test_expect_success 'stash --keep-index with file deleted in index does not resu
        test_path_is_missing to-remove
 '
 
+test_expect_success 'stash apply should succeed with unmodified file' '
+       echo base >file &&
+       git add file &&
+       git commit -m base &&
+
+       # now stash a modification
+       echo modified >file &&
+       git stash &&
+
+       # make the file stat dirty
+       cp file other &&
+       mv other file &&
+
+       git stash apply
+'
+
 test_done