git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Thomas Gummerer <t.gummerer@gmail.com>
Cc: Grzegorz Rajchman <rayman17@gmail.com>, git@vger.kernel.org
Subject: Re: [BUG] git stash pop --quiet deletes files in git 2.24.0
Date: Tue, 12 Nov 2019 14:21:01 +0900	[thread overview]
Message-ID: <xmqqftitfz5u.fsf@gitster-ct.c.googlers.com> (raw)
In-Reply-To: <20191111195641.GC3115@cat> (Thomas Gummerer's message of "Mon, 11 Nov 2019 19:56:41 +0000")

Thomas Gummerer <t.gummerer@gmail.com> writes:

>> > From what you are saying above, and from my testing I think this
>> > refresh is actually unnecessary, and we could just remove it outright.
>> 
>> Perhaps.  But later it will bite us when somebody wants to rewrite
>> the "status at the end" part in C.
>
> Hmm, wouldn't the not re-reading the index part bite us there, rather
> than the not refreshing the index?

Yes.  Just removing the refresh-and-write that caused us to write
out incorrect data would "fix" the bug, while leaving the bug of not
re-reading to bite us later.

> Below is the patch that I believe has the least chances of biting us
> in the future, with the appropriate updated tests.  I had considered
> leaving the 'refresh_and_write_cache()' call there, but as I was
> writing the commit message I had a harder and harder time justifying
> that, so it's gone now, which I think is the right thing to do.
> Leaving it there would be okay as well, however I don't think it would
> have any benefit.
>
> --- >8 ---
> Subject: [PATCH] stash: make sure we have a valid index before writing it
>
> In 'do_apply_stash()' we refresh the index in the end.  Since
> 34933d0eff ("stash: make sure to write refreshed cache", 2019-09-11),
> we also write that refreshed index when --quiet is given to 'git stash
> apply'.
>
> However if '--index' is not given to 'git stash apply', we also
> discard the index in the else clause just before.  This leads to
> writing the discarded index, which means we essentially write an empty
> index file.  This is obviously not correct, or the behaviour the user
> wanted.  We should not modify the users index without being asked to
> do so.
>
> Make sure to re-read the index after discarding the current in-core
> index, to avoid dealing with outdated information.

Yup.  The "!has_index" codepath calls update_index() that turns the
on-disk index into the desired shape (would it help explaining that
in the previous paragraph, by the way?) so all we need to do is to
read it back into core.  Makes sense.

> We can drop the 'refresh_and_write_cache' completely in the quiet
> case.  Previously in legacy stash we relied on 'git status' to refresh
> the index after calling 'git read-tree' when '--index' was passed to
> 'git apply'.  However the 'reset_tree()' call that replaced 'git
> read-tree' always passes options that are equivalent to '-m', making
> the refresh of the index unnecessary.

OK.

> We could also drop the 'discard_cache()' + 'read_cache()', however
> that would make it easy to fall into the same trap as 34933d0eff did,
> so it's better to avoid that.

This is the discarded alternative of the main fix we saw earlier.
Perhaps it may make the flow of thought easier to follow if we moved
it up before talking about "refresh-and-write can be thrown away"?

> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
> ---
>  builtin/stash.c  | 6 ++----
>  t/t3903-stash.sh | 5 ++++-
>  2 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/builtin/stash.c b/builtin/stash.c
> index ab30d1e920..d00567285f 100644
> --- a/builtin/stash.c
> +++ b/builtin/stash.c
> @@ -482,12 +482,10 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
>  			return -1;
>  
>  		discard_cache();
> +		read_cache();

A comment

    /* read back the result of update_index() back from the disk */

before discard_cache() may be warranted?

>  	}
>  
> -	if (quiet) {
> -		if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
> -			warning("could not refresh index");
> -	} else {

OK.

> +	if (!quiet) {
>  		struct child_process cp = CHILD_PROCESS_INIT;
>  
>  		/*
> diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
> index 392954d6dd..b1c973e3d9 100755
> --- a/t/t3903-stash.sh
> +++ b/t/t3903-stash.sh
> @@ -232,8 +232,9 @@ test_expect_success 'save -q is quiet' '
>  	test_must_be_empty output.out
>  '
>  
> -test_expect_success 'pop -q is quiet' '
> +test_expect_success 'pop -q works and is quiet' '
>  	git stash pop -q >output.out 2>&1 &&
> +	test bar = "$(git show :file)" &&

Ah, this is to ensure that we didn't lose the "file" from the index?

Denton is on the quest of removing "$(git command substitution)"
used in a way that might hide the error from git invocation in a
separate thread [*1*].  This may want to become

	git rev-parse --verify :file &&

or

	git show :file >actual && echo bar >expect &&
	test_cmp expect actual &&

perhaps?

>  	test_must_be_empty output.out
>  '
>  
> @@ -242,6 +243,8 @@ test_expect_success 'pop -q --index works and is quiet' '
>  	git add file &&
>  	git stash save --quiet &&
>  	git stash pop -q --index >output.out 2>&1 &&
> +	git diff-files file2 >file2.diff &&
> +	test_must_be_empty file2.diff &&
>  	test foo = "$(git show :file)" &&
>  	test_must_be_empty output.out
>  '

Dittto.

Thanks.


[Reference]

*1* <2f9052fd94ebb6fe93ea6fe2e7cd3c717635c822.1573517561.git.liu.denton@gmail.com>

Note that "var=$(git subcmd)" is special and will signal us a failure
of the git invocation.

  reply	other threads:[~2019-11-12  5:21 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-07 10:36 [BUG] git stash pop --quiet deletes files in git 2.24.0 Grzegorz Rajchman
2019-11-07 18:49 ` Thomas Gummerer
2019-11-08  2:32   ` Junio C Hamano
2019-11-08 16:59     ` Thomas Gummerer
2019-11-10  6:11       ` Junio C Hamano
2019-11-11 19:56         ` Thomas Gummerer
2019-11-12  5:21           ` Junio C Hamano [this message]
2019-11-13 11:15             ` Thomas Gummerer
2019-11-13 13:31               ` Junio C Hamano
2019-11-13 15:01                 ` [PATCH v3] stash: make sure we have a valid index before writing it Thomas Gummerer
2019-11-14  2:07                   ` Junio C Hamano
2019-11-13 11:17           ` [PATCH v2 1/2] t3903: avoid git commands inside command substitution Thomas Gummerer
2019-11-13 11:17             ` [PATCH v2 2/2] stash: make sure we have a valid index before writing it Thomas Gummerer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqftitfz5u.fsf@gitster-ct.c.googlers.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=rayman17@gmail.com \
    --cc=t.gummerer@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).