diff.con commit git-diff -B output fix. (bc1a580)
   1/*
   2 * Copyright (C) 2005 Junio C Hamano
   3 */
   4#include <sys/types.h>
   5#include <sys/wait.h>
   6#include <signal.h>
   7#include "cache.h"
   8#include "quote.h"
   9#include "diff.h"
  10#include "diffcore.h"
  11#include "delta.h"
  12#include "xdiff-interface.h"
  13#include "color.h"
  14
  15static int use_size_cache;
  16
  17static int diff_detect_rename_default;
  18static int diff_rename_limit_default = -1;
  19static int diff_use_color_default;
  20
  21static char diff_colors[][COLOR_MAXLEN] = {
  22        "\033[m",       /* reset */
  23        "",             /* PLAIN (normal) */
  24        "\033[1m",      /* METAINFO (bold) */
  25        "\033[36m",     /* FRAGINFO (cyan) */
  26        "\033[31m",     /* OLD (red) */
  27        "\033[32m",     /* NEW (green) */
  28        "\033[33m",     /* COMMIT (yellow) */
  29        "\033[41m",     /* WHITESPACE (red background) */
  30};
  31
  32static int parse_diff_color_slot(const char *var, int ofs)
  33{
  34        if (!strcasecmp(var+ofs, "plain"))
  35                return DIFF_PLAIN;
  36        if (!strcasecmp(var+ofs, "meta"))
  37                return DIFF_METAINFO;
  38        if (!strcasecmp(var+ofs, "frag"))
  39                return DIFF_FRAGINFO;
  40        if (!strcasecmp(var+ofs, "old"))
  41                return DIFF_FILE_OLD;
  42        if (!strcasecmp(var+ofs, "new"))
  43                return DIFF_FILE_NEW;
  44        if (!strcasecmp(var+ofs, "commit"))
  45                return DIFF_COMMIT;
  46        if (!strcasecmp(var+ofs, "whitespace"))
  47                return DIFF_WHITESPACE;
  48        die("bad config variable '%s'", var);
  49}
  50
  51/*
  52 * These are to give UI layer defaults.
  53 * The core-level commands such as git-diff-files should
  54 * never be affected by the setting of diff.renames
  55 * the user happens to have in the configuration file.
  56 */
  57int git_diff_ui_config(const char *var, const char *value)
  58{
  59        if (!strcmp(var, "diff.renamelimit")) {
  60                diff_rename_limit_default = git_config_int(var, value);
  61                return 0;
  62        }
  63        if (!strcmp(var, "diff.color")) {
  64                diff_use_color_default = git_config_colorbool(var, value);
  65                return 0;
  66        }
  67        if (!strcmp(var, "diff.renames")) {
  68                if (!value)
  69                        diff_detect_rename_default = DIFF_DETECT_RENAME;
  70                else if (!strcasecmp(value, "copies") ||
  71                         !strcasecmp(value, "copy"))
  72                        diff_detect_rename_default = DIFF_DETECT_COPY;
  73                else if (git_config_bool(var,value))
  74                        diff_detect_rename_default = DIFF_DETECT_RENAME;
  75                return 0;
  76        }
  77        if (!strncmp(var, "diff.color.", 11)) {
  78                int slot = parse_diff_color_slot(var, 11);
  79                color_parse(value, var, diff_colors[slot]);
  80                return 0;
  81        }
  82        return git_default_config(var, value);
  83}
  84
  85static char *quote_one(const char *str)
  86{
  87        int needlen;
  88        char *xp;
  89
  90        if (!str)
  91                return NULL;
  92        needlen = quote_c_style(str, NULL, NULL, 0);
  93        if (!needlen)
  94                return xstrdup(str);
  95        xp = xmalloc(needlen + 1);
  96        quote_c_style(str, xp, NULL, 0);
  97        return xp;
  98}
  99
 100static char *quote_two(const char *one, const char *two)
 101{
 102        int need_one = quote_c_style(one, NULL, NULL, 1);
 103        int need_two = quote_c_style(two, NULL, NULL, 1);
 104        char *xp;
 105
 106        if (need_one + need_two) {
 107                if (!need_one) need_one = strlen(one);
 108                if (!need_two) need_one = strlen(two);
 109
 110                xp = xmalloc(need_one + need_two + 3);
 111                xp[0] = '"';
 112                quote_c_style(one, xp + 1, NULL, 1);
 113                quote_c_style(two, xp + need_one + 1, NULL, 1);
 114                strcpy(xp + need_one + need_two + 1, "\"");
 115                return xp;
 116        }
 117        need_one = strlen(one);
 118        need_two = strlen(two);
 119        xp = xmalloc(need_one + need_two + 1);
 120        strcpy(xp, one);
 121        strcpy(xp + need_one, two);
 122        return xp;
 123}
 124
 125static const char *external_diff(void)
 126{
 127        static const char *external_diff_cmd = NULL;
 128        static int done_preparing = 0;
 129
 130        if (done_preparing)
 131                return external_diff_cmd;
 132        external_diff_cmd = getenv("GIT_EXTERNAL_DIFF");
 133        done_preparing = 1;
 134        return external_diff_cmd;
 135}
 136
 137#define TEMPFILE_PATH_LEN               50
 138
 139static struct diff_tempfile {
 140        const char *name; /* filename external diff should read from */
 141        char hex[41];
 142        char mode[10];
 143        char tmp_path[TEMPFILE_PATH_LEN];
 144} diff_temp[2];
 145
 146static int count_lines(const char *data, int size)
 147{
 148        int count, ch, completely_empty = 1, nl_just_seen = 0;
 149        count = 0;
 150        while (0 < size--) {
 151                ch = *data++;
 152                if (ch == '\n') {
 153                        count++;
 154                        nl_just_seen = 1;
 155                        completely_empty = 0;
 156                }
 157                else {
 158                        nl_just_seen = 0;
 159                        completely_empty = 0;
 160                }
 161        }
 162        if (completely_empty)
 163                return 0;
 164        if (!nl_just_seen)
 165                count++; /* no trailing newline */
 166        return count;
 167}
 168
 169static void print_line_count(int count)
 170{
 171        switch (count) {
 172        case 0:
 173                printf("0,0");
 174                break;
 175        case 1:
 176                printf("1");
 177                break;
 178        default:
 179                printf("1,%d", count);
 180                break;
 181        }
 182}
 183
 184static void copy_file(int prefix, const char *data, int size)
 185{
 186        int ch, nl_just_seen = 1;
 187        while (0 < size--) {
 188                ch = *data++;
 189                if (nl_just_seen)
 190                        putchar(prefix);
 191                putchar(ch);
 192                if (ch == '\n')
 193                        nl_just_seen = 1;
 194                else
 195                        nl_just_seen = 0;
 196        }
 197        if (!nl_just_seen)
 198                printf("\n\\ No newline at end of file\n");
 199}
 200
 201static void emit_rewrite_diff(const char *name_a,
 202                              const char *name_b,
 203                              struct diff_filespec *one,
 204                              struct diff_filespec *two)
 205{
 206        int lc_a, lc_b;
 207        diff_populate_filespec(one, 0);
 208        diff_populate_filespec(two, 0);
 209        lc_a = count_lines(one->data, one->size);
 210        lc_b = count_lines(two->data, two->size);
 211        printf("--- a/%s\n+++ b/%s\n@@ -", name_a, name_b);
 212        print_line_count(lc_a);
 213        printf(" +");
 214        print_line_count(lc_b);
 215        printf(" @@\n");
 216        if (lc_a)
 217                copy_file('-', one->data, one->size);
 218        if (lc_b)
 219                copy_file('+', two->data, two->size);
 220}
 221
 222static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
 223{
 224        if (!DIFF_FILE_VALID(one)) {
 225                mf->ptr = (char *)""; /* does not matter */
 226                mf->size = 0;
 227                return 0;
 228        }
 229        else if (diff_populate_filespec(one, 0))
 230                return -1;
 231        mf->ptr = one->data;
 232        mf->size = one->size;
 233        return 0;
 234}
 235
 236struct diff_words_buffer {
 237        mmfile_t text;
 238        long alloc;
 239        long current; /* output pointer */
 240        int suppressed_newline;
 241};
 242
 243static void diff_words_append(char *line, unsigned long len,
 244                struct diff_words_buffer *buffer)
 245{
 246        if (buffer->text.size + len > buffer->alloc) {
 247                buffer->alloc = (buffer->text.size + len) * 3 / 2;
 248                buffer->text.ptr = xrealloc(buffer->text.ptr, buffer->alloc);
 249        }
 250        line++;
 251        len--;
 252        memcpy(buffer->text.ptr + buffer->text.size, line, len);
 253        buffer->text.size += len;
 254}
 255
 256struct diff_words_data {
 257        struct xdiff_emit_state xm;
 258        struct diff_words_buffer minus, plus;
 259};
 260
 261static void print_word(struct diff_words_buffer *buffer, int len, int color,
 262                int suppress_newline)
 263{
 264        const char *ptr;
 265        int eol = 0;
 266
 267        if (len == 0)
 268                return;
 269
 270        ptr  = buffer->text.ptr + buffer->current;
 271        buffer->current += len;
 272
 273        if (ptr[len - 1] == '\n') {
 274                eol = 1;
 275                len--;
 276        }
 277
 278        fputs(diff_get_color(1, color), stdout);
 279        fwrite(ptr, len, 1, stdout);
 280        fputs(diff_get_color(1, DIFF_RESET), stdout);
 281
 282        if (eol) {
 283                if (suppress_newline)
 284                        buffer->suppressed_newline = 1;
 285                else
 286                        putchar('\n');
 287        }
 288}
 289
 290static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
 291{
 292        struct diff_words_data *diff_words = priv;
 293
 294        if (diff_words->minus.suppressed_newline) {
 295                if (line[0] != '+')
 296                        putchar('\n');
 297                diff_words->minus.suppressed_newline = 0;
 298        }
 299
 300        len--;
 301        switch (line[0]) {
 302                case '-':
 303                        print_word(&diff_words->minus, len, DIFF_FILE_OLD, 1);
 304                        break;
 305                case '+':
 306                        print_word(&diff_words->plus, len, DIFF_FILE_NEW, 0);
 307                        break;
 308                case ' ':
 309                        print_word(&diff_words->plus, len, DIFF_PLAIN, 0);
 310                        diff_words->minus.current += len;
 311                        break;
 312        }
 313}
 314
 315/* this executes the word diff on the accumulated buffers */
 316static void diff_words_show(struct diff_words_data *diff_words)
 317{
 318        xpparam_t xpp;
 319        xdemitconf_t xecfg;
 320        xdemitcb_t ecb;
 321        mmfile_t minus, plus;
 322        int i;
 323
 324        minus.size = diff_words->minus.text.size;
 325        minus.ptr = xmalloc(minus.size);
 326        memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size);
 327        for (i = 0; i < minus.size; i++)
 328                if (isspace(minus.ptr[i]))
 329                        minus.ptr[i] = '\n';
 330        diff_words->minus.current = 0;
 331
 332        plus.size = diff_words->plus.text.size;
 333        plus.ptr = xmalloc(plus.size);
 334        memcpy(plus.ptr, diff_words->plus.text.ptr, plus.size);
 335        for (i = 0; i < plus.size; i++)
 336                if (isspace(plus.ptr[i]))
 337                        plus.ptr[i] = '\n';
 338        diff_words->plus.current = 0;
 339
 340        xpp.flags = XDF_NEED_MINIMAL;
 341        xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc;
 342        xecfg.flags = 0;
 343        ecb.outf = xdiff_outf;
 344        ecb.priv = diff_words;
 345        diff_words->xm.consume = fn_out_diff_words_aux;
 346        xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb);
 347
 348        free(minus.ptr);
 349        free(plus.ptr);
 350        diff_words->minus.text.size = diff_words->plus.text.size = 0;
 351
 352        if (diff_words->minus.suppressed_newline) {
 353                putchar('\n');
 354                diff_words->minus.suppressed_newline = 0;
 355        }
 356}
 357
 358struct emit_callback {
 359        struct xdiff_emit_state xm;
 360        int nparents, color_diff;
 361        const char **label_path;
 362        struct diff_words_data *diff_words;
 363};
 364
 365static void free_diff_words_data(struct emit_callback *ecbdata)
 366{
 367        if (ecbdata->diff_words) {
 368                /* flush buffers */
 369                if (ecbdata->diff_words->minus.text.size ||
 370                                ecbdata->diff_words->plus.text.size)
 371                        diff_words_show(ecbdata->diff_words);
 372
 373                if (ecbdata->diff_words->minus.text.ptr)
 374                        free (ecbdata->diff_words->minus.text.ptr);
 375                if (ecbdata->diff_words->plus.text.ptr)
 376                        free (ecbdata->diff_words->plus.text.ptr);
 377                free(ecbdata->diff_words);
 378                ecbdata->diff_words = NULL;
 379        }
 380}
 381
 382const char *diff_get_color(int diff_use_color, enum color_diff ix)
 383{
 384        if (diff_use_color)
 385                return diff_colors[ix];
 386        return "";
 387}
 388
 389static void emit_line(const char *set, const char *reset, const char *line, int len)
 390{
 391        if (len > 0 && line[len-1] == '\n')
 392                len--;
 393        fputs(set, stdout);
 394        fwrite(line, len, 1, stdout);
 395        puts(reset);
 396}
 397
 398static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
 399{
 400        int col0 = ecbdata->nparents;
 401        int last_tab_in_indent = -1;
 402        int last_space_in_indent = -1;
 403        int i;
 404        int tail = len;
 405        int need_highlight_leading_space = 0;
 406        const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
 407        const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
 408
 409        if (!*ws) {
 410                emit_line(set, reset, line, len);
 411                return;
 412        }
 413
 414        /* The line is a newly added line.  Does it have funny leading
 415         * whitespaces?  In indent, SP should never precede a TAB.
 416         */
 417        for (i = col0; i < len; i++) {
 418                if (line[i] == '\t') {
 419                        last_tab_in_indent = i;
 420                        if (0 <= last_space_in_indent)
 421                                need_highlight_leading_space = 1;
 422                }
 423                else if (line[i] == ' ')
 424                        last_space_in_indent = i;
 425                else
 426                        break;
 427        }
 428        fputs(set, stdout);
 429        fwrite(line, col0, 1, stdout);
 430        fputs(reset, stdout);
 431        if (((i == len) || line[i] == '\n') && i != col0) {
 432                /* The whole line was indent */
 433                emit_line(ws, reset, line + col0, len - col0);
 434                return;
 435        }
 436        i = col0;
 437        if (need_highlight_leading_space) {
 438                while (i < last_tab_in_indent) {
 439                        if (line[i] == ' ') {
 440                                fputs(ws, stdout);
 441                                putchar(' ');
 442                                fputs(reset, stdout);
 443                        }
 444                        else
 445                                putchar(line[i]);
 446                        i++;
 447                }
 448        }
 449        tail = len - 1;
 450        if (line[tail] == '\n' && i < tail)
 451                tail--;
 452        while (i < tail) {
 453                if (!isspace(line[tail]))
 454                        break;
 455                tail--;
 456        }
 457        if ((i < tail && line[tail + 1] != '\n')) {
 458                /* This has whitespace between tail+1..len */
 459                fputs(set, stdout);
 460                fwrite(line + i, tail - i + 1, 1, stdout);
 461                fputs(reset, stdout);
 462                emit_line(ws, reset, line + tail + 1, len - tail - 1);
 463        }
 464        else
 465                emit_line(set, reset, line + i, len - i);
 466}
 467
 468static void fn_out_consume(void *priv, char *line, unsigned long len)
 469{
 470        int i;
 471        int color;
 472        struct emit_callback *ecbdata = priv;
 473        const char *set = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
 474        const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
 475
 476        if (ecbdata->label_path[0]) {
 477                printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset);
 478                printf("%s+++ %s%s\n", set, ecbdata->label_path[1], reset);
 479                ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
 480        }
 481
 482        /* This is not really necessary for now because
 483         * this codepath only deals with two-way diffs.
 484         */
 485        for (i = 0; i < len && line[i] == '@'; i++)
 486                ;
 487        if (2 <= i && i < len && line[i] == ' ') {
 488                ecbdata->nparents = i - 1;
 489                emit_line(diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO),
 490                          reset, line, len);
 491                return;
 492        }
 493
 494        if (len < ecbdata->nparents) {
 495                set = reset;
 496                emit_line(reset, reset, line, len);
 497                return;
 498        }
 499
 500        color = DIFF_PLAIN;
 501        if (ecbdata->diff_words && ecbdata->nparents != 1)
 502                /* fall back to normal diff */
 503                free_diff_words_data(ecbdata);
 504        if (ecbdata->diff_words) {
 505                if (line[0] == '-') {
 506                        diff_words_append(line, len,
 507                                          &ecbdata->diff_words->minus);
 508                        return;
 509                } else if (line[0] == '+') {
 510                        diff_words_append(line, len,
 511                                          &ecbdata->diff_words->plus);
 512                        return;
 513                }
 514                if (ecbdata->diff_words->minus.text.size ||
 515                    ecbdata->diff_words->plus.text.size)
 516                        diff_words_show(ecbdata->diff_words);
 517                line++;
 518                len--;
 519                emit_line(set, reset, line, len);
 520                return;
 521        }
 522        for (i = 0; i < ecbdata->nparents && len; i++) {
 523                if (line[i] == '-')
 524                        color = DIFF_FILE_OLD;
 525                else if (line[i] == '+')
 526                        color = DIFF_FILE_NEW;
 527        }
 528
 529        if (color != DIFF_FILE_NEW) {
 530                emit_line(diff_get_color(ecbdata->color_diff, color),
 531                          reset, line, len);
 532                return;
 533        }
 534        emit_add_line(reset, ecbdata, line, len);
 535}
 536
 537static char *pprint_rename(const char *a, const char *b)
 538{
 539        const char *old = a;
 540        const char *new = b;
 541        char *name = NULL;
 542        int pfx_length, sfx_length;
 543        int len_a = strlen(a);
 544        int len_b = strlen(b);
 545
 546        /* Find common prefix */
 547        pfx_length = 0;
 548        while (*old && *new && *old == *new) {
 549                if (*old == '/')
 550                        pfx_length = old - a + 1;
 551                old++;
 552                new++;
 553        }
 554
 555        /* Find common suffix */
 556        old = a + len_a;
 557        new = b + len_b;
 558        sfx_length = 0;
 559        while (a <= old && b <= new && *old == *new) {
 560                if (*old == '/')
 561                        sfx_length = len_a - (old - a);
 562                old--;
 563                new--;
 564        }
 565
 566        /*
 567         * pfx{mid-a => mid-b}sfx
 568         * {pfx-a => pfx-b}sfx
 569         * pfx{sfx-a => sfx-b}
 570         * name-a => name-b
 571         */
 572        if (pfx_length + sfx_length) {
 573                int a_midlen = len_a - pfx_length - sfx_length;
 574                int b_midlen = len_b - pfx_length - sfx_length;
 575                if (a_midlen < 0) a_midlen = 0;
 576                if (b_midlen < 0) b_midlen = 0;
 577
 578                name = xmalloc(pfx_length + a_midlen + b_midlen + sfx_length + 7);
 579                sprintf(name, "%.*s{%.*s => %.*s}%s",
 580                        pfx_length, a,
 581                        a_midlen, a + pfx_length,
 582                        b_midlen, b + pfx_length,
 583                        a + len_a - sfx_length);
 584        }
 585        else {
 586                name = xmalloc(len_a + len_b + 5);
 587                sprintf(name, "%s => %s", a, b);
 588        }
 589        return name;
 590}
 591
 592struct diffstat_t {
 593        struct xdiff_emit_state xm;
 594
 595        int nr;
 596        int alloc;
 597        struct diffstat_file {
 598                char *name;
 599                unsigned is_unmerged:1;
 600                unsigned is_binary:1;
 601                unsigned is_renamed:1;
 602                unsigned int added, deleted;
 603        } **files;
 604};
 605
 606static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
 607                                          const char *name_a,
 608                                          const char *name_b)
 609{
 610        struct diffstat_file *x;
 611        x = xcalloc(sizeof (*x), 1);
 612        if (diffstat->nr == diffstat->alloc) {
 613                diffstat->alloc = alloc_nr(diffstat->alloc);
 614                diffstat->files = xrealloc(diffstat->files,
 615                                diffstat->alloc * sizeof(x));
 616        }
 617        diffstat->files[diffstat->nr++] = x;
 618        if (name_b) {
 619                x->name = pprint_rename(name_a, name_b);
 620                x->is_renamed = 1;
 621        }
 622        else
 623                x->name = xstrdup(name_a);
 624        return x;
 625}
 626
 627static void diffstat_consume(void *priv, char *line, unsigned long len)
 628{
 629        struct diffstat_t *diffstat = priv;
 630        struct diffstat_file *x = diffstat->files[diffstat->nr - 1];
 631
 632        if (line[0] == '+')
 633                x->added++;
 634        else if (line[0] == '-')
 635                x->deleted++;
 636}
 637
 638static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
 639static const char minuses[]= "----------------------------------------------------------------------";
 640const char mime_boundary_leader[] = "------------";
 641
 642static void show_stats(struct diffstat_t* data)
 643{
 644        int i, len, add, del, total, adds = 0, dels = 0;
 645        int max, max_change = 0, max_len = 0;
 646        int total_files = data->nr;
 647
 648        if (data->nr == 0)
 649                return;
 650
 651        for (i = 0; i < data->nr; i++) {
 652                struct diffstat_file *file = data->files[i];
 653
 654                len = strlen(file->name);
 655                if (max_len < len)
 656                        max_len = len;
 657
 658                if (file->is_binary || file->is_unmerged)
 659                        continue;
 660                if (max_change < file->added + file->deleted)
 661                        max_change = file->added + file->deleted;
 662        }
 663
 664        for (i = 0; i < data->nr; i++) {
 665                const char *prefix = "";
 666                char *name = data->files[i]->name;
 667                int added = data->files[i]->added;
 668                int deleted = data->files[i]->deleted;
 669
 670                if (0 < (len = quote_c_style(name, NULL, NULL, 0))) {
 671                        char *qname = xmalloc(len + 1);
 672                        quote_c_style(name, qname, NULL, 0);
 673                        free(name);
 674                        data->files[i]->name = name = qname;
 675                }
 676
 677                /*
 678                 * "scale" the filename
 679                 */
 680                len = strlen(name);
 681                max = max_len;
 682                if (max > 50)
 683                        max = 50;
 684                if (len > max) {
 685                        char *slash;
 686                        prefix = "...";
 687                        max -= 3;
 688                        name += len - max;
 689                        slash = strchr(name, '/');
 690                        if (slash)
 691                                name = slash;
 692                }
 693                len = max;
 694
 695                /*
 696                 * scale the add/delete
 697                 */
 698                max = max_change;
 699                if (max + len > 70)
 700                        max = 70 - len;
 701
 702                if (data->files[i]->is_binary) {
 703                        printf(" %s%-*s |  Bin\n", prefix, len, name);
 704                        goto free_diffstat_file;
 705                }
 706                else if (data->files[i]->is_unmerged) {
 707                        printf(" %s%-*s |  Unmerged\n", prefix, len, name);
 708                        goto free_diffstat_file;
 709                }
 710                else if (!data->files[i]->is_renamed &&
 711                         (added + deleted == 0)) {
 712                        total_files--;
 713                        goto free_diffstat_file;
 714                }
 715
 716                add = added;
 717                del = deleted;
 718                total = add + del;
 719                adds += add;
 720                dels += del;
 721
 722                if (max_change > 0) {
 723                        total = (total * max + max_change / 2) / max_change;
 724                        add = (add * max + max_change / 2) / max_change;
 725                        del = total - add;
 726                }
 727                printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
 728                                len, name, added + deleted,
 729                                add, pluses, del, minuses);
 730        free_diffstat_file:
 731                free(data->files[i]->name);
 732                free(data->files[i]);
 733        }
 734        free(data->files);
 735        printf(" %d files changed, %d insertions(+), %d deletions(-)\n",
 736                        total_files, adds, dels);
 737}
 738
 739struct checkdiff_t {
 740        struct xdiff_emit_state xm;
 741        const char *filename;
 742        int lineno;
 743};
 744
 745static void checkdiff_consume(void *priv, char *line, unsigned long len)
 746{
 747        struct checkdiff_t *data = priv;
 748
 749        if (line[0] == '+') {
 750                int i, spaces = 0;
 751
 752                data->lineno++;
 753
 754                /* check space before tab */
 755                for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++)
 756                        if (line[i] == ' ')
 757                                spaces++;
 758                if (line[i - 1] == '\t' && spaces)
 759                        printf("%s:%d: space before tab:%.*s\n",
 760                                data->filename, data->lineno, (int)len, line);
 761
 762                /* check white space at line end */
 763                if (line[len - 1] == '\n')
 764                        len--;
 765                if (isspace(line[len - 1]))
 766                        printf("%s:%d: white space at end: %.*s\n",
 767                                data->filename, data->lineno, (int)len, line);
 768        } else if (line[0] == ' ')
 769                data->lineno++;
 770        else if (line[0] == '@') {
 771                char *plus = strchr(line, '+');
 772                if (plus)
 773                        data->lineno = strtol(plus, NULL, 10);
 774                else
 775                        die("invalid diff");
 776        }
 777}
 778
 779static unsigned char *deflate_it(char *data,
 780                                 unsigned long size,
 781                                 unsigned long *result_size)
 782{
 783        int bound;
 784        unsigned char *deflated;
 785        z_stream stream;
 786
 787        memset(&stream, 0, sizeof(stream));
 788        deflateInit(&stream, zlib_compression_level);
 789        bound = deflateBound(&stream, size);
 790        deflated = xmalloc(bound);
 791        stream.next_out = deflated;
 792        stream.avail_out = bound;
 793
 794        stream.next_in = (unsigned char *)data;
 795        stream.avail_in = size;
 796        while (deflate(&stream, Z_FINISH) == Z_OK)
 797                ; /* nothing */
 798        deflateEnd(&stream);
 799        *result_size = stream.total_out;
 800        return deflated;
 801}
 802
 803static void emit_binary_diff_body(mmfile_t *one, mmfile_t *two)
 804{
 805        void *cp;
 806        void *delta;
 807        void *deflated;
 808        void *data;
 809        unsigned long orig_size;
 810        unsigned long delta_size;
 811        unsigned long deflate_size;
 812        unsigned long data_size;
 813
 814        /* We could do deflated delta, or we could do just deflated two,
 815         * whichever is smaller.
 816         */
 817        delta = NULL;
 818        deflated = deflate_it(two->ptr, two->size, &deflate_size);
 819        if (one->size && two->size) {
 820                delta = diff_delta(one->ptr, one->size,
 821                                   two->ptr, two->size,
 822                                   &delta_size, deflate_size);
 823                if (delta) {
 824                        void *to_free = delta;
 825                        orig_size = delta_size;
 826                        delta = deflate_it(delta, delta_size, &delta_size);
 827                        free(to_free);
 828                }
 829        }
 830
 831        if (delta && delta_size < deflate_size) {
 832                printf("delta %lu\n", orig_size);
 833                free(deflated);
 834                data = delta;
 835                data_size = delta_size;
 836        }
 837        else {
 838                printf("literal %lu\n", two->size);
 839                free(delta);
 840                data = deflated;
 841                data_size = deflate_size;
 842        }
 843
 844        /* emit data encoded in base85 */
 845        cp = data;
 846        while (data_size) {
 847                int bytes = (52 < data_size) ? 52 : data_size;
 848                char line[70];
 849                data_size -= bytes;
 850                if (bytes <= 26)
 851                        line[0] = bytes + 'A' - 1;
 852                else
 853                        line[0] = bytes - 26 + 'a' - 1;
 854                encode_85(line + 1, cp, bytes);
 855                cp = (char *) cp + bytes;
 856                puts(line);
 857        }
 858        printf("\n");
 859        free(data);
 860}
 861
 862static void emit_binary_diff(mmfile_t *one, mmfile_t *two)
 863{
 864        printf("GIT binary patch\n");
 865        emit_binary_diff_body(one, two);
 866        emit_binary_diff_body(two, one);
 867}
 868
 869#define FIRST_FEW_BYTES 8000
 870static int mmfile_is_binary(mmfile_t *mf)
 871{
 872        long sz = mf->size;
 873        if (FIRST_FEW_BYTES < sz)
 874                sz = FIRST_FEW_BYTES;
 875        return !!memchr(mf->ptr, 0, sz);
 876}
 877
 878static void builtin_diff(const char *name_a,
 879                         const char *name_b,
 880                         struct diff_filespec *one,
 881                         struct diff_filespec *two,
 882                         const char *xfrm_msg,
 883                         struct diff_options *o,
 884                         int complete_rewrite)
 885{
 886        mmfile_t mf1, mf2;
 887        const char *lbl[2];
 888        char *a_one, *b_two;
 889        const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
 890        const char *reset = diff_get_color(o->color_diff, DIFF_RESET);
 891
 892        a_one = quote_two("a/", name_a);
 893        b_two = quote_two("b/", name_b);
 894        lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
 895        lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
 896        printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
 897        if (lbl[0][0] == '/') {
 898                /* /dev/null */
 899                printf("%snew file mode %06o%s\n", set, two->mode, reset);
 900                if (xfrm_msg && xfrm_msg[0])
 901                        printf("%s%s%s\n", set, xfrm_msg, reset);
 902        }
 903        else if (lbl[1][0] == '/') {
 904                printf("%sdeleted file mode %06o%s\n", set, one->mode, reset);
 905                if (xfrm_msg && xfrm_msg[0])
 906                        printf("%s%s%s\n", set, xfrm_msg, reset);
 907        }
 908        else {
 909                if (one->mode != two->mode) {
 910                        printf("%sold mode %06o%s\n", set, one->mode, reset);
 911                        printf("%snew mode %06o%s\n", set, two->mode, reset);
 912                }
 913                if (xfrm_msg && xfrm_msg[0])
 914                        printf("%s%s%s\n", set, xfrm_msg, reset);
 915                /*
 916                 * we do not run diff between different kind
 917                 * of objects.
 918                 */
 919                if ((one->mode ^ two->mode) & S_IFMT)
 920                        goto free_ab_and_return;
 921                if (complete_rewrite) {
 922                        emit_rewrite_diff(name_a, name_b, one, two);
 923                        goto free_ab_and_return;
 924                }
 925        }
 926
 927        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
 928                die("unable to read files to diff");
 929
 930        if (!o->text && (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))) {
 931                /* Quite common confusing case */
 932                if (mf1.size == mf2.size &&
 933                    !memcmp(mf1.ptr, mf2.ptr, mf1.size))
 934                        goto free_ab_and_return;
 935                if (o->binary)
 936                        emit_binary_diff(&mf1, &mf2);
 937                else
 938                        printf("Binary files %s and %s differ\n",
 939                               lbl[0], lbl[1]);
 940        }
 941        else {
 942                /* Crazy xdl interfaces.. */
 943                const char *diffopts = getenv("GIT_DIFF_OPTS");
 944                xpparam_t xpp;
 945                xdemitconf_t xecfg;
 946                xdemitcb_t ecb;
 947                struct emit_callback ecbdata;
 948
 949                memset(&ecbdata, 0, sizeof(ecbdata));
 950                ecbdata.label_path = lbl;
 951                ecbdata.color_diff = o->color_diff;
 952                xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
 953                xecfg.ctxlen = o->context;
 954                xecfg.flags = XDL_EMIT_FUNCNAMES;
 955                if (!diffopts)
 956                        ;
 957                else if (!strncmp(diffopts, "--unified=", 10))
 958                        xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
 959                else if (!strncmp(diffopts, "-u", 2))
 960                        xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
 961                ecb.outf = xdiff_outf;
 962                ecb.priv = &ecbdata;
 963                ecbdata.xm.consume = fn_out_consume;
 964                if (o->color_diff_words)
 965                        ecbdata.diff_words =
 966                                xcalloc(1, sizeof(struct diff_words_data));
 967                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
 968                if (o->color_diff_words)
 969                        free_diff_words_data(&ecbdata);
 970        }
 971
 972 free_ab_and_return:
 973        free(a_one);
 974        free(b_two);
 975        return;
 976}
 977
 978static void builtin_diffstat(const char *name_a, const char *name_b,
 979                             struct diff_filespec *one,
 980                             struct diff_filespec *two,
 981                             struct diffstat_t *diffstat,
 982                             struct diff_options *o,
 983                             int complete_rewrite)
 984{
 985        mmfile_t mf1, mf2;
 986        struct diffstat_file *data;
 987
 988        data = diffstat_add(diffstat, name_a, name_b);
 989
 990        if (!one || !two) {
 991                data->is_unmerged = 1;
 992                return;
 993        }
 994        if (complete_rewrite) {
 995                diff_populate_filespec(one, 0);
 996                diff_populate_filespec(two, 0);
 997                data->deleted = count_lines(one->data, one->size);
 998                data->added = count_lines(two->data, two->size);
 999                return;
1000        }
1001        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1002                die("unable to read files to diff");
1003
1004        if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
1005                data->is_binary = 1;
1006        else {
1007                /* Crazy xdl interfaces.. */
1008                xpparam_t xpp;
1009                xdemitconf_t xecfg;
1010                xdemitcb_t ecb;
1011
1012                xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
1013                xecfg.ctxlen = 0;
1014                xecfg.flags = 0;
1015                ecb.outf = xdiff_outf;
1016                ecb.priv = diffstat;
1017                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
1018        }
1019}
1020
1021static void builtin_checkdiff(const char *name_a, const char *name_b,
1022                             struct diff_filespec *one,
1023                             struct diff_filespec *two)
1024{
1025        mmfile_t mf1, mf2;
1026        struct checkdiff_t data;
1027
1028        if (!two)
1029                return;
1030
1031        memset(&data, 0, sizeof(data));
1032        data.xm.consume = checkdiff_consume;
1033        data.filename = name_b ? name_b : name_a;
1034        data.lineno = 0;
1035
1036        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1037                die("unable to read files to diff");
1038
1039        if (mmfile_is_binary(&mf2))
1040                return;
1041        else {
1042                /* Crazy xdl interfaces.. */
1043                xpparam_t xpp;
1044                xdemitconf_t xecfg;
1045                xdemitcb_t ecb;
1046
1047                xpp.flags = XDF_NEED_MINIMAL;
1048                xecfg.ctxlen = 0;
1049                xecfg.flags = 0;
1050                ecb.outf = xdiff_outf;
1051                ecb.priv = &data;
1052                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
1053        }
1054}
1055
1056struct diff_filespec *alloc_filespec(const char *path)
1057{
1058        int namelen = strlen(path);
1059        struct diff_filespec *spec = xmalloc(sizeof(*spec) + namelen + 1);
1060
1061        memset(spec, 0, sizeof(*spec));
1062        spec->path = (char *)(spec + 1);
1063        memcpy(spec->path, path, namelen+1);
1064        return spec;
1065}
1066
1067void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
1068                   unsigned short mode)
1069{
1070        if (mode) {
1071                spec->mode = canon_mode(mode);
1072                hashcpy(spec->sha1, sha1);
1073                spec->sha1_valid = !is_null_sha1(sha1);
1074        }
1075}
1076
1077/*
1078 * Given a name and sha1 pair, if the dircache tells us the file in
1079 * the work tree has that object contents, return true, so that
1080 * prepare_temp_file() does not have to inflate and extract.
1081 */
1082static int work_tree_matches(const char *name, const unsigned char *sha1)
1083{
1084        struct cache_entry *ce;
1085        struct stat st;
1086        int pos, len;
1087
1088        /* We do not read the cache ourselves here, because the
1089         * benchmark with my previous version that always reads cache
1090         * shows that it makes things worse for diff-tree comparing
1091         * two linux-2.6 kernel trees in an already checked out work
1092         * tree.  This is because most diff-tree comparisons deal with
1093         * only a small number of files, while reading the cache is
1094         * expensive for a large project, and its cost outweighs the
1095         * savings we get by not inflating the object to a temporary
1096         * file.  Practically, this code only helps when we are used
1097         * by diff-cache --cached, which does read the cache before
1098         * calling us.
1099         */
1100        if (!active_cache)
1101                return 0;
1102
1103        len = strlen(name);
1104        pos = cache_name_pos(name, len);
1105        if (pos < 0)
1106                return 0;
1107        ce = active_cache[pos];
1108        if ((lstat(name, &st) < 0) ||
1109            !S_ISREG(st.st_mode) || /* careful! */
1110            ce_match_stat(ce, &st, 0) ||
1111            hashcmp(sha1, ce->sha1))
1112                return 0;
1113        /* we return 1 only when we can stat, it is a regular file,
1114         * stat information matches, and sha1 recorded in the cache
1115         * matches.  I.e. we know the file in the work tree really is
1116         * the same as the <name, sha1> pair.
1117         */
1118        return 1;
1119}
1120
1121static struct sha1_size_cache {
1122        unsigned char sha1[20];
1123        unsigned long size;
1124} **sha1_size_cache;
1125static int sha1_size_cache_nr, sha1_size_cache_alloc;
1126
1127static struct sha1_size_cache *locate_size_cache(unsigned char *sha1,
1128                                                 int find_only,
1129                                                 unsigned long size)
1130{
1131        int first, last;
1132        struct sha1_size_cache *e;
1133
1134        first = 0;
1135        last = sha1_size_cache_nr;
1136        while (last > first) {
1137                int cmp, next = (last + first) >> 1;
1138                e = sha1_size_cache[next];
1139                cmp = hashcmp(e->sha1, sha1);
1140                if (!cmp)
1141                        return e;
1142                if (cmp < 0) {
1143                        last = next;
1144                        continue;
1145                }
1146                first = next+1;
1147        }
1148        /* not found */
1149        if (find_only)
1150                return NULL;
1151        /* insert to make it at "first" */
1152        if (sha1_size_cache_alloc <= sha1_size_cache_nr) {
1153                sha1_size_cache_alloc = alloc_nr(sha1_size_cache_alloc);
1154                sha1_size_cache = xrealloc(sha1_size_cache,
1155                                           sha1_size_cache_alloc *
1156                                           sizeof(*sha1_size_cache));
1157        }
1158        sha1_size_cache_nr++;
1159        if (first < sha1_size_cache_nr)
1160                memmove(sha1_size_cache + first + 1, sha1_size_cache + first,
1161                        (sha1_size_cache_nr - first - 1) *
1162                        sizeof(*sha1_size_cache));
1163        e = xmalloc(sizeof(struct sha1_size_cache));
1164        sha1_size_cache[first] = e;
1165        hashcpy(e->sha1, sha1);
1166        e->size = size;
1167        return e;
1168}
1169
1170/*
1171 * While doing rename detection and pickaxe operation, we may need to
1172 * grab the data for the blob (or file) for our own in-core comparison.
1173 * diff_filespec has data and size fields for this purpose.
1174 */
1175int diff_populate_filespec(struct diff_filespec *s, int size_only)
1176{
1177        int err = 0;
1178        if (!DIFF_FILE_VALID(s))
1179                die("internal error: asking to populate invalid file.");
1180        if (S_ISDIR(s->mode))
1181                return -1;
1182
1183        if (!use_size_cache)
1184                size_only = 0;
1185
1186        if (s->data)
1187                return err;
1188        if (!s->sha1_valid ||
1189            work_tree_matches(s->path, s->sha1)) {
1190                struct stat st;
1191                int fd;
1192                if (lstat(s->path, &st) < 0) {
1193                        if (errno == ENOENT) {
1194                        err_empty:
1195                                err = -1;
1196                        empty:
1197                                s->data = (char *)"";
1198                                s->size = 0;
1199                                return err;
1200                        }
1201                }
1202                s->size = st.st_size;
1203                if (!s->size)
1204                        goto empty;
1205                if (size_only)
1206                        return 0;
1207                if (S_ISLNK(st.st_mode)) {
1208                        int ret;
1209                        s->data = xmalloc(s->size);
1210                        s->should_free = 1;
1211                        ret = readlink(s->path, s->data, s->size);
1212                        if (ret < 0) {
1213                                free(s->data);
1214                                goto err_empty;
1215                        }
1216                        return 0;
1217                }
1218                fd = open(s->path, O_RDONLY);
1219                if (fd < 0)
1220                        goto err_empty;
1221                s->data = mmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
1222                close(fd);
1223                if (s->data == MAP_FAILED)
1224                        goto err_empty;
1225                s->should_munmap = 1;
1226        }
1227        else {
1228                char type[20];
1229                struct sha1_size_cache *e;
1230
1231                if (size_only) {
1232                        e = locate_size_cache(s->sha1, 1, 0);
1233                        if (e) {
1234                                s->size = e->size;
1235                                return 0;
1236                        }
1237                        if (!sha1_object_info(s->sha1, type, &s->size))
1238                                locate_size_cache(s->sha1, 0, s->size);
1239                }
1240                else {
1241                        s->data = read_sha1_file(s->sha1, type, &s->size);
1242                        s->should_free = 1;
1243                }
1244        }
1245        return 0;
1246}
1247
1248void diff_free_filespec_data(struct diff_filespec *s)
1249{
1250        if (s->should_free)
1251                free(s->data);
1252        else if (s->should_munmap)
1253                munmap(s->data, s->size);
1254        s->should_free = s->should_munmap = 0;
1255        s->data = NULL;
1256        free(s->cnt_data);
1257        s->cnt_data = NULL;
1258}
1259
1260static void prep_temp_blob(struct diff_tempfile *temp,
1261                           void *blob,
1262                           unsigned long size,
1263                           const unsigned char *sha1,
1264                           int mode)
1265{
1266        int fd;
1267
1268        fd = git_mkstemp(temp->tmp_path, TEMPFILE_PATH_LEN, ".diff_XXXXXX");
1269        if (fd < 0)
1270                die("unable to create temp-file");
1271        if (write(fd, blob, size) != size)
1272                die("unable to write temp-file");
1273        close(fd);
1274        temp->name = temp->tmp_path;
1275        strcpy(temp->hex, sha1_to_hex(sha1));
1276        temp->hex[40] = 0;
1277        sprintf(temp->mode, "%06o", mode);
1278}
1279
1280static void prepare_temp_file(const char *name,
1281                              struct diff_tempfile *temp,
1282                              struct diff_filespec *one)
1283{
1284        if (!DIFF_FILE_VALID(one)) {
1285        not_a_valid_file:
1286                /* A '-' entry produces this for file-2, and
1287                 * a '+' entry produces this for file-1.
1288                 */
1289                temp->name = "/dev/null";
1290                strcpy(temp->hex, ".");
1291                strcpy(temp->mode, ".");
1292                return;
1293        }
1294
1295        if (!one->sha1_valid ||
1296            work_tree_matches(name, one->sha1)) {
1297                struct stat st;
1298                if (lstat(name, &st) < 0) {
1299                        if (errno == ENOENT)
1300                                goto not_a_valid_file;
1301                        die("stat(%s): %s", name, strerror(errno));
1302                }
1303                if (S_ISLNK(st.st_mode)) {
1304                        int ret;
1305                        char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
1306                        if (sizeof(buf) <= st.st_size)
1307                                die("symlink too long: %s", name);
1308                        ret = readlink(name, buf, st.st_size);
1309                        if (ret < 0)
1310                                die("readlink(%s)", name);
1311                        prep_temp_blob(temp, buf, st.st_size,
1312                                       (one->sha1_valid ?
1313                                        one->sha1 : null_sha1),
1314                                       (one->sha1_valid ?
1315                                        one->mode : S_IFLNK));
1316                }
1317                else {
1318                        /* we can borrow from the file in the work tree */
1319                        temp->name = name;
1320                        if (!one->sha1_valid)
1321                                strcpy(temp->hex, sha1_to_hex(null_sha1));
1322                        else
1323                                strcpy(temp->hex, sha1_to_hex(one->sha1));
1324                        /* Even though we may sometimes borrow the
1325                         * contents from the work tree, we always want
1326                         * one->mode.  mode is trustworthy even when
1327                         * !(one->sha1_valid), as long as
1328                         * DIFF_FILE_VALID(one).
1329                         */
1330                        sprintf(temp->mode, "%06o", one->mode);
1331                }
1332                return;
1333        }
1334        else {
1335                if (diff_populate_filespec(one, 0))
1336                        die("cannot read data blob for %s", one->path);
1337                prep_temp_blob(temp, one->data, one->size,
1338                               one->sha1, one->mode);
1339        }
1340}
1341
1342static void remove_tempfile(void)
1343{
1344        int i;
1345
1346        for (i = 0; i < 2; i++)
1347                if (diff_temp[i].name == diff_temp[i].tmp_path) {
1348                        unlink(diff_temp[i].name);
1349                        diff_temp[i].name = NULL;
1350                }
1351}
1352
1353static void remove_tempfile_on_signal(int signo)
1354{
1355        remove_tempfile();
1356        signal(SIGINT, SIG_DFL);
1357        raise(signo);
1358}
1359
1360static int spawn_prog(const char *pgm, const char **arg)
1361{
1362        pid_t pid;
1363        int status;
1364
1365        fflush(NULL);
1366        pid = fork();
1367        if (pid < 0)
1368                die("unable to fork");
1369        if (!pid) {
1370                execvp(pgm, (char *const*) arg);
1371                exit(255);
1372        }
1373
1374        while (waitpid(pid, &status, 0) < 0) {
1375                if (errno == EINTR)
1376                        continue;
1377                return -1;
1378        }
1379
1380        /* Earlier we did not check the exit status because
1381         * diff exits non-zero if files are different, and
1382         * we are not interested in knowing that.  It was a
1383         * mistake which made it harder to quit a diff-*
1384         * session that uses the git-apply-patch-script as
1385         * the GIT_EXTERNAL_DIFF.  A custom GIT_EXTERNAL_DIFF
1386         * should also exit non-zero only when it wants to
1387         * abort the entire diff-* session.
1388         */
1389        if (WIFEXITED(status) && !WEXITSTATUS(status))
1390                return 0;
1391        return -1;
1392}
1393
1394/* An external diff command takes:
1395 *
1396 * diff-cmd name infile1 infile1-sha1 infile1-mode \
1397 *               infile2 infile2-sha1 infile2-mode [ rename-to ]
1398 *
1399 */
1400static void run_external_diff(const char *pgm,
1401                              const char *name,
1402                              const char *other,
1403                              struct diff_filespec *one,
1404                              struct diff_filespec *two,
1405                              const char *xfrm_msg,
1406                              int complete_rewrite)
1407{
1408        const char *spawn_arg[10];
1409        struct diff_tempfile *temp = diff_temp;
1410        int retval;
1411        static int atexit_asked = 0;
1412        const char *othername;
1413        const char **arg = &spawn_arg[0];
1414
1415        othername = (other? other : name);
1416        if (one && two) {
1417                prepare_temp_file(name, &temp[0], one);
1418                prepare_temp_file(othername, &temp[1], two);
1419                if (! atexit_asked &&
1420                    (temp[0].name == temp[0].tmp_path ||
1421                     temp[1].name == temp[1].tmp_path)) {
1422                        atexit_asked = 1;
1423                        atexit(remove_tempfile);
1424                }
1425                signal(SIGINT, remove_tempfile_on_signal);
1426        }
1427
1428        if (one && two) {
1429                *arg++ = pgm;
1430                *arg++ = name;
1431                *arg++ = temp[0].name;
1432                *arg++ = temp[0].hex;
1433                *arg++ = temp[0].mode;
1434                *arg++ = temp[1].name;
1435                *arg++ = temp[1].hex;
1436                *arg++ = temp[1].mode;
1437                if (other) {
1438                        *arg++ = other;
1439                        *arg++ = xfrm_msg;
1440                }
1441        } else {
1442                *arg++ = pgm;
1443                *arg++ = name;
1444        }
1445        *arg = NULL;
1446        retval = spawn_prog(pgm, spawn_arg);
1447        remove_tempfile();
1448        if (retval) {
1449                fprintf(stderr, "external diff died, stopping at %s.\n", name);
1450                exit(1);
1451        }
1452}
1453
1454static void run_diff_cmd(const char *pgm,
1455                         const char *name,
1456                         const char *other,
1457                         struct diff_filespec *one,
1458                         struct diff_filespec *two,
1459                         const char *xfrm_msg,
1460                         struct diff_options *o,
1461                         int complete_rewrite)
1462{
1463        if (pgm) {
1464                run_external_diff(pgm, name, other, one, two, xfrm_msg,
1465                                  complete_rewrite);
1466                return;
1467        }
1468        if (one && two)
1469                builtin_diff(name, other ? other : name,
1470                             one, two, xfrm_msg, o, complete_rewrite);
1471        else
1472                printf("* Unmerged path %s\n", name);
1473}
1474
1475static void diff_fill_sha1_info(struct diff_filespec *one)
1476{
1477        if (DIFF_FILE_VALID(one)) {
1478                if (!one->sha1_valid) {
1479                        struct stat st;
1480                        if (lstat(one->path, &st) < 0)
1481                                die("stat %s", one->path);
1482                        if (index_path(one->sha1, one->path, &st, 0))
1483                                die("cannot hash %s\n", one->path);
1484                }
1485        }
1486        else
1487                hashclr(one->sha1);
1488}
1489
1490static void run_diff(struct diff_filepair *p, struct diff_options *o)
1491{
1492        const char *pgm = external_diff();
1493        char msg[PATH_MAX*2+300], *xfrm_msg;
1494        struct diff_filespec *one;
1495        struct diff_filespec *two;
1496        const char *name;
1497        const char *other;
1498        char *name_munged, *other_munged;
1499        int complete_rewrite = 0;
1500        int len;
1501
1502        if (DIFF_PAIR_UNMERGED(p)) {
1503                /* unmerged */
1504                run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0);
1505                return;
1506        }
1507
1508        name = p->one->path;
1509        other = (strcmp(name, p->two->path) ? p->two->path : NULL);
1510        name_munged = quote_one(name);
1511        other_munged = quote_one(other);
1512        one = p->one; two = p->two;
1513
1514        diff_fill_sha1_info(one);
1515        diff_fill_sha1_info(two);
1516
1517        len = 0;
1518        switch (p->status) {
1519        case DIFF_STATUS_COPIED:
1520                len += snprintf(msg + len, sizeof(msg) - len,
1521                                "similarity index %d%%\n"
1522                                "copy from %s\n"
1523                                "copy to %s\n",
1524                                (int)(0.5 + p->score * 100.0/MAX_SCORE),
1525                                name_munged, other_munged);
1526                break;
1527        case DIFF_STATUS_RENAMED:
1528                len += snprintf(msg + len, sizeof(msg) - len,
1529                                "similarity index %d%%\n"
1530                                "rename from %s\n"
1531                                "rename to %s\n",
1532                                (int)(0.5 + p->score * 100.0/MAX_SCORE),
1533                                name_munged, other_munged);
1534                break;
1535        case DIFF_STATUS_MODIFIED:
1536                if (p->score) {
1537                        len += snprintf(msg + len, sizeof(msg) - len,
1538                                        "dissimilarity index %d%%\n",
1539                                        (int)(0.5 + p->score *
1540                                              100.0/MAX_SCORE));
1541                        complete_rewrite = 1;
1542                        break;
1543                }
1544                /* fallthru */
1545        default:
1546                /* nothing */
1547                ;
1548        }
1549
1550        if (hashcmp(one->sha1, two->sha1)) {
1551                int abbrev = o->full_index ? 40 : DEFAULT_ABBREV;
1552
1553                if (o->binary) {
1554                        mmfile_t mf;
1555                        if ((!fill_mmfile(&mf, one) && mmfile_is_binary(&mf)) ||
1556                            (!fill_mmfile(&mf, two) && mmfile_is_binary(&mf)))
1557                                abbrev = 40;
1558                }
1559                len += snprintf(msg + len, sizeof(msg) - len,
1560                                "index %.*s..%.*s",
1561                                abbrev, sha1_to_hex(one->sha1),
1562                                abbrev, sha1_to_hex(two->sha1));
1563                if (one->mode == two->mode)
1564                        len += snprintf(msg + len, sizeof(msg) - len,
1565                                        " %06o", one->mode);
1566                len += snprintf(msg + len, sizeof(msg) - len, "\n");
1567        }
1568
1569        if (len)
1570                msg[--len] = 0;
1571        xfrm_msg = len ? msg : NULL;
1572
1573        if (!pgm &&
1574            DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
1575            (S_IFMT & one->mode) != (S_IFMT & two->mode)) {
1576                /* a filepair that changes between file and symlink
1577                 * needs to be split into deletion and creation.
1578                 */
1579                struct diff_filespec *null = alloc_filespec(two->path);
1580                run_diff_cmd(NULL, name, other, one, null, xfrm_msg, o, 0);
1581                free(null);
1582                null = alloc_filespec(one->path);
1583                run_diff_cmd(NULL, name, other, null, two, xfrm_msg, o, 0);
1584                free(null);
1585        }
1586        else
1587                run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o,
1588                             complete_rewrite);
1589
1590        free(name_munged);
1591        free(other_munged);
1592}
1593
1594static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
1595                         struct diffstat_t *diffstat)
1596{
1597        const char *name;
1598        const char *other;
1599        int complete_rewrite = 0;
1600
1601        if (DIFF_PAIR_UNMERGED(p)) {
1602                /* unmerged */
1603                builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0);
1604                return;
1605        }
1606
1607        name = p->one->path;
1608        other = (strcmp(name, p->two->path) ? p->two->path : NULL);
1609
1610        diff_fill_sha1_info(p->one);
1611        diff_fill_sha1_info(p->two);
1612
1613        if (p->status == DIFF_STATUS_MODIFIED && p->score)
1614                complete_rewrite = 1;
1615        builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite);
1616}
1617
1618static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
1619{
1620        const char *name;
1621        const char *other;
1622
1623        if (DIFF_PAIR_UNMERGED(p)) {
1624                /* unmerged */
1625                return;
1626        }
1627
1628        name = p->one->path;
1629        other = (strcmp(name, p->two->path) ? p->two->path : NULL);
1630
1631        diff_fill_sha1_info(p->one);
1632        diff_fill_sha1_info(p->two);
1633
1634        builtin_checkdiff(name, other, p->one, p->two);
1635}
1636
1637void diff_setup(struct diff_options *options)
1638{
1639        memset(options, 0, sizeof(*options));
1640        options->line_termination = '\n';
1641        options->break_opt = -1;
1642        options->rename_limit = -1;
1643        options->context = 3;
1644        options->msg_sep = "";
1645
1646        options->change = diff_change;
1647        options->add_remove = diff_addremove;
1648        options->color_diff = diff_use_color_default;
1649        options->detect_rename = diff_detect_rename_default;
1650}
1651
1652int diff_setup_done(struct diff_options *options)
1653{
1654        int count = 0;
1655
1656        if (options->output_format & DIFF_FORMAT_NAME)
1657                count++;
1658        if (options->output_format & DIFF_FORMAT_NAME_STATUS)
1659                count++;
1660        if (options->output_format & DIFF_FORMAT_CHECKDIFF)
1661                count++;
1662        if (options->output_format & DIFF_FORMAT_NO_OUTPUT)
1663                count++;
1664        if (count > 1)
1665                die("--name-only, --name-status, --check and -s are mutually exclusive");
1666
1667        if (options->find_copies_harder)
1668                options->detect_rename = DIFF_DETECT_COPY;
1669
1670        if (options->output_format & (DIFF_FORMAT_NAME |
1671                                      DIFF_FORMAT_NAME_STATUS |
1672                                      DIFF_FORMAT_CHECKDIFF |
1673                                      DIFF_FORMAT_NO_OUTPUT))
1674                options->output_format &= ~(DIFF_FORMAT_RAW |
1675                                            DIFF_FORMAT_DIFFSTAT |
1676                                            DIFF_FORMAT_SUMMARY |
1677                                            DIFF_FORMAT_PATCH);
1678
1679        /*
1680         * These cases always need recursive; we do not drop caller-supplied
1681         * recursive bits for other formats here.
1682         */
1683        if (options->output_format & (DIFF_FORMAT_PATCH |
1684                                      DIFF_FORMAT_DIFFSTAT |
1685                                      DIFF_FORMAT_CHECKDIFF))
1686                options->recursive = 1;
1687        /*
1688         * Also pickaxe would not work very well if you do not say recursive
1689         */
1690        if (options->pickaxe)
1691                options->recursive = 1;
1692
1693        if (options->detect_rename && options->rename_limit < 0)
1694                options->rename_limit = diff_rename_limit_default;
1695        if (options->setup & DIFF_SETUP_USE_CACHE) {
1696                if (!active_cache)
1697                        /* read-cache does not die even when it fails
1698                         * so it is safe for us to do this here.  Also
1699                         * it does not smudge active_cache or active_nr
1700                         * when it fails, so we do not have to worry about
1701                         * cleaning it up ourselves either.
1702                         */
1703                        read_cache();
1704        }
1705        if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
1706                use_size_cache = 1;
1707        if (options->abbrev <= 0 || 40 < options->abbrev)
1708                options->abbrev = 40; /* full */
1709
1710        return 0;
1711}
1712
1713static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
1714{
1715        char c, *eq;
1716        int len;
1717
1718        if (*arg != '-')
1719                return 0;
1720        c = *++arg;
1721        if (!c)
1722                return 0;
1723        if (c == arg_short) {
1724                c = *++arg;
1725                if (!c)
1726                        return 1;
1727                if (val && isdigit(c)) {
1728                        char *end;
1729                        int n = strtoul(arg, &end, 10);
1730                        if (*end)
1731                                return 0;
1732                        *val = n;
1733                        return 1;
1734                }
1735                return 0;
1736        }
1737        if (c != '-')
1738                return 0;
1739        arg++;
1740        eq = strchr(arg, '=');
1741        if (eq)
1742                len = eq - arg;
1743        else
1744                len = strlen(arg);
1745        if (!len || strncmp(arg, arg_long, len))
1746                return 0;
1747        if (eq) {
1748                int n;
1749                char *end;
1750                if (!isdigit(*++eq))
1751                        return 0;
1752                n = strtoul(eq, &end, 10);
1753                if (*end)
1754                        return 0;
1755                *val = n;
1756        }
1757        return 1;
1758}
1759
1760int diff_opt_parse(struct diff_options *options, const char **av, int ac)
1761{
1762        const char *arg = av[0];
1763        if (!strcmp(arg, "-p") || !strcmp(arg, "-u"))
1764                options->output_format |= DIFF_FORMAT_PATCH;
1765        else if (opt_arg(arg, 'U', "unified", &options->context))
1766                options->output_format |= DIFF_FORMAT_PATCH;
1767        else if (!strcmp(arg, "--raw"))
1768                options->output_format |= DIFF_FORMAT_RAW;
1769        else if (!strcmp(arg, "--patch-with-raw")) {
1770                options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW;
1771        }
1772        else if (!strcmp(arg, "--stat"))
1773                options->output_format |= DIFF_FORMAT_DIFFSTAT;
1774        else if (!strcmp(arg, "--check"))
1775                options->output_format |= DIFF_FORMAT_CHECKDIFF;
1776        else if (!strcmp(arg, "--summary"))
1777                options->output_format |= DIFF_FORMAT_SUMMARY;
1778        else if (!strcmp(arg, "--patch-with-stat")) {
1779                options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT;
1780        }
1781        else if (!strcmp(arg, "-z"))
1782                options->line_termination = 0;
1783        else if (!strncmp(arg, "-l", 2))
1784                options->rename_limit = strtoul(arg+2, NULL, 10);
1785        else if (!strcmp(arg, "--full-index"))
1786                options->full_index = 1;
1787        else if (!strcmp(arg, "--binary")) {
1788                options->output_format |= DIFF_FORMAT_PATCH;
1789                options->binary = 1;
1790        }
1791        else if (!strcmp(arg, "-a") || !strcmp(arg, "--text")) {
1792                options->text = 1;
1793        }
1794        else if (!strcmp(arg, "--name-only"))
1795                options->output_format |= DIFF_FORMAT_NAME;
1796        else if (!strcmp(arg, "--name-status"))
1797                options->output_format |= DIFF_FORMAT_NAME_STATUS;
1798        else if (!strcmp(arg, "-R"))
1799                options->reverse_diff = 1;
1800        else if (!strncmp(arg, "-S", 2))
1801                options->pickaxe = arg + 2;
1802        else if (!strcmp(arg, "-s")) {
1803                options->output_format |= DIFF_FORMAT_NO_OUTPUT;
1804        }
1805        else if (!strncmp(arg, "-O", 2))
1806                options->orderfile = arg + 2;
1807        else if (!strncmp(arg, "--diff-filter=", 14))
1808                options->filter = arg + 14;
1809        else if (!strcmp(arg, "--pickaxe-all"))
1810                options->pickaxe_opts = DIFF_PICKAXE_ALL;
1811        else if (!strcmp(arg, "--pickaxe-regex"))
1812                options->pickaxe_opts = DIFF_PICKAXE_REGEX;
1813        else if (!strncmp(arg, "-B", 2)) {
1814                if ((options->break_opt =
1815                     diff_scoreopt_parse(arg)) == -1)
1816                        return -1;
1817        }
1818        else if (!strncmp(arg, "-M", 2)) {
1819                if ((options->rename_score =
1820                     diff_scoreopt_parse(arg)) == -1)
1821                        return -1;
1822                options->detect_rename = DIFF_DETECT_RENAME;
1823        }
1824        else if (!strncmp(arg, "-C", 2)) {
1825                if ((options->rename_score =
1826                     diff_scoreopt_parse(arg)) == -1)
1827                        return -1;
1828                options->detect_rename = DIFF_DETECT_COPY;
1829        }
1830        else if (!strcmp(arg, "--find-copies-harder"))
1831                options->find_copies_harder = 1;
1832        else if (!strcmp(arg, "--abbrev"))
1833                options->abbrev = DEFAULT_ABBREV;
1834        else if (!strncmp(arg, "--abbrev=", 9)) {
1835                options->abbrev = strtoul(arg + 9, NULL, 10);
1836                if (options->abbrev < MINIMUM_ABBREV)
1837                        options->abbrev = MINIMUM_ABBREV;
1838                else if (40 < options->abbrev)
1839                        options->abbrev = 40;
1840        }
1841        else if (!strcmp(arg, "--color"))
1842                options->color_diff = 1;
1843        else if (!strcmp(arg, "--no-color"))
1844                options->color_diff = 0;
1845        else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
1846                options->xdl_opts |= XDF_IGNORE_WHITESPACE;
1847        else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
1848                options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
1849        else if (!strcmp(arg, "--color-words"))
1850                options->color_diff = options->color_diff_words = 1;
1851        else if (!strcmp(arg, "--no-renames"))
1852                options->detect_rename = 0;
1853        else
1854                return 0;
1855        return 1;
1856}
1857
1858static int parse_num(const char **cp_p)
1859{
1860        unsigned long num, scale;
1861        int ch, dot;
1862        const char *cp = *cp_p;
1863
1864        num = 0;
1865        scale = 1;
1866        dot = 0;
1867        for(;;) {
1868                ch = *cp;
1869                if ( !dot && ch == '.' ) {
1870                        scale = 1;
1871                        dot = 1;
1872                } else if ( ch == '%' ) {
1873                        scale = dot ? scale*100 : 100;
1874                        cp++;   /* % is always at the end */
1875                        break;
1876                } else if ( ch >= '0' && ch <= '9' ) {
1877                        if ( scale < 100000 ) {
1878                                scale *= 10;
1879                                num = (num*10) + (ch-'0');
1880                        }
1881                } else {
1882                        break;
1883                }
1884                cp++;
1885        }
1886        *cp_p = cp;
1887
1888        /* user says num divided by scale and we say internally that
1889         * is MAX_SCORE * num / scale.
1890         */
1891        return (num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale);
1892}
1893
1894int diff_scoreopt_parse(const char *opt)
1895{
1896        int opt1, opt2, cmd;
1897
1898        if (*opt++ != '-')
1899                return -1;
1900        cmd = *opt++;
1901        if (cmd != 'M' && cmd != 'C' && cmd != 'B')
1902                return -1; /* that is not a -M, -C nor -B option */
1903
1904        opt1 = parse_num(&opt);
1905        if (cmd != 'B')
1906                opt2 = 0;
1907        else {
1908                if (*opt == 0)
1909                        opt2 = 0;
1910                else if (*opt != '/')
1911                        return -1; /* we expect -B80/99 or -B80 */
1912                else {
1913                        opt++;
1914                        opt2 = parse_num(&opt);
1915                }
1916        }
1917        if (*opt != 0)
1918                return -1;
1919        return opt1 | (opt2 << 16);
1920}
1921
1922struct diff_queue_struct diff_queued_diff;
1923
1924void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp)
1925{
1926        if (queue->alloc <= queue->nr) {
1927                queue->alloc = alloc_nr(queue->alloc);
1928                queue->queue = xrealloc(queue->queue,
1929                                        sizeof(dp) * queue->alloc);
1930        }
1931        queue->queue[queue->nr++] = dp;
1932}
1933
1934struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
1935                                 struct diff_filespec *one,
1936                                 struct diff_filespec *two)
1937{
1938        struct diff_filepair *dp = xcalloc(1, sizeof(*dp));
1939        dp->one = one;
1940        dp->two = two;
1941        if (queue)
1942                diff_q(queue, dp);
1943        return dp;
1944}
1945
1946void diff_free_filepair(struct diff_filepair *p)
1947{
1948        diff_free_filespec_data(p->one);
1949        diff_free_filespec_data(p->two);
1950        free(p->one);
1951        free(p->two);
1952        free(p);
1953}
1954
1955/* This is different from find_unique_abbrev() in that
1956 * it stuffs the result with dots for alignment.
1957 */
1958const char *diff_unique_abbrev(const unsigned char *sha1, int len)
1959{
1960        int abblen;
1961        const char *abbrev;
1962        if (len == 40)
1963                return sha1_to_hex(sha1);
1964
1965        abbrev = find_unique_abbrev(sha1, len);
1966        if (!abbrev)
1967                return sha1_to_hex(sha1);
1968        abblen = strlen(abbrev);
1969        if (abblen < 37) {
1970                static char hex[41];
1971                if (len < abblen && abblen <= len + 2)
1972                        sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
1973                else
1974                        sprintf(hex, "%s...", abbrev);
1975                return hex;
1976        }
1977        return sha1_to_hex(sha1);
1978}
1979
1980static void diff_flush_raw(struct diff_filepair *p,
1981                           struct diff_options *options)
1982{
1983        int two_paths;
1984        char status[10];
1985        int abbrev = options->abbrev;
1986        const char *path_one, *path_two;
1987        int inter_name_termination = '\t';
1988        int line_termination = options->line_termination;
1989
1990        if (!line_termination)
1991                inter_name_termination = 0;
1992
1993        path_one = p->one->path;
1994        path_two = p->two->path;
1995        if (line_termination) {
1996                path_one = quote_one(path_one);
1997                path_two = quote_one(path_two);
1998        }
1999
2000        if (p->score)
2001                sprintf(status, "%c%03d", p->status,
2002                        (int)(0.5 + p->score * 100.0/MAX_SCORE));
2003        else {
2004                status[0] = p->status;
2005                status[1] = 0;
2006        }
2007        switch (p->status) {
2008        case DIFF_STATUS_COPIED:
2009        case DIFF_STATUS_RENAMED:
2010                two_paths = 1;
2011                break;
2012        case DIFF_STATUS_ADDED:
2013        case DIFF_STATUS_DELETED:
2014                two_paths = 0;
2015                break;
2016        default:
2017                two_paths = 0;
2018                break;
2019        }
2020        if (!(options->output_format & DIFF_FORMAT_NAME_STATUS)) {
2021                printf(":%06o %06o %s ",
2022                       p->one->mode, p->two->mode,
2023                       diff_unique_abbrev(p->one->sha1, abbrev));
2024                printf("%s ",
2025                       diff_unique_abbrev(p->two->sha1, abbrev));
2026        }
2027        printf("%s%c%s", status, inter_name_termination, path_one);
2028        if (two_paths)
2029                printf("%c%s", inter_name_termination, path_two);
2030        putchar(line_termination);
2031        if (path_one != p->one->path)
2032                free((void*)path_one);
2033        if (path_two != p->two->path)
2034                free((void*)path_two);
2035}
2036
2037static void diff_flush_name(struct diff_filepair *p, int line_termination)
2038{
2039        char *path = p->two->path;
2040
2041        if (line_termination)
2042                path = quote_one(p->two->path);
2043        printf("%s%c", path, line_termination);
2044        if (p->two->path != path)
2045                free(path);
2046}
2047
2048int diff_unmodified_pair(struct diff_filepair *p)
2049{
2050        /* This function is written stricter than necessary to support
2051         * the currently implemented transformers, but the idea is to
2052         * let transformers to produce diff_filepairs any way they want,
2053         * and filter and clean them up here before producing the output.
2054         */
2055        struct diff_filespec *one, *two;
2056
2057        if (DIFF_PAIR_UNMERGED(p))
2058                return 0; /* unmerged is interesting */
2059
2060        one = p->one;
2061        two = p->two;
2062
2063        /* deletion, addition, mode or type change
2064         * and rename are all interesting.
2065         */
2066        if (DIFF_FILE_VALID(one) != DIFF_FILE_VALID(two) ||
2067            DIFF_PAIR_MODE_CHANGED(p) ||
2068            strcmp(one->path, two->path))
2069                return 0;
2070
2071        /* both are valid and point at the same path.  that is, we are
2072         * dealing with a change.
2073         */
2074        if (one->sha1_valid && two->sha1_valid &&
2075            !hashcmp(one->sha1, two->sha1))
2076                return 1; /* no change */
2077        if (!one->sha1_valid && !two->sha1_valid)
2078                return 1; /* both look at the same file on the filesystem. */
2079        return 0;
2080}
2081
2082static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
2083{
2084        if (diff_unmodified_pair(p))
2085                return;
2086
2087        if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2088            (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2089                return; /* no tree diffs in patch format */
2090
2091        run_diff(p, o);
2092}
2093
2094static void diff_flush_stat(struct diff_filepair *p, struct diff_options *o,
2095                            struct diffstat_t *diffstat)
2096{
2097        if (diff_unmodified_pair(p))
2098                return;
2099
2100        if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2101            (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2102                return; /* no tree diffs in patch format */
2103
2104        run_diffstat(p, o, diffstat);
2105}
2106
2107static void diff_flush_checkdiff(struct diff_filepair *p,
2108                struct diff_options *o)
2109{
2110        if (diff_unmodified_pair(p))
2111                return;
2112
2113        if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2114            (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2115                return; /* no tree diffs in patch format */
2116
2117        run_checkdiff(p, o);
2118}
2119
2120int diff_queue_is_empty(void)
2121{
2122        struct diff_queue_struct *q = &diff_queued_diff;
2123        int i;
2124        for (i = 0; i < q->nr; i++)
2125                if (!diff_unmodified_pair(q->queue[i]))
2126                        return 0;
2127        return 1;
2128}
2129
2130#if DIFF_DEBUG
2131void diff_debug_filespec(struct diff_filespec *s, int x, const char *one)
2132{
2133        fprintf(stderr, "queue[%d] %s (%s) %s %06o %s\n",
2134                x, one ? one : "",
2135                s->path,
2136                DIFF_FILE_VALID(s) ? "valid" : "invalid",
2137                s->mode,
2138                s->sha1_valid ? sha1_to_hex(s->sha1) : "");
2139        fprintf(stderr, "queue[%d] %s size %lu flags %d\n",
2140                x, one ? one : "",
2141                s->size, s->xfrm_flags);
2142}
2143
2144void diff_debug_filepair(const struct diff_filepair *p, int i)
2145{
2146        diff_debug_filespec(p->one, i, "one");
2147        diff_debug_filespec(p->two, i, "two");
2148        fprintf(stderr, "score %d, status %c stays %d broken %d\n",
2149                p->score, p->status ? p->status : '?',
2150                p->source_stays, p->broken_pair);
2151}
2152
2153void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
2154{
2155        int i;
2156        if (msg)
2157                fprintf(stderr, "%s\n", msg);
2158        fprintf(stderr, "q->nr = %d\n", q->nr);
2159        for (i = 0; i < q->nr; i++) {
2160                struct diff_filepair *p = q->queue[i];
2161                diff_debug_filepair(p, i);
2162        }
2163}
2164#endif
2165
2166static void diff_resolve_rename_copy(void)
2167{
2168        int i, j;
2169        struct diff_filepair *p, *pp;
2170        struct diff_queue_struct *q = &diff_queued_diff;
2171
2172        diff_debug_queue("resolve-rename-copy", q);
2173
2174        for (i = 0; i < q->nr; i++) {
2175                p = q->queue[i];
2176                p->status = 0; /* undecided */
2177                if (DIFF_PAIR_UNMERGED(p))
2178                        p->status = DIFF_STATUS_UNMERGED;
2179                else if (!DIFF_FILE_VALID(p->one))
2180                        p->status = DIFF_STATUS_ADDED;
2181                else if (!DIFF_FILE_VALID(p->two))
2182                        p->status = DIFF_STATUS_DELETED;
2183                else if (DIFF_PAIR_TYPE_CHANGED(p))
2184                        p->status = DIFF_STATUS_TYPE_CHANGED;
2185
2186                /* from this point on, we are dealing with a pair
2187                 * whose both sides are valid and of the same type, i.e.
2188                 * either in-place edit or rename/copy edit.
2189                 */
2190                else if (DIFF_PAIR_RENAME(p)) {
2191                        if (p->source_stays) {
2192                                p->status = DIFF_STATUS_COPIED;
2193                                continue;
2194                        }
2195                        /* See if there is some other filepair that
2196                         * copies from the same source as us.  If so
2197                         * we are a copy.  Otherwise we are either a
2198                         * copy if the path stays, or a rename if it
2199                         * does not, but we already handled "stays" case.
2200                         */
2201                        for (j = i + 1; j < q->nr; j++) {
2202                                pp = q->queue[j];
2203                                if (strcmp(pp->one->path, p->one->path))
2204                                        continue; /* not us */
2205                                if (!DIFF_PAIR_RENAME(pp))
2206                                        continue; /* not a rename/copy */
2207                                /* pp is a rename/copy from the same source */
2208                                p->status = DIFF_STATUS_COPIED;
2209                                break;
2210                        }
2211                        if (!p->status)
2212                                p->status = DIFF_STATUS_RENAMED;
2213                }
2214                else if (hashcmp(p->one->sha1, p->two->sha1) ||
2215                         p->one->mode != p->two->mode)
2216                        p->status = DIFF_STATUS_MODIFIED;
2217                else {
2218                        /* This is a "no-change" entry and should not
2219                         * happen anymore, but prepare for broken callers.
2220                         */
2221                        error("feeding unmodified %s to diffcore",
2222                              p->one->path);
2223                        p->status = DIFF_STATUS_UNKNOWN;
2224                }
2225        }
2226        diff_debug_queue("resolve-rename-copy done", q);
2227}
2228
2229static int check_pair_status(struct diff_filepair *p)
2230{
2231        switch (p->status) {
2232        case DIFF_STATUS_UNKNOWN:
2233                return 0;
2234        case 0:
2235                die("internal error in diff-resolve-rename-copy");
2236        default:
2237                return 1;
2238        }
2239}
2240
2241static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
2242{
2243        int fmt = opt->output_format;
2244
2245        if (fmt & DIFF_FORMAT_CHECKDIFF)
2246                diff_flush_checkdiff(p, opt);
2247        else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
2248                diff_flush_raw(p, opt);
2249        else if (fmt & DIFF_FORMAT_NAME)
2250                diff_flush_name(p, opt->line_termination);
2251}
2252
2253static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs)
2254{
2255        if (fs->mode)
2256                printf(" %s mode %06o %s\n", newdelete, fs->mode, fs->path);
2257        else
2258                printf(" %s %s\n", newdelete, fs->path);
2259}
2260
2261
2262static void show_mode_change(struct diff_filepair *p, int show_name)
2263{
2264        if (p->one->mode && p->two->mode && p->one->mode != p->two->mode) {
2265                if (show_name)
2266                        printf(" mode change %06o => %06o %s\n",
2267                               p->one->mode, p->two->mode, p->two->path);
2268                else
2269                        printf(" mode change %06o => %06o\n",
2270                               p->one->mode, p->two->mode);
2271        }
2272}
2273
2274static void show_rename_copy(const char *renamecopy, struct diff_filepair *p)
2275{
2276        const char *old, *new;
2277
2278        /* Find common prefix */
2279        old = p->one->path;
2280        new = p->two->path;
2281        while (1) {
2282                const char *slash_old, *slash_new;
2283                slash_old = strchr(old, '/');
2284                slash_new = strchr(new, '/');
2285                if (!slash_old ||
2286                    !slash_new ||
2287                    slash_old - old != slash_new - new ||
2288                    memcmp(old, new, slash_new - new))
2289                        break;
2290                old = slash_old + 1;
2291                new = slash_new + 1;
2292        }
2293        /* p->one->path thru old is the common prefix, and old and new
2294         * through the end of names are renames
2295         */
2296        if (old != p->one->path)
2297                printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy,
2298                       (int)(old - p->one->path), p->one->path,
2299                       old, new, (int)(0.5 + p->score * 100.0/MAX_SCORE));
2300        else
2301                printf(" %s %s => %s (%d%%)\n", renamecopy,
2302                       p->one->path, p->two->path,
2303                       (int)(0.5 + p->score * 100.0/MAX_SCORE));
2304        show_mode_change(p, 0);
2305}
2306
2307static void diff_summary(struct diff_filepair *p)
2308{
2309        switch(p->status) {
2310        case DIFF_STATUS_DELETED:
2311                show_file_mode_name("delete", p->one);
2312                break;
2313        case DIFF_STATUS_ADDED:
2314                show_file_mode_name("create", p->two);
2315                break;
2316        case DIFF_STATUS_COPIED:
2317                show_rename_copy("copy", p);
2318                break;
2319        case DIFF_STATUS_RENAMED:
2320                show_rename_copy("rename", p);
2321                break;
2322        default:
2323                if (p->score) {
2324                        printf(" rewrite %s (%d%%)\n", p->two->path,
2325                                (int)(0.5 + p->score * 100.0/MAX_SCORE));
2326                        show_mode_change(p, 0);
2327                } else  show_mode_change(p, 1);
2328                break;
2329        }
2330}
2331
2332struct patch_id_t {
2333        struct xdiff_emit_state xm;
2334        SHA_CTX *ctx;
2335        int patchlen;
2336};
2337
2338static int remove_space(char *line, int len)
2339{
2340        int i;
2341        char *dst = line;
2342        unsigned char c;
2343
2344        for (i = 0; i < len; i++)
2345                if (!isspace((c = line[i])))
2346                        *dst++ = c;
2347
2348        return dst - line;
2349}
2350
2351static void patch_id_consume(void *priv, char *line, unsigned long len)
2352{
2353        struct patch_id_t *data = priv;
2354        int new_len;
2355
2356        /* Ignore line numbers when computing the SHA1 of the patch */
2357        if (!strncmp(line, "@@ -", 4))
2358                return;
2359
2360        new_len = remove_space(line, len);
2361
2362        SHA1_Update(data->ctx, line, new_len);
2363        data->patchlen += new_len;
2364}
2365
2366/* returns 0 upon success, and writes result into sha1 */
2367static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
2368{
2369        struct diff_queue_struct *q = &diff_queued_diff;
2370        int i;
2371        SHA_CTX ctx;
2372        struct patch_id_t data;
2373        char buffer[PATH_MAX * 4 + 20];
2374
2375        SHA1_Init(&ctx);
2376        memset(&data, 0, sizeof(struct patch_id_t));
2377        data.ctx = &ctx;
2378        data.xm.consume = patch_id_consume;
2379
2380        for (i = 0; i < q->nr; i++) {
2381                xpparam_t xpp;
2382                xdemitconf_t xecfg;
2383                xdemitcb_t ecb;
2384                mmfile_t mf1, mf2;
2385                struct diff_filepair *p = q->queue[i];
2386                int len1, len2;
2387
2388                if (p->status == 0)
2389                        return error("internal diff status error");
2390                if (p->status == DIFF_STATUS_UNKNOWN)
2391                        continue;
2392                if (diff_unmodified_pair(p))
2393                        continue;
2394                if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
2395                    (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
2396                        continue;
2397                if (DIFF_PAIR_UNMERGED(p))
2398                        continue;
2399
2400                diff_fill_sha1_info(p->one);
2401                diff_fill_sha1_info(p->two);
2402                if (fill_mmfile(&mf1, p->one) < 0 ||
2403                                fill_mmfile(&mf2, p->two) < 0)
2404                        return error("unable to read files to diff");
2405
2406                /* Maybe hash p->two? into the patch id? */
2407                if (mmfile_is_binary(&mf2))
2408                        continue;
2409
2410                len1 = remove_space(p->one->path, strlen(p->one->path));
2411                len2 = remove_space(p->two->path, strlen(p->two->path));
2412                if (p->one->mode == 0)
2413                        len1 = snprintf(buffer, sizeof(buffer),
2414                                        "diff--gita/%.*sb/%.*s"
2415                                        "newfilemode%06o"
2416                                        "---/dev/null"
2417                                        "+++b/%.*s",
2418                                        len1, p->one->path,
2419                                        len2, p->two->path,
2420                                        p->two->mode,
2421                                        len2, p->two->path);
2422                else if (p->two->mode == 0)
2423                        len1 = snprintf(buffer, sizeof(buffer),
2424                                        "diff--gita/%.*sb/%.*s"
2425                                        "deletedfilemode%06o"
2426                                        "---a/%.*s"
2427                                        "+++/dev/null",
2428                                        len1, p->one->path,
2429                                        len2, p->two->path,
2430                                        p->one->mode,
2431                                        len1, p->one->path);
2432                else
2433                        len1 = snprintf(buffer, sizeof(buffer),
2434                                        "diff--gita/%.*sb/%.*s"
2435                                        "---a/%.*s"
2436                                        "+++b/%.*s",
2437                                        len1, p->one->path,
2438                                        len2, p->two->path,
2439                                        len1, p->one->path,
2440                                        len2, p->two->path);
2441                SHA1_Update(&ctx, buffer, len1);
2442
2443                xpp.flags = XDF_NEED_MINIMAL;
2444                xecfg.ctxlen = 3;
2445                xecfg.flags = XDL_EMIT_FUNCNAMES;
2446                ecb.outf = xdiff_outf;
2447                ecb.priv = &data;
2448                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
2449        }
2450
2451        SHA1_Final(sha1, &ctx);
2452        return 0;
2453}
2454
2455int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)
2456{
2457        struct diff_queue_struct *q = &diff_queued_diff;
2458        int i;
2459        int result = diff_get_patch_id(options, sha1);
2460
2461        for (i = 0; i < q->nr; i++)
2462                diff_free_filepair(q->queue[i]);
2463
2464        free(q->queue);
2465        q->queue = NULL;
2466        q->nr = q->alloc = 0;
2467
2468        return result;
2469}
2470
2471static int is_summary_empty(const struct diff_queue_struct *q)
2472{
2473        int i;
2474
2475        for (i = 0; i < q->nr; i++) {
2476                const struct diff_filepair *p = q->queue[i];
2477
2478                switch (p->status) {
2479                case DIFF_STATUS_DELETED:
2480                case DIFF_STATUS_ADDED:
2481                case DIFF_STATUS_COPIED:
2482                case DIFF_STATUS_RENAMED:
2483                        return 0;
2484                default:
2485                        if (p->score)
2486                                return 0;
2487                        if (p->one->mode && p->two->mode &&
2488                            p->one->mode != p->two->mode)
2489                                return 0;
2490                        break;
2491                }
2492        }
2493        return 1;
2494}
2495
2496void diff_flush(struct diff_options *options)
2497{
2498        struct diff_queue_struct *q = &diff_queued_diff;
2499        int i, output_format = options->output_format;
2500        int separator = 0;
2501
2502        /*
2503         * Order: raw, stat, summary, patch
2504         * or:    name/name-status/checkdiff (other bits clear)
2505         */
2506        if (!q->nr)
2507                goto free_queue;
2508
2509        if (output_format & (DIFF_FORMAT_RAW |
2510                             DIFF_FORMAT_NAME |
2511                             DIFF_FORMAT_NAME_STATUS |
2512                             DIFF_FORMAT_CHECKDIFF)) {
2513                for (i = 0; i < q->nr; i++) {
2514                        struct diff_filepair *p = q->queue[i];
2515                        if (check_pair_status(p))
2516                                flush_one_pair(p, options);
2517                }
2518                separator++;
2519        }
2520
2521        if (output_format & DIFF_FORMAT_DIFFSTAT) {
2522                struct diffstat_t diffstat;
2523
2524                memset(&diffstat, 0, sizeof(struct diffstat_t));
2525                diffstat.xm.consume = diffstat_consume;
2526                for (i = 0; i < q->nr; i++) {
2527                        struct diff_filepair *p = q->queue[i];
2528                        if (check_pair_status(p))
2529                                diff_flush_stat(p, options, &diffstat);
2530                }
2531                show_stats(&diffstat);
2532                separator++;
2533        }
2534
2535        if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) {
2536                for (i = 0; i < q->nr; i++)
2537                        diff_summary(q->queue[i]);
2538                separator++;
2539        }
2540
2541        if (output_format & DIFF_FORMAT_PATCH) {
2542                if (separator) {
2543                        if (options->stat_sep) {
2544                                /* attach patch instead of inline */
2545                                fputs(options->stat_sep, stdout);
2546                        } else {
2547                                putchar(options->line_termination);
2548                        }
2549                }
2550
2551                for (i = 0; i < q->nr; i++) {
2552                        struct diff_filepair *p = q->queue[i];
2553                        if (check_pair_status(p))
2554                                diff_flush_patch(p, options);
2555                }
2556        }
2557
2558        if (output_format & DIFF_FORMAT_CALLBACK)
2559                options->format_callback(q, options, options->format_callback_data);
2560
2561        for (i = 0; i < q->nr; i++)
2562                diff_free_filepair(q->queue[i]);
2563free_queue:
2564        free(q->queue);
2565        q->queue = NULL;
2566        q->nr = q->alloc = 0;
2567}
2568
2569static void diffcore_apply_filter(const char *filter)
2570{
2571        int i;
2572        struct diff_queue_struct *q = &diff_queued_diff;
2573        struct diff_queue_struct outq;
2574        outq.queue = NULL;
2575        outq.nr = outq.alloc = 0;
2576
2577        if (!filter)
2578                return;
2579
2580        if (strchr(filter, DIFF_STATUS_FILTER_AON)) {
2581                int found;
2582                for (i = found = 0; !found && i < q->nr; i++) {
2583                        struct diff_filepair *p = q->queue[i];
2584                        if (((p->status == DIFF_STATUS_MODIFIED) &&
2585                             ((p->score &&
2586                               strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
2587                              (!p->score &&
2588                               strchr(filter, DIFF_STATUS_MODIFIED)))) ||
2589                            ((p->status != DIFF_STATUS_MODIFIED) &&
2590                             strchr(filter, p->status)))
2591                                found++;
2592                }
2593                if (found)
2594                        return;
2595
2596                /* otherwise we will clear the whole queue
2597                 * by copying the empty outq at the end of this
2598                 * function, but first clear the current entries
2599                 * in the queue.
2600                 */
2601                for (i = 0; i < q->nr; i++)
2602                        diff_free_filepair(q->queue[i]);
2603        }
2604        else {
2605                /* Only the matching ones */
2606                for (i = 0; i < q->nr; i++) {
2607                        struct diff_filepair *p = q->queue[i];
2608
2609                        if (((p->status == DIFF_STATUS_MODIFIED) &&
2610                             ((p->score &&
2611                               strchr(filter, DIFF_STATUS_FILTER_BROKEN)) ||
2612                              (!p->score &&
2613                               strchr(filter, DIFF_STATUS_MODIFIED)))) ||
2614                            ((p->status != DIFF_STATUS_MODIFIED) &&
2615                             strchr(filter, p->status)))
2616                                diff_q(&outq, p);
2617                        else
2618                                diff_free_filepair(p);
2619                }
2620        }
2621        free(q->queue);
2622        *q = outq;
2623}
2624
2625void diffcore_std(struct diff_options *options)
2626{
2627        if (options->break_opt != -1)
2628                diffcore_break(options->break_opt);
2629        if (options->detect_rename)
2630                diffcore_rename(options);
2631        if (options->break_opt != -1)
2632                diffcore_merge_broken();
2633        if (options->pickaxe)
2634                diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
2635        if (options->orderfile)
2636                diffcore_order(options->orderfile);
2637        diff_resolve_rename_copy();
2638        diffcore_apply_filter(options->filter);
2639}
2640
2641
2642void diffcore_std_no_resolve(struct diff_options *options)
2643{
2644        if (options->pickaxe)
2645                diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
2646        if (options->orderfile)
2647                diffcore_order(options->orderfile);
2648        diffcore_apply_filter(options->filter);
2649}
2650
2651void diff_addremove(struct diff_options *options,
2652                    int addremove, unsigned mode,
2653                    const unsigned char *sha1,
2654                    const char *base, const char *path)
2655{
2656        char concatpath[PATH_MAX];
2657        struct diff_filespec *one, *two;
2658
2659        /* This may look odd, but it is a preparation for
2660         * feeding "there are unchanged files which should
2661         * not produce diffs, but when you are doing copy
2662         * detection you would need them, so here they are"
2663         * entries to the diff-core.  They will be prefixed
2664         * with something like '=' or '*' (I haven't decided
2665         * which but should not make any difference).
2666         * Feeding the same new and old to diff_change() 
2667         * also has the same effect.
2668         * Before the final output happens, they are pruned after
2669         * merged into rename/copy pairs as appropriate.
2670         */
2671        if (options->reverse_diff)
2672                addremove = (addremove == '+' ? '-' :
2673                             addremove == '-' ? '+' : addremove);
2674
2675        if (!path) path = "";
2676        sprintf(concatpath, "%s%s", base, path);
2677        one = alloc_filespec(concatpath);
2678        two = alloc_filespec(concatpath);
2679
2680        if (addremove != '+')
2681                fill_filespec(one, sha1, mode);
2682        if (addremove != '-')
2683                fill_filespec(two, sha1, mode);
2684
2685        diff_queue(&diff_queued_diff, one, two);
2686}
2687
2688void diff_change(struct diff_options *options,
2689                 unsigned old_mode, unsigned new_mode,
2690                 const unsigned char *old_sha1,
2691                 const unsigned char *new_sha1,
2692                 const char *base, const char *path) 
2693{
2694        char concatpath[PATH_MAX];
2695        struct diff_filespec *one, *two;
2696
2697        if (options->reverse_diff) {
2698                unsigned tmp;
2699                const unsigned char *tmp_c;
2700                tmp = old_mode; old_mode = new_mode; new_mode = tmp;
2701                tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
2702        }
2703        if (!path) path = "";
2704        sprintf(concatpath, "%s%s", base, path);
2705        one = alloc_filespec(concatpath);
2706        two = alloc_filespec(concatpath);
2707        fill_filespec(one, old_sha1, old_mode);
2708        fill_filespec(two, new_sha1, new_mode);
2709
2710        diff_queue(&diff_queued_diff, one, two);
2711}
2712
2713void diff_unmerge(struct diff_options *options,
2714                  const char *path)
2715{
2716        struct diff_filespec *one, *two;
2717        one = alloc_filespec(path);
2718        two = alloc_filespec(path);
2719        diff_queue(&diff_queued_diff, one, two);
2720}