All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org,  Johannes Sixt <j6t@kdbg.org>,
	 Harald Nordgren <haraldnordgren@gmail.com>
Subject: Re: [PATCH v4 2/2] bisect: add --reset-when-found to leave when done
Date: Sat, 01 Aug 2026 12:54:31 -0700	[thread overview]
Message-ID: <xmqqwlu97h1k.fsf@gitster.g> (raw)
In-Reply-To: <f5f370df1bab91872e32398386935d71d48a831b.1785577445.git.gitgitgadget@gmail.com> (Harald Nordgren via GitGitGadget's message of "Sat, 01 Aug 2026 09:44:05 +0000")

"Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com> writes:

> @@ -1211,6 +1212,7 @@ int bisect_clean_state(void)
>  	unlink_or_warn(git_path_bisect_run());
>  	unlink_or_warn(git_path_bisect_terms());
>  	unlink_or_warn(git_path_bisect_first_parent());
> +	unlink_or_warn(git_path_bisect_reset_when_found());
>  	/*
>  	 * Cleanup BISECT_START last to support the --no-checkout option
>  	 * introduced in the commit 4796e823a.

OK.  If we

> +static int bisect_reset_when_found(struct bisect_terms *terms)
> +{
> +	struct strbuf value = STRBUF_INIT;
> +	enum reset_when_found_mode mode;
> +	char *commit = NULL;
> +	int res;
> +
> +	if (strbuf_read_file(&value, git_path_bisect_reset_when_found(), 0) < 0) {
> +		res = error_errno(_("could not read '%s'"),
> +				  git_path_bisect_reset_when_found());
> +		goto cleanup;
> +	}

We expect that the caller calls this function only when we are doing
"--reset-when-found"; otherwise we would give an error message from
here even though we do not cause any damage otherwise.

We also expect that the callers refrain from calling this function
when bisect_next() that they eventually reach would not want to
immediately reset.

The defer_reset arrangement looks somewhat ugly even though what it
achieves may be a worthy thing to do.  Is the only code path that
passes defer_reset==true down the call chain the bisect_run()
codepath, to give that single caller a chance to close files that
bisect_reset() would remove by calling bisect_clean_state()?

I am wondering if the result of solving it slightly differently may
give us cleaner and easier to follow code, namely, we stop calling
bisect_clean_state() from bisect_reset().  Of course you would need
to find different place to call bisect_clean_state() to compensate,
if we go that route, but how many code paths do we have that depends
on bisect_reset() calling biesct_clean_state()?

Among existing callers of bisect_reset():

 - Does replay have to call reset?  Just like start does, isn't it
   sufficient to call clean_state?

 - cmd_bisect__reset() calls reset and returns, but it can call
   clean fater reset returns, if we need to make reset not to call
   clean.

> +	strbuf_trim(&value);
> +	if (parse_reset_when_found(value.buf, &mode)) {
> +		res = -1;
> +		goto cleanup;
> +	}
> +
> +	if (mode == RESET_WHEN_FOUND_TO_FOUND)
> +		commit = xstrfmt("refs/bisect/%s", terms->term_bad);
> +	res = bisect_reset(commit, 1);
> +
> +cleanup:
> +	free(commit);
> +	strbuf_release(&value);
> +	return res;
> +}

OK, "commit" is NULL unless mode specifies TO_FOUND in which case we
jump to the bad commit we found.  bisect_reset() knows that commit==NULL
means we go back to where we started.  OK.

> @@ -697,6 +760,9 @@ static enum bisect_error bisect_next(struct bisect_terms *terms, const char *pre
>  
>  	if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
>  		res = bisect_successful(terms);
> +		if (!res && !defer_reset &&
> +		    !is_empty_or_missing_file(git_path_bisect_reset_when_found()))
> +			res = bisect_reset_when_found(terms);
>  		return res ? res : BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND;
>  	} else if (res == BISECT_ONLY_SKIPPED_LEFT) {
>  		res = bisect_skipped_commits(terms);

This is the first ugliness I mentioned earlier.

> @@ -1311,7 +1415,7 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
>  		saved_stdout = dup(1);
>  		dup2(temporary_stdout_fd, 1);
>  
> -		res = bisect_state(terms, 1, &new_state);
> +		res = bisect_state(terms, 1, &new_state, true);
>  
>  		fflush(stdout);
>  		dup2(saved_stdout, 1);
> @@ -1327,7 +1431,11 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
>  			res = BISECT_OK;
>  		} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
>  			printf(_("bisect found first '%s' commit\n"), terms->term_bad);
> -			res = BISECT_OK;
> +			if (!is_empty_or_missing_file(git_path_bisect_reset_when_found()) &&
> +			    bisect_reset_when_found(terms))
> +				res = BISECT_FAILED;
> +			else
> +				res = BISECT_OK;
>  		} else if (res) {
>  			error(_("bisect run failed: 'git bisect %s'"
>  				" exited with error code %d"), new_state, res);

And these are the second one, that made the first one needed.

Another thing that I find a bit iffy is that earlier we said:

    We expect that the caller calls this function only when we are doing
    "--reset-when-found"; otherwise we would give an error message from
    here even though we do not cause any damage otherwise.

    We also expect that the callers refrain from calling this function
    when bisect_next() that they eventually reach would not want to
    immediately reset.

but the way the callers see if "--reset-when-found" is in effect
looks quite ad-hoc.  Instead of sprinkling "do we have that file in
the filesystem and what does it say?" all over the place, I wonder
if it is simpler to reason about if we do these checks upfront and
store the parsed result in a variable, so that places that say
!is_empty_or_missing_file(...) etc. do not have to?  After all, we
do not keep calling get_terms() in the middle of operation, and
instead use values from "struct bisect_terms" that somebody else
prepared much earlier before terms->term_good and terms->term_bad
are used, right?  Shouldn't it be handled pretty much the same way?


  reply	other threads:[~2026-08-01 19:54 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-16  5:35 [PATCH 0/3] bisect: add --auto-reset to leave when done Harald Nordgren via GitGitGadget
2026-07-16  5:35 ` [PATCH 1/3] bisect: read run output from the open descriptor Harald Nordgren via GitGitGadget
2026-07-16  5:35 ` [PATCH 2/3] bisect: let bisect_reset() optionally check out quietly Harald Nordgren via GitGitGadget
2026-07-16  5:35 ` [PATCH 3/3] bisect: add --auto-reset to leave when done Harald Nordgren via GitGitGadget
2026-07-16 17:22   ` Junio C Hamano
2026-07-16 21:22     ` Harald Nordgren
2026-07-17  5:00       ` Junio C Hamano
2026-07-17  9:16         ` Harald Nordgren
2026-07-17 16:43           ` Junio C Hamano
2026-07-17 18:27 ` [PATCH v2 0/3] " Harald Nordgren via GitGitGadget
2026-07-17 18:27   ` [PATCH v2 1/3] bisect: read run output from the open descriptor Harald Nordgren via GitGitGadget
2026-07-17 22:42     ` Junio C Hamano
2026-07-18 16:24     ` Johannes Sixt
2026-07-17 18:27   ` [PATCH v2 2/3] bisect: let bisect_reset() optionally check out quietly Harald Nordgren via GitGitGadget
2026-07-17 18:27   ` [PATCH v2 3/3] bisect: add --auto-reset to leave when done Harald Nordgren via GitGitGadget
2026-07-18 16:18     ` Johannes Sixt
2026-07-20  1:14       ` Junio C Hamano
2026-07-20  9:10   ` [PATCH v3 0/2] " Harald Nordgren via GitGitGadget
2026-07-20  9:10     ` [PATCH v3 1/2] bisect: let bisect_reset() optionally check out quietly Harald Nordgren via GitGitGadget
2026-07-20  9:10     ` [PATCH v3 2/2] bisect: add --reset-when-found to leave when done Harald Nordgren via GitGitGadget
2026-07-23  9:17       ` Johannes Sixt
2026-07-23 14:27         ` Junio C Hamano
2026-08-01  6:51         ` Harald Nordgren
2026-07-20 17:20     ` [PATCH v3 0/2] bisect: add --auto-reset " Junio C Hamano
2026-08-01  9:44     ` [PATCH v4 0/2] bisect: add --reset-when-found " Harald Nordgren via GitGitGadget
2026-08-01  9:44       ` [PATCH v4 1/2] bisect: let bisect_reset() optionally check out quietly Harald Nordgren via GitGitGadget
2026-08-01 19:15         ` Junio C Hamano
2026-08-01  9:44       ` [PATCH v4 2/2] bisect: add --reset-when-found to leave when done Harald Nordgren via GitGitGadget
2026-08-01 19:54         ` Junio C Hamano [this message]
2026-08-01 21:40           ` Junio C Hamano
2026-08-02  9:31       ` [PATCH v5 0/2] " Harald Nordgren via GitGitGadget
2026-08-02  9:31         ` [PATCH v5 1/2] bisect: let bisect_reset() optionally check out quietly Harald Nordgren via GitGitGadget
2026-08-02  9:31         ` [PATCH v5 2/2] bisect: add --reset-when-found to leave when done Harald Nordgren via GitGitGadget
2026-08-02 16:01         ` [PATCH v5 0/2] " Junio C Hamano
2026-08-02 21:24         ` [PATCH v6 " Harald Nordgren via GitGitGadget
2026-08-02 21:24           ` [PATCH v6 1/2] bisect: let bisect_reset() optionally check out quietly Harald Nordgren via GitGitGadget
2026-08-02 21:24           ` [PATCH v6 2/2] bisect: add --reset-when-found to leave when done Harald Nordgren via GitGitGadget
2026-08-03  0:08             ` Junio C Hamano
2026-08-06  7:30               ` Harald Nordgren
2026-08-06 13:50                 ` Junio C Hamano
2026-08-06 15:59                   ` Harald Nordgren
2026-08-06 17:36                     ` Junio C Hamano

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

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

  git send-email \
    --in-reply-to=xmqqwlu97h1k.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=haraldnordgren@gmail.com \
    --cc=j6t@kdbg.org \
    /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.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.