git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Miriam Rubio <mirucam@gmail.com>
Cc: git@vger.kernel.org, Tanushree Tumane <tanushreetumane@gmail.com>,
	Christian Couder <chriscool@tuxfamily.org>
Subject: Re: [PATCH v6 5/6] bisect--helper: reimplement `bisect_run` shell
Date: Thu, 02 Sep 2021 16:43:02 -0700	[thread overview]
Message-ID: <xmqqtuj2h7cp.fsf@gitster.g> (raw)
In-Reply-To: <20210902090421.93113-6-mirucam@gmail.com> (Miriam Rubio's message of "Thu, 2 Sep 2021 11:04:20 +0200")

Miriam Rubio <mirucam@gmail.com> writes:

> From: Tanushree Tumane <tanushreetumane@gmail.com>
>
> Reimplement the `bisect_run()` shell function
> in C and also add `--bisect-run` subcommand to
> `git bisect--helper` to call it from git-bisect.sh.
>
> Mentored-by: Christian Couder <chriscool@tuxfamily.org>
> Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>
> Signed-off-by: Miriam Rubio <mirucam@gmail.com>
> ---
>  builtin/bisect--helper.c | 97 ++++++++++++++++++++++++++++++++++++++++
>  git-bisect.sh            | 62 +------------------------
>  2 files changed, 98 insertions(+), 61 deletions(-)
>
> diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
> index 1e118a966a..8e9ed9c318 100644
> --- a/builtin/bisect--helper.c
> +++ b/builtin/bisect--helper.c
> @@ -18,6 +18,7 @@ static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
>  static GIT_PATH_FUNC(git_path_head_name, "head-name")
>  static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
>  static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
> +static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
>  
>  static const char * const git_bisect_helper_usage[] = {
>  	N_("git bisect--helper --bisect-reset [<commit>]"),
> @@ -31,6 +32,7 @@ static const char * const git_bisect_helper_usage[] = {
>  	N_("git bisect--helper --bisect-replay <filename>"),
>  	N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
>  	N_("git bisect--helper --bisect-visualize"),
> +	N_("git bisect--helper --bisect-run <cmd>..."),
>  	NULL
>  };
>  
> @@ -144,6 +146,19 @@ static int append_to_file(const char *path, const char *format, ...)
>  	return res;
>  }
>  
> +static int print_file_to_stdout(const char *path)
> +{
> +	int fd = open(path, O_RDONLY);
> +	int ret = 0;
> +
> +	if (fd < 0)
> +		return error_errno(_("cannot open file '%s' for reading"), path);
> +	if (copy_fd(fd, 1) < 0)
> +		ret = error_errno(_("failed to read '%s'"), path);
> +	close(fd);
> +	return ret;
> +}
> +
>  static int check_term_format(const char *term, const char *orig_term)
>  {
>  	int res;
> @@ -1075,6 +1090,79 @@ static int bisect_visualize(struct bisect_terms *terms, const char **argv, int a
>  	return res;
>  }
>  
> +static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
> +{
> +	int res = BISECT_OK;
> +	struct strbuf command = STRBUF_INIT;
> +	struct strvec args = STRVEC_INIT;
> +	struct strvec run_args = STRVEC_INIT;
> +	const char *new_state;
> +	int temporary_stdout_fd, saved_stdout;
> +
> +	if (bisect_next_check(terms, NULL))
> +		return BISECT_FAILED;
> +
> +	if (argc)
> +		sq_quote_argv(&command, argv);
> +	else {
> +		error(_("bisect run failed: no command provided."));
> +		return BISECT_FAILED;
> +	}
> +	strvec_push(&run_args, command.buf);
> +
> +	while (1) {
> +		strvec_clear(&args);
> +
> +		printf(_("running %s\n"), command.buf);
> +		res = run_command_v_opt(run_args.v, RUN_USING_SHELL);
> +
> +		if (res < 0 || 128 <= res) {
> +			error(_("bisect run failed: exit code %d from"
> +				" '%s' is < 0 or >= 128"), res, command.buf);
> +			strbuf_release(&command);
> +			return res;
> +		}
> +
> +		if (res == 125)
> +			new_state = "skip";
> +		else
> +			new_state = res > 0 ? terms->term_bad : terms->term_good;

It is easier to follow the code if you spelled out this part as

		else if (!res)
			new_state = terms->term_good;
		else
			new_state = terms->term_bad;

because that would consistently handle the three cases.  Of course
you _could_ do

		new_state = (res == 125)
			  ? "skip"
			  : (res > 0)
			  ? terms->term_bad
			  : terms->term_good;

instead, but that would be harder to read.


> +		temporary_stdout_fd = open(git_path_bisect_run(), O_CREAT | O_WRONLY | O_TRUNC, 0666);

Can this open fail, and if it fails, what do we want to do?

> +		saved_stdout = dup(1);
> +		dup2(temporary_stdout_fd, 1);
> +
> +		res = bisect_state(terms, &new_state, 1);
> +
> +		dup2(saved_stdout, 1);
> +		close(saved_stdout);
> +		close(temporary_stdout_fd);

Hmph, now you lost me.  Whose output are we working around here with
the redirection?  

	... goes and looks ...

Ahh, OK.  bisect_next_all() to bisect_checkout() all assume that
they only need to write to the standard output, so we need to do
this dance (unless we are willing to update the bisect.c functions
to accept FILE * as parameter, that is).

However, they use not just write(2) but stdio to do their output,
no?  Don't we need to fflush(stdout) around the redirection dance,
one to empty the output that was associated with the real standard
output stream before asking bisect_state() to write to fd #1 via
stdio, and one more time to flush out what bisect_state() wrote to
the stdio after the call returns before closing the fd we opened to
the BISECT_RUN file?

> +		print_file_to_stdout(git_path_bisect_run());

OK.  So this corresponds to the "write bisect-state to ./git/BISECT_RUN
and then cat it" in the scripted version.

> +		if (res == BISECT_ONLY_SKIPPED_LEFT)
> +			error(_("bisect run cannot continue any more"));
> +		else if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) {
> +			printf(_("bisect run success"));
> +			res = BISECT_OK;
> +		} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
> +			printf(_("bisect found first bad commit"));
> +			res = BISECT_OK;
> +		} else if (res) {
> +			error(_("bisect run failed:'git bisect--helper --bisect-state"
> +			" %s' exited with error code %d"), args.v[0], res);
> +		} else {
> +			continue;
> +		}
> +
> +		strbuf_release(&command);
> +		strvec_clear(&args);
> +		strvec_clear(&run_args);
> +		return res;
> +	}
> +}

OK, the "res to diag" and clearing the resources at the end of the
function looks good to me.

Thanks.

  reply	other threads:[~2021-09-02 23:43 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-02  9:04 [PATCH v6 0/6] Finish converting git bisect to C part 4 Miriam Rubio
2021-09-02  9:04 ` [PATCH v6 1/6] t6030-bisect-porcelain: add tests to control bisect run exit cases Miriam Rubio
2021-09-02 21:44   ` Junio C Hamano
2021-09-02  9:04 ` [PATCH v6 2/6] t6030-bisect-porcelain: add test for bisect visualize Miriam Rubio
2021-09-02 22:05   ` Junio C Hamano
2021-09-02  9:04 ` [PATCH v6 3/6] run-command: make `exists_in_PATH()` non-static Miriam Rubio
2021-09-02 22:19   ` Junio C Hamano
2021-09-02  9:04 ` [PATCH v6 4/6] bisect--helper: reimplement `bisect_visualize()`shell function in C Miriam Rubio
2021-09-02 22:28   ` Junio C Hamano
2021-09-02  9:04 ` [PATCH v6 5/6] bisect--helper: reimplement `bisect_run` shell Miriam Rubio
2021-09-02 23:43   ` Junio C Hamano [this message]
2021-09-06  7:33     ` Johannes Schindelin
2021-09-06  8:34       ` Miriam R.
2021-09-07 18:32         ` Junio C Hamano
2021-09-09  7:51           ` Johannes Schindelin
2021-09-02  9:04 ` [PATCH v6 6/6] bisect--helper: retire `--bisect-next-check` subcommand Miriam Rubio
2021-09-02 23:43   ` 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

  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=xmqqtuj2h7cp.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=chriscool@tuxfamily.org \
    --cc=git@vger.kernel.org \
    --cc=mirucam@gmail.com \
    --cc=tanushreetumane@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).