Message ID | 20200423070704.39872-5-mirucam@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Finish converting git bisect to C part 2 | expand |
Hi Miriam, On Thu, 23 Apr 2020, Miriam Rubio wrote: > From: Pranit Bauva <pranit.bauva@gmail.com> > > Reimplement the `bisect_autostart()` shell function in C and add the > C implementation from `bisect_next()` which was previously left > uncovered. Also add a subcommand `--bisect-autostart` to > `git bisect--helper` be called from `bisect_state()` from > git-bisect.sh . I know you did not author this, but maybe I can still ask you to address a couple of concerns I have? I kind of stumble when I read "Also add a subcommand ... be called from ... from ...". Also, why the funny space before the full stop? > Using `--bisect-autostart` subcommand is a temporary measure to port > shell function to C so as to use the existing test suite. As more Likewise, "... to port shell function..." might benefit from inserting "the" in the middle? > functions are ported, this subcommand will be retired and > bisect_autostart() will be called directly by `bisect_state()`. > > Mentored-by: Lars Schneider <larsxschneider@gmail.com> > Mentored-by: Christian Couder <chriscool@tuxfamily.org> > Mentored-by: Johannes Schindelin <johannes.schindelin@gmx.de> > Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com> > Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com> > Signed-off-by: Miriam Rubio <mirucam@gmail.com> > --- > builtin/bisect--helper.c | 40 +++++++++++++++++++++++++++++++++++++++- > git-bisect.sh | 25 ++----------------------- > 2 files changed, 41 insertions(+), 24 deletions(-) > > diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c > index d3b2b33df0..9df69800e3 100644 > --- a/builtin/bisect--helper.c > +++ b/builtin/bisect--helper.c > @@ -29,6 +29,7 @@ static const char * const git_bisect_helper_usage[] = { > N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"), > N_("git bisect--helper --bisect-start [--term-{old,good}=<term> --term-{new,bad}=<term>]" > "[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]"), > + N_("git bisect--helper --bisect-autostart"), > NULL > }; > > @@ -55,6 +56,8 @@ static void set_terms(struct bisect_terms *terms, const char *bad, > static const char vocab_bad[] = "bad|new"; > static const char vocab_good[] = "good|old"; > > +static int bisect_autostart(struct bisect_terms *terms); > + Why forward-declare it? There is no reference before it is defined below, so I think this forward-declaration can be removed without any problem. > /* > * Check whether the string `term` belongs to the set of strings > * included in the variable arguments. > @@ -630,6 +633,32 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, > return res; > } > > +static int bisect_autostart(struct bisect_terms *terms) > +{ > + const char *yesno; > + > + if (!is_empty_or_missing_file(git_path_bisect_start())) > + return 0; This is a bit more convoluted to read than the shell script: bisect_autostart() { test -s "$GIT_DIR/BISECT_START" || { gettextln "You need to start by \"git bisect start\"" >&2 [...] } } The `test -s <file>` command succeeds if the file exists and is non-empty. Which makes sense: either the file exists and is non-empty, or we need to do something. When I read the C version, it takes me a bit more time to figure out what is going on here. Maybe we could introduce a helper function like this and use it here? static inline int file_is_not_empty(const char *path) { return !is_empty_or_missing_file(path); } > + > + fprintf(stderr, _("You need to start by \"git bisect " > + "start\"\n")); If you use `fprintf_ln()` here, you can keep the string identical to the shell script version, i.e. without the trailing newline. That will allow the translations to be re-used, lessening the burden of the i18n team. > + > + if (!isatty(STDIN_FILENO)) > + return 1; I would prefer it if only `cmd_*()` functions return positive values for the error case. > + > + /* > + * TRANSLATORS: Make sure to include [Y] and [n] in your > + * translation. The program will only accept English input > + * at this point. > + */ > + yesno = git_prompt(_("Do you want me to do it for you " > + "[Y/n]? "), PROMPT_ECHO); Technically, `PROMPT_ECHO` is not required here as `git_prompt()` adds that flag implicitly unless you pass in `PASS_ASKPASS`, but I guess it does not hurt here. However, I cannot fail to note that this constitutes a change of behavior, as `git_prompt()` does _not_ read from `stdin`. Maybe we should call `git_read_line_interactively()` instead, after writing the prompt to `stderr` explicitly? > + if (starts_with(yesno, _("n")) || starts_with(yesno, _("N"))) This is wrong: "n" and "N" should not be translated, as they are not translated in the shell script version, either: case "$yesno" in [Nn]*) exit ;; esac In light of this, a much, much shorter version would be: if (tolower(*yesno) == 'n') return -1; (I use `-1` here because this is not within a `cmd_*()` function.) However, I still think that we need to call `free(yesno);` or we leak memory. My preferred way would be: int ret; [...] ret = tolower(*yesno) == 'n' ? -1 : bisect_start(terms, 0, NULL, 0); free(yesno); return ret; > + return 1; > + > + return bisect_start(terms, 0, NULL, 0); > +} > + > int cmd_bisect__helper(int argc, const char **argv, const char *prefix) > { > enum { > @@ -642,7 +671,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) > CHECK_AND_SET_TERMS, > BISECT_NEXT_CHECK, > BISECT_TERMS, > - BISECT_START > + BISECT_START, > + BISECT_AUTOSTART, > } cmdmode = 0; > int no_checkout = 0, res = 0, nolog = 0; > struct option options[] = { > @@ -666,6 +696,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) > N_("print out the bisect terms"), BISECT_TERMS), > OPT_CMDMODE(0, "bisect-start", &cmdmode, > N_("start the bisect session"), BISECT_START), > + OPT_CMDMODE(0, "bisect-autostart", &cmdmode, > + N_("start the bisection if BISECT_START is empty or missing"), BISECT_AUTOSTART), Not that it matters a lot because this command mode will go away soon thereafter, but this describes an implementation detail rather than the purpose of the function. I would much rather read "start the bisection if it has not yet been started" instead. > OPT_BOOL(0, "no-checkout", &no_checkout, > N_("update BISECT_HEAD instead of checking out the current commit")), > OPT_BOOL(0, "no-log", &nolog, > @@ -727,6 +759,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) > set_terms(&terms, "bad", "good"); > res = bisect_start(&terms, no_checkout, argv, argc); > break; > + case BISECT_AUTOSTART: > + if (argc) > + return error(_("--bisect-autostart requires 0 arguments")); Maybe "--bisect-autostart does not accept arguments" instead? Ciao, Dscho > + set_terms(&terms, "bad", "good"); > + res = bisect_autostart(&terms); > + break; > default: > BUG("unknown subcommand %d", (int)cmdmode); > } > diff --git a/git-bisect.sh b/git-bisect.sh > index efee12b8b1..426d443e7e 100755 > --- a/git-bisect.sh > +++ b/git-bisect.sh > @@ -49,27 +49,6 @@ bisect_head() > fi > } > > -bisect_autostart() { > - test -s "$GIT_DIR/BISECT_START" || { > - gettextln "You need to start by \"git bisect start\"" >&2 > - if test -t 0 > - then > - # TRANSLATORS: Make sure to include [Y] and [n] in your > - # translation. The program will only accept English input > - # at this point. > - gettext "Do you want me to do it for you [Y/n]? " >&2 > - read yesno > - case "$yesno" in > - [Nn]*) > - exit ;; > - esac > - bisect_start > - else > - exit 1 > - fi > - } > -} > - > bisect_start() { > git bisect--helper --bisect-start $@ || exit > > @@ -108,7 +87,7 @@ bisect_skip() { > } > > bisect_state() { > - bisect_autostart > + git bisect--helper --bisect-autostart > state=$1 > git bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit > get_terms > @@ -149,7 +128,7 @@ bisect_auto_next() { > > bisect_next() { > case "$#" in 0) ;; *) usage ;; esac > - bisect_autostart > + git bisect--helper --bisect-autostart > git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit > > # Perform all bisection computation, display and checkout > -- > 2.25.0 > >
Hi Miriam, On Fri, 22 May 2020, Johannes Schindelin wrote: > On Thu, 23 Apr 2020, Miriam Rubio wrote: > > > + /* > > + * TRANSLATORS: Make sure to include [Y] and [n] in your > > + * translation. The program will only accept English input > > + * at this point. > > + */ > > + yesno = git_prompt(_("Do you want me to do it for you " > > + "[Y/n]? "), PROMPT_ECHO); > > [...] > > I still think that we need to call `free(yesno);` or we leak memory. Never mind. I got fooled by the fact that `git_prompt()` returns `char *`. It actually returns the pointer `buf.buf` of a `static `strbuf buf`, so there is nothing to `free()` here. Sorry for the noise, Dscho
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index d3b2b33df0..9df69800e3 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -29,6 +29,7 @@ static const char * const git_bisect_helper_usage[] = { N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"), N_("git bisect--helper --bisect-start [--term-{old,good}=<term> --term-{new,bad}=<term>]" "[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]"), + N_("git bisect--helper --bisect-autostart"), NULL }; @@ -55,6 +56,8 @@ static void set_terms(struct bisect_terms *terms, const char *bad, static const char vocab_bad[] = "bad|new"; static const char vocab_good[] = "good|old"; +static int bisect_autostart(struct bisect_terms *terms); + /* * Check whether the string `term` belongs to the set of strings * included in the variable arguments. @@ -630,6 +633,32 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, return res; } +static int bisect_autostart(struct bisect_terms *terms) +{ + const char *yesno; + + if (!is_empty_or_missing_file(git_path_bisect_start())) + return 0; + + fprintf(stderr, _("You need to start by \"git bisect " + "start\"\n")); + + if (!isatty(STDIN_FILENO)) + return 1; + + /* + * TRANSLATORS: Make sure to include [Y] and [n] in your + * translation. The program will only accept English input + * at this point. + */ + yesno = git_prompt(_("Do you want me to do it for you " + "[Y/n]? "), PROMPT_ECHO); + if (starts_with(yesno, _("n")) || starts_with(yesno, _("N"))) + return 1; + + return bisect_start(terms, 0, NULL, 0); +} + int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { @@ -642,7 +671,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) CHECK_AND_SET_TERMS, BISECT_NEXT_CHECK, BISECT_TERMS, - BISECT_START + BISECT_START, + BISECT_AUTOSTART, } cmdmode = 0; int no_checkout = 0, res = 0, nolog = 0; struct option options[] = { @@ -666,6 +696,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("print out the bisect terms"), BISECT_TERMS), OPT_CMDMODE(0, "bisect-start", &cmdmode, N_("start the bisect session"), BISECT_START), + OPT_CMDMODE(0, "bisect-autostart", &cmdmode, + N_("start the bisection if BISECT_START is empty or missing"), BISECT_AUTOSTART), OPT_BOOL(0, "no-checkout", &no_checkout, N_("update BISECT_HEAD instead of checking out the current commit")), OPT_BOOL(0, "no-log", &nolog, @@ -727,6 +759,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) set_terms(&terms, "bad", "good"); res = bisect_start(&terms, no_checkout, argv, argc); break; + case BISECT_AUTOSTART: + if (argc) + return error(_("--bisect-autostart requires 0 arguments")); + set_terms(&terms, "bad", "good"); + res = bisect_autostart(&terms); + break; default: BUG("unknown subcommand %d", (int)cmdmode); } diff --git a/git-bisect.sh b/git-bisect.sh index efee12b8b1..426d443e7e 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -49,27 +49,6 @@ bisect_head() fi } -bisect_autostart() { - test -s "$GIT_DIR/BISECT_START" || { - gettextln "You need to start by \"git bisect start\"" >&2 - if test -t 0 - then - # TRANSLATORS: Make sure to include [Y] and [n] in your - # translation. The program will only accept English input - # at this point. - gettext "Do you want me to do it for you [Y/n]? " >&2 - read yesno - case "$yesno" in - [Nn]*) - exit ;; - esac - bisect_start - else - exit 1 - fi - } -} - bisect_start() { git bisect--helper --bisect-start $@ || exit @@ -108,7 +87,7 @@ bisect_skip() { } bisect_state() { - bisect_autostart + git bisect--helper --bisect-autostart state=$1 git bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit get_terms @@ -149,7 +128,7 @@ bisect_auto_next() { bisect_next() { case "$#" in 0) ;; *) usage ;; esac - bisect_autostart + git bisect--helper --bisect-autostart git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit # Perform all bisection computation, display and checkout