blame.con commit Merge git://git.kernel.org/pub/scm/gitk/gitk (659db3f)
   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#include "quote.h"
  21
  22#ifndef DEBUG
  23#define DEBUG 0
  24#endif
  25
  26static const char blame_usage[] =
  27"git-blame [-c] [-l] [-t] [-f] [-n] [-p] [-S <revs-file>] [--] file [commit]\n"
  28"  -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
  29"  -l, --long          Show long commit SHA1 (Default: off)\n"
  30"  -t, --time          Show raw timestamp (Default: off)\n"
  31"  -f, --show-name     Show original filename (Default: auto)\n"
  32"  -n, --show-number   Show original linenumber (Default: off)\n"
  33"  -p, --porcelain     Show in a format designed for machine consumption\n"
  34"  -S revs-file        Use revisions from revs-file instead of calling git-rev-list\n"
  35"  -h, --help          This message";
  36
  37static struct commit **blame_lines;
  38static int num_blame_lines;
  39static char *blame_contents;
  40static int blame_len;
  41
  42struct util_info {
  43        int *line_map;
  44        unsigned char sha1[20]; /* blob sha, not commit! */
  45        char *buf;
  46        unsigned long size;
  47        int num_lines;
  48        const char *pathname;
  49        unsigned meta_given:1;
  50
  51        void *topo_data;
  52};
  53
  54struct chunk {
  55        int off1, len1; /* --- */
  56        int off2, len2; /* +++ */
  57};
  58
  59struct patch {
  60        struct chunk *chunks;
  61        int num;
  62};
  63
  64static void get_blob(struct commit *commit);
  65
  66/* Only used for statistics */
  67static int num_get_patch;
  68static int num_commits;
  69static int patch_time;
  70static int num_read_blob;
  71
  72struct blame_diff_state {
  73        struct xdiff_emit_state xm;
  74        struct patch *ret;
  75};
  76
  77static void process_u0_diff(void *state_, char *line, unsigned long len)
  78{
  79        struct blame_diff_state *state = state_;
  80        struct chunk *chunk;
  81
  82        if (len < 4 || line[0] != '@' || line[1] != '@')
  83                return;
  84
  85        if (DEBUG)
  86                printf("chunk line: %.*s", (int)len, line);
  87        state->ret->num++;
  88        state->ret->chunks = xrealloc(state->ret->chunks,
  89                                      sizeof(struct chunk) * state->ret->num);
  90        chunk = &state->ret->chunks[state->ret->num - 1];
  91
  92        assert(!strncmp(line, "@@ -", 4));
  93
  94        if (parse_hunk_header(line, len,
  95                              &chunk->off1, &chunk->len1,
  96                              &chunk->off2, &chunk->len2)) {
  97                state->ret->num--;
  98                return;
  99        }
 100
 101        if (chunk->len1 == 0)
 102                chunk->off1++;
 103        if (chunk->len2 == 0)
 104                chunk->off2++;
 105
 106        if (chunk->off1 > 0)
 107                chunk->off1--;
 108        if (chunk->off2 > 0)
 109                chunk->off2--;
 110
 111        assert(chunk->off1 >= 0);
 112        assert(chunk->off2 >= 0);
 113}
 114
 115static struct patch *get_patch(struct commit *commit, struct commit *other)
 116{
 117        struct blame_diff_state state;
 118        xpparam_t xpp;
 119        xdemitconf_t xecfg;
 120        mmfile_t file_c, file_o;
 121        xdemitcb_t ecb;
 122        struct util_info *info_c = (struct util_info *)commit->util;
 123        struct util_info *info_o = (struct util_info *)other->util;
 124        struct timeval tv_start, tv_end;
 125
 126        get_blob(commit);
 127        file_c.ptr = info_c->buf;
 128        file_c.size = info_c->size;
 129
 130        get_blob(other);
 131        file_o.ptr = info_o->buf;
 132        file_o.size = info_o->size;
 133
 134        gettimeofday(&tv_start, NULL);
 135
 136        xpp.flags = XDF_NEED_MINIMAL;
 137        xecfg.ctxlen = 0;
 138        xecfg.flags = 0;
 139        ecb.outf = xdiff_outf;
 140        ecb.priv = &state;
 141        memset(&state, 0, sizeof(state));
 142        state.xm.consume = process_u0_diff;
 143        state.ret = xmalloc(sizeof(struct patch));
 144        state.ret->chunks = NULL;
 145        state.ret->num = 0;
 146
 147        xdl_diff(&file_c, &file_o, &xpp, &xecfg, &ecb);
 148
 149        gettimeofday(&tv_end, NULL);
 150        patch_time += 1000000 * (tv_end.tv_sec - tv_start.tv_sec) +
 151                tv_end.tv_usec - tv_start.tv_usec;
 152
 153        num_get_patch++;
 154        return state.ret;
 155}
 156
 157static void free_patch(struct patch *p)
 158{
 159        free(p->chunks);
 160        free(p);
 161}
 162
 163static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
 164                                  int baselen, const char *pathname,
 165                                  unsigned mode, int stage);
 166
 167static unsigned char blob_sha1[20];
 168static const char *blame_file;
 169static int get_blob_sha1(struct tree *t, const char *pathname,
 170                         unsigned char *sha1)
 171{
 172        const char *pathspec[2];
 173        blame_file = pathname;
 174        pathspec[0] = pathname;
 175        pathspec[1] = NULL;
 176        hashclr(blob_sha1);
 177        read_tree_recursive(t, "", 0, 0, pathspec, get_blob_sha1_internal);
 178
 179        if (is_null_sha1(blob_sha1))
 180                return -1;
 181
 182        hashcpy(sha1, blob_sha1);
 183        return 0;
 184}
 185
 186static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
 187                                  int baselen, const char *pathname,
 188                                  unsigned mode, int stage)
 189{
 190        if (S_ISDIR(mode))
 191                return READ_TREE_RECURSIVE;
 192
 193        if (strncmp(blame_file, base, baselen) ||
 194            strcmp(blame_file + baselen, pathname))
 195                return -1;
 196
 197        hashcpy(blob_sha1, sha1);
 198        return -1;
 199}
 200
 201static void get_blob(struct commit *commit)
 202{
 203        struct util_info *info = commit->util;
 204        char type[20];
 205
 206        if (info->buf)
 207                return;
 208
 209        info->buf = read_sha1_file(info->sha1, type, &info->size);
 210        num_read_blob++;
 211
 212        assert(!strcmp(type, blob_type));
 213}
 214
 215/* For debugging only */
 216static void print_patch(struct patch *p)
 217{
 218        int i;
 219        printf("Num chunks: %d\n", p->num);
 220        for (i = 0; i < p->num; i++) {
 221                printf("%d,%d %d,%d\n", p->chunks[i].off1, p->chunks[i].len1,
 222                       p->chunks[i].off2, p->chunks[i].len2);
 223        }
 224}
 225
 226#if DEBUG
 227/* For debugging only */
 228static void print_map(struct commit *cmit, struct commit *other)
 229{
 230        struct util_info *util = cmit->util;
 231        struct util_info *util2 = other->util;
 232
 233        int i;
 234        int max =
 235            util->num_lines >
 236            util2->num_lines ? util->num_lines : util2->num_lines;
 237        int num;
 238
 239        if (print_map == NULL)
 240                ; /* to avoid "unused function" warning */
 241
 242        for (i = 0; i < max; i++) {
 243                printf("i: %d ", i);
 244                num = -1;
 245
 246                if (i < util->num_lines) {
 247                        num = util->line_map[i];
 248                        printf("%d\t", num);
 249                }
 250                else
 251                        printf("\t");
 252
 253                if (i < util2->num_lines) {
 254                        int num2 = util2->line_map[i];
 255                        printf("%d\t", num2);
 256                        if (num != -1 && num2 != num)
 257                                printf("---");
 258                }
 259                else
 260                        printf("\t");
 261
 262                printf("\n");
 263        }
 264}
 265#endif
 266
 267/* p is a patch from commit to other. */
 268static void fill_line_map(struct commit *commit, struct commit *other,
 269                          struct patch *p)
 270{
 271        struct util_info *util = commit->util;
 272        struct util_info *util2 = other->util;
 273        int *map = util->line_map;
 274        int *map2 = util2->line_map;
 275        int cur_chunk = 0;
 276        int i1, i2;
 277
 278        if (DEBUG) {
 279                if (p->num)
 280                        print_patch(p);
 281                printf("num lines 1: %d num lines 2: %d\n", util->num_lines,
 282                       util2->num_lines);
 283        }
 284
 285        for (i1 = 0, i2 = 0; i1 < util->num_lines; i1++, i2++) {
 286                struct chunk *chunk = NULL;
 287                if (cur_chunk < p->num)
 288                        chunk = &p->chunks[cur_chunk];
 289
 290                if (chunk && chunk->off1 == i1) {
 291                        if (DEBUG && i2 != chunk->off2)
 292                                printf("i2: %d off2: %d\n", i2, chunk->off2);
 293
 294                        assert(i2 == chunk->off2);
 295
 296                        i1--;
 297                        i2--;
 298                        if (chunk->len1 > 0)
 299                                i1 += chunk->len1;
 300
 301                        if (chunk->len2 > 0)
 302                                i2 += chunk->len2;
 303
 304                        cur_chunk++;
 305                }
 306                else {
 307                        if (i2 >= util2->num_lines)
 308                                break;
 309
 310                        if (map[i1] != map2[i2] && map[i1] != -1) {
 311                                if (DEBUG)
 312                                        printf("map: i1: %d %d %p i2: %d %d %p\n",
 313                                               i1, map[i1],
 314                                               (void *) (i1 != -1 ? blame_lines[map[i1]] : NULL),
 315                                               i2, map2[i2],
 316                                               (void *) (i2 != -1 ? blame_lines[map2[i2]] : NULL));
 317                                if (map2[i2] != -1 &&
 318                                    blame_lines[map[i1]] &&
 319                                    !blame_lines[map2[i2]])
 320                                        map[i1] = map2[i2];
 321                        }
 322
 323                        if (map[i1] == -1 && map2[i2] != -1)
 324                                map[i1] = map2[i2];
 325                }
 326
 327                if (DEBUG > 1)
 328                        printf("l1: %d l2: %d i1: %d i2: %d\n",
 329                               map[i1], map2[i2], i1, i2);
 330        }
 331}
 332
 333static int map_line(struct commit *commit, int line)
 334{
 335        struct util_info *info = commit->util;
 336        assert(line >= 0 && line < info->num_lines);
 337        return info->line_map[line];
 338}
 339
 340static struct util_info *get_util(struct commit *commit)
 341{
 342        struct util_info *util = commit->util;
 343
 344        if (util)
 345                return util;
 346
 347        util = xcalloc(1, sizeof(struct util_info));
 348        util->num_lines = -1;
 349        commit->util = util;
 350        return util;
 351}
 352
 353static int fill_util_info(struct commit *commit)
 354{
 355        struct util_info *util = commit->util;
 356
 357        assert(util);
 358        assert(util->pathname);
 359
 360        return !!get_blob_sha1(commit->tree, util->pathname, util->sha1);
 361}
 362
 363static void alloc_line_map(struct commit *commit)
 364{
 365        struct util_info *util = commit->util;
 366        int i;
 367
 368        if (util->line_map)
 369                return;
 370
 371        get_blob(commit);
 372
 373        util->num_lines = 0;
 374        for (i = 0; i < util->size; i++) {
 375                if (util->buf[i] == '\n')
 376                        util->num_lines++;
 377        }
 378        if (util->buf[util->size - 1] != '\n')
 379                util->num_lines++;
 380
 381        util->line_map = xmalloc(sizeof(int) * util->num_lines);
 382
 383        for (i = 0; i < util->num_lines; i++)
 384                util->line_map[i] = -1;
 385}
 386
 387static void init_first_commit(struct commit *commit, const char *filename)
 388{
 389        struct util_info *util = commit->util;
 390        int i;
 391
 392        util->pathname = filename;
 393        if (fill_util_info(commit))
 394                die("fill_util_info failed");
 395
 396        alloc_line_map(commit);
 397
 398        util = commit->util;
 399
 400        for (i = 0; i < util->num_lines; i++)
 401                util->line_map[i] = i;
 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
 511static int compare_tree_path(struct rev_info *revs,
 512                             struct commit *c1, struct commit *c2)
 513{
 514        int ret;
 515        const char *paths[2];
 516        struct util_info *util = c2->util;
 517        paths[0] = util->pathname;
 518        paths[1] = NULL;
 519
 520        diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
 521                              &revs->pruning);
 522        ret = rev_compare_tree(revs, c1->tree, c2->tree);
 523        diff_tree_release_paths(&revs->pruning);
 524        return ret;
 525}
 526
 527static int same_tree_as_empty_path(struct rev_info *revs, struct tree *t1,
 528                                   const char *path)
 529{
 530        int ret;
 531        const char *paths[2];
 532        paths[0] = path;
 533        paths[1] = NULL;
 534
 535        diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
 536                              &revs->pruning);
 537        ret = rev_same_tree_as_empty(revs, t1);
 538        diff_tree_release_paths(&revs->pruning);
 539        return ret;
 540}
 541
 542static const char *find_rename(struct commit *commit, struct commit *parent)
 543{
 544        struct util_info *cutil = commit->util;
 545        struct diff_options diff_opts;
 546        const char *paths[1];
 547        int i;
 548
 549        if (DEBUG) {
 550                printf("find_rename commit: %s ",
 551                       sha1_to_hex(commit->object.sha1));
 552                puts(sha1_to_hex(parent->object.sha1));
 553        }
 554
 555        diff_setup(&diff_opts);
 556        diff_opts.recursive = 1;
 557        diff_opts.detect_rename = DIFF_DETECT_RENAME;
 558        paths[0] = NULL;
 559        diff_tree_setup_paths(paths, &diff_opts);
 560        if (diff_setup_done(&diff_opts) < 0)
 561                die("diff_setup_done failed");
 562
 563        diff_tree_sha1(commit->tree->object.sha1, parent->tree->object.sha1,
 564                       "", &diff_opts);
 565        diffcore_std(&diff_opts);
 566
 567        for (i = 0; i < diff_queued_diff.nr; i++) {
 568                struct diff_filepair *p = diff_queued_diff.queue[i];
 569
 570                if (p->status == 'R' &&
 571                    !strcmp(p->one->path, cutil->pathname)) {
 572                        if (DEBUG)
 573                                printf("rename %s -> %s\n",
 574                                       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                        struct util_info *util = commit->util;
 617                        if (revs->remove_empty_trees &&
 618                            same_tree_as_empty_path(revs, p->tree,
 619                                                    util->pathname)) {
 620                                const char *new_name = find_rename(commit, p);
 621                                if (new_name) {
 622                                        struct util_info *putil = get_util(p);
 623                                        if (!putil->pathname)
 624                                                putil->pathname = xstrdup(new_name);
 625                                }
 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
 647struct commit_info
 648{
 649        char *author;
 650        char *author_mail;
 651        unsigned long author_time;
 652        char *author_tz;
 653
 654        /* filled only when asked for details */
 655        char *committer;
 656        char *committer_mail;
 657        unsigned long committer_time;
 658        char *committer_tz;
 659
 660        char *summary;
 661};
 662
 663static void get_ac_line(const char *inbuf, const char *what,
 664                        int bufsz, char *person, char **mail,
 665                        unsigned long *time, char **tz)
 666{
 667        int len;
 668        char *tmp, *endp;
 669
 670        tmp = strstr(inbuf, what);
 671        if (!tmp)
 672                goto error_out;
 673        tmp += strlen(what);
 674        endp = strchr(tmp, '\n');
 675        if (!endp)
 676                len = strlen(tmp);
 677        else
 678                len = endp - tmp;
 679        if (bufsz <= len) {
 680        error_out:
 681                /* Ugh */
 682                person = *mail = *tz = "(unknown)";
 683                *time = 0;
 684                return;
 685        }
 686        memcpy(person, tmp, len);
 687
 688        tmp = person;
 689        tmp += len;
 690        *tmp = 0;
 691        while (*tmp != ' ')
 692                tmp--;
 693        *tz = tmp+1;
 694
 695        *tmp = 0;
 696        while (*tmp != ' ')
 697                tmp--;
 698        *time = strtoul(tmp, NULL, 10);
 699
 700        *tmp = 0;
 701        while (*tmp != ' ')
 702                tmp--;
 703        *mail = tmp + 1;
 704        *tmp = 0;
 705}
 706
 707static void get_commit_info(struct commit *commit, struct commit_info *ret, int detailed)
 708{
 709        int len;
 710        char *tmp, *endp;
 711        static char author_buf[1024];
 712        static char committer_buf[1024];
 713        static char summary_buf[1024];
 714
 715        ret->author = author_buf;
 716        get_ac_line(commit->buffer, "\nauthor ",
 717                    sizeof(author_buf), author_buf, &ret->author_mail,
 718                    &ret->author_time, &ret->author_tz);
 719
 720        if (!detailed)
 721                return;
 722
 723        ret->committer = committer_buf;
 724        get_ac_line(commit->buffer, "\ncommitter ",
 725                    sizeof(committer_buf), committer_buf, &ret->committer_mail,
 726                    &ret->committer_time, &ret->committer_tz);
 727
 728        ret->summary = summary_buf;
 729        tmp = strstr(commit->buffer, "\n\n");
 730        if (!tmp) {
 731        error_out:
 732                sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1));
 733                return;
 734        }
 735        tmp += 2;
 736        endp = strchr(tmp, '\n');
 737        if (!endp)
 738                goto error_out;
 739        len = endp - tmp;
 740        if (len >= sizeof(summary_buf))
 741                goto error_out;
 742        memcpy(summary_buf, tmp, len);
 743        summary_buf[len] = 0;
 744}
 745
 746static const char *format_time(unsigned long time, const char *tz_str,
 747                               int show_raw_time)
 748{
 749        static char time_buf[128];
 750        time_t t = time;
 751        int minutes, tz;
 752        struct tm *tm;
 753
 754        if (show_raw_time) {
 755                sprintf(time_buf, "%lu %s", time, tz_str);
 756                return time_buf;
 757        }
 758
 759        tz = atoi(tz_str);
 760        minutes = tz < 0 ? -tz : tz;
 761        minutes = (minutes / 100)*60 + (minutes % 100);
 762        minutes = tz < 0 ? -minutes : minutes;
 763        t = time + minutes * 60;
 764        tm = gmtime(&t);
 765
 766        strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
 767        strcat(time_buf, tz_str);
 768        return time_buf;
 769}
 770
 771static void topo_setter(struct commit *c, void *data)
 772{
 773        struct util_info *util = c->util;
 774        util->topo_data = data;
 775}
 776
 777static void *topo_getter(struct commit *c)
 778{
 779        struct util_info *util = c->util;
 780        return util->topo_data;
 781}
 782
 783static int read_ancestry(const char *graft_file,
 784                         unsigned char **start_sha1)
 785{
 786        FILE *fp = fopen(graft_file, "r");
 787        char buf[1024];
 788        if (!fp)
 789                return -1;
 790        while (fgets(buf, sizeof(buf), fp)) {
 791                /* The format is just "Commit Parent1 Parent2 ...\n" */
 792                int len = strlen(buf);
 793                struct commit_graft *graft = read_graft_line(buf, len);
 794                register_commit_graft(graft, 0);
 795                if (!*start_sha1)
 796                        *start_sha1 = graft->sha1;
 797        }
 798        fclose(fp);
 799        return 0;
 800}
 801
 802static int lineno_width(int lines)
 803{
 804        int i, width;
 805
 806        for (width = 1, i = 10; i <= lines + 1; width++)
 807                i *= 10;
 808        return width;
 809}
 810
 811static int find_orig_linenum(struct util_info *u, int lineno)
 812{
 813        int i;
 814
 815        for (i = 0; i < u->num_lines; i++)
 816                if (lineno == u->line_map[i])
 817                        return i + 1;
 818        return 0;
 819}
 820
 821static void emit_meta(struct commit *c, int lno,
 822                      int sha1_len, int compatibility, int porcelain,
 823                      int show_name, int show_number, int show_raw_time,
 824                      int longest_file, int longest_author,
 825                      int max_digits, int max_orig_digits)
 826{
 827        struct util_info *u;
 828        int lineno;
 829        struct commit_info ci;
 830
 831        u = c->util;
 832        lineno = find_orig_linenum(u, lno);
 833
 834        if (porcelain) {
 835                int group_size = -1;
 836                struct commit *cc = (lno == 0) ? NULL : blame_lines[lno-1];
 837                if (cc != c) {
 838                        /* This is the beginning of this group */
 839                        int i;
 840                        for (i = lno + 1; i < num_blame_lines; i++)
 841                                if (blame_lines[i] != c)
 842                                        break;
 843                        group_size = i - lno;
 844                }
 845                if (0 < group_size)
 846                        printf("%s %d %d %d\n", sha1_to_hex(c->object.sha1),
 847                               lineno, lno + 1, group_size);
 848                else
 849                        printf("%s %d %d\n", sha1_to_hex(c->object.sha1),
 850                               lineno, lno + 1);
 851                if (!u->meta_given) {
 852                        get_commit_info(c, &ci, 1);
 853                        printf("author %s\n", ci.author);
 854                        printf("author-mail %s\n", ci.author_mail);
 855                        printf("author-time %lu\n", ci.author_time);
 856                        printf("author-tz %s\n", ci.author_tz);
 857                        printf("committer %s\n", ci.committer);
 858                        printf("committer-mail %s\n", ci.committer_mail);
 859                        printf("committer-time %lu\n", ci.committer_time);
 860                        printf("committer-tz %s\n", ci.committer_tz);
 861                        printf("filename ");
 862                        if (quote_c_style(u->pathname, NULL, NULL, 0))
 863                                quote_c_style(u->pathname, NULL, stdout, 0);
 864                        else
 865                                fputs(u->pathname, stdout);
 866                        printf("\nsummary %s\n", ci.summary);
 867
 868                        u->meta_given = 1;
 869                }
 870                putchar('\t');
 871                return;
 872        }
 873
 874        get_commit_info(c, &ci, 0);
 875        fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
 876        if (compatibility) {
 877                printf("\t(%10s\t%10s\t%d)", ci.author,
 878                       format_time(ci.author_time, ci.author_tz,
 879                                   show_raw_time),
 880                       lno + 1);
 881        }
 882        else {
 883                if (show_name)
 884                        printf(" %-*.*s", longest_file, longest_file,
 885                               u->pathname);
 886                if (show_number)
 887                        printf(" %*d", max_orig_digits,
 888                               lineno);
 889                printf(" (%-*.*s %10s %*d) ",
 890                       longest_author, longest_author, ci.author,
 891                       format_time(ci.author_time, ci.author_tz,
 892                                   show_raw_time),
 893                       max_digits, lno + 1);
 894        }
 895}
 896
 897int main(int argc, const char **argv)
 898{
 899        int i;
 900        struct commit *initial = NULL;
 901        unsigned char sha1[20], *sha1_p = NULL;
 902
 903        const char *filename = NULL, *commit = NULL;
 904        char filename_buf[256];
 905        int sha1_len = 8;
 906        int compatibility = 0;
 907        int show_raw_time = 0;
 908        int options = 1;
 909        struct commit *start_commit;
 910
 911        const char *args[10];
 912        struct rev_info rev;
 913
 914        struct commit_info ci;
 915        const char *buf;
 916        int max_digits, max_orig_digits;
 917        int longest_file, longest_author, longest_file_lines;
 918        int show_name = 0;
 919        int show_number = 0;
 920        int porcelain = 0;
 921
 922        const char *prefix = setup_git_directory();
 923        git_config(git_default_config);
 924
 925        for (i = 1; i < argc; i++) {
 926                if (options) {
 927                        if (!strcmp(argv[i], "-h") ||
 928                           !strcmp(argv[i], "--help"))
 929                                usage(blame_usage);
 930                        if (!strcmp(argv[i], "-l") ||
 931                            !strcmp(argv[i], "--long")) {
 932                                sha1_len = 40;
 933                                continue;
 934                        }
 935                        if (!strcmp(argv[i], "-c") ||
 936                            !strcmp(argv[i], "--compatibility")) {
 937                                compatibility = 1;
 938                                continue;
 939                        }
 940                        if (!strcmp(argv[i], "-t") ||
 941                            !strcmp(argv[i], "--time")) {
 942                                show_raw_time = 1;
 943                                continue;
 944                        }
 945                        if (!strcmp(argv[i], "-S")) {
 946                                if (i + 1 < argc &&
 947                                    !read_ancestry(argv[i + 1], &sha1_p)) {
 948                                        compatibility = 1;
 949                                        i++;
 950                                        continue;
 951                                }
 952                                usage(blame_usage);
 953                        }
 954                        if (!strcmp(argv[i], "-f") ||
 955                            !strcmp(argv[i], "--show-name")) {
 956                                show_name = 1;
 957                                continue;
 958                        }
 959                        if (!strcmp(argv[i], "-n") ||
 960                            !strcmp(argv[i], "--show-number")) {
 961                                show_number = 1;
 962                                continue;
 963                        }
 964                        if (!strcmp(argv[i], "-p") ||
 965                            !strcmp(argv[i], "--porcelain")) {
 966                                porcelain = 1;
 967                                sha1_len = 40;
 968                                show_raw_time = 1;
 969                                continue;
 970                        }
 971                        if (!strcmp(argv[i], "--")) {
 972                                options = 0;
 973                                continue;
 974                        }
 975                        if (argv[i][0] == '-')
 976                                usage(blame_usage);
 977                        options = 0;
 978                }
 979
 980                if (!options) {
 981                        if (!filename)
 982                                filename = argv[i];
 983                        else if (!commit)
 984                                commit = argv[i];
 985                        else
 986                                usage(blame_usage);
 987                }
 988        }
 989
 990        if (!filename)
 991                usage(blame_usage);
 992        if (commit && sha1_p)
 993                usage(blame_usage);
 994        else if (!commit)
 995                commit = "HEAD";
 996
 997        if (prefix)
 998                sprintf(filename_buf, "%s%s", prefix, filename);
 999        else
1000                strcpy(filename_buf, filename);
1001        filename = filename_buf;
1002
1003        if (!sha1_p) {
1004                if (get_sha1(commit, sha1))
1005                        die("get_sha1 failed, commit '%s' not found", commit);
1006                sha1_p = sha1;
1007        }
1008        start_commit = lookup_commit_reference(sha1_p);
1009        get_util(start_commit)->pathname = filename;
1010        if (fill_util_info(start_commit)) {
1011                printf("%s not found in %s\n", filename, commit);
1012                return 1;
1013        }
1014
1015        init_revisions(&rev, setup_git_directory());
1016        rev.remove_empty_trees = 1;
1017        rev.topo_order = 1;
1018        rev.prune_fn = simplify_commit;
1019        rev.topo_setter = topo_setter;
1020        rev.topo_getter = topo_getter;
1021        rev.parents = 1;
1022        rev.limited = 1;
1023
1024        commit_list_insert(start_commit, &rev.commits);
1025
1026        args[0] = filename;
1027        args[1] = NULL;
1028        diff_tree_setup_paths(args, &rev.pruning);
1029        prepare_revision_walk(&rev);
1030        process_commits(&rev, filename, &initial);
1031
1032        for (i = 0; i < num_blame_lines; i++)
1033                if (!blame_lines[i])
1034                        blame_lines[i] = initial;
1035
1036        buf = blame_contents;
1037        max_digits = lineno_width(num_blame_lines);
1038
1039        longest_file = 0;
1040        longest_author = 0;
1041        longest_file_lines = 0;
1042        for (i = 0; i < num_blame_lines; i++) {
1043                struct commit *c = blame_lines[i];
1044                struct util_info *u;
1045                u = c->util;
1046
1047                if (!show_name && strcmp(filename, u->pathname))
1048                        show_name = 1;
1049                if (longest_file < strlen(u->pathname))
1050                        longest_file = strlen(u->pathname);
1051                if (longest_file_lines < u->num_lines)
1052                        longest_file_lines = u->num_lines;
1053                get_commit_info(c, &ci, 0);
1054                if (longest_author < strlen(ci.author))
1055                        longest_author = strlen(ci.author);
1056        }
1057
1058        max_orig_digits = lineno_width(longest_file_lines);
1059
1060        for (i = 0; i < num_blame_lines; i++) {
1061                emit_meta(blame_lines[i], i,
1062                          sha1_len, compatibility, porcelain,
1063                          show_name, show_number, show_raw_time,
1064                          longest_file, longest_author,
1065                          max_digits, max_orig_digits);
1066
1067                if (i == num_blame_lines - 1) {
1068                        fwrite(buf, blame_len - (buf - blame_contents),
1069                               1, stdout);
1070                        if (blame_contents[blame_len-1] != '\n')
1071                                putc('\n', stdout);
1072                }
1073                else {
1074                        char *next_buf = strchr(buf, '\n') + 1;
1075                        fwrite(buf, next_buf - buf, 1, stdout);
1076                        buf = next_buf;
1077                }
1078        }
1079
1080        if (DEBUG) {
1081                printf("num read blob: %d\n", num_read_blob);
1082                printf("num get patch: %d\n", num_get_patch);
1083                printf("num commits: %d\n", num_commits);
1084                printf("patch time: %f\n", patch_time / 1000000.0);
1085                printf("initial: %s\n", sha1_to_hex(initial->object.sha1));
1086        }
1087
1088        return 0;
1089}