mirror of
https://github.com/git/git.git
synced 2024-11-18 20:23:51 +01:00
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:
parent
d937d4aca1
commit
0871984d30
4
bisect.c
4
bisect.c
@ -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);
|
||||
|
2
bisect.h
2
bisect.h
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
127
git-bisect.sh
127
git-bisect.sh
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user