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 <stuberl@ensimag.grenoble-inp.fr> Tweaked-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Antoine Delaite <antoine.delaite@ensimag.grenoble-inp.fr> Signed-off-by: Louis Stuber <stuberl@ensimag.grenoble-inp.fr> Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr> Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr> Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr> Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr> Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
43f9d9f3a6
commit
cb46d630ba
33
bisect.c
33
bisect.c
@ -904,6 +904,36 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
|
|||||||
log_tree_commit(&opt, 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
|
* We use the convention that exiting with an exit code 10 means that
|
||||||
* the bisection process finished successfully.
|
* the bisection process finished successfully.
|
||||||
@ -920,8 +950,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
|
|||||||
const unsigned char *bisect_rev;
|
const unsigned char *bisect_rev;
|
||||||
char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
|
char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
|
||||||
|
|
||||||
term_bad = "bad";
|
read_bisect_terms(&term_bad, &term_good);
|
||||||
term_good = "good";
|
|
||||||
if (read_bisect_refs())
|
if (read_bisect_refs())
|
||||||
die("reading bisect refs failed");
|
die("reading bisect refs failed");
|
||||||
|
|
||||||
|
2
bisect.h
2
bisect.h
@ -26,4 +26,6 @@ extern int bisect_next_all(const char *prefix, int no_checkout);
|
|||||||
|
|
||||||
extern int estimate_bisect_steps(int all);
|
extern int estimate_bisect_steps(int all);
|
||||||
|
|
||||||
|
extern void read_bisect_terms(const char **bad, const char **good);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,6 +77,7 @@ bisect_start() {
|
|||||||
orig_args=$(git rev-parse --sq-quote "$@")
|
orig_args=$(git rev-parse --sq-quote "$@")
|
||||||
bad_seen=0
|
bad_seen=0
|
||||||
eval=''
|
eval=''
|
||||||
|
must_write_terms=0
|
||||||
if test "z$(git rev-parse --is-bare-repository)" != zfalse
|
if test "z$(git rev-parse --is-bare-repository)" != zfalse
|
||||||
then
|
then
|
||||||
mode=--no-checkout
|
mode=--no-checkout
|
||||||
@ -101,6 +102,14 @@ bisect_start() {
|
|||||||
die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
|
die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
|
||||||
break
|
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
|
case $bad_seen in
|
||||||
0) state=$TERM_BAD ; bad_seen=1 ;;
|
0) state=$TERM_BAD ; bad_seen=1 ;;
|
||||||
*) state=$TERM_GOOD ;;
|
*) state=$TERM_GOOD ;;
|
||||||
@ -172,6 +181,10 @@ bisect_start() {
|
|||||||
} &&
|
} &&
|
||||||
git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
|
git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
|
||||||
eval "$eval true" &&
|
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
|
echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
|
||||||
#
|
#
|
||||||
# Check if we can proceed to the next bisect state.
|
# Check if we can proceed to the next bisect state.
|
||||||
@ -232,6 +245,7 @@ bisect_skip() {
|
|||||||
bisect_state() {
|
bisect_state() {
|
||||||
bisect_autostart
|
bisect_autostart
|
||||||
state=$1
|
state=$1
|
||||||
|
check_and_set_terms $state
|
||||||
case "$#,$state" in
|
case "$#,$state" in
|
||||||
0,*)
|
0,*)
|
||||||
die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
|
die "$(gettext "Please call 'bisect_state' with at least one argument.")" ;;
|
||||||
@ -291,15 +305,17 @@ bisect_next_check() {
|
|||||||
: bisect without $TERM_GOOD...
|
: bisect without $TERM_GOOD...
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
bad_syn=$(bisect_voc bad)
|
||||||
|
good_syn=$(bisect_voc good)
|
||||||
if test -s "$GIT_DIR/BISECT_START"
|
if test -s "$GIT_DIR/BISECT_START"
|
||||||
then
|
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
|
else
|
||||||
gettextln "You need to start by \"git bisect start\".
|
eval_gettextln "You need to start by \"git bisect start\".
|
||||||
You then need to give me at least one good and one bad revision.
|
You then need to give me at least one \$good_syn and one \$bad_syn revision.
|
||||||
(You can use \"git bisect bad\" and \"git bisect good\" for that.)" >&2
|
(You can use \"git bisect \$bad_syn\" and \"git bisect \$good_syn\" for that.)" >&2
|
||||||
fi
|
fi
|
||||||
exit 1 ;;
|
exit 1 ;;
|
||||||
esac
|
esac
|
||||||
@ -402,6 +418,7 @@ bisect_clean_state() {
|
|||||||
rm -f "$GIT_DIR/BISECT_LOG" &&
|
rm -f "$GIT_DIR/BISECT_LOG" &&
|
||||||
rm -f "$GIT_DIR/BISECT_NAMES" &&
|
rm -f "$GIT_DIR/BISECT_NAMES" &&
|
||||||
rm -f "$GIT_DIR/BISECT_RUN" &&
|
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
|
# Cleanup head-name if it got left by an old version of git-bisect
|
||||||
rm -f "$GIT_DIR/head-name" &&
|
rm -f "$GIT_DIR/head-name" &&
|
||||||
git update-ref -d --no-deref BISECT_HEAD &&
|
git update-ref -d --no-deref BISECT_HEAD &&
|
||||||
@ -422,11 +439,13 @@ bisect_replay () {
|
|||||||
rev="$command"
|
rev="$command"
|
||||||
command="$bisect"
|
command="$bisect"
|
||||||
fi
|
fi
|
||||||
|
get_terms
|
||||||
|
check_and_set_terms "$command"
|
||||||
case "$command" in
|
case "$command" in
|
||||||
start)
|
start)
|
||||||
cmd="bisect_start $rev"
|
cmd="bisect_start $rev"
|
||||||
eval "$cmd" ;;
|
eval "$cmd" ;;
|
||||||
$TERM_GOOD|$TERM_BAD|skip)
|
"$TERM_GOOD"|"$TERM_BAD"|skip)
|
||||||
bisect_write "$command" "$rev" ;;
|
bisect_write "$command" "$rev" ;;
|
||||||
*)
|
*)
|
||||||
die "$(gettext "?? what are you talking about?")" ;;
|
die "$(gettext "?? what are you talking about?")" ;;
|
||||||
@ -499,18 +518,62 @@ bisect_log () {
|
|||||||
cat "$GIT_DIR/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
|
case "$#" in
|
||||||
0)
|
0)
|
||||||
usage ;;
|
usage ;;
|
||||||
*)
|
*)
|
||||||
cmd="$1"
|
cmd="$1"
|
||||||
|
get_terms
|
||||||
shift
|
shift
|
||||||
case "$cmd" in
|
case "$cmd" in
|
||||||
help)
|
help)
|
||||||
git bisect -h ;;
|
git bisect -h ;;
|
||||||
start)
|
start)
|
||||||
bisect_start "$@" ;;
|
bisect_start "$@" ;;
|
||||||
bad|good)
|
bad|good|"$TERM_BAD"|"$TERM_GOOD")
|
||||||
bisect_state "$cmd" "$@" ;;
|
bisect_state "$cmd" "$@" ;;
|
||||||
skip)
|
skip)
|
||||||
bisect_skip "$@" ;;
|
bisect_skip "$@" ;;
|
||||||
|
18
revision.c
18
revision.c
@ -18,9 +18,13 @@
|
|||||||
#include "commit-slab.h"
|
#include "commit-slab.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "cache-tree.h"
|
#include "cache-tree.h"
|
||||||
|
#include "bisect.h"
|
||||||
|
|
||||||
volatile show_early_output_fn_t show_early_output;
|
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)
|
char *path_name(const struct name_path *path, const char *name)
|
||||||
{
|
{
|
||||||
const struct name_path *p;
|
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;
|
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)
|
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)
|
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,
|
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);
|
handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
|
||||||
clear_ref_exclusion(&revs->ref_excludes);
|
clear_ref_exclusion(&revs->ref_excludes);
|
||||||
} else if (!strcmp(arg, "--bisect")) {
|
} 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, for_each_bad_bisect_ref);
|
||||||
handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
|
handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
|
||||||
revs->bisect = 1;
|
revs->bisect = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user