git-rev-list: add --bisect-vars option.
[gitweb.git] / builtin-rev-list.c
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);