bisect: limit the searchspace by pathspecs

It was surprisingly easy to do.

	git bisect start <pathspec>

followed by all the normal "git bisect good/bad" stuff.

Almost totally untested, and I guarantee that if your pathnames have
spaces in them (or your GIT_DIR has spaces in it) this won't work. I don't
know how to fix that, my shell programming isn't good enough.

This involves small changes to make "git-rev-list --bisect" work in the
presense of a pathspec limiter, and then truly trivial (and that's the
broken part) changes to make "git bisect" save away and use the pathspec.

I tried one bisection, and a "git bisect visualize", and it all looked
correct. But hey, don't be surprised if it has problems.

		Linus

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Linus Torvalds 2005-11-27 11:32:03 -08:00 committed by Junio C Hamano
parent 9ef2b3cbf6
commit b3cfd939c3
2 changed files with 17 additions and 11 deletions

View File

@ -33,7 +33,6 @@ bisect_autostart() {
} }
bisect_start() { bisect_start() {
case "$#" in 0) ;; *) usage ;; esac
# #
# Verify HEAD. If we were bisecting before this, reset to the # Verify HEAD. If we were bisecting before this, reset to the
# top-of-line master first! # top-of-line master first!
@ -57,7 +56,8 @@ bisect_start() {
rm -f "$GIT_DIR/refs/heads/bisect" rm -f "$GIT_DIR/refs/heads/bisect"
rm -rf "$GIT_DIR/refs/bisect/" rm -rf "$GIT_DIR/refs/bisect/"
mkdir "$GIT_DIR/refs/bisect" mkdir "$GIT_DIR/refs/bisect"
echo "git-bisect start" >"$GIT_DIR/BISECT_LOG" echo "git-bisect start $@" >"$GIT_DIR/BISECT_LOG"
echo "$@" > "$GIT_DIR/BISECT_NAMES"
} }
bisect_bad() { bisect_bad() {
@ -121,7 +121,7 @@ bisect_next() {
bad=$(git-rev-parse --verify refs/bisect/bad) && bad=$(git-rev-parse --verify refs/bisect/bad) &&
good=$(git-rev-parse --sq --revs-only --not \ good=$(git-rev-parse --sq --revs-only --not \
$(cd "$GIT_DIR" && ls refs/bisect/good-*)) && $(cd "$GIT_DIR" && ls refs/bisect/good-*)) &&
rev=$(eval "git-rev-list --bisect $good $bad") || exit rev=$(eval "git-rev-list --bisect $good $bad -- $(cat $GIT_DIR/BISECT_NAMES)") || exit
if [ -z "$rev" ]; then if [ -z "$rev" ]; then
echo "$bad was both good and bad" echo "$bad was both good and bad"
exit 1 exit 1
@ -131,7 +131,7 @@ bisect_next() {
git-diff-tree --pretty $rev git-diff-tree --pretty $rev
exit 0 exit 0
fi fi
nr=$(eval "git-rev-list $rev $good" | wc -l) || exit nr=$(eval "git-rev-list $rev $good -- $(cat $GIT_DIR/BISECT_NAMES)" | wc -l) || exit
echo "Bisecting: $nr revisions left to test after this" echo "Bisecting: $nr revisions left to test after this"
echo "$rev" > "$GIT_DIR/refs/heads/new-bisect" echo "$rev" > "$GIT_DIR/refs/heads/new-bisect"
git checkout new-bisect || exit git checkout new-bisect || exit
@ -142,7 +142,7 @@ bisect_next() {
bisect_visualize() { bisect_visualize() {
bisect_next_check fail bisect_next_check fail
gitk bisect/bad --not `cd "$GIT_DIR/refs" && echo bisect/good-*` gitk bisect/bad --not `cd "$GIT_DIR/refs" && echo bisect/good-*` -- $(cat $GIT_DIR/BISECT_NAMES)
} }
bisect_reset() { bisect_reset() {

View File

@ -350,7 +350,8 @@ static int count_distance(struct commit_list *entry)
if (commit->object.flags & (UNINTERESTING | COUNTED)) if (commit->object.flags & (UNINTERESTING | COUNTED))
break; break;
nr++; if (!paths || (commit->object.flags & TREECHANGE))
nr++;
commit->object.flags |= COUNTED; commit->object.flags |= COUNTED;
p = commit->parents; p = commit->parents;
entry = p; entry = p;
@ -362,6 +363,7 @@ static int count_distance(struct commit_list *entry)
} }
} }
} }
return nr; return nr;
} }
@ -382,15 +384,20 @@ static struct commit_list *find_bisection(struct commit_list *list)
nr = 0; nr = 0;
p = list; p = list;
while (p) { while (p) {
nr++; if (!paths || (p->item->object.flags & TREECHANGE))
nr++;
p = p->next; p = p->next;
} }
closest = 0; closest = 0;
best = list; best = list;
p = list; for (p = list; p; p = p->next) {
while (p) { int distance;
int distance = count_distance(p);
if (paths && !(p->item->object.flags & TREECHANGE))
continue;
distance = count_distance(p);
clear_distance(list); clear_distance(list);
if (nr - distance < distance) if (nr - distance < distance)
distance = nr - distance; distance = nr - distance;
@ -398,7 +405,6 @@ static struct commit_list *find_bisection(struct commit_list *list)
best = p; best = p;
closest = distance; closest = distance;
} }
p = p->next;
} }
if (best) if (best)
best->next = NULL; best->next = NULL;