Skip to content

Commit cb46d63

Browse files
CanardChouChinoisstuberl
authored andcommitted
bisect: simplify the addition of new bisect terms
We create a file BISECT_TERMS in the repository .git to be read during a bisection. There's no user-interface yet, but "git bisect" works if terms other than old/new or bad/good are set in .git/BISECT_TERMS. The fonctions to be changed if we add new terms are quite few. In git-bisect.sh: check_and_set_terms bisect_voc Co-authored-by: Louis Stuber <[email protected]> Tweaked-by: Matthieu Moy <[email protected]> Signed-off-by: Antoine Delaite <[email protected]> Signed-off-by: Louis Stuber <[email protected]> Signed-off-by: Valentin Duperray <[email protected]> Signed-off-by: Franck Jonas <[email protected]> Signed-off-by: Lucien Kong <[email protected]> Signed-off-by: Thomas Nguy <[email protected]> Signed-off-by: Huynh Khoi Nguyen Nguyen <[email protected]> Signed-off-by: Matthieu Moy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 43f9d9f commit cb46d63

File tree

4 files changed

+120
-12
lines changed

4 files changed

+120
-12
lines changed

Diff for: bisect.c

+31-2
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,36 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
904904
log_tree_commit(&opt, commit);
905905
}
906906

907+
/*
908+
* The terms used for this bisect session are stored in BISECT_TERMS.
909+
* We read them and store them to adapt the messages accordingly.
910+
* Default is bad/good.
911+
*/
912+
void read_bisect_terms(const char **read_bad, const char **read_good)
913+
{
914+
struct strbuf str = STRBUF_INIT;
915+
const char *filename = git_path("BISECT_TERMS");
916+
FILE *fp = fopen(filename, "r");
917+
918+
if (!fp) {
919+
if (errno == ENOENT) {
920+
*read_bad = "bad";
921+
*read_good = "good";
922+
return;
923+
} else {
924+
die("could not read file '%s': %s", filename,
925+
strerror(errno));
926+
}
927+
} else {
928+
strbuf_getline(&str, fp, '\n');
929+
*read_bad = strbuf_detach(&str, NULL);
930+
strbuf_getline(&str, fp, '\n');
931+
*read_good = strbuf_detach(&str, NULL);
932+
}
933+
strbuf_release(&str);
934+
fclose(fp);
935+
}
936+
907937
/*
908938
* We use the convention that exiting with an exit code 10 means that
909939
* the bisection process finished successfully.
@@ -920,8 +950,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
920950
const unsigned char *bisect_rev;
921951
char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
922952

923-
term_bad = "bad";
924-
term_good = "good";
953+
read_bisect_terms(&term_bad, &term_good);
925954
if (read_bisect_refs())
926955
die("reading bisect refs failed");
927956

Diff for: bisect.h

+2
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ extern int bisect_next_all(const char *prefix, int no_checkout);
2626

2727
extern int estimate_bisect_steps(int all);
2828

29+
extern void read_bisect_terms(const char **bad, const char **good);
30+
2931
#endif

Diff for: git-bisect.sh

+71-8
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ bisect_start() {
7777
orig_args=$(git rev-parse --sq-quote "$@")
7878
bad_seen=0
7979
eval=''
80+
must_write_terms=0
8081
if test "z$(git rev-parse --is-bare-repository)" != zfalse
8182
then
8283
mode=--no-checkout
@@ -101,6 +102,14 @@ bisect_start() {
101102
die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
102103
break
103104
}
105+
106+
# The user ran "git bisect start <sha1>
107+
# <sha1>", hence did not explicitly specify
108+
# the terms, but we are already starting to
109+
# set references named with the default terms,
110+
# and won't be able to change afterwards.
111+
must_write_terms=1
112+
104113
case $bad_seen in
105114
0) state=$TERM_BAD ; bad_seen=1 ;;
106115
*) state=$TERM_GOOD ;;
@@ -172,6 +181,10 @@ bisect_start() {
172181
} &&
173182
git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
174183
eval "$eval true" &&
184+
if test $must_write_terms -eq 1
185+
then
186+
write_terms "$TERM_BAD" "$TERM_GOOD"
187+
fi &&
175188
echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
176189
#
177190
# Check if we can proceed to the next bisect state.
@@ -232,6 +245,7 @@ bisect_skip() {
232245
bisect_state() {
233246
bisect_autostart
234247
state=$1
248+
check_and_set_terms $state
235249
case "$#,$state" in
236250
0,*)
237251
die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
@@ -291,15 +305,17 @@ bisect_next_check() {
291305
: bisect without $TERM_GOOD...
292306
;;
293307
*)
294-
308+
bad_syn=$(bisect_voc bad)
309+
good_syn=$(bisect_voc good)
295310
if test -s "$GIT_DIR/BISECT_START"
296311
then
297-
gettextln "You need to give me at least one good and one bad revision.
298-
(You can use \"git bisect bad\" and \"git bisect good\" for that.)" >&2
312+
313+
eval_gettextln "You need to give me at least one \$bad_syn and one \$good_syn revision.
314+
(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
299315
else
300-
gettextln "You need to start by \"git bisect start\".
301-
You then need to give me at least one good and one bad revision.
302-
(You can use \"git bisect bad\" and \"git bisect good\" for that.)" >&2
316+
eval_gettextln "You need to start by \"git bisect start\".
317+
You then need to give me at least one \$good_syn and one \$bad_syn revision.
318+
(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
303319
fi
304320
exit 1 ;;
305321
esac
@@ -402,6 +418,7 @@ bisect_clean_state() {
402418
rm -f "$GIT_DIR/BISECT_LOG" &&
403419
rm -f "$GIT_DIR/BISECT_NAMES" &&
404420
rm -f "$GIT_DIR/BISECT_RUN" &&
421+
rm -f "$GIT_DIR/BISECT_TERMS" &&
405422
# Cleanup head-name if it got left by an old version of git-bisect
406423
rm -f "$GIT_DIR/head-name" &&
407424
git update-ref -d --no-deref BISECT_HEAD &&
@@ -422,11 +439,13 @@ bisect_replay () {
422439
rev="$command"
423440
command="$bisect"
424441
fi
442+
get_terms
443+
check_and_set_terms "$command"
425444
case "$command" in
426445
start)
427446
cmd="bisect_start $rev"
428447
eval "$cmd" ;;
429-
$TERM_GOOD|$TERM_BAD|skip)
448+
"$TERM_GOOD"|"$TERM_BAD"|skip)
430449
bisect_write "$command" "$rev" ;;
431450
*)
432451
die "$(gettext "?? what are you talking about?")" ;;
@@ -499,18 +518,62 @@ bisect_log () {
499518
cat "$GIT_DIR/BISECT_LOG"
500519
}
501520

521+
get_terms () {
522+
if test -s "$GIT_DIR/BISECT_TERMS"
523+
then
524+
{
525+
read TERM_BAD
526+
read TERM_GOOD
527+
} <"$GIT_DIR/BISECT_TERMS"
528+
fi
529+
}
530+
531+
write_terms () {
532+
TERM_BAD=$1
533+
TERM_GOOD=$2
534+
printf '%s\n%s\n' "$TERM_BAD" "$TERM_GOOD" >"$GIT_DIR/BISECT_TERMS"
535+
}
536+
537+
check_and_set_terms () {
538+
cmd="$1"
539+
case "$cmd" in
540+
skip|start|terms) ;;
541+
*)
542+
if test -s "$GIT_DIR/BISECT_TERMS" && test "$cmd" != "$TERM_BAD" && test "$cmd" != "$TERM_GOOD"
543+
then
544+
die "$(eval_gettext "Invalid command: you're currently in a \$TERM_BAD/\$TERM_GOOD bisect.")"
545+
fi
546+
case "$cmd" in
547+
bad|good)
548+
if ! test -s "$GIT_DIR/BISECT_TERMS"
549+
then
550+
write_terms bad good
551+
fi
552+
;;
553+
esac ;;
554+
esac
555+
}
556+
557+
bisect_voc () {
558+
case "$1" in
559+
bad) echo "bad" ;;
560+
good) echo "good" ;;
561+
esac
562+
}
563+
502564
case "$#" in
503565
0)
504566
usage ;;
505567
*)
506568
cmd="$1"
569+
get_terms
507570
shift
508571
case "$cmd" in
509572
help)
510573
git bisect -h ;;
511574
start)
512575
bisect_start "$@" ;;
513-
bad|good)
576+
bad|good|"$TERM_BAD"|"$TERM_GOOD")
514577
bisect_state "$cmd" "$@" ;;
515578
skip)
516579
bisect_skip "$@" ;;

Diff for: revision.c

+16-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
#include "commit-slab.h"
1919
#include "dir.h"
2020
#include "cache-tree.h"
21+
#include "bisect.h"
2122

2223
volatile show_early_output_fn_t show_early_output;
2324

25+
static const char *term_bad;
26+
static const char *term_good;
27+
2428
char *path_name(const struct name_path *path, const char *name)
2529
{
2630
const struct name_path *p;
@@ -2076,14 +2080,23 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
20762080
ctx->argc -= n;
20772081
}
20782082

2083+
static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) {
2084+
struct strbuf bisect_refs = STRBUF_INIT;
2085+
int status;
2086+
strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
2087+
status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
2088+
strbuf_release(&bisect_refs);
2089+
return status;
2090+
}
2091+
20792092
static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
20802093
{
2081-
return for_each_ref_in_submodule(submodule, "refs/bisect/bad", fn, cb_data);
2094+
return for_each_bisect_ref(submodule, fn, cb_data, term_bad);
20822095
}
20832096

20842097
static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
20852098
{
2086-
return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data);
2099+
return for_each_bisect_ref(submodule, fn, cb_data, term_good);
20872100
}
20882101

20892102
static int handle_revision_pseudo_opt(const char *submodule,
@@ -2112,6 +2125,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
21122125
handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
21132126
clear_ref_exclusion(&revs->ref_excludes);
21142127
} else if (!strcmp(arg, "--bisect")) {
2128+
read_bisect_terms(&term_bad, &term_good);
21152129
handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
21162130
handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
21172131
revs->bisect = 1;

0 commit comments

Comments
 (0)