Commit cb46d630 authored by Antoine Delaite's avatar Antoine Delaite Committed by Junio C Hamano

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: default avatarLouis Stuber <[email protected]>
Tweaked-by: default avatarMatthieu Moy <[email protected]>
Signed-off-by: default avatarAntoine Delaite <[email protected]>
Signed-off-by: default avatarLouis Stuber <[email protected]>
Signed-off-by: default avatarValentin Duperray <[email protected]>
Signed-off-by: default avatarFranck Jonas <[email protected]>
Signed-off-by: default avatarLucien Kong <[email protected]>
Signed-off-by: default avatarThomas Nguy <[email protected]>
Signed-off-by: default avatarHuynh Khoi Nguyen Nguyen <[email protected]>
Signed-off-by: default avatarMatthieu Moy <[email protected]>
Signed-off-by: default avatarJunio C Hamano <[email protected]>
parent 43f9d9f3
......@@ -904,6 +904,36 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
log_tree_commit(&opt, commit);
}
/*
* The terms used for this bisect session are stored in BISECT_TERMS.
* We read them and store them to adapt the messages accordingly.
* Default is bad/good.
*/
void read_bisect_terms(const char **read_bad, const char **read_good)
{
struct strbuf str = STRBUF_INIT;
const char *filename = git_path("BISECT_TERMS");
FILE *fp = fopen(filename, "r");
if (!fp) {
if (errno == ENOENT) {
*read_bad = "bad";
*read_good = "good";
return;
} else {
die("could not read file '%s': %s", filename,
strerror(errno));
}
} else {
strbuf_getline(&str, fp, '\n');
*read_bad = strbuf_detach(&str, NULL);
strbuf_getline(&str, fp, '\n');
*read_good = strbuf_detach(&str, NULL);
}
strbuf_release(&str);
fclose(fp);
}
/*
* We use the convention that exiting with an exit code 10 means that
* the bisection process finished successfully.
......@@ -920,8 +950,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
const unsigned char *bisect_rev;
char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
term_bad = "bad";
term_good = "good";
read_bisect_terms(&term_bad, &term_good);
if (read_bisect_refs())
die("reading bisect refs failed");
......
......@@ -26,4 +26,6 @@ extern int bisect_next_all(const char *prefix, int no_checkout);
extern int estimate_bisect_steps(int all);
extern void read_bisect_terms(const char **bad, const char **good);
#endif
......@@ -77,6 +77,7 @@ bisect_start() {
orig_args=$(git rev-parse --sq-quote "[email protected]")
bad_seen=0
eval=''
must_write_terms=0
if test "z$(git rev-parse --is-bare-repository)" != zfalse
then
mode=--no-checkout
......@@ -101,6 +102,14 @@ bisect_start() {
die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
break
}
# The user ran "git bisect start <sha1>
# <sha1>", hence did not explicitly specify
# the terms, but we are already starting to
# set references named with the default terms,
# and won't be able to change afterwards.
must_write_terms=1
case $bad_seen in
0) state=$TERM_BAD ; bad_seen=1 ;;
*) state=$TERM_GOOD ;;
......@@ -172,6 +181,10 @@ bisect_start() {
} &&
git rev-parse --sq-quote "[email protected]" >"$GIT_DIR/BISECT_NAMES" &&
eval "$eval true" &&
if test $must_write_terms -eq 1
then
write_terms "$TERM_BAD" "$TERM_GOOD"
fi &&
echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
#
# Check if we can proceed to the next bisect state.
......@@ -232,6 +245,7 @@ bisect_skip() {
bisect_state() {
bisect_autostart
state=$1
check_and_set_terms $state
case "$#,$state" in
0,*)
die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
......@@ -291,15 +305,17 @@ bisect_next_check() {
: bisect without $TERM_GOOD...
;;
*)
bad_syn=$(bisect_voc bad)
good_syn=$(bisect_voc good)
if test -s "$GIT_DIR/BISECT_START"
then
gettextln "You need to give me at least one good and one bad revision.
(You can use \"git bisect bad\" and \"git bisect good\" for that.)" >&2
eval_gettextln "You need to give me at least one \$bad_syn and one \$good_syn revision.
(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
else
gettextln "You need to start by \"git bisect start\".
You then need to give me at least one good and one bad revision.
(You can use \"git bisect bad\" and \"git bisect good\" for that.)" >&2
eval_gettextln "You need to start by \"git bisect start\".
You then need to give me at least one \$good_syn and one \$bad_syn revision.
(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
fi
exit 1 ;;
esac
......@@ -402,6 +418,7 @@ bisect_clean_state() {
rm -f "$GIT_DIR/BISECT_LOG" &&
rm -f "$GIT_DIR/BISECT_NAMES" &&
rm -f "$GIT_DIR/BISECT_RUN" &&
rm -f "$GIT_DIR/BISECT_TERMS" &&
# Cleanup head-name if it got left by an old version of git-bisect
rm -f "$GIT_DIR/head-name" &&
git update-ref -d --no-deref BISECT_HEAD &&
......@@ -422,11 +439,13 @@ bisect_replay () {
rev="$command"
command="$bisect"
fi
get_terms
check_and_set_terms "$command"
case "$command" in
start)
cmd="bisect_start $rev"
eval "$cmd" ;;
$TERM_GOOD|$TERM_BAD|skip)
"$TERM_GOOD"|"$TERM_BAD"|skip)
bisect_write "$command" "$rev" ;;
*)
die "$(gettext "?? what are you talking about?")" ;;
......@@ -499,18 +518,62 @@ bisect_log () {
cat "$GIT_DIR/BISECT_LOG"
}
get_terms () {
if test -s "$GIT_DIR/BISECT_TERMS"
then
{
read TERM_BAD
read TERM_GOOD
} <"$GIT_DIR/BISECT_TERMS"
fi
}
write_terms () {
TERM_BAD=$1
TERM_GOOD=$2
printf '%s\n%s\n' "$TERM_BAD" "$TERM_GOOD" >"$GIT_DIR/BISECT_TERMS"
}
check_and_set_terms () {
cmd="$1"
case "$cmd" in
skip|start|terms) ;;
*)
if test -s "$GIT_DIR/BISECT_TERMS" && test "$cmd" != "$TERM_BAD" && test "$cmd" != "$TERM_GOOD"
then
die "$(eval_gettext "Invalid command: you're currently in a \$TERM_BAD/\$TERM_GOOD bisect.")"
fi
case "$cmd" in
bad|good)
if ! test -s "$GIT_DIR/BISECT_TERMS"
then
write_terms bad good
fi
;;
esac ;;
esac
}
bisect_voc () {
case "$1" in
bad) echo "bad" ;;
good) echo "good" ;;
esac
}
case "$#" in
0)
usage ;;
*)
cmd="$1"
get_terms
shift
case "$cmd" in
help)
git bisect -h ;;
start)
bisect_start "[email protected]" ;;
bad|good)
bad|good|"$TERM_BAD"|"$TERM_GOOD")
bisect_state "$cmd" "[email protected]" ;;
skip)
bisect_skip "[email protected]" ;;
......
......@@ -18,9 +18,13 @@
#include "commit-slab.h"
#include "dir.h"
#include "cache-tree.h"
#include "bisect.h"
volatile show_early_output_fn_t show_early_output;
static const char *term_bad;
static const char *term_good;
char *path_name(const struct name_path *path, const char *name)
{
const struct name_path *p;
......@@ -2076,14 +2080,23 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
ctx->argc -= n;
}
static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) {
struct strbuf bisect_refs = STRBUF_INIT;
int status;
strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
strbuf_release(&bisect_refs);
return status;
}
static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
{
return for_each_ref_in_submodule(submodule, "refs/bisect/bad", fn, cb_data);
return for_each_bisect_ref(submodule, fn, cb_data, term_bad);
}
static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
{
return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data);
return for_each_bisect_ref(submodule, fn, cb_data, term_good);
}
static int handle_revision_pseudo_opt(const char *submodule,
......@@ -2112,6 +2125,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
clear_ref_exclusion(&revs->ref_excludes);
} else if (!strcmp(arg, "--bisect")) {
read_bisect_terms(&term_bad, &term_good);
handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
revs->bisect = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment