зеркало из https://github.com/microsoft/git.git
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:
Родитель
d937d4aca1
Коммит
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.
|
* the bisection process finished successfully.
|
||||||
* In this case the calling shell script should exit 0.
|
* 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 rev_info revs;
|
||||||
struct commit_list *tried;
|
struct commit_list *tried;
|
||||||
|
@ -841,6 +841,8 @@ int bisect_next_exit(const char *prefix)
|
||||||
if (read_bisect_refs())
|
if (read_bisect_refs())
|
||||||
die("reading bisect refs failed");
|
die("reading bisect refs failed");
|
||||||
|
|
||||||
|
check_good_are_ancestors_of_bad(prefix);
|
||||||
|
|
||||||
bisect_rev_setup(&revs, prefix);
|
bisect_rev_setup(&revs, prefix);
|
||||||
|
|
||||||
bisect_common(&revs, &reaches, &all);
|
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 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);
|
extern int estimate_bisect_steps(int all);
|
||||||
|
|
||||||
|
|
|
@ -4,24 +4,24 @@
|
||||||
#include "bisect.h"
|
#include "bisect.h"
|
||||||
|
|
||||||
static const char * const git_bisect_helper_usage[] = {
|
static const char * const git_bisect_helper_usage[] = {
|
||||||
"git bisect--helper --next-exit",
|
"git bisect--helper --next-all",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int next_exit = 0;
|
int next_all = 0;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOLEAN(0, "next-exit", &next_exit,
|
OPT_BOOLEAN(0, "next-all", &next_all,
|
||||||
"output bisect result and exit instuctions"),
|
"perform 'git bisect next'"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
|
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);
|
usage_with_options(git_bisect_helper_usage, options);
|
||||||
|
|
||||||
/* next-exit */
|
/* next-all */
|
||||||
return bisect_next_exit(prefix);
|
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")
|
test "$1" = $(cat "$GIT_DIR/BISECT_EXPECTED_REV")
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_expected_rev() {
|
|
||||||
echo "$1" > "$GIT_DIR/BISECT_EXPECTED_REV"
|
|
||||||
}
|
|
||||||
|
|
||||||
check_expected_revs() {
|
check_expected_revs() {
|
||||||
for _rev in "$@"; do
|
for _rev in "$@"; do
|
||||||
if ! is_expected_rev "$_rev"; then
|
if ! is_expected_rev "$_rev"; then
|
||||||
|
@ -269,132 +265,13 @@ bisect_auto_next() {
|
||||||
bisect_next_check && bisect_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() {
|
bisect_next() {
|
||||||
case "$#" in 0) ;; *) usage ;; esac
|
case "$#" in 0) ;; *) usage ;; esac
|
||||||
bisect_autostart
|
bisect_autostart
|
||||||
bisect_next_check good
|
bisect_next_check good
|
||||||
|
|
||||||
# Get bad, good and skipped revs
|
# Perform all bisection computation, display and checkout
|
||||||
bad=$(git rev-parse --verify refs/bisect/bad) &&
|
git bisect--helper --next-all
|
||||||
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
|
|
||||||
res=$?
|
res=$?
|
||||||
|
|
||||||
# Check if we should exit because bisection is finished
|
# Check if we should exit because bisection is finished
|
||||||
|
|
Загрузка…
Ссылка в новой задаче