8e34186f9599ea265e0d779fb0b9bbdae85ec7fa
   1#include "cache.h"
   2#include "commit.h"
   3#include "diff.h"
   4#include "revision.h"
   5#include "refs.h"
   6#include "list-objects.h"
   7#include "quote.h"
   8#include "sha1-lookup.h"
   9#include "run-command.h"
  10#include "bisect.h"
  11
  12struct sha1_array {
  13        unsigned char (*sha1)[20];
  14        int sha1_nr;
  15        int sha1_alloc;
  16};
  17
  18static struct sha1_array good_revs;
  19static struct sha1_array skipped_revs;
  20
  21static const unsigned char *current_bad_sha1;
  22
  23struct argv_array {
  24        const char **argv;
  25        int argv_nr;
  26        int argv_alloc;
  27};
  28
  29struct argv_array rev_argv;
  30
  31static const char *argv_diff_tree[] = {"diff-tree", "--pretty", NULL, NULL};
  32static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
  33static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
  34
  35/* bits #0-15 in revision.h */
  36
  37#define COUNTED         (1u<<16)
  38
  39/*
  40 * This is a truly stupid algorithm, but it's only
  41 * used for bisection, and we just don't care enough.
  42 *
  43 * We care just barely enough to avoid recursing for
  44 * non-merge entries.
  45 */
  46static int count_distance(struct commit_list *entry)
  47{
  48        int nr = 0;
  49
  50        while (entry) {
  51                struct commit *commit = entry->item;
  52                struct commit_list *p;
  53
  54                if (commit->object.flags & (UNINTERESTING | COUNTED))
  55                        break;
  56                if (!(commit->object.flags & TREESAME))
  57                        nr++;
  58                commit->object.flags |= COUNTED;
  59                p = commit->parents;
  60                entry = p;
  61                if (p) {
  62                        p = p->next;
  63                        while (p) {
  64                                nr += count_distance(p);
  65                                p = p->next;
  66                        }
  67                }
  68        }
  69
  70        return nr;
  71}
  72
  73static void clear_distance(struct commit_list *list)
  74{
  75        while (list) {
  76                struct commit *commit = list->item;
  77                commit->object.flags &= ~COUNTED;
  78                list = list->next;
  79        }
  80}
  81
  82#define DEBUG_BISECT 0
  83
  84static inline int weight(struct commit_list *elem)
  85{
  86        return *((int*)(elem->item->util));
  87}
  88
  89static inline void weight_set(struct commit_list *elem, int weight)
  90{
  91        *((int*)(elem->item->util)) = weight;
  92}
  93
  94static int count_interesting_parents(struct commit *commit)
  95{
  96        struct commit_list *p;
  97        int count;
  98
  99        for (count = 0, p = commit->parents; p; p = p->next) {
 100                if (p->item->object.flags & UNINTERESTING)
 101                        continue;
 102                count++;
 103        }
 104        return count;
 105}
 106
 107static inline int halfway(struct commit_list *p, int nr)
 108{
 109        /*
 110         * Don't short-cut something we are not going to return!
 111         */
 112        if (p->item->object.flags & TREESAME)
 113                return 0;
 114        if (DEBUG_BISECT)
 115                return 0;
 116        /*
 117         * 2 and 3 are halfway of 5.
 118         * 3 is halfway of 6 but 2 and 4 are not.
 119         */
 120        switch (2 * weight(p) - nr) {
 121        case -1: case 0: case 1:
 122                return 1;
 123        default:
 124                return 0;
 125        }
 126}
 127
 128#if !DEBUG_BISECT
 129#define show_list(a,b,c,d) do { ; } while (0)
 130#else
 131static void show_list(const char *debug, int counted, int nr,
 132                      struct commit_list *list)
 133{
 134        struct commit_list *p;
 135
 136        fprintf(stderr, "%s (%d/%d)\n", debug, counted, nr);
 137
 138        for (p = list; p; p = p->next) {
 139                struct commit_list *pp;
 140                struct commit *commit = p->item;
 141                unsigned flags = commit->object.flags;
 142                enum object_type type;
 143                unsigned long size;
 144                char *buf = read_sha1_file(commit->object.sha1, &type, &size);
 145                char *ep, *sp;
 146
 147                fprintf(stderr, "%c%c%c ",
 148                        (flags & TREESAME) ? ' ' : 'T',
 149                        (flags & UNINTERESTING) ? 'U' : ' ',
 150                        (flags & COUNTED) ? 'C' : ' ');
 151                if (commit->util)
 152                        fprintf(stderr, "%3d", weight(p));
 153                else
 154                        fprintf(stderr, "---");
 155                fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
 156                for (pp = commit->parents; pp; pp = pp->next)
 157                        fprintf(stderr, " %.*s", 8,
 158                                sha1_to_hex(pp->item->object.sha1));
 159
 160                sp = strstr(buf, "\n\n");
 161                if (sp) {
 162                        sp += 2;
 163                        for (ep = sp; *ep && *ep != '\n'; ep++)
 164                                ;
 165                        fprintf(stderr, " %.*s", (int)(ep - sp), sp);
 166                }
 167                fprintf(stderr, "\n");
 168        }
 169}
 170#endif /* DEBUG_BISECT */
 171
 172static struct commit_list *best_bisection(struct commit_list *list, int nr)
 173{
 174        struct commit_list *p, *best;
 175        int best_distance = -1;
 176
 177        best = list;
 178        for (p = list; p; p = p->next) {
 179                int distance;
 180                unsigned flags = p->item->object.flags;
 181
 182                if (flags & TREESAME)
 183                        continue;
 184                distance = weight(p);
 185                if (nr - distance < distance)
 186                        distance = nr - distance;
 187                if (distance > best_distance) {
 188                        best = p;
 189                        best_distance = distance;
 190                }
 191        }
 192
 193        return best;
 194}
 195
 196struct commit_dist {
 197        struct commit *commit;
 198        int distance;
 199};
 200
 201static int compare_commit_dist(const void *a_, const void *b_)
 202{
 203        struct commit_dist *a, *b;
 204
 205        a = (struct commit_dist *)a_;
 206        b = (struct commit_dist *)b_;
 207        if (a->distance != b->distance)
 208                return b->distance - a->distance; /* desc sort */
 209        return hashcmp(a->commit->object.sha1, b->commit->object.sha1);
 210}
 211
 212static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
 213{
 214        struct commit_list *p;
 215        struct commit_dist *array = xcalloc(nr, sizeof(*array));
 216        int cnt, i;
 217
 218        for (p = list, cnt = 0; p; p = p->next) {
 219                int distance;
 220                unsigned flags = p->item->object.flags;
 221
 222                if (flags & TREESAME)
 223                        continue;
 224                distance = weight(p);
 225                if (nr - distance < distance)
 226                        distance = nr - distance;
 227                array[cnt].commit = p->item;
 228                array[cnt].distance = distance;
 229                cnt++;
 230        }
 231        qsort(array, cnt, sizeof(*array), compare_commit_dist);
 232        for (p = list, i = 0; i < cnt; i++) {
 233                struct name_decoration *r = xmalloc(sizeof(*r) + 100);
 234                struct object *obj = &(array[i].commit->object);
 235
 236                sprintf(r->name, "dist=%d", array[i].distance);
 237                r->next = add_decoration(&name_decoration, obj, r);
 238                p->item = array[i].commit;
 239                p = p->next;
 240        }
 241        if (p)
 242                p->next = NULL;
 243        free(array);
 244        return list;
 245}
 246
 247/*
 248 * zero or positive weight is the number of interesting commits it can
 249 * reach, including itself.  Especially, weight = 0 means it does not
 250 * reach any tree-changing commits (e.g. just above uninteresting one
 251 * but traversal is with pathspec).
 252 *
 253 * weight = -1 means it has one parent and its distance is yet to
 254 * be computed.
 255 *
 256 * weight = -2 means it has more than one parent and its distance is
 257 * unknown.  After running count_distance() first, they will get zero
 258 * or positive distance.
 259 */
 260static struct commit_list *do_find_bisection(struct commit_list *list,
 261                                             int nr, int *weights,
 262                                             int find_all)
 263{
 264        int n, counted;
 265        struct commit_list *p;
 266
 267        counted = 0;
 268
 269        for (n = 0, p = list; p; p = p->next) {
 270                struct commit *commit = p->item;
 271                unsigned flags = commit->object.flags;
 272
 273                p->item->util = &weights[n++];
 274                switch (count_interesting_parents(commit)) {
 275                case 0:
 276                        if (!(flags & TREESAME)) {
 277                                weight_set(p, 1);
 278                                counted++;
 279                                show_list("bisection 2 count one",
 280                                          counted, nr, list);
 281                        }
 282                        /*
 283                         * otherwise, it is known not to reach any
 284                         * tree-changing commit and gets weight 0.
 285                         */
 286                        break;
 287                case 1:
 288                        weight_set(p, -1);
 289                        break;
 290                default:
 291                        weight_set(p, -2);
 292                        break;
 293                }
 294        }
 295
 296        show_list("bisection 2 initialize", counted, nr, list);
 297
 298        /*
 299         * If you have only one parent in the resulting set
 300         * then you can reach one commit more than that parent
 301         * can reach.  So we do not have to run the expensive
 302         * count_distance() for single strand of pearls.
 303         *
 304         * However, if you have more than one parents, you cannot
 305         * just add their distance and one for yourself, since
 306         * they usually reach the same ancestor and you would
 307         * end up counting them twice that way.
 308         *
 309         * So we will first count distance of merges the usual
 310         * way, and then fill the blanks using cheaper algorithm.
 311         */
 312        for (p = list; p; p = p->next) {
 313                if (p->item->object.flags & UNINTERESTING)
 314                        continue;
 315                if (weight(p) != -2)
 316                        continue;
 317                weight_set(p, count_distance(p));
 318                clear_distance(list);
 319
 320                /* Does it happen to be at exactly half-way? */
 321                if (!find_all && halfway(p, nr))
 322                        return p;
 323                counted++;
 324        }
 325
 326        show_list("bisection 2 count_distance", counted, nr, list);
 327
 328        while (counted < nr) {
 329                for (p = list; p; p = p->next) {
 330                        struct commit_list *q;
 331                        unsigned flags = p->item->object.flags;
 332
 333                        if (0 <= weight(p))
 334                                continue;
 335                        for (q = p->item->parents; q; q = q->next) {
 336                                if (q->item->object.flags & UNINTERESTING)
 337                                        continue;
 338                                if (0 <= weight(q))
 339                                        break;
 340                        }
 341                        if (!q)
 342                                continue;
 343
 344                        /*
 345                         * weight for p is unknown but q is known.
 346                         * add one for p itself if p is to be counted,
 347                         * otherwise inherit it from q directly.
 348                         */
 349                        if (!(flags & TREESAME)) {
 350                                weight_set(p, weight(q)+1);
 351                                counted++;
 352                                show_list("bisection 2 count one",
 353                                          counted, nr, list);
 354                        }
 355                        else
 356                                weight_set(p, weight(q));
 357
 358                        /* Does it happen to be at exactly half-way? */
 359                        if (!find_all && halfway(p, nr))
 360                                return p;
 361                }
 362        }
 363
 364        show_list("bisection 2 counted all", counted, nr, list);
 365
 366        if (!find_all)
 367                return best_bisection(list, nr);
 368        else
 369                return best_bisection_sorted(list, nr);
 370}
 371
 372struct commit_list *find_bisection(struct commit_list *list,
 373                                          int *reaches, int *all,
 374                                          int find_all)
 375{
 376        int nr, on_list;
 377        struct commit_list *p, *best, *next, *last;
 378        int *weights;
 379
 380        show_list("bisection 2 entry", 0, 0, list);
 381
 382        /*
 383         * Count the number of total and tree-changing items on the
 384         * list, while reversing the list.
 385         */
 386        for (nr = on_list = 0, last = NULL, p = list;
 387             p;
 388             p = next) {
 389                unsigned flags = p->item->object.flags;
 390
 391                next = p->next;
 392                if (flags & UNINTERESTING)
 393                        continue;
 394                p->next = last;
 395                last = p;
 396                if (!(flags & TREESAME))
 397                        nr++;
 398                on_list++;
 399        }
 400        list = last;
 401        show_list("bisection 2 sorted", 0, nr, list);
 402
 403        *all = nr;
 404        weights = xcalloc(on_list, sizeof(*weights));
 405
 406        /* Do the real work of finding bisection commit. */
 407        best = do_find_bisection(list, nr, weights, find_all);
 408        if (best) {
 409                if (!find_all)
 410                        best->next = NULL;
 411                *reaches = weight(best);
 412        }
 413        free(weights);
 414        return best;
 415}
 416
 417static void argv_array_push(struct argv_array *array, const char *string)
 418{
 419        ALLOC_GROW(array->argv, array->argv_nr + 1, array->argv_alloc);
 420        array->argv[array->argv_nr++] = string;
 421}
 422
 423static void argv_array_push_sha1(struct argv_array *array,
 424                                 const unsigned char *sha1,
 425                                 const char *format)
 426{
 427        struct strbuf buf = STRBUF_INIT;
 428        strbuf_addf(&buf, format, sha1_to_hex(sha1));
 429        argv_array_push(array, strbuf_detach(&buf, NULL));
 430}
 431
 432static void sha1_array_push(struct sha1_array *array,
 433                            const unsigned char *sha1)
 434{
 435        ALLOC_GROW(array->sha1, array->sha1_nr + 1, array->sha1_alloc);
 436        hashcpy(array->sha1[array->sha1_nr++], sha1);
 437}
 438
 439static int register_ref(const char *refname, const unsigned char *sha1,
 440                        int flags, void *cb_data)
 441{
 442        if (!strcmp(refname, "bad")) {
 443                current_bad_sha1 = sha1;
 444        } else if (!prefixcmp(refname, "good-")) {
 445                sha1_array_push(&good_revs, sha1);
 446        } else if (!prefixcmp(refname, "skip-")) {
 447                sha1_array_push(&skipped_revs, sha1);
 448        }
 449
 450        return 0;
 451}
 452
 453static int read_bisect_refs(void)
 454{
 455        return for_each_ref_in("refs/bisect/", register_ref, NULL);
 456}
 457
 458void read_bisect_paths(struct argv_array *array)
 459{
 460        struct strbuf str = STRBUF_INIT;
 461        const char *filename = git_path("BISECT_NAMES");
 462        FILE *fp = fopen(filename, "r");
 463
 464        if (!fp)
 465                die("Could not open file '%s': %s", filename, strerror(errno));
 466
 467        while (strbuf_getline(&str, fp, '\n') != EOF) {
 468                char *quoted;
 469                int res;
 470
 471                strbuf_trim(&str);
 472                quoted = strbuf_detach(&str, NULL);
 473                res = sq_dequote_to_argv(quoted, &array->argv,
 474                                         &array->argv_nr, &array->argv_alloc);
 475                if (res)
 476                        die("Badly quoted content in file '%s': %s",
 477                            filename, quoted);
 478        }
 479
 480        strbuf_release(&str);
 481        fclose(fp);
 482}
 483
 484static int skipcmp(const void *a, const void *b)
 485{
 486        return hashcmp(a, b);
 487}
 488
 489static void prepare_skipped(void)
 490{
 491        qsort(skipped_revs.sha1, skipped_revs.sha1_nr,
 492              sizeof(*skipped_revs.sha1), skipcmp);
 493}
 494
 495static const unsigned char *skipped_sha1_access(size_t index, void *table)
 496{
 497        unsigned char (*skipped)[20] = table;
 498        return skipped[index];
 499}
 500
 501static int lookup_skipped(unsigned char *sha1)
 502{
 503        return sha1_pos(sha1, skipped_revs.sha1, skipped_revs.sha1_nr,
 504                        skipped_sha1_access);
 505}
 506
 507struct commit_list *filter_skipped(struct commit_list *list,
 508                                   struct commit_list **tried,
 509                                   int show_all)
 510{
 511        struct commit_list *filtered = NULL, **f = &filtered;
 512
 513        *tried = NULL;
 514
 515        if (!skipped_revs.sha1_nr)
 516                return list;
 517
 518        prepare_skipped();
 519
 520        while (list) {
 521                struct commit_list *next = list->next;
 522                list->next = NULL;
 523                if (0 <= lookup_skipped(list->item->object.sha1)) {
 524                        /* Move current to tried list */
 525                        *tried = list;
 526                        tried = &list->next;
 527                } else {
 528                        if (!show_all)
 529                                return list;
 530                        /* Move current to filtered list */
 531                        *f = list;
 532                        f = &list->next;
 533                }
 534                list = next;
 535        }
 536
 537        return filtered;
 538}
 539
 540static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
 541{
 542        int i;
 543
 544        init_revisions(revs, prefix);
 545        revs->abbrev = 0;
 546        revs->commit_format = CMIT_FMT_UNSPECIFIED;
 547
 548        if (read_bisect_refs())
 549                die("reading bisect refs failed");
 550
 551        /* rev_argv.argv[0] will be ignored by setup_revisions */
 552        argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
 553        argv_array_push_sha1(&rev_argv, current_bad_sha1, "%s");
 554        for (i = 0; i < good_revs.sha1_nr; i++)
 555                argv_array_push_sha1(&rev_argv, good_revs.sha1[i], "^%s");
 556        argv_array_push(&rev_argv, xstrdup("--"));
 557        read_bisect_paths(&rev_argv);
 558        argv_array_push(&rev_argv, NULL);
 559
 560        setup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);
 561        revs->limited = 1;
 562}
 563
 564static void bisect_common(struct rev_info *revs, const char *prefix,
 565                          int *reaches, int *all)
 566{
 567        bisect_rev_setup(revs, prefix);
 568
 569        if (prepare_revision_walk(revs))
 570                die("revision walk setup failed");
 571        if (revs->tree_objects)
 572                mark_edges_uninteresting(revs->commits, revs, NULL);
 573
 574        revs->commits = find_bisection(revs->commits, reaches, all,
 575                                       !!skipped_revs.sha1_nr);
 576}
 577
 578static void exit_if_skipped_commits(struct commit_list *tried,
 579                                    const unsigned char *bad)
 580{
 581        if (!tried)
 582                return;
 583
 584        printf("There are only 'skip'ped commits left to test.\n"
 585               "The first bad commit could be any of:\n");
 586        print_commit_list(tried, "%s\n", "%s\n");
 587        if (bad)
 588                printf("%s\n", sha1_to_hex(bad));
 589        printf("We cannot bisect more!\n");
 590        exit(2);
 591}
 592
 593static void mark_expected_rev(char *bisect_rev_hex)
 594{
 595        int len = strlen(bisect_rev_hex);
 596        const char *filename = git_path("BISECT_EXPECTED_REV");
 597        int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
 598
 599        if (fd < 0)
 600                die("could not create file '%s': %s",
 601                    filename, strerror(errno));
 602
 603        bisect_rev_hex[len] = '\n';
 604        write_or_die(fd, bisect_rev_hex, len + 1);
 605        bisect_rev_hex[len] = '\0';
 606
 607        if (close(fd) < 0)
 608                die("closing file %s: %s", filename, strerror(errno));
 609}
 610
 611static int bisect_checkout(char *bisect_rev_hex)
 612{
 613        int res;
 614
 615        mark_expected_rev(bisect_rev_hex);
 616
 617        argv_checkout[2] = bisect_rev_hex;
 618        res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
 619        if (res)
 620                exit(res);
 621
 622        argv_show_branch[1] = bisect_rev_hex;
 623        return run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
 624}
 625
 626/*
 627 * We use the convention that exiting with an exit code 10 means that
 628 * the bisection process finished successfully.
 629 * In this case the calling shell script should exit 0.
 630 */
 631int bisect_next_exit(const char *prefix)
 632{
 633        struct rev_info revs;
 634        struct commit_list *tried;
 635        int reaches = 0, all = 0, nr;
 636        const unsigned char *bisect_rev;
 637        char bisect_rev_hex[41];
 638
 639        bisect_common(&revs, prefix, &reaches, &all);
 640
 641        revs.commits = filter_skipped(revs.commits, &tried, 0);
 642
 643        if (!revs.commits) {
 644                /*
 645                 * We should exit here only if the "bad"
 646                 * commit is also a "skip" commit.
 647                 */
 648                exit_if_skipped_commits(tried, NULL);
 649
 650                printf("%s was both good and bad\n",
 651                       sha1_to_hex(current_bad_sha1));
 652                exit(1);
 653        }
 654
 655        bisect_rev = revs.commits->item->object.sha1;
 656        memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), 41);
 657
 658        if (!hashcmp(bisect_rev, current_bad_sha1)) {
 659                exit_if_skipped_commits(tried, current_bad_sha1);
 660                printf("%s is first bad commit\n", bisect_rev_hex);
 661                argv_diff_tree[2] = bisect_rev_hex;
 662                run_command_v_opt(argv_diff_tree, RUN_GIT_CMD);
 663                /* This means the bisection process succeeded. */
 664                exit(10);
 665        }
 666
 667        nr = all - reaches - 1;
 668        printf("Bisecting: %d revisions left to test after this "
 669               "(roughly %d steps)\n", nr, estimate_bisect_steps(all));
 670
 671        return bisect_checkout(bisect_rev_hex);
 672}
 673