blame.con commit test-lib.sh: A command dying due to a signal is an unexpected failure. (40cf043)
   1/*
   2 * Copyright (C) 2006, Fredrik Kuivinen <freku045@student.liu.se>
   3 */
   4
   5#include <assert.h>
   6#include <time.h>
   7#include <sys/time.h>
   8#include <math.h>
   9
  10#include "cache.h"
  11#include "refs.h"
  12#include "tag.h"
  13#include "commit.h"
  14#include "tree.h"
  15#include "blob.h"
  16#include "diff.h"
  17#include "diffcore.h"
  18#include "revision.h"
  19#include "xdiff-interface.h"
  20
  21#ifndef DEBUG
  22#define DEBUG 0
  23#endif
  24
  25static const char blame_usage[] = "git-blame [-c] [-l] [-t] [-S <revs-file>] [--] file [commit]\n"
  26        "  -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
  27        "  -l, --long          Show long commit SHA1 (Default: off)\n"
  28        "  -t, --time          Show raw timestamp (Default: off)\n"
  29        "  -S, --revs-file     Use revisions from revs-file instead of calling git-rev-list\n"
  30        "  -h, --help          This message";
  31
  32static struct commit **blame_lines;
  33static int num_blame_lines;
  34static char* blame_contents;
  35static int blame_len;
  36
  37struct util_info {
  38        int *line_map;
  39        unsigned char sha1[20]; /* blob sha, not commit! */
  40        char *buf;
  41        unsigned long size;
  42        int num_lines;
  43        const char* pathname;
  44
  45        void* topo_data;
  46};
  47
  48struct chunk {
  49        int off1, len1; /* --- */
  50        int off2, len2; /* +++ */
  51};
  52
  53struct patch {
  54        struct chunk *chunks;
  55        int num;
  56};
  57
  58static void get_blob(struct commit *commit);
  59
  60/* Only used for statistics */
  61static int num_get_patch;
  62static int num_commits;
  63static int patch_time;
  64
  65struct blame_diff_state {
  66        struct xdiff_emit_state xm;
  67        struct patch *ret;
  68};
  69
  70static void process_u0_diff(void *state_, char *line, unsigned long len)
  71{
  72        struct blame_diff_state *state = state_;
  73        struct chunk *chunk;
  74
  75        if (len < 4 || line[0] != '@' || line[1] != '@')
  76                return;
  77
  78        if (DEBUG)
  79                printf("chunk line: %.*s", (int)len, line);
  80        state->ret->num++;
  81        state->ret->chunks = xrealloc(state->ret->chunks,
  82                                      sizeof(struct chunk) * state->ret->num);
  83        chunk = &state->ret->chunks[state->ret->num - 1];
  84
  85        assert(!strncmp(line, "@@ -", 4));
  86
  87        if (parse_hunk_header(line, len,
  88                              &chunk->off1, &chunk->len1,
  89                              &chunk->off2, &chunk->len2)) {
  90                state->ret->num--;
  91                return;
  92        }
  93
  94        if (chunk->len1 == 0)
  95                chunk->off1++;
  96        if (chunk->len2 == 0)
  97                chunk->off2++;
  98
  99        if (chunk->off1 > 0)
 100                chunk->off1--;
 101        if (chunk->off2 > 0)
 102                chunk->off2--;
 103
 104        assert(chunk->off1 >= 0);
 105        assert(chunk->off2 >= 0);
 106}
 107
 108static struct patch *get_patch(struct commit *commit, struct commit *other)
 109{
 110        struct blame_diff_state state;
 111        xpparam_t xpp;
 112        xdemitconf_t xecfg;
 113        mmfile_t file_c, file_o;
 114        xdemitcb_t ecb;
 115        struct util_info *info_c = (struct util_info *)commit->util;
 116        struct util_info *info_o = (struct util_info *)other->util;
 117        struct timeval tv_start, tv_end;
 118
 119        get_blob(commit);
 120        file_c.ptr = info_c->buf;
 121        file_c.size = info_c->size;
 122
 123        get_blob(other);
 124        file_o.ptr = info_o->buf;
 125        file_o.size = info_o->size;
 126
 127        gettimeofday(&tv_start, NULL);
 128
 129        xpp.flags = XDF_NEED_MINIMAL;
 130        xecfg.ctxlen = 0;
 131        xecfg.flags = 0;
 132        ecb.outf = xdiff_outf;
 133        ecb.priv = &state;
 134        memset(&state, 0, sizeof(state));
 135        state.xm.consume = process_u0_diff;
 136        state.ret = xmalloc(sizeof(struct patch));
 137        state.ret->chunks = NULL;
 138        state.ret->num = 0;
 139
 140        xdl_diff(&file_c, &file_o, &xpp, &xecfg, &ecb);
 141
 142        gettimeofday(&tv_end, NULL);
 143        patch_time += 1000000 * (tv_end.tv_sec - tv_start.tv_sec) +
 144                tv_end.tv_usec - tv_start.tv_usec;
 145
 146        num_get_patch++;
 147        return state.ret;
 148}
 149
 150static void free_patch(struct patch *p)
 151{
 152        free(p->chunks);
 153        free(p);
 154}
 155
 156static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
 157                                  int baselen, const char *pathname,
 158                                  unsigned mode, int stage);
 159
 160static unsigned char blob_sha1[20];
 161static const char* blame_file;
 162static int get_blob_sha1(struct tree *t, const char *pathname,
 163                         unsigned char *sha1)
 164{
 165        int i;
 166        const char *pathspec[2];
 167        blame_file = pathname;
 168        pathspec[0] = pathname;
 169        pathspec[1] = NULL;
 170        hashclr(blob_sha1);
 171        read_tree_recursive(t, "", 0, 0, pathspec, get_blob_sha1_internal);
 172
 173        for (i = 0; i < 20; i++) {
 174                if (blob_sha1[i] != 0)
 175                        break;
 176        }
 177
 178        if (i == 20)
 179                return -1;
 180
 181        hashcpy(sha1, blob_sha1);
 182        return 0;
 183}
 184
 185static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
 186                                  int baselen, const char *pathname,
 187                                  unsigned mode, int stage)
 188{
 189        if (S_ISDIR(mode))
 190                return READ_TREE_RECURSIVE;
 191
 192        if (strncmp(blame_file, base, baselen) ||
 193            strcmp(blame_file + baselen, pathname))
 194                return -1;
 195
 196        hashcpy(blob_sha1, sha1);
 197        return -1;
 198}
 199
 200static void get_blob(struct commit *commit)
 201{
 202        struct util_info *info = commit->util;
 203        char type[20];
 204
 205        if (info->buf)
 206                return;
 207
 208        info->buf = read_sha1_file(info->sha1, type, &info->size);
 209
 210        assert(!strcmp(type, blob_type));
 211}
 212
 213/* For debugging only */
 214static void print_patch(struct patch *p)
 215{
 216        int i;
 217        printf("Num chunks: %d\n", p->num);
 218        for (i = 0; i < p->num; i++) {
 219                printf("%d,%d %d,%d\n", p->chunks[i].off1, p->chunks[i].len1,
 220                       p->chunks[i].off2, p->chunks[i].len2);
 221        }
 222}
 223
 224#if DEBUG
 225/* For debugging only */
 226static void print_map(struct commit *cmit, struct commit *other)
 227{
 228        struct util_info *util = cmit->util;
 229        struct util_info *util2 = other->util;
 230
 231        int i;
 232        int max =
 233            util->num_lines >
 234            util2->num_lines ? util->num_lines : util2->num_lines;
 235        int num;
 236
 237        if (print_map == NULL)
 238                ; /* to avoid "unused function" warning */
 239
 240        for (i = 0; i < max; i++) {
 241                printf("i: %d ", i);
 242                num = -1;
 243
 244                if (i < util->num_lines) {
 245                        num = util->line_map[i];
 246                        printf("%d\t", num);
 247                } else
 248                        printf("\t");
 249
 250                if (i < util2->num_lines) {
 251                        int num2 = util2->line_map[i];
 252                        printf("%d\t", num2);
 253                        if (num != -1 && num2 != num)
 254                                printf("---");
 255                } else
 256                        printf("\t");
 257
 258                printf("\n");
 259        }
 260}
 261#endif
 262
 263/* p is a patch from commit to other. */
 264static void fill_line_map(struct commit *commit, struct commit *other,
 265                          struct patch *p)
 266{
 267        struct util_info *util = commit->util;
 268        struct util_info *util2 = other->util;
 269        int *map = util->line_map;
 270        int *map2 = util2->line_map;
 271        int cur_chunk = 0;
 272        int i1, i2;
 273
 274        if (p->num && DEBUG)
 275                print_patch(p);
 276
 277        if (DEBUG)
 278                printf("num lines 1: %d num lines 2: %d\n", util->num_lines,
 279                       util2->num_lines);
 280
 281        for (i1 = 0, i2 = 0; i1 < util->num_lines; i1++, i2++) {
 282                struct chunk *chunk = NULL;
 283                if (cur_chunk < p->num)
 284                        chunk = &p->chunks[cur_chunk];
 285
 286                if (chunk && chunk->off1 == i1) {
 287                        if (DEBUG && i2 != chunk->off2)
 288                                printf("i2: %d off2: %d\n", i2, chunk->off2);
 289
 290                        assert(i2 == chunk->off2);
 291
 292                        i1--;
 293                        i2--;
 294                        if (chunk->len1 > 0)
 295                                i1 += chunk->len1;
 296
 297                        if (chunk->len2 > 0)
 298                                i2 += chunk->len2;
 299
 300                        cur_chunk++;
 301                } else {
 302                        if (i2 >= util2->num_lines)
 303                                break;
 304
 305                        if (map[i1] != map2[i2] && map[i1] != -1) {
 306                                if (DEBUG)
 307                                        printf("map: i1: %d %d %p i2: %d %d %p\n",
 308                                               i1, map[i1],
 309                                               (void *) (i1 != -1 ? blame_lines[map[i1]] : NULL),
 310                                               i2, map2[i2],
 311                                               (void *) (i2 != -1 ? blame_lines[map2[i2]] : NULL));
 312                                if (map2[i2] != -1 &&
 313                                    blame_lines[map[i1]] &&
 314                                    !blame_lines[map2[i2]])
 315                                        map[i1] = map2[i2];
 316                        }
 317
 318                        if (map[i1] == -1 && map2[i2] != -1)
 319                                map[i1] = map2[i2];
 320                }
 321
 322                if (DEBUG > 1)
 323                        printf("l1: %d l2: %d i1: %d i2: %d\n",
 324                               map[i1], map2[i2], i1, i2);
 325        }
 326}
 327
 328static int map_line(struct commit *commit, int line)
 329{
 330        struct util_info *info = commit->util;
 331        assert(line >= 0 && line < info->num_lines);
 332        return info->line_map[line];
 333}
 334
 335static struct util_info* get_util(struct commit *commit)
 336{
 337        struct util_info *util = commit->util;
 338
 339        if (util)
 340                return util;
 341
 342        util = xmalloc(sizeof(struct util_info));
 343        util->buf = NULL;
 344        util->size = 0;
 345        util->line_map = NULL;
 346        util->num_lines = -1;
 347        util->pathname = NULL;
 348        commit->util = util;
 349        return util;
 350}
 351
 352static int fill_util_info(struct commit *commit)
 353{
 354        struct util_info *util = commit->util;
 355
 356        assert(util);
 357        assert(util->pathname);
 358
 359        return !!get_blob_sha1(commit->tree, util->pathname, util->sha1);
 360}
 361
 362static void alloc_line_map(struct commit *commit)
 363{
 364        struct util_info *util = commit->util;
 365        int i;
 366
 367        if (util->line_map)
 368                return;
 369
 370        get_blob(commit);
 371
 372        util->num_lines = 0;
 373        for (i = 0; i < util->size; i++) {
 374                if (util->buf[i] == '\n')
 375                        util->num_lines++;
 376        }
 377        if(util->buf[util->size - 1] != '\n')
 378                util->num_lines++;
 379
 380        util->line_map = xmalloc(sizeof(int) * util->num_lines);
 381
 382        for (i = 0; i < util->num_lines; i++)
 383                util->line_map[i] = -1;
 384}
 385
 386static void init_first_commit(struct commit* commit, const char* filename)
 387{
 388        struct util_info* util = commit->util;
 389        int i;
 390
 391        util->pathname = filename;
 392        if (fill_util_info(commit))
 393                die("fill_util_info failed");
 394
 395        alloc_line_map(commit);
 396
 397        util = commit->util;
 398
 399        for (i = 0; i < util->num_lines; i++)
 400                util->line_map[i] = i;
 401}
 402
 403
 404static void process_commits(struct rev_info *rev, const char *path,
 405                            struct commit** initial)
 406{
 407        int i;
 408        struct util_info* util;
 409        int lines_left;
 410        int *blame_p;
 411        int *new_lines;
 412        int new_lines_len;
 413
 414        struct commit* commit = get_revision(rev);
 415        assert(commit);
 416        init_first_commit(commit, path);
 417
 418        util = commit->util;
 419        num_blame_lines = util->num_lines;
 420        blame_lines = xmalloc(sizeof(struct commit *) * num_blame_lines);
 421        blame_contents = util->buf;
 422        blame_len = util->size;
 423
 424        for (i = 0; i < num_blame_lines; i++)
 425                blame_lines[i] = NULL;
 426
 427        lines_left = num_blame_lines;
 428        blame_p = xmalloc(sizeof(int) * num_blame_lines);
 429        new_lines = xmalloc(sizeof(int) * num_blame_lines);
 430        do {
 431                struct commit_list *parents;
 432                int num_parents;
 433                struct util_info *util;
 434
 435                if (DEBUG)
 436                        printf("\nProcessing commit: %d %s\n", num_commits,
 437                               sha1_to_hex(commit->object.sha1));
 438
 439                if (lines_left == 0)
 440                        return;
 441
 442                num_commits++;
 443                memset(blame_p, 0, sizeof(int) * num_blame_lines);
 444                new_lines_len = 0;
 445                num_parents = 0;
 446                for (parents = commit->parents;
 447                     parents != NULL; parents = parents->next)
 448                        num_parents++;
 449
 450                if(num_parents == 0)
 451                        *initial = commit;
 452
 453                if (fill_util_info(commit))
 454                        continue;
 455
 456                alloc_line_map(commit);
 457                util = commit->util;
 458
 459                for (parents = commit->parents;
 460                     parents != NULL; parents = parents->next) {
 461                        struct commit *parent = parents->item;
 462                        struct patch *patch;
 463
 464                        if (parse_commit(parent) < 0)
 465                                die("parse_commit error");
 466
 467                        if (DEBUG)
 468                                printf("parent: %s\n",
 469                                       sha1_to_hex(parent->object.sha1));
 470
 471                        if (fill_util_info(parent)) {
 472                                num_parents--;
 473                                continue;
 474                        }
 475
 476                        patch = get_patch(parent, commit);
 477                        alloc_line_map(parent);
 478                        fill_line_map(parent, commit, patch);
 479
 480                        for (i = 0; i < patch->num; i++) {
 481                            int l;
 482                            for (l = 0; l < patch->chunks[i].len2; l++) {
 483                                int mapped_line =
 484                                    map_line(commit, patch->chunks[i].off2 + l);
 485                                if (mapped_line != -1) {
 486                                    blame_p[mapped_line]++;
 487                                    if (blame_p[mapped_line] == num_parents)
 488                                        new_lines[new_lines_len++] = mapped_line;
 489                                }
 490                            }
 491                        }
 492                        free_patch(patch);
 493                }
 494
 495                if (DEBUG)
 496                        printf("parents: %d\n", num_parents);
 497
 498                for (i = 0; i < new_lines_len; i++) {
 499                        int mapped_line = new_lines[i];
 500                        if (blame_lines[mapped_line] == NULL) {
 501                                blame_lines[mapped_line] = commit;
 502                                lines_left--;
 503                                if (DEBUG)
 504                                        printf("blame: mapped: %d i: %d\n",
 505                                               mapped_line, i);
 506                        }
 507                }
 508        } while ((commit = get_revision(rev)) != NULL);
 509}
 510
 511
 512static int compare_tree_path(struct rev_info* revs,
 513                             struct commit* c1, struct commit* c2)
 514{
 515        int ret;
 516        const char* paths[2];
 517        struct util_info* util = c2->util;
 518        paths[0] = util->pathname;
 519        paths[1] = NULL;
 520
 521        diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
 522                              &revs->pruning);
 523        ret = rev_compare_tree(revs, c1->tree, c2->tree);
 524        diff_tree_release_paths(&revs->pruning);
 525        return ret;
 526}
 527
 528
 529static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1,
 530                                   const char* path)
 531{
 532        int ret;
 533        const char* paths[2];
 534        paths[0] = path;
 535        paths[1] = NULL;
 536
 537        diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
 538                              &revs->pruning);
 539        ret = rev_same_tree_as_empty(revs, t1);
 540        diff_tree_release_paths(&revs->pruning);
 541        return ret;
 542}
 543
 544static const char* find_rename(struct commit* commit, struct commit* parent)
 545{
 546        struct util_info* cutil = commit->util;
 547        struct diff_options diff_opts;
 548        const char *paths[1];
 549        int i;
 550
 551        if (DEBUG) {
 552                printf("find_rename commit: %s ",
 553                       sha1_to_hex(commit->object.sha1));
 554                puts(sha1_to_hex(parent->object.sha1));
 555        }
 556
 557        diff_setup(&diff_opts);
 558        diff_opts.recursive = 1;
 559        diff_opts.detect_rename = DIFF_DETECT_RENAME;
 560        paths[0] = NULL;
 561        diff_tree_setup_paths(paths, &diff_opts);
 562        if (diff_setup_done(&diff_opts) < 0)
 563                die("diff_setup_done failed");
 564
 565        diff_tree_sha1(commit->tree->object.sha1, parent->tree->object.sha1,
 566                       "", &diff_opts);
 567        diffcore_std(&diff_opts);
 568
 569        for (i = 0; i < diff_queued_diff.nr; i++) {
 570                struct diff_filepair *p = diff_queued_diff.queue[i];
 571
 572                if (p->status == 'R' && !strcmp(p->one->path, cutil->pathname)) {
 573                        if (DEBUG)
 574                                printf("rename %s -> %s\n", p->one->path, p->two->path);
 575                        return p->two->path;
 576                }
 577        }
 578
 579        return 0;
 580}
 581
 582static void simplify_commit(struct rev_info *revs, struct commit *commit)
 583{
 584        struct commit_list **pp, *parent;
 585
 586        if (!commit->tree)
 587                return;
 588
 589        if (!commit->parents) {
 590                struct util_info* util = commit->util;
 591                if (!same_tree_as_empty_path(revs, commit->tree,
 592                                             util->pathname))
 593                        commit->object.flags |= TREECHANGE;
 594                return;
 595        }
 596
 597        pp = &commit->parents;
 598        while ((parent = *pp) != NULL) {
 599                struct commit *p = parent->item;
 600
 601                if (p->object.flags & UNINTERESTING) {
 602                        pp = &parent->next;
 603                        continue;
 604                }
 605
 606                parse_commit(p);
 607                switch (compare_tree_path(revs, p, commit)) {
 608                case REV_TREE_SAME:
 609                        parent->next = NULL;
 610                        commit->parents = parent;
 611                        get_util(p)->pathname = get_util(commit)->pathname;
 612                        return;
 613
 614                case REV_TREE_NEW:
 615                {
 616
 617                        struct util_info* util = commit->util;
 618                        if (revs->remove_empty_trees &&
 619                            same_tree_as_empty_path(revs, p->tree,
 620                                                    util->pathname)) {
 621                                const char* new_name = find_rename(commit, p);
 622                                if (new_name) {
 623                                        struct util_info* putil = get_util(p);
 624                                        if (!putil->pathname)
 625                                                putil->pathname = xstrdup(new_name);
 626                                } else {
 627                                        *pp = parent->next;
 628                                        continue;
 629                                }
 630                        }
 631                }
 632
 633                /* fallthrough */
 634                case REV_TREE_DIFFERENT:
 635                        pp = &parent->next;
 636                        if (!get_util(p)->pathname)
 637                                get_util(p)->pathname =
 638                                        get_util(commit)->pathname;
 639                        continue;
 640                }
 641                die("bad tree compare for commit %s",
 642                    sha1_to_hex(commit->object.sha1));
 643        }
 644        commit->object.flags |= TREECHANGE;
 645}
 646
 647
 648struct commit_info
 649{
 650        char* author;
 651        char* author_mail;
 652        unsigned long author_time;
 653        char* author_tz;
 654};
 655
 656static void get_commit_info(struct commit* commit, struct commit_info* ret)
 657{
 658        int len;
 659        char* tmp;
 660        static char author_buf[1024];
 661
 662        tmp = strstr(commit->buffer, "\nauthor ") + 8;
 663        len = strchr(tmp, '\n') - tmp;
 664        ret->author = author_buf;
 665        memcpy(ret->author, tmp, len);
 666
 667        tmp = ret->author;
 668        tmp += len;
 669        *tmp = 0;
 670        while(*tmp != ' ')
 671                tmp--;
 672        ret->author_tz = tmp+1;
 673
 674        *tmp = 0;
 675        while(*tmp != ' ')
 676                tmp--;
 677        ret->author_time = strtoul(tmp, NULL, 10);
 678
 679        *tmp = 0;
 680        while(*tmp != ' ')
 681                tmp--;
 682        ret->author_mail = tmp + 1;
 683
 684        *tmp = 0;
 685}
 686
 687static const char* format_time(unsigned long time, const char* tz_str,
 688                               int show_raw_time)
 689{
 690        static char time_buf[128];
 691        time_t t = time;
 692        int minutes, tz;
 693        struct tm *tm;
 694
 695        if (show_raw_time) {
 696                sprintf(time_buf, "%lu %s", time, tz_str);
 697                return time_buf;
 698        }
 699
 700        tz = atoi(tz_str);
 701        minutes = tz < 0 ? -tz : tz;
 702        minutes = (minutes / 100)*60 + (minutes % 100);
 703        minutes = tz < 0 ? -minutes : minutes;
 704        t = time + minutes * 60;
 705        tm = gmtime(&t);
 706
 707        strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
 708        strcat(time_buf, tz_str);
 709        return time_buf;
 710}
 711
 712static void topo_setter(struct commit* c, void* data)
 713{
 714        struct util_info* util = c->util;
 715        util->topo_data = data;
 716}
 717
 718static void* topo_getter(struct commit* c)
 719{
 720        struct util_info* util = c->util;
 721        return util->topo_data;
 722}
 723
 724static int read_ancestry(const char *graft_file,
 725                         unsigned char **start_sha1)
 726{
 727        FILE *fp = fopen(graft_file, "r");
 728        char buf[1024];
 729        if (!fp)
 730                return -1;
 731        while (fgets(buf, sizeof(buf), fp)) {
 732                /* The format is just "Commit Parent1 Parent2 ...\n" */
 733                int len = strlen(buf);
 734                struct commit_graft *graft = read_graft_line(buf, len);
 735                register_commit_graft(graft, 0);
 736                if (!*start_sha1)
 737                        *start_sha1 = graft->sha1;
 738        }
 739        fclose(fp);
 740        return 0;
 741}
 742
 743int main(int argc, const char **argv)
 744{
 745        int i;
 746        struct commit *initial = NULL;
 747        unsigned char sha1[20], *sha1_p = NULL;
 748
 749        const char *filename = NULL, *commit = NULL;
 750        char filename_buf[256];
 751        int sha1_len = 8;
 752        int compatibility = 0;
 753        int show_raw_time = 0;
 754        int options = 1;
 755        struct commit* start_commit;
 756
 757        const char* args[10];
 758        struct rev_info rev;
 759
 760        struct commit_info ci;
 761        const char *buf;
 762        int max_digits;
 763        int longest_file, longest_author;
 764        int found_rename;
 765
 766        const char* prefix = setup_git_directory();
 767        git_config(git_default_config);
 768
 769        for(i = 1; i < argc; i++) {
 770                if(options) {
 771                        if(!strcmp(argv[i], "-h") ||
 772                           !strcmp(argv[i], "--help"))
 773                                usage(blame_usage);
 774                        else if(!strcmp(argv[i], "-l") ||
 775                                !strcmp(argv[i], "--long")) {
 776                                sha1_len = 40;
 777                                continue;
 778                        } else if(!strcmp(argv[i], "-c") ||
 779                                  !strcmp(argv[i], "--compatibility")) {
 780                                compatibility = 1;
 781                                continue;
 782                        } else if(!strcmp(argv[i], "-t") ||
 783                                  !strcmp(argv[i], "--time")) {
 784                                show_raw_time = 1;
 785                                continue;
 786                        } else if(!strcmp(argv[i], "-S")) {
 787                                if (i + 1 < argc &&
 788                                    !read_ancestry(argv[i + 1], &sha1_p)) {
 789                                        compatibility = 1;
 790                                        i++;
 791                                        continue;
 792                                }
 793                                usage(blame_usage);
 794                        } else if(!strcmp(argv[i], "--")) {
 795                                options = 0;
 796                                continue;
 797                        } else if(argv[i][0] == '-')
 798                                usage(blame_usage);
 799                        else
 800                                options = 0;
 801                }
 802
 803                if(!options) {
 804                        if(!filename)
 805                                filename = argv[i];
 806                        else if(!commit)
 807                                commit = argv[i];
 808                        else
 809                                usage(blame_usage);
 810                }
 811        }
 812
 813        if(!filename)
 814                usage(blame_usage);
 815        if (commit && sha1_p)
 816                usage(blame_usage);
 817        else if(!commit)
 818                commit = "HEAD";
 819
 820        if(prefix)
 821                sprintf(filename_buf, "%s%s", prefix, filename);
 822        else
 823                strcpy(filename_buf, filename);
 824        filename = filename_buf;
 825
 826        if (!sha1_p) {
 827                if (get_sha1(commit, sha1))
 828                        die("get_sha1 failed, commit '%s' not found", commit);
 829                sha1_p = sha1;
 830        }
 831        start_commit = lookup_commit_reference(sha1_p);
 832        get_util(start_commit)->pathname = filename;
 833        if (fill_util_info(start_commit)) {
 834                printf("%s not found in %s\n", filename, commit);
 835                return 1;
 836        }
 837
 838
 839        init_revisions(&rev, setup_git_directory());
 840        rev.remove_empty_trees = 1;
 841        rev.topo_order = 1;
 842        rev.prune_fn = simplify_commit;
 843        rev.topo_setter = topo_setter;
 844        rev.topo_getter = topo_getter;
 845        rev.parents = 1;
 846        rev.limited = 1;
 847
 848        commit_list_insert(start_commit, &rev.commits);
 849
 850        args[0] = filename;
 851        args[1] = NULL;
 852        diff_tree_setup_paths(args, &rev.pruning);
 853        prepare_revision_walk(&rev);
 854        process_commits(&rev, filename, &initial);
 855
 856        buf = blame_contents;
 857        for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++)
 858                i *= 10;
 859
 860        longest_file = 0;
 861        longest_author = 0;
 862        found_rename = 0;
 863        for (i = 0; i < num_blame_lines; i++) {
 864                struct commit *c = blame_lines[i];
 865                struct util_info* u;
 866                if (!c)
 867                        c = initial;
 868                u = c->util;
 869
 870                if (!found_rename && strcmp(filename, u->pathname))
 871                        found_rename = 1;
 872                if (longest_file < strlen(u->pathname))
 873                        longest_file = strlen(u->pathname);
 874                get_commit_info(c, &ci);
 875                if (longest_author < strlen(ci.author))
 876                        longest_author = strlen(ci.author);
 877        }
 878
 879        for (i = 0; i < num_blame_lines; i++) {
 880                struct commit *c = blame_lines[i];
 881                struct util_info* u;
 882
 883                if (!c)
 884                        c = initial;
 885
 886                u = c->util;
 887                get_commit_info(c, &ci);
 888                fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
 889                if(compatibility) {
 890                        printf("\t(%10s\t%10s\t%d)", ci.author,
 891                               format_time(ci.author_time, ci.author_tz,
 892                                           show_raw_time),
 893                               i+1);
 894                } else {
 895                        if (found_rename)
 896                                printf(" %-*.*s", longest_file, longest_file,
 897                                       u->pathname);
 898                        printf(" (%-*.*s %10s %*d) ",
 899                               longest_author, longest_author, ci.author,
 900                               format_time(ci.author_time, ci.author_tz,
 901                                           show_raw_time),
 902                               max_digits, i+1);
 903                }
 904
 905                if(i == num_blame_lines - 1) {
 906                        fwrite(buf, blame_len - (buf - blame_contents),
 907                               1, stdout);
 908                        if(blame_contents[blame_len-1] != '\n')
 909                                putc('\n', stdout);
 910                } else {
 911                        char* next_buf = strchr(buf, '\n') + 1;
 912                        fwrite(buf, next_buf - buf, 1, stdout);
 913                        buf = next_buf;
 914                }
 915        }
 916
 917        if (DEBUG) {
 918                printf("num get patch: %d\n", num_get_patch);
 919                printf("num commits: %d\n", num_commits);
 920                printf("patch time: %f\n", patch_time / 1000000.0);
 921                printf("initial: %s\n", sha1_to_hex(initial->object.sha1));
 922        }
 923
 924        return 0;
 925}