Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
2 people authored and Junio C Hamano committed Aug 3, 2015
1 parent 43f9d9f commit cb46d63
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 12 deletions.
33 changes: 31 additions & 2 deletions bisect.c
Expand Up @@ -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.
Expand All @@ -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");

Expand Down
2 changes: 2 additions & 0 deletions bisect.h
Expand Up @@ -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
79 changes: 71 additions & 8 deletions git-bisect.sh
Expand Up @@ -77,6 +77,7 @@ bisect_start() {
orig_args=$(git rev-parse --sq-quote "$@")
bad_seen=0
eval=''
must_write_terms=0
if test "z$(git rev-parse --is-bare-repository)" != zfalse
then
mode=--no-checkout
Expand All @@ -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 ;;
Expand Down Expand Up @@ -172,6 +181,10 @@ bisect_start() {
} &&
git rev-parse --sq-quote "$@" >"$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.
Expand Down Expand Up @@ -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.")" ;;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 &&
Expand All @@ -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?")" ;;
Expand Down Expand Up @@ -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 "$@" ;;
bad|good)
bad|good|"$TERM_BAD"|"$TERM_GOOD")
bisect_state "$cmd" "$@" ;;
skip)
bisect_skip "$@" ;;
Expand Down
18 changes: 16 additions & 2 deletions revision.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit cb46d63

Please sign in to comment.