Skip to content

Commit 129a6cf

Browse files
pranitbauva1997gitster
authored andcommitted
bisect--helper: bisect_next_check shell function in C
Reimplement `bisect_next_check` shell function in C and add `bisect-next-check` subcommand to `git bisect--helper` to call it from git-bisect.sh . `bisect_voc` shell function is no longer useful now and is replaced by using a char *[] of "new|bad" and "good|old" values. Using `--bisect-next-check` is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired but its implementation will be called by some other methods. Helped-by: Stephan Beyer <[email protected]> Mentored-by: Lars Schneider <[email protected]> Mentored-by: Christian Couder <[email protected]> Mentored-by: Johannes Schindelin <[email protected]> Signed-off-by: Pranit Bauva <[email protected]> Signed-off-by: Tanushree Tumane <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4fbdbd5 commit 129a6cf

File tree

2 files changed

+91
-57
lines changed

2 files changed

+91
-57
lines changed

builtin/bisect--helper.c

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "dir.h"
77
#include "argv-array.h"
88
#include "run-command.h"
9+
#include "prompt.h"
910

1011
static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
1112
static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
@@ -21,6 +22,7 @@ static const char * const git_bisect_helper_usage[] = {
2122
N_("git bisect--helper --bisect-reset [<commit>]"),
2223
N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"),
2324
N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"),
25+
N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
2426
NULL
2527
};
2628

@@ -44,6 +46,9 @@ static void set_terms(struct bisect_terms *terms, const char *bad,
4446
terms->term_bad = xstrdup(bad);
4547
}
4648

49+
static const char *vocab_bad = "bad|new";
50+
static const char *vocab_good = "good|old";
51+
4752
/*
4853
* Check whether the string `term` belongs to the set of strings
4954
* included in the variable arguments.
@@ -262,6 +267,78 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
262267
return 0;
263268
}
264269

270+
static int mark_good(const char *refname, const struct object_id *oid,
271+
int flag, void *cb_data)
272+
{
273+
int *m_good = (int *)cb_data;
274+
*m_good = 0;
275+
return 1;
276+
}
277+
278+
static const char *need_bad_and_good_revision_warning =
279+
N_("You need to give me at least one %s and %s revision.\n"
280+
"You can use \"git bisect %s\" and \"git bisect %s\" for that.");
281+
282+
static const char *need_bisect_start_warning =
283+
N_("You need to start by \"git bisect start\".\n"
284+
"You then need to give me at least one %s and %s revision.\n"
285+
"You can use \"git bisect %s\" and \"git bisect %s\" for that.");
286+
287+
static int bisect_next_check(const struct bisect_terms *terms,
288+
const char *current_term)
289+
{
290+
int missing_good = 1, missing_bad = 1, retval = 0;
291+
const char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
292+
const char *good_glob = xstrfmt("%s-*", terms->term_good);
293+
294+
if (ref_exists(bad_ref))
295+
missing_bad = 0;
296+
297+
for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/",
298+
(void *) &missing_good);
299+
300+
if (!missing_good && !missing_bad)
301+
goto finish;
302+
303+
if (!current_term) {
304+
retval = -1;
305+
goto finish;
306+
}
307+
308+
if (missing_good && !missing_bad &&
309+
!strcmp(current_term, terms->term_good)) {
310+
char *yesno;
311+
/*
312+
* have bad (or new) but not good (or old). We could bisect
313+
* although this is less optimum.
314+
*/
315+
warning(_("bisecting only with a %s commit"), terms->term_bad);
316+
if (!isatty(0))
317+
goto finish;
318+
/*
319+
* TRANSLATORS: Make sure to include [Y] and [n] in your
320+
* translation. The program will only accept English input
321+
* at this point.
322+
*/
323+
yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO);
324+
if (starts_with(yesno, "N") || starts_with(yesno, "n"))
325+
retval = -1;
326+
goto finish;
327+
}
328+
if (!is_empty_or_missing_file(git_path_bisect_start())) {
329+
retval = error(_(need_bad_and_good_revision_warning),
330+
vocab_bad, vocab_good, vocab_bad, vocab_good);
331+
} else {
332+
retval = error(_(need_bisect_start_warning),
333+
vocab_good, vocab_bad, vocab_good, vocab_bad);
334+
}
335+
336+
finish:
337+
free((void *) good_glob);
338+
free((void *) bad_ref);
339+
return retval;
340+
}
341+
265342
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
266343
{
267344
enum {
@@ -271,7 +348,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
271348
CHECK_EXPECTED_REVS,
272349
BISECT_RESET,
273350
BISECT_WRITE,
274-
CHECK_AND_SET_TERMS
351+
CHECK_AND_SET_TERMS,
352+
BISECT_NEXT_CHECK
275353
} cmdmode = 0;
276354
int no_checkout = 0, res = 0, nolog = 0;
277355
struct option options[] = {
@@ -289,6 +367,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
289367
N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE),
290368
OPT_CMDMODE(0, "check-and-set-terms", &cmdmode,
291369
N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS),
370+
OPT_CMDMODE(0, "bisect-next-check", &cmdmode,
371+
N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK),
292372
OPT_BOOL(0, "no-checkout", &no_checkout,
293373
N_("update BISECT_HEAD instead of checking out the current commit")),
294374
OPT_BOOL(0, "no-log", &nolog,
@@ -333,6 +413,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
333413
set_terms(&terms, argv[2], argv[1]);
334414
res = check_and_set_terms(&terms, argv[0]);
335415
break;
416+
case BISECT_NEXT_CHECK:
417+
if (argc != 2 && argc != 3)
418+
return error(_("--bisect-next-check requires 2 or 3 arguments"));
419+
set_terms(&terms, argv[1], argv[0]);
420+
res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);
421+
break;
336422
default:
337423
return error("BUG: unknown subcommand '%d'", cmdmode);
338424
}

git-bisect.sh

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -271,59 +271,14 @@ bisect_state() {
271271
bisect_auto_next
272272
}
273273

274-
bisect_next_check() {
275-
missing_good= missing_bad=
276-
git show-ref -q --verify refs/bisect/$TERM_BAD || missing_bad=t
277-
test -n "$(git for-each-ref "refs/bisect/$TERM_GOOD-*")" || missing_good=t
278-
279-
case "$missing_good,$missing_bad,$1" in
280-
,,*)
281-
: have both $TERM_GOOD and $TERM_BAD - ok
282-
;;
283-
*,)
284-
# do not have both but not asked to fail - just report.
285-
false
286-
;;
287-
t,,"$TERM_GOOD")
288-
# have bad (or new) but not good (or old). we could bisect although
289-
# this is less optimum.
290-
eval_gettextln "Warning: bisecting only with a \$TERM_BAD commit." >&2
291-
if test -t 0
292-
then
293-
# TRANSLATORS: Make sure to include [Y] and [n] in your
294-
# translation. The program will only accept English input
295-
# at this point.
296-
gettext "Are you sure [Y/n]? " >&2
297-
read yesno
298-
case "$yesno" in [Nn]*) exit 1 ;; esac
299-
fi
300-
: bisect without $TERM_GOOD...
301-
;;
302-
*)
303-
bad_syn=$(bisect_voc bad)
304-
good_syn=$(bisect_voc good)
305-
if test -s "$GIT_DIR/BISECT_START"
306-
then
307-
308-
eval_gettextln "You need to give me at least one \$bad_syn and one \$good_syn revision.
309-
(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
310-
else
311-
eval_gettextln "You need to start by \"git bisect start\".
312-
You then need to give me at least one \$good_syn and one \$bad_syn revision.
313-
(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
314-
fi
315-
exit 1 ;;
316-
esac
317-
}
318-
319274
bisect_auto_next() {
320-
bisect_next_check && bisect_next || :
275+
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD && bisect_next || :
321276
}
322277

323278
bisect_next() {
324279
case "$#" in 0) ;; *) usage ;; esac
325280
bisect_autostart
326-
bisect_next_check $TERM_GOOD
281+
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD $TERM_GOOD|| exit
327282

328283
# Perform all bisection computation, display and checkout
329284
git bisect--helper --next-all $(test -f "$GIT_DIR/BISECT_HEAD" && echo --no-checkout)
@@ -355,7 +310,7 @@ bisect_next() {
355310
}
356311

357312
bisect_visualize() {
358-
bisect_next_check fail
313+
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
359314

360315
if test $# = 0
361316
then
@@ -409,7 +364,7 @@ bisect_replay () {
409364
}
410365

411366
bisect_run () {
412-
bisect_next_check fail
367+
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
413368

414369
test -n "$*" || die "$(gettext "bisect run failed: no command provided.")"
415370

@@ -484,13 +439,6 @@ get_terms () {
484439
fi
485440
}
486441

487-
bisect_voc () {
488-
case "$1" in
489-
bad) echo "bad|new" ;;
490-
good) echo "good|old" ;;
491-
esac
492-
}
493-
494442
bisect_terms () {
495443
get_terms
496444
if ! test -s "$GIT_DIR/BISECT_TERMS"

0 commit comments

Comments
 (0)