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