builtin / blame.con commit builtin/blame: dim uninteresting metadata lines (cdc2d5f)
   1/*
   2 * Blame
   3 *
   4 * Copyright (c) 2006, 2014 by its authors
   5 * See COPYING for licensing conditions
   6 */
   7
   8#include "cache.h"
   9#include "config.h"
  10#include "color.h"
  11#include "builtin.h"
  12#include "commit.h"
  13#include "diff.h"
  14#include "revision.h"
  15#include "quote.h"
  16#include "string-list.h"
  17#include "mailmap.h"
  18#include "parse-options.h"
  19#include "prio-queue.h"
  20#include "utf8.h"
  21#include "userdiff.h"
  22#include "line-range.h"
  23#include "line-log.h"
  24#include "dir.h"
  25#include "progress.h"
  26#include "blame.h"
  27
  28static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
  29
  30static const char *blame_opt_usage[] = {
  31        blame_usage,
  32        "",
  33        N_("<rev-opts> are documented in git-rev-list(1)"),
  34        NULL
  35};
  36
  37static int longest_file;
  38static int longest_author;
  39static int max_orig_digits;
  40static int max_digits;
  41static int max_score_digits;
  42static int show_root;
  43static int reverse;
  44static int blank_boundary;
  45static int incremental;
  46static int xdl_opts;
  47static int abbrev = -1;
  48static int no_whole_file_rename;
  49static int show_progress;
  50static char repeated_meta_color[COLOR_MAXLEN];
  51
  52static struct date_mode blame_date_mode = { DATE_ISO8601 };
  53static size_t blame_date_width;
  54
  55static struct string_list mailmap = STRING_LIST_INIT_NODUP;
  56
  57#ifndef DEBUG
  58#define DEBUG 0
  59#endif
  60
  61static unsigned blame_move_score;
  62static unsigned blame_copy_score;
  63
  64/* Remember to update object flag allocation in object.h */
  65#define METAINFO_SHOWN          (1u<<12)
  66#define MORE_THAN_ONE_PATH      (1u<<13)
  67
  68struct progress_info {
  69        struct progress *progress;
  70        int blamed_lines;
  71};
  72
  73static const char *nth_line_cb(void *data, long lno)
  74{
  75        return blame_nth_line((struct blame_scoreboard *)data, lno);
  76}
  77
  78/*
  79 * Information on commits, used for output.
  80 */
  81struct commit_info {
  82        struct strbuf author;
  83        struct strbuf author_mail;
  84        timestamp_t author_time;
  85        struct strbuf author_tz;
  86
  87        /* filled only when asked for details */
  88        struct strbuf committer;
  89        struct strbuf committer_mail;
  90        timestamp_t committer_time;
  91        struct strbuf committer_tz;
  92
  93        struct strbuf summary;
  94};
  95
  96/*
  97 * Parse author/committer line in the commit object buffer
  98 */
  99static void get_ac_line(const char *inbuf, const char *what,
 100        struct strbuf *name, struct strbuf *mail,
 101        timestamp_t *time, struct strbuf *tz)
 102{
 103        struct ident_split ident;
 104        size_t len, maillen, namelen;
 105        char *tmp, *endp;
 106        const char *namebuf, *mailbuf;
 107
 108        tmp = strstr(inbuf, what);
 109        if (!tmp)
 110                goto error_out;
 111        tmp += strlen(what);
 112        endp = strchr(tmp, '\n');
 113        if (!endp)
 114                len = strlen(tmp);
 115        else
 116                len = endp - tmp;
 117
 118        if (split_ident_line(&ident, tmp, len)) {
 119        error_out:
 120                /* Ugh */
 121                tmp = "(unknown)";
 122                strbuf_addstr(name, tmp);
 123                strbuf_addstr(mail, tmp);
 124                strbuf_addstr(tz, tmp);
 125                *time = 0;
 126                return;
 127        }
 128
 129        namelen = ident.name_end - ident.name_begin;
 130        namebuf = ident.name_begin;
 131
 132        maillen = ident.mail_end - ident.mail_begin;
 133        mailbuf = ident.mail_begin;
 134
 135        if (ident.date_begin && ident.date_end)
 136                *time = strtoul(ident.date_begin, NULL, 10);
 137        else
 138                *time = 0;
 139
 140        if (ident.tz_begin && ident.tz_end)
 141                strbuf_add(tz, ident.tz_begin, ident.tz_end - ident.tz_begin);
 142        else
 143                strbuf_addstr(tz, "(unknown)");
 144
 145        /*
 146         * Now, convert both name and e-mail using mailmap
 147         */
 148        map_user(&mailmap, &mailbuf, &maillen,
 149                 &namebuf, &namelen);
 150
 151        strbuf_addf(mail, "<%.*s>", (int)maillen, mailbuf);
 152        strbuf_add(name, namebuf, namelen);
 153}
 154
 155static void commit_info_init(struct commit_info *ci)
 156{
 157
 158        strbuf_init(&ci->author, 0);
 159        strbuf_init(&ci->author_mail, 0);
 160        strbuf_init(&ci->author_tz, 0);
 161        strbuf_init(&ci->committer, 0);
 162        strbuf_init(&ci->committer_mail, 0);
 163        strbuf_init(&ci->committer_tz, 0);
 164        strbuf_init(&ci->summary, 0);
 165}
 166
 167static void commit_info_destroy(struct commit_info *ci)
 168{
 169
 170        strbuf_release(&ci->author);
 171        strbuf_release(&ci->author_mail);
 172        strbuf_release(&ci->author_tz);
 173        strbuf_release(&ci->committer);
 174        strbuf_release(&ci->committer_mail);
 175        strbuf_release(&ci->committer_tz);
 176        strbuf_release(&ci->summary);
 177}
 178
 179static void get_commit_info(struct commit *commit,
 180                            struct commit_info *ret,
 181                            int detailed)
 182{
 183        int len;
 184        const char *subject, *encoding;
 185        const char *message;
 186
 187        commit_info_init(ret);
 188
 189        encoding = get_log_output_encoding();
 190        message = logmsg_reencode(commit, NULL, encoding);
 191        get_ac_line(message, "\nauthor ",
 192                    &ret->author, &ret->author_mail,
 193                    &ret->author_time, &ret->author_tz);
 194
 195        if (!detailed) {
 196                unuse_commit_buffer(commit, message);
 197                return;
 198        }
 199
 200        get_ac_line(message, "\ncommitter ",
 201                    &ret->committer, &ret->committer_mail,
 202                    &ret->committer_time, &ret->committer_tz);
 203
 204        len = find_commit_subject(message, &subject);
 205        if (len)
 206                strbuf_add(&ret->summary, subject, len);
 207        else
 208                strbuf_addf(&ret->summary, "(%s)", oid_to_hex(&commit->object.oid));
 209
 210        unuse_commit_buffer(commit, message);
 211}
 212
 213/*
 214 * Write out any suspect information which depends on the path. This must be
 215 * handled separately from emit_one_suspect_detail(), because a given commit
 216 * may have changes in multiple paths. So this needs to appear each time
 217 * we mention a new group.
 218 *
 219 * To allow LF and other nonportable characters in pathnames,
 220 * they are c-style quoted as needed.
 221 */
 222static void write_filename_info(struct blame_origin *suspect)
 223{
 224        if (suspect->previous) {
 225                struct blame_origin *prev = suspect->previous;
 226                printf("previous %s ", oid_to_hex(&prev->commit->object.oid));
 227                write_name_quoted(prev->path, stdout, '\n');
 228        }
 229        printf("filename ");
 230        write_name_quoted(suspect->path, stdout, '\n');
 231}
 232
 233/*
 234 * Porcelain/Incremental format wants to show a lot of details per
 235 * commit.  Instead of repeating this every line, emit it only once,
 236 * the first time each commit appears in the output (unless the
 237 * user has specifically asked for us to repeat).
 238 */
 239static int emit_one_suspect_detail(struct blame_origin *suspect, int repeat)
 240{
 241        struct commit_info ci;
 242
 243        if (!repeat && (suspect->commit->object.flags & METAINFO_SHOWN))
 244                return 0;
 245
 246        suspect->commit->object.flags |= METAINFO_SHOWN;
 247        get_commit_info(suspect->commit, &ci, 1);
 248        printf("author %s\n", ci.author.buf);
 249        printf("author-mail %s\n", ci.author_mail.buf);
 250        printf("author-time %"PRItime"\n", ci.author_time);
 251        printf("author-tz %s\n", ci.author_tz.buf);
 252        printf("committer %s\n", ci.committer.buf);
 253        printf("committer-mail %s\n", ci.committer_mail.buf);
 254        printf("committer-time %"PRItime"\n", ci.committer_time);
 255        printf("committer-tz %s\n", ci.committer_tz.buf);
 256        printf("summary %s\n", ci.summary.buf);
 257        if (suspect->commit->object.flags & UNINTERESTING)
 258                printf("boundary\n");
 259
 260        commit_info_destroy(&ci);
 261
 262        return 1;
 263}
 264
 265/*
 266 * The blame_entry is found to be guilty for the range.
 267 * Show it in incremental output.
 268 */
 269static void found_guilty_entry(struct blame_entry *ent, void *data)
 270{
 271        struct progress_info *pi = (struct progress_info *)data;
 272
 273        if (incremental) {
 274                struct blame_origin *suspect = ent->suspect;
 275
 276                printf("%s %d %d %d\n",
 277                       oid_to_hex(&suspect->commit->object.oid),
 278                       ent->s_lno + 1, ent->lno + 1, ent->num_lines);
 279                emit_one_suspect_detail(suspect, 0);
 280                write_filename_info(suspect);
 281                maybe_flush_or_die(stdout, "stdout");
 282        }
 283        pi->blamed_lines += ent->num_lines;
 284        display_progress(pi->progress, pi->blamed_lines);
 285}
 286
 287static const char *format_time(timestamp_t time, const char *tz_str,
 288                               int show_raw_time)
 289{
 290        static struct strbuf time_buf = STRBUF_INIT;
 291
 292        strbuf_reset(&time_buf);
 293        if (show_raw_time) {
 294                strbuf_addf(&time_buf, "%"PRItime" %s", time, tz_str);
 295        }
 296        else {
 297                const char *time_str;
 298                size_t time_width;
 299                int tz;
 300                tz = atoi(tz_str);
 301                time_str = show_date(time, tz, &blame_date_mode);
 302                strbuf_addstr(&time_buf, time_str);
 303                /*
 304                 * Add space paddings to time_buf to display a fixed width
 305                 * string, and use time_width for display width calibration.
 306                 */
 307                for (time_width = utf8_strwidth(time_str);
 308                     time_width < blame_date_width;
 309                     time_width++)
 310                        strbuf_addch(&time_buf, ' ');
 311        }
 312        return time_buf.buf;
 313}
 314
 315#define OUTPUT_ANNOTATE_COMPAT  001
 316#define OUTPUT_LONG_OBJECT_NAME 002
 317#define OUTPUT_RAW_TIMESTAMP    004
 318#define OUTPUT_PORCELAIN        010
 319#define OUTPUT_SHOW_NAME        020
 320#define OUTPUT_SHOW_NUMBER      040
 321#define OUTPUT_SHOW_SCORE       0100
 322#define OUTPUT_NO_AUTHOR        0200
 323#define OUTPUT_SHOW_EMAIL       0400
 324#define OUTPUT_LINE_PORCELAIN   01000
 325#define OUTPUT_COLOR_LINE       02000
 326
 327static void emit_porcelain_details(struct blame_origin *suspect, int repeat)
 328{
 329        if (emit_one_suspect_detail(suspect, repeat) ||
 330            (suspect->commit->object.flags & MORE_THAN_ONE_PATH))
 331                write_filename_info(suspect);
 332}
 333
 334static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent,
 335                           int opt)
 336{
 337        int repeat = opt & OUTPUT_LINE_PORCELAIN;
 338        int cnt;
 339        const char *cp;
 340        struct blame_origin *suspect = ent->suspect;
 341        char hex[GIT_MAX_HEXSZ + 1];
 342
 343        oid_to_hex_r(hex, &suspect->commit->object.oid);
 344        printf("%s %d %d %d\n",
 345               hex,
 346               ent->s_lno + 1,
 347               ent->lno + 1,
 348               ent->num_lines);
 349        emit_porcelain_details(suspect, repeat);
 350
 351        cp = blame_nth_line(sb, ent->lno);
 352        for (cnt = 0; cnt < ent->num_lines; cnt++) {
 353                char ch;
 354                if (cnt) {
 355                        printf("%s %d %d\n", hex,
 356                               ent->s_lno + 1 + cnt,
 357                               ent->lno + 1 + cnt);
 358                        if (repeat)
 359                                emit_porcelain_details(suspect, 1);
 360                }
 361                putchar('\t');
 362                do {
 363                        ch = *cp++;
 364                        putchar(ch);
 365                } while (ch != '\n' &&
 366                         cp < sb->final_buf + sb->final_buf_size);
 367        }
 368
 369        if (sb->final_buf_size && cp[-1] != '\n')
 370                putchar('\n');
 371}
 372
 373static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int opt)
 374{
 375        int cnt;
 376        const char *cp;
 377        struct blame_origin *suspect = ent->suspect;
 378        struct commit_info ci;
 379        char hex[GIT_MAX_HEXSZ + 1];
 380        int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
 381        const char *color = NULL, *reset = NULL;
 382
 383        get_commit_info(suspect->commit, &ci, 1);
 384        oid_to_hex_r(hex, &suspect->commit->object.oid);
 385
 386        cp = blame_nth_line(sb, ent->lno);
 387        for (cnt = 0; cnt < ent->num_lines; cnt++) {
 388                char ch;
 389                int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev;
 390
 391                if (opt & OUTPUT_COLOR_LINE) {
 392                        if (cnt > 0) {
 393                                color = repeated_meta_color;
 394                                reset = GIT_COLOR_RESET;
 395                        } else  {
 396                                color = NULL;
 397                                reset = NULL;
 398                        }
 399                }
 400                if (color)
 401                        fputs(color, stdout);
 402
 403                if (suspect->commit->object.flags & UNINTERESTING) {
 404                        if (blank_boundary)
 405                                memset(hex, ' ', length);
 406                        else if (!(opt & OUTPUT_ANNOTATE_COMPAT)) {
 407                                length--;
 408                                putchar('^');
 409                        }
 410                }
 411
 412                printf("%.*s", length, hex);
 413                if (opt & OUTPUT_ANNOTATE_COMPAT) {
 414                        const char *name;
 415                        if (opt & OUTPUT_SHOW_EMAIL)
 416                                name = ci.author_mail.buf;
 417                        else
 418                                name = ci.author.buf;
 419                        printf("\t(%10s\t%10s\t%d)", name,
 420                               format_time(ci.author_time, ci.author_tz.buf,
 421                                           show_raw_time),
 422                               ent->lno + 1 + cnt);
 423                } else {
 424                        if (opt & OUTPUT_SHOW_SCORE)
 425                                printf(" %*d %02d",
 426                                       max_score_digits, ent->score,
 427                                       ent->suspect->refcnt);
 428                        if (opt & OUTPUT_SHOW_NAME)
 429                                printf(" %-*.*s", longest_file, longest_file,
 430                                       suspect->path);
 431                        if (opt & OUTPUT_SHOW_NUMBER)
 432                                printf(" %*d", max_orig_digits,
 433                                       ent->s_lno + 1 + cnt);
 434
 435                        if (!(opt & OUTPUT_NO_AUTHOR)) {
 436                                const char *name;
 437                                int pad;
 438                                if (opt & OUTPUT_SHOW_EMAIL)
 439                                        name = ci.author_mail.buf;
 440                                else
 441                                        name = ci.author.buf;
 442                                pad = longest_author - utf8_strwidth(name);
 443                                printf(" (%s%*s %10s",
 444                                       name, pad, "",
 445                                       format_time(ci.author_time,
 446                                                   ci.author_tz.buf,
 447                                                   show_raw_time));
 448                        }
 449                        printf(" %*d) ",
 450                               max_digits, ent->lno + 1 + cnt);
 451                }
 452                if (reset)
 453                        fputs(reset, stdout);
 454                do {
 455                        ch = *cp++;
 456                        putchar(ch);
 457                } while (ch != '\n' &&
 458                         cp < sb->final_buf + sb->final_buf_size);
 459        }
 460
 461        if (sb->final_buf_size && cp[-1] != '\n')
 462                putchar('\n');
 463
 464        commit_info_destroy(&ci);
 465}
 466
 467static void output(struct blame_scoreboard *sb, int option)
 468{
 469        struct blame_entry *ent;
 470
 471        if (option & OUTPUT_PORCELAIN) {
 472                for (ent = sb->ent; ent; ent = ent->next) {
 473                        int count = 0;
 474                        struct blame_origin *suspect;
 475                        struct commit *commit = ent->suspect->commit;
 476                        if (commit->object.flags & MORE_THAN_ONE_PATH)
 477                                continue;
 478                        for (suspect = commit->util; suspect; suspect = suspect->next) {
 479                                if (suspect->guilty && count++) {
 480                                        commit->object.flags |= MORE_THAN_ONE_PATH;
 481                                        break;
 482                                }
 483                        }
 484                }
 485        }
 486
 487        for (ent = sb->ent; ent; ent = ent->next) {
 488                if (option & OUTPUT_PORCELAIN)
 489                        emit_porcelain(sb, ent, option);
 490                else {
 491                        emit_other(sb, ent, option);
 492                }
 493        }
 494}
 495
 496/*
 497 * Add phony grafts for use with -S; this is primarily to
 498 * support git's cvsserver that wants to give a linear history
 499 * to its clients.
 500 */
 501static int read_ancestry(const char *graft_file)
 502{
 503        FILE *fp = fopen_or_warn(graft_file, "r");
 504        struct strbuf buf = STRBUF_INIT;
 505        if (!fp)
 506                return -1;
 507        while (!strbuf_getwholeline(&buf, fp, '\n')) {
 508                /* The format is just "Commit Parent1 Parent2 ...\n" */
 509                struct commit_graft *graft = read_graft_line(&buf);
 510                if (graft)
 511                        register_commit_graft(graft, 0);
 512        }
 513        fclose(fp);
 514        strbuf_release(&buf);
 515        return 0;
 516}
 517
 518static int update_auto_abbrev(int auto_abbrev, struct blame_origin *suspect)
 519{
 520        const char *uniq = find_unique_abbrev(suspect->commit->object.oid.hash,
 521                                              auto_abbrev);
 522        int len = strlen(uniq);
 523        if (auto_abbrev < len)
 524                return len;
 525        return auto_abbrev;
 526}
 527
 528/*
 529 * How many columns do we need to show line numbers, authors,
 530 * and filenames?
 531 */
 532static void find_alignment(struct blame_scoreboard *sb, int *option)
 533{
 534        int longest_src_lines = 0;
 535        int longest_dst_lines = 0;
 536        unsigned largest_score = 0;
 537        struct blame_entry *e;
 538        int compute_auto_abbrev = (abbrev < 0);
 539        int auto_abbrev = DEFAULT_ABBREV;
 540
 541        for (e = sb->ent; e; e = e->next) {
 542                struct blame_origin *suspect = e->suspect;
 543                int num;
 544
 545                if (compute_auto_abbrev)
 546                        auto_abbrev = update_auto_abbrev(auto_abbrev, suspect);
 547                if (strcmp(suspect->path, sb->path))
 548                        *option |= OUTPUT_SHOW_NAME;
 549                num = strlen(suspect->path);
 550                if (longest_file < num)
 551                        longest_file = num;
 552                if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
 553                        struct commit_info ci;
 554                        suspect->commit->object.flags |= METAINFO_SHOWN;
 555                        get_commit_info(suspect->commit, &ci, 1);
 556                        if (*option & OUTPUT_SHOW_EMAIL)
 557                                num = utf8_strwidth(ci.author_mail.buf);
 558                        else
 559                                num = utf8_strwidth(ci.author.buf);
 560                        if (longest_author < num)
 561                                longest_author = num;
 562                        commit_info_destroy(&ci);
 563                }
 564                num = e->s_lno + e->num_lines;
 565                if (longest_src_lines < num)
 566                        longest_src_lines = num;
 567                num = e->lno + e->num_lines;
 568                if (longest_dst_lines < num)
 569                        longest_dst_lines = num;
 570                if (largest_score < blame_entry_score(sb, e))
 571                        largest_score = blame_entry_score(sb, e);
 572        }
 573        max_orig_digits = decimal_width(longest_src_lines);
 574        max_digits = decimal_width(longest_dst_lines);
 575        max_score_digits = decimal_width(largest_score);
 576
 577        if (compute_auto_abbrev)
 578                /* one more abbrev length is needed for the boundary commit */
 579                abbrev = auto_abbrev + 1;
 580}
 581
 582static void sanity_check_on_fail(struct blame_scoreboard *sb, int baa)
 583{
 584        int opt = OUTPUT_SHOW_SCORE | OUTPUT_SHOW_NUMBER | OUTPUT_SHOW_NAME;
 585        find_alignment(sb, &opt);
 586        output(sb, opt);
 587        die("Baa %d!", baa);
 588}
 589
 590static unsigned parse_score(const char *arg)
 591{
 592        char *end;
 593        unsigned long score = strtoul(arg, &end, 10);
 594        if (*end)
 595                return 0;
 596        return score;
 597}
 598
 599static const char *add_prefix(const char *prefix, const char *path)
 600{
 601        return prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
 602}
 603
 604static int git_blame_config(const char *var, const char *value, void *cb)
 605{
 606        if (!strcmp(var, "blame.showroot")) {
 607                show_root = git_config_bool(var, value);
 608                return 0;
 609        }
 610        if (!strcmp(var, "blame.blankboundary")) {
 611                blank_boundary = git_config_bool(var, value);
 612                return 0;
 613        }
 614        if (!strcmp(var, "blame.showemail")) {
 615                int *output_option = cb;
 616                if (git_config_bool(var, value))
 617                        *output_option |= OUTPUT_SHOW_EMAIL;
 618                else
 619                        *output_option &= ~OUTPUT_SHOW_EMAIL;
 620                return 0;
 621        }
 622        if (!strcmp(var, "blame.date")) {
 623                if (!value)
 624                        return config_error_nonbool(var);
 625                parse_date_format(value, &blame_date_mode);
 626                return 0;
 627        }
 628        if (!strcmp(var, "color.blame.repeatedlines")) {
 629                if (color_parse_mem(value, strlen(value), repeated_meta_color))
 630                        warning(_("invalid color '%s' in color.blame.repeatedLines"),
 631                                value);
 632                return 0;
 633        }
 634
 635        if (git_diff_heuristic_config(var, value, cb) < 0)
 636                return -1;
 637        if (userdiff_config(var, value) < 0)
 638                return -1;
 639
 640        return git_default_config(var, value, cb);
 641}
 642
 643static int blame_copy_callback(const struct option *option, const char *arg, int unset)
 644{
 645        int *opt = option->value;
 646
 647        /*
 648         * -C enables copy from removed files;
 649         * -C -C enables copy from existing files, but only
 650         *       when blaming a new file;
 651         * -C -C -C enables copy from existing files for
 652         *          everybody
 653         */
 654        if (*opt & PICKAXE_BLAME_COPY_HARDER)
 655                *opt |= PICKAXE_BLAME_COPY_HARDEST;
 656        if (*opt & PICKAXE_BLAME_COPY)
 657                *opt |= PICKAXE_BLAME_COPY_HARDER;
 658        *opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
 659
 660        if (arg)
 661                blame_copy_score = parse_score(arg);
 662        return 0;
 663}
 664
 665static int blame_move_callback(const struct option *option, const char *arg, int unset)
 666{
 667        int *opt = option->value;
 668
 669        *opt |= PICKAXE_BLAME_MOVE;
 670
 671        if (arg)
 672                blame_move_score = parse_score(arg);
 673        return 0;
 674}
 675
 676int cmd_blame(int argc, const char **argv, const char *prefix)
 677{
 678        struct rev_info revs;
 679        const char *path;
 680        struct blame_scoreboard sb;
 681        struct blame_origin *o;
 682        struct blame_entry *ent = NULL;
 683        long dashdash_pos, lno;
 684        struct progress_info pi = { NULL, 0 };
 685
 686        struct string_list range_list = STRING_LIST_INIT_NODUP;
 687        int output_option = 0, opt = 0;
 688        int show_stats = 0;
 689        const char *revs_file = NULL;
 690        const char *contents_from = NULL;
 691        const struct option options[] = {
 692                OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
 693                OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
 694                OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
 695                OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")),
 696                OPT_BOOL(0, "progress", &show_progress, N_("Force progress reporting")),
 697                OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE),
 698                OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
 699                OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
 700                OPT_BIT('p', "porcelain", &output_option, N_("Show in a format designed for machine consumption"), OUTPUT_PORCELAIN),
 701                OPT_BIT(0, "line-porcelain", &output_option, N_("Show porcelain format with per-line commit information"), OUTPUT_PORCELAIN|OUTPUT_LINE_PORCELAIN),
 702                OPT_BIT('c', NULL, &output_option, N_("Use the same output mode as git-annotate (Default: off)"), OUTPUT_ANNOTATE_COMPAT),
 703                OPT_BIT('t', NULL, &output_option, N_("Show raw timestamp (Default: off)"), OUTPUT_RAW_TIMESTAMP),
 704                OPT_BIT('l', NULL, &output_option, N_("Show long commit SHA1 (Default: off)"), OUTPUT_LONG_OBJECT_NAME),
 705                OPT_BIT('s', NULL, &output_option, N_("Suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR),
 706                OPT_BIT('e', "show-email", &output_option, N_("Show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL),
 707                OPT_BIT('w', NULL, &xdl_opts, N_("Ignore whitespace differences"), XDF_IGNORE_WHITESPACE),
 708                OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE),
 709
 710                /*
 711                 * The following two options are parsed by parse_revision_opt()
 712                 * and are only included here to get included in the "-h"
 713                 * output:
 714                 */
 715                { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, parse_opt_unknown_cb },
 716
 717                OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL),
 718                OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from <file> instead of calling git-rev-list")),
 719                OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use <file>'s contents as the final image")),
 720                { OPTION_CALLBACK, 'C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback },
 721                { OPTION_CALLBACK, 'M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback },
 722                OPT_STRING_LIST('L', NULL, &range_list, N_("n,m"), N_("Process only line range n,m, counting from 1")),
 723                OPT__ABBREV(&abbrev),
 724                OPT_END()
 725        };
 726
 727        struct parse_opt_ctx_t ctx;
 728        int cmd_is_annotate = !strcmp(argv[0], "annotate");
 729        struct range_set ranges;
 730        unsigned int range_i;
 731        long anchor;
 732
 733        git_config(git_blame_config, &output_option);
 734        init_revisions(&revs, NULL);
 735        revs.date_mode = blame_date_mode;
 736        revs.diffopt.flags.allow_textconv = 1;
 737        revs.diffopt.flags.follow_renames = 1;
 738
 739        save_commit_buffer = 0;
 740        dashdash_pos = 0;
 741        show_progress = -1;
 742
 743        parse_options_start(&ctx, argc, argv, prefix, options,
 744                            PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
 745        for (;;) {
 746                switch (parse_options_step(&ctx, options, blame_opt_usage)) {
 747                case PARSE_OPT_HELP:
 748                        exit(129);
 749                case PARSE_OPT_DONE:
 750                        if (ctx.argv[0])
 751                                dashdash_pos = ctx.cpidx;
 752                        goto parse_done;
 753                }
 754
 755                if (!strcmp(ctx.argv[0], "--reverse")) {
 756                        ctx.argv[0] = "--children";
 757                        reverse = 1;
 758                }
 759                parse_revision_opt(&revs, &ctx, options, blame_opt_usage);
 760        }
 761parse_done:
 762        no_whole_file_rename = !revs.diffopt.flags.follow_renames;
 763        xdl_opts |= revs.diffopt.xdl_opts & XDF_INDENT_HEURISTIC;
 764        revs.diffopt.flags.follow_renames = 0;
 765        argc = parse_options_end(&ctx);
 766
 767        if (incremental || (output_option & OUTPUT_PORCELAIN)) {
 768                if (show_progress > 0)
 769                        die(_("--progress can't be used with --incremental or porcelain formats"));
 770                show_progress = 0;
 771        } else if (show_progress < 0)
 772                show_progress = isatty(2);
 773
 774        if (0 < abbrev && abbrev < GIT_SHA1_HEXSZ)
 775                /* one more abbrev length is needed for the boundary commit */
 776                abbrev++;
 777        else if (!abbrev)
 778                abbrev = GIT_SHA1_HEXSZ;
 779
 780        if (revs_file && read_ancestry(revs_file))
 781                die_errno("reading graft file '%s' failed", revs_file);
 782
 783        if (cmd_is_annotate) {
 784                output_option |= OUTPUT_ANNOTATE_COMPAT;
 785                blame_date_mode.type = DATE_ISO8601;
 786        } else {
 787                blame_date_mode = revs.date_mode;
 788        }
 789
 790        /* The maximum width used to show the dates */
 791        switch (blame_date_mode.type) {
 792        case DATE_RFC2822:
 793                blame_date_width = sizeof("Thu, 19 Oct 2006 16:00:04 -0700");
 794                break;
 795        case DATE_ISO8601_STRICT:
 796                blame_date_width = sizeof("2006-10-19T16:00:04-07:00");
 797                break;
 798        case DATE_ISO8601:
 799                blame_date_width = sizeof("2006-10-19 16:00:04 -0700");
 800                break;
 801        case DATE_RAW:
 802                blame_date_width = sizeof("1161298804 -0700");
 803                break;
 804        case DATE_UNIX:
 805                blame_date_width = sizeof("1161298804");
 806                break;
 807        case DATE_SHORT:
 808                blame_date_width = sizeof("2006-10-19");
 809                break;
 810        case DATE_RELATIVE:
 811                /*
 812                 * TRANSLATORS: This string is used to tell us the
 813                 * maximum display width for a relative timestamp in
 814                 * "git blame" output.  For C locale, "4 years, 11
 815                 * months ago", which takes 22 places, is the longest
 816                 * among various forms of relative timestamps, but
 817                 * your language may need more or fewer display
 818                 * columns.
 819                 */
 820                blame_date_width = utf8_strwidth(_("4 years, 11 months ago")) + 1; /* add the null */
 821                break;
 822        case DATE_NORMAL:
 823                blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
 824                break;
 825        case DATE_STRFTIME:
 826                blame_date_width = strlen(show_date(0, 0, &blame_date_mode)) + 1; /* add the null */
 827                break;
 828        }
 829        blame_date_width -= 1; /* strip the null */
 830
 831        if (revs.diffopt.flags.find_copies_harder)
 832                opt |= (PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE |
 833                        PICKAXE_BLAME_COPY_HARDER);
 834
 835        /*
 836         * We have collected options unknown to us in argv[1..unk]
 837         * which are to be passed to revision machinery if we are
 838         * going to do the "bottom" processing.
 839         *
 840         * The remaining are:
 841         *
 842         * (1) if dashdash_pos != 0, it is either
 843         *     "blame [revisions] -- <path>" or
 844         *     "blame -- <path> <rev>"
 845         *
 846         * (2) otherwise, it is one of the two:
 847         *     "blame [revisions] <path>"
 848         *     "blame <path> <rev>"
 849         *
 850         * Note that we must strip out <path> from the arguments: we do not
 851         * want the path pruning but we may want "bottom" processing.
 852         */
 853        if (dashdash_pos) {
 854                switch (argc - dashdash_pos - 1) {
 855                case 2: /* (1b) */
 856                        if (argc != 4)
 857                                usage_with_options(blame_opt_usage, options);
 858                        /* reorder for the new way: <rev> -- <path> */
 859                        argv[1] = argv[3];
 860                        argv[3] = argv[2];
 861                        argv[2] = "--";
 862                        /* FALLTHROUGH */
 863                case 1: /* (1a) */
 864                        path = add_prefix(prefix, argv[--argc]);
 865                        argv[argc] = NULL;
 866                        break;
 867                default:
 868                        usage_with_options(blame_opt_usage, options);
 869                }
 870        } else {
 871                if (argc < 2)
 872                        usage_with_options(blame_opt_usage, options);
 873                path = add_prefix(prefix, argv[argc - 1]);
 874                if (argc == 3 && !file_exists(path)) { /* (2b) */
 875                        path = add_prefix(prefix, argv[1]);
 876                        argv[1] = argv[2];
 877                }
 878                argv[argc - 1] = "--";
 879
 880                setup_work_tree();
 881                if (!file_exists(path))
 882                        die_errno("cannot stat path '%s'", path);
 883        }
 884
 885        revs.disable_stdin = 1;
 886        setup_revisions(argc, argv, &revs, NULL);
 887
 888        init_scoreboard(&sb);
 889        sb.revs = &revs;
 890        sb.contents_from = contents_from;
 891        sb.reverse = reverse;
 892        setup_scoreboard(&sb, path, &o);
 893        lno = sb.num_lines;
 894
 895        if (lno && !range_list.nr)
 896                string_list_append(&range_list, "1");
 897
 898        anchor = 1;
 899        range_set_init(&ranges, range_list.nr);
 900        for (range_i = 0; range_i < range_list.nr; ++range_i) {
 901                long bottom, top;
 902                if (parse_range_arg(range_list.items[range_i].string,
 903                                    nth_line_cb, &sb, lno, anchor,
 904                                    &bottom, &top, sb.path))
 905                        usage(blame_usage);
 906                if (lno < top || ((lno || bottom) && lno < bottom))
 907                        die(Q_("file %s has only %lu line",
 908                               "file %s has only %lu lines",
 909                               lno), path, lno);
 910                if (bottom < 1)
 911                        bottom = 1;
 912                if (top < 1)
 913                        top = lno;
 914                bottom--;
 915                range_set_append_unsafe(&ranges, bottom, top);
 916                anchor = top + 1;
 917        }
 918        sort_and_merge_range_set(&ranges);
 919
 920        for (range_i = ranges.nr; range_i > 0; --range_i) {
 921                const struct range *r = &ranges.ranges[range_i - 1];
 922                ent = blame_entry_prepend(ent, r->start, r->end, o);
 923        }
 924
 925        o->suspects = ent;
 926        prio_queue_put(&sb.commits, o->commit);
 927
 928        blame_origin_decref(o);
 929
 930        range_set_release(&ranges);
 931        string_list_clear(&range_list, 0);
 932
 933        sb.ent = NULL;
 934        sb.path = path;
 935
 936        if (blame_move_score)
 937                sb.move_score = blame_move_score;
 938        if (blame_copy_score)
 939                sb.copy_score = blame_copy_score;
 940
 941        sb.debug = DEBUG;
 942        sb.on_sanity_fail = &sanity_check_on_fail;
 943
 944        sb.show_root = show_root;
 945        sb.xdl_opts = xdl_opts;
 946        sb.no_whole_file_rename = no_whole_file_rename;
 947
 948        read_mailmap(&mailmap, NULL);
 949
 950        sb.found_guilty_entry = &found_guilty_entry;
 951        sb.found_guilty_entry_data = &pi;
 952        if (show_progress)
 953                pi.progress = start_delayed_progress(_("Blaming lines"), sb.num_lines);
 954
 955        assign_blame(&sb, opt);
 956
 957        stop_progress(&pi.progress);
 958
 959        if (!incremental)
 960                setup_pager();
 961        else
 962                return 0;
 963
 964        blame_sort_final(&sb);
 965
 966        blame_coalesce(&sb);
 967
 968        if (!(output_option & OUTPUT_PORCELAIN)) {
 969                find_alignment(&sb, &output_option);
 970                if (!*repeated_meta_color &&
 971                    (output_option & OUTPUT_COLOR_LINE))
 972                        strcpy(repeated_meta_color, GIT_COLOR_CYAN);
 973        }
 974        if (output_option & OUTPUT_ANNOTATE_COMPAT)
 975                output_option &= ~OUTPUT_COLOR_LINE;
 976
 977        output(&sb, output_option);
 978        free((void *)sb.final_buf);
 979        for (ent = sb.ent; ent; ) {
 980                struct blame_entry *e = ent->next;
 981                free(ent);
 982                ent = e;
 983        }
 984
 985        if (show_stats) {
 986                printf("num read blob: %d\n", sb.num_read_blob);
 987                printf("num get patch: %d\n", sb.num_get_patch);
 988                printf("num commits: %d\n", sb.num_commits);
 989        }
 990        return 0;
 991}