bisect: make "git bisect" use new "--next-all" bisect-helper function

This patch replace the "--next-exit" option of "git bisect--helper"
with a "--next-all" option that does merge base checking using
the "check_good_are_ancestors_of_bad" function implemented in
"bisect.c" in a former patch.

The new "--next-all" option is then used in "git-bisect.sh" instead
of the "--next-exit" option, and all the shell functions in
"git-bisect.sh" that are now unused are removed.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Christian Couder 2009-05-09 17:55:47 +02:00 committed by Junio C Hamano
parent d937d4aca1
commit 0871984d30
4 changed files with 13 additions and 134 deletions

View file

@ -830,7 +830,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
* the bisection process finished successfully.
* In this case the calling shell script should exit 0.
*/
int bisect_next_exit(const char *prefix)
int bisect_next_all(const char *prefix)
{
struct rev_info revs;
struct commit_list *tried;
@ -841,6 +841,8 @@ int bisect_next_exit(const char *prefix)
if (read_bisect_refs())
die("reading bisect refs failed");
check_good_are_ancestors_of_bad(prefix);
bisect_rev_setup(&revs, prefix);
bisect_common(&revs, &reaches, &all);

View file

@ -27,7 +27,7 @@ struct rev_list_info {
extern int show_bisect_vars(struct rev_list_info *info, int reaches, int all);
extern int bisect_next_exit(const char *prefix);
extern int bisect_next_all(const char *prefix);
extern int estimate_bisect_steps(int all);

View file

@ -4,24 +4,24 @@
#include "bisect.h"
static const char * const git_bisect_helper_usage[] = {
"git bisect--helper --next-exit",
"git bisect--helper --next-all",
NULL
};
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
{
int next_exit = 0;
int next_all = 0;
struct option options[] = {
OPT_BOOLEAN(0, "next-exit", &next_exit,
"output bisect result and exit instuctions"),
OPT_BOOLEAN(0, "next-all", &next_all,
"perform 'git bisect next'"),
OPT_END()
};
argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
if (!next_exit)
if (!next_all)
usage_with_options(git_bisect_helper_usage, options);
/* next-exit */
return bisect_next_exit(prefix);
/* next-all */
return bisect_next_all(prefix);
}

View file

@ -167,10 +167,6 @@ is_expected_rev() {
test "$1" = $(cat "$GIT_DIR/BISECT_EXPECTED_REV")
}
mark_expected_rev() {
echo "$1" > "$GIT_DIR/BISECT_EXPECTED_REV"
}
check_expected_revs() {
for _rev in "$@"; do
if ! is_expected_rev "$_rev"; then
@ -269,132 +265,13 @@ bisect_auto_next() {
bisect_next_check && bisect_next || :
}
bisect_checkout() {
_rev="$1"
_msg="$2"
echo "Bisecting: $_msg"
mark_expected_rev "$_rev"
git checkout -q "$_rev" -- || exit
git show-branch "$_rev"
}
is_among() {
_rev="$1"
_list="$2"
case "$_list" in *$_rev*) return 0 ;; esac
return 1
}
handle_bad_merge_base() {
_badmb="$1"
_good="$2"
if is_expected_rev "$_badmb"; then
cat >&2 <<EOF
The merge base $_badmb is bad.
This means the bug has been fixed between $_badmb and [$_good].
EOF
exit 3
else
cat >&2 <<EOF
Some good revs are not ancestor of the bad rev.
git bisect cannot work properly in this case.
Maybe you mistake good and bad revs?
EOF
exit 1
fi
}
handle_skipped_merge_base() {
_mb="$1"
_bad="$2"
_good="$3"
cat >&2 <<EOF
Warning: the merge base between $_bad and [$_good] must be skipped.
So we cannot be sure the first bad commit is between $_mb and $_bad.
We continue anyway.
EOF
}
#
# "check_merge_bases" checks that merge bases are not "bad".
#
# - If one is "good", that's good, we have nothing to do.
# - If one is "bad", it means the user assumed something wrong
# and we must exit.
# - If one is "skipped", we can't know but we should warn.
# - If we don't know, we should check it out and ask the user to test.
#
# In the last case we will return 1, and otherwise 0.
#
check_merge_bases() {
_bad="$1"
_good="$2"
_skip="$3"
for _mb in $(git merge-base --all $_bad $_good)
do
if is_among "$_mb" "$_good"; then
continue
elif test "$_mb" = "$_bad"; then
handle_bad_merge_base "$_bad" "$_good"
elif is_among "$_mb" "$_skip"; then
handle_skipped_merge_base "$_mb" "$_bad" "$_good"
else
bisect_checkout "$_mb" "a merge base must be tested"
return 1
fi
done
return 0
}
#
# "check_good_are_ancestors_of_bad" checks that all "good" revs are
# ancestor of the "bad" rev.
#
# If that's not the case, we need to check the merge bases.
# If a merge base must be tested by the user we return 1 and
# otherwise 0.
#
check_good_are_ancestors_of_bad() {
test -f "$GIT_DIR/BISECT_ANCESTORS_OK" &&
return
_bad="$1"
_good=$(echo $2 | sed -e 's/\^//g')
_skip="$3"
# Bisecting with no good rev is ok
test -z "$_good" && return
_side=$(git rev-list $_good ^$_bad)
if test -n "$_side"; then
# Return if a checkout was done
check_merge_bases "$_bad" "$_good" "$_skip" || return
fi
: > "$GIT_DIR/BISECT_ANCESTORS_OK"
return 0
}
bisect_next() {
case "$#" in 0) ;; *) usage ;; esac
bisect_autostart
bisect_next_check good
# Get bad, good and skipped revs
bad=$(git rev-parse --verify refs/bisect/bad) &&
good=$(git for-each-ref --format='^%(objectname)' \
"refs/bisect/good-*" | tr '\012' ' ') &&
skip=$(git for-each-ref --format='%(objectname)' \
"refs/bisect/skip-*" | tr '\012' ' ') || exit
# Maybe some merge bases must be tested first
check_good_are_ancestors_of_bad "$bad" "$good" "$skip"
# Return now if a checkout has already been done
test "$?" -eq "1" && return
# Perform bisection computation, display and checkout
git bisect--helper --next-exit
# Perform all bisection computation, display and checkout
git bisect--helper --next-all
res=$?
# Check if we should exit because bisection is finished