git-rev-list: add --bisect-vars option.
authorJunio C Hamano <junkio@cox.net>
Thu, 22 Mar 2007 05:15:54 +0000 (22:15 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 22 Mar 2007 08:32:31 +0000 (01:32 -0700)
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 <junkio@cox.net>
Documentation/git-rev-list.txt
builtin-rev-list.c

index 4f145eaba47175e48dd592ffe5018be5cb4cb375..3fa45b81cc6de7b5104d343538c9ad040c208ce1 100644 (file)
@@ -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
index c2db5a5b037babf9020353d9b11dc348915b6c1b..723e4d419c64d3782b3612a1d1a7975e1f006146 100644 (file)
@@ -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);