From 457f08a030c8542b90172d24de4b8d11c4dae80f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 21 Mar 2007 22:15:54 -0700 Subject: [PATCH] git-rev-list: add --bisect-vars option. This adds --bisect-vars option to rev-list. The output is suitable for `eval` in shell and defines five variables: - bisect_rev is the next revision to test. - bisect_nr is the expected number of commits to test after bisect_rev is tested. - bisect_good is the expected number of commits to test if bisect_rev turns out to be good. - bisect_bad is the expected number of commits to test if bisect_rev turns out to be bad. - bisect_all is the number of commits we are bisecting right now. The documentation text was partly stolen from Johannes Schindelin's patch. Signed-off-by: Junio C Hamano --- Documentation/git-rev-list.txt | 13 ++++++++ builtin-rev-list.c | 54 ++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index 4f145eaba4..3fa45b81cc 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -26,6 +26,7 @@ SYNOPSIS [ [\--objects | \--objects-edge] [ \--unpacked ] ] [ \--pretty | \--header ] [ \--bisect ] + [ \--bisect-vars ] [ \--merge ] [ \--reverse ] [ \--walk-reflogs ] @@ -249,6 +250,18 @@ introduces a regression is thus reduced to a binary search: repeatedly generate and test new 'midpoint's until the commit chain is of length one. +--bisect-vars:: + +This calculates the same as `--bisect`, but outputs text ready +to be eval'ed by the shell. These lines will assign the name of +the midpoint revision to the variable `bisect_rev`, and the +expected number of commits to be tested after `bisect_rev` is +tested to `bisect_nr`, the expected number of commits to be +tested if `bisect_rev` turns out to be good to `bisect_good`, +the expected number of commits to be tested if `bisect_rev` +turns out to be bad to `bisect_bad`, and the number of commits +we are bisecting right now to `bisect_all`. + -- Commit Ordering diff --git a/builtin-rev-list.c b/builtin-rev-list.c index c2db5a5b03..723e4d419c 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -36,7 +36,8 @@ static const char rev_list_usage[] = " --abbrev=nr | --no-abbrev\n" " --abbrev-commit\n" " special purpose:\n" -" --bisect" +" --bisect\n" +" --bisect-vars" ; static struct rev_info revs; @@ -168,7 +169,8 @@ static void clear_distance(struct commit_list *list) } } -static struct commit_list *find_bisection(struct commit_list *list) +static struct commit_list *find_bisection(struct commit_list *list, + int *reaches, int *all) { int nr, closest; struct commit_list *p, *best; @@ -180,21 +182,23 @@ static struct commit_list *find_bisection(struct commit_list *list) nr++; p = p->next; } + *all = nr; closest = 0; best = list; for (p = list; p; p = p->next) { - int distance; + int distance, reach; if (revs.prune_fn && !(p->item->object.flags & TREECHANGE)) continue; - distance = count_distance(p); + distance = reach = count_distance(p); clear_distance(list); if (nr - distance < distance) distance = nr - distance; if (distance > closest) { best = p; + *reaches = reach; closest = distance; } } @@ -225,6 +229,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) struct commit_list *list; int i; int read_from_stdin = 0; + int bisect_show_vars = 0; git_config(git_default_config); init_revisions(&revs, prefix); @@ -247,6 +252,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) bisect_list = 1; continue; } + if (!strcmp(arg, "--bisect-vars")) { + bisect_list = 1; + bisect_show_vars = 1; + continue; + } if (!strcmp(arg, "--stdin")) { if (read_from_stdin++) die("--stdin given twice?"); @@ -285,8 +295,40 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (revs.tree_objects) mark_edges_uninteresting(revs.commits, &revs, show_edge); - if (bisect_list) - revs.commits = find_bisection(revs.commits); + if (bisect_list) { + int reaches = reaches, all = all; + + revs.commits = find_bisection(revs.commits, + &reaches, &all); + if (bisect_show_vars) { + int cnt; + if (!revs.commits) + return 1; + /* + * revs.commits can reach "reaches" commits among + * "all" commits. If it is good, then there are + * (all-reaches) commits left to be bisected. + * On the other hand, if it is bad, then the set + * to bisect is "reaches". + * A bisect set of size N has (N-1) commits further + * to test, as we already know one bad one. + */ + cnt = all-reaches; + if (cnt < reaches) + cnt = reaches; + printf("bisect_rev=%s\n" + "bisect_nr=%d\n" + "bisect_good=%d\n" + "bisect_bad=%d\n" + "bisect_all=%d\n", + sha1_to_hex(revs.commits->item->object.sha1), + cnt - 1, + all - reaches - 1, + reaches - 1, + all); + return 0; + } + } traverse_commit_list(&revs, show_commit, show_object);