apply.con commit git-rev-list: add "--parents" command line flag (9765800)
   1/*
   2 * apply.c
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 *
   6 * This applies patches on top of some (arbitrary) version of the SCM.
   7 *
   8 * NOTE! It does all its work in the index file, and only cares about
   9 * the files in the working directory if you tell it to "merge" the
  10 * patch apply.
  11 *
  12 * Even when merging it always takes the source from the index, and
  13 * uses the working tree as a "branch" for a 3-way merge.
  14 */
  15#include <ctype.h>
  16
  17#include "cache.h"
  18
  19// We default to the merge behaviour, since that's what most people would
  20// expect.
  21//
  22//  --check turns on checking that the working tree matches the
  23//    files that are being modified, but doesn't apply the patch
  24//  --stat does just a diffstat, and doesn't actually apply
  25//  --show-files shows the directory changes
  26//
  27static int merge_patch = 1;
  28static int diffstat = 0;
  29static int check = 0;
  30static int apply = 1;
  31static int show_files = 0;
  32static const char apply_usage[] = "git-apply [--stat] [--check] [--show-files] <patch>";
  33
  34/*
  35 * For "diff-stat" like behaviour, we keep track of the biggest change
  36 * we've seen, and the longest filename. That allows us to do simple
  37 * scaling.
  38 */
  39static int max_change, max_len;
  40
  41/*
  42 * Various "current state", notably line numbers and what
  43 * file (and how) we're patching right now.. The "is_xxxx"
  44 * things are flags, where -1 means "don't know yet".
  45 */
  46static int linenr = 1;
  47
  48struct fragment {
  49        unsigned long oldpos, oldlines;
  50        unsigned long newpos, newlines;
  51        const char *patch;
  52        int size;
  53        struct fragment *next;
  54};
  55
  56struct patch {
  57        char *new_name, *old_name, *def_name;
  58        unsigned int old_mode, new_mode;
  59        int is_rename, is_copy, is_new, is_delete;
  60        int lines_added, lines_deleted;
  61        struct fragment *fragments;
  62        struct patch *next;
  63};
  64
  65#define CHUNKSIZE (8192)
  66#define SLOP (16)
  67
  68static void *read_patch_file(int fd, unsigned long *sizep)
  69{
  70        unsigned long size = 0, alloc = CHUNKSIZE;
  71        void *buffer = xmalloc(alloc);
  72
  73        for (;;) {
  74                int nr = alloc - size;
  75                if (nr < 1024) {
  76                        alloc += CHUNKSIZE;
  77                        buffer = xrealloc(buffer, alloc);
  78                        nr = alloc - size;
  79                }
  80                nr = read(fd, buffer + size, nr);
  81                if (!nr)
  82                        break;
  83                if (nr < 0) {
  84                        if (errno == EAGAIN)
  85                                continue;
  86                        die("git-apply: read returned %s", strerror(errno));
  87                }
  88                size += nr;
  89        }
  90        *sizep = size;
  91
  92        /*
  93         * Make sure that we have some slop in the buffer
  94         * so that we can do speculative "memcmp" etc, and
  95         * see to it that it is NUL-filled.
  96         */
  97        if (alloc < size + SLOP)
  98                buffer = xrealloc(buffer, size + SLOP);
  99        memset(buffer + size, 0, SLOP);
 100        return buffer;
 101}
 102
 103static unsigned long linelen(char *buffer, unsigned long size)
 104{
 105        unsigned long len = 0;
 106        while (size--) {
 107                len++;
 108                if (*buffer++ == '\n')
 109                        break;
 110        }
 111        return len;
 112}
 113
 114static int is_dev_null(const char *str)
 115{
 116        return !memcmp("/dev/null", str, 9) && isspace(str[9]);
 117}
 118
 119#define TERM_EXIST      1
 120#define TERM_SPACE      2
 121#define TERM_TAB        4
 122
 123static int name_terminate(const char *name, int namelen, int c, int terminate)
 124{
 125        if (c == ' ' && !(terminate & TERM_SPACE))
 126                return 0;
 127        if (c == '\t' && !(terminate & TERM_TAB))
 128                return 0;
 129
 130        /*
 131         * Do we want an existing name? Return false and
 132         * continue if it's not there.
 133         */
 134        if (terminate & TERM_EXIST)
 135                return cache_name_pos(name, namelen) >= 0;
 136
 137        return 1;
 138}
 139
 140static char * find_name(const char *line, char *def, int p_value, int terminate)
 141{
 142        int len;
 143        const char *start = line;
 144        char *name;
 145
 146        for (;;) {
 147                char c = *line;
 148
 149                if (isspace(c)) {
 150                        if (c == '\n')
 151                                break;
 152                        if (name_terminate(start, line-start, c, terminate))
 153                                break;
 154                }
 155                line++;
 156                if (c == '/' && !--p_value)
 157                        start = line;
 158        }
 159        if (!start)
 160                return def;
 161        len = line - start;
 162        if (!len)
 163                return def;
 164
 165        /*
 166         * Generally we prefer the shorter name, especially
 167         * if the other one is just a variation of that with
 168         * something else tacked on to the end (ie "file.orig"
 169         * or "file~").
 170         */
 171        if (def) {
 172                int deflen = strlen(def);
 173                if (deflen < len && !strncmp(start, def, deflen))
 174                        return def;
 175        }
 176
 177        name = xmalloc(len + 1);
 178        memcpy(name, start, len);
 179        name[len] = 0;
 180        free(def);
 181        return name;
 182}
 183
 184/*
 185 * Get the name etc info from the --/+++ lines of a traditional patch header
 186 *
 187 * NOTE! This hardcodes "-p1" behaviour in filename detection.
 188 *
 189 * FIXME! The end-of-filename heuristics are kind of screwy. For existing
 190 * files, we can happily check the index for a match, but for creating a
 191 * new file we should try to match whatever "patch" does. I have no idea.
 192 */
 193static void parse_traditional_patch(const char *first, const char *second, struct patch *patch)
 194{
 195        int p_value = 1;
 196        char *name;
 197
 198        first += 4;     // skip "--- "
 199        second += 4;    // skip "+++ "
 200        if (is_dev_null(first)) {
 201                patch->is_new = 1;
 202                patch->is_delete = 0;
 203                name = find_name(second, NULL, p_value, TERM_SPACE | TERM_TAB);
 204                patch->new_name = name;
 205        } else if (is_dev_null(second)) {
 206                patch->is_new = 0;
 207                patch->is_delete = 1;
 208                name = find_name(first, NULL, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
 209                patch->old_name = name;
 210        } else {
 211                name = find_name(first, NULL, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
 212                name = find_name(second, name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
 213                patch->old_name = patch->new_name = name;
 214        }
 215        if (!name)
 216                die("unable to find filename in patch at line %d", linenr);
 217}
 218
 219static int gitdiff_hdrend(const char *line, struct patch *patch)
 220{
 221        return -1;
 222}
 223
 224/*
 225 * We're anal about diff header consistency, to make
 226 * sure that we don't end up having strange ambiguous
 227 * patches floating around.
 228 *
 229 * As a result, gitdiff_{old|new}name() will check
 230 * their names against any previous information, just
 231 * to make sure..
 232 */
 233static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
 234{
 235        int len;
 236        const char *name;
 237
 238        if (!orig_name && !isnull)
 239                return find_name(line, NULL, 1, 0);
 240
 241        name = "/dev/null";
 242        len = 9;
 243        if (orig_name) {
 244                name = orig_name;
 245                len = strlen(name);
 246                if (isnull)
 247                        die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
 248        }
 249
 250        if (*name == '/')
 251                goto absolute_path;
 252
 253        for (;;) {
 254                char c = *line++;
 255                if (c == '\n')
 256                        break;
 257                if (c != '/')
 258                        continue;
 259absolute_path:
 260                if (memcmp(line, name, len) || line[len] != '\n')
 261                        break;
 262                return orig_name;
 263        }
 264        die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
 265        return NULL;
 266}
 267
 268static int gitdiff_oldname(const char *line, struct patch *patch)
 269{
 270        patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, "old");
 271        return 0;
 272}
 273
 274static int gitdiff_newname(const char *line, struct patch *patch)
 275{
 276        patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, "new");
 277        return 0;
 278}
 279
 280static int gitdiff_oldmode(const char *line, struct patch *patch)
 281{
 282        patch->old_mode = strtoul(line, NULL, 8);
 283        return 0;
 284}
 285
 286static int gitdiff_newmode(const char *line, struct patch *patch)
 287{
 288        patch->new_mode = strtoul(line, NULL, 8);
 289        return 0;
 290}
 291
 292static int gitdiff_delete(const char *line, struct patch *patch)
 293{
 294        patch->is_delete = 1;
 295        patch->old_name = patch->def_name;
 296        return gitdiff_oldmode(line, patch);
 297}
 298
 299static int gitdiff_newfile(const char *line, struct patch *patch)
 300{
 301        patch->is_new = 1;
 302        patch->new_name = patch->def_name;
 303        return gitdiff_newmode(line, patch);
 304}
 305
 306static int gitdiff_copysrc(const char *line, struct patch *patch)
 307{
 308        patch->is_copy = 1;
 309        patch->old_name = find_name(line, NULL, 0, 0);
 310        return 0;
 311}
 312
 313static int gitdiff_copydst(const char *line, struct patch *patch)
 314{
 315        patch->is_copy = 1;
 316        patch->new_name = find_name(line, NULL, 0, 0);
 317        return 0;
 318}
 319
 320static int gitdiff_renamesrc(const char *line, struct patch *patch)
 321{
 322        patch->is_rename = 1;
 323        patch->old_name = find_name(line, NULL, 0, 0);
 324        return 0;
 325}
 326
 327static int gitdiff_renamedst(const char *line, struct patch *patch)
 328{
 329        patch->is_rename = 1;
 330        patch->new_name = find_name(line, NULL, 0, 0);
 331        return 0;
 332}
 333
 334static int gitdiff_similarity(const char *line, struct patch *patch)
 335{
 336        return 0;
 337}
 338
 339static int gitdiff_dissimilarity(const char *line, struct patch *patch)
 340{
 341        return 0;
 342}
 343
 344/*
 345 * This is normal for a diff that doesn't change anything: we'll fall through
 346 * into the next diff. Tell the parser to break out.
 347 */
 348static int gitdiff_unrecognized(const char *line, struct patch *patch)
 349{
 350        return -1;
 351}
 352
 353static char *git_header_name(char *line)
 354{
 355        int len;
 356        char *name, *second;
 357
 358        /*
 359         * Find the first '/'
 360         */
 361        name = line;
 362        for (;;) {
 363                char c = *name++;
 364                if (c == '\n')
 365                        return NULL;
 366                if (c == '/')
 367                        break;
 368        }
 369
 370        /*
 371         * We don't accept absolute paths (/dev/null) as possibly valid
 372         */
 373        if (name == line+1)
 374                return NULL;
 375
 376        /*
 377         * Accept a name only if it shows up twice, exactly the same
 378         * form.
 379         */
 380        for (len = 0 ; ; len++) {
 381                char c = name[len];
 382
 383                switch (c) {
 384                default:
 385                        continue;
 386                case '\n':
 387                        break;
 388                case '\t': case ' ':
 389                        second = name+len;
 390                        for (;;) {
 391                                char c = *second++;
 392                                if (c == '\n')
 393                                        return NULL;
 394                                if (c == '/')
 395                                        break;
 396                        }
 397                        if (second[len] == '\n' && !memcmp(name, second, len)) {
 398                                char *ret = xmalloc(len + 1);
 399                                memcpy(ret, name, len);
 400                                ret[len] = 0;
 401                                return ret;
 402                        }
 403                }
 404        }
 405        return NULL;
 406}
 407
 408/* Verify that we recognize the lines following a git header */
 409static int parse_git_header(char *line, int len, unsigned int size, struct patch *patch)
 410{
 411        unsigned long offset;
 412
 413        /* A git diff has explicit new/delete information, so we don't guess */
 414        patch->is_new = 0;
 415        patch->is_delete = 0;
 416
 417        /*
 418         * Some things may not have the old name in the
 419         * rest of the headers anywhere (pure mode changes,
 420         * or removing or adding empty files), so we get
 421         * the default name from the header.
 422         */
 423        patch->def_name = git_header_name(line + strlen("diff --git "));
 424
 425        line += len;
 426        size -= len;
 427        linenr++;
 428        for (offset = len ; size > 0 ; offset += len, size -= len, line += len, linenr++) {
 429                static const struct opentry {
 430                        const char *str;
 431                        int (*fn)(const char *, struct patch *);
 432                } optable[] = {
 433                        { "@@ -", gitdiff_hdrend },
 434                        { "--- ", gitdiff_oldname },
 435                        { "+++ ", gitdiff_newname },
 436                        { "old mode ", gitdiff_oldmode },
 437                        { "new mode ", gitdiff_newmode },
 438                        { "deleted file mode ", gitdiff_delete },
 439                        { "new file mode ", gitdiff_newfile },
 440                        { "copy from ", gitdiff_copysrc },
 441                        { "copy to ", gitdiff_copydst },
 442                        { "rename from ", gitdiff_renamesrc },
 443                        { "rename to ", gitdiff_renamedst },
 444                        { "similarity index ", gitdiff_similarity },
 445                        { "dissimilarity index ", gitdiff_dissimilarity },
 446                        { "", gitdiff_unrecognized },
 447                };
 448                int i;
 449
 450                len = linelen(line, size);
 451                if (!len || line[len-1] != '\n')
 452                        break;
 453                for (i = 0; i < sizeof(optable) / sizeof(optable[0]); i++) {
 454                        const struct opentry *p = optable + i;
 455                        int oplen = strlen(p->str);
 456                        if (len < oplen || memcmp(p->str, line, oplen))
 457                                continue;
 458                        if (p->fn(line + oplen, patch) < 0)
 459                                return offset;
 460                        break;
 461                }
 462        }
 463
 464        return offset;
 465}
 466
 467static int parse_num(const char *line, unsigned long *p)
 468{
 469        char *ptr;
 470
 471        if (!isdigit(*line))
 472                return 0;
 473        *p = strtoul(line, &ptr, 10);
 474        return ptr - line;
 475}
 476
 477static int parse_range(const char *line, int len, int offset, const char *expect,
 478                        unsigned long *p1, unsigned long *p2)
 479{
 480        int digits, ex;
 481
 482        if (offset < 0 || offset >= len)
 483                return -1;
 484        line += offset;
 485        len -= offset;
 486
 487        digits = parse_num(line, p1);
 488        if (!digits)
 489                return -1;
 490
 491        offset += digits;
 492        line += digits;
 493        len -= digits;
 494
 495        *p2 = *p1;
 496        if (*line == ',') {
 497                digits = parse_num(line+1, p2);
 498                if (!digits)
 499                        return -1;
 500
 501                offset += digits+1;
 502                line += digits+1;
 503                len -= digits+1;
 504        }
 505
 506        ex = strlen(expect);
 507        if (ex > len)
 508                return -1;
 509        if (memcmp(line, expect, ex))
 510                return -1;
 511
 512        return offset + ex;
 513}
 514
 515/*
 516 * Parse a unified diff fragment header of the
 517 * form "@@ -a,b +c,d @@"
 518 */
 519static int parse_fragment_header(char *line, int len, struct fragment *fragment)
 520{
 521        int offset;
 522
 523        if (!len || line[len-1] != '\n')
 524                return -1;
 525
 526        /* Figure out the number of lines in a fragment */
 527        offset = parse_range(line, len, 4, " +", &fragment->oldpos, &fragment->oldlines);
 528        offset = parse_range(line, len, offset, " @@", &fragment->newpos, &fragment->newlines);
 529
 530        return offset;
 531}
 532
 533static int find_header(char *line, unsigned long size, int *hdrsize, struct patch *patch)
 534{
 535        unsigned long offset, len;
 536
 537        patch->is_rename = patch->is_copy = 0;
 538        patch->is_new = patch->is_delete = -1;
 539        patch->old_mode = patch->new_mode = 0;
 540        patch->old_name = patch->new_name = NULL;
 541        for (offset = 0; size > 0; offset += len, size -= len, line += len, linenr++) {
 542                unsigned long nextlen;
 543
 544                len = linelen(line, size);
 545                if (!len)
 546                        break;
 547
 548                /* Testing this early allows us to take a few shortcuts.. */
 549                if (len < 6)
 550                        continue;
 551
 552                /*
 553                 * Make sure we don't find any unconnected patch fragmants.
 554                 * That's a sign that we didn't find a header, and that a
 555                 * patch has become corrupted/broken up.
 556                 */
 557                if (!memcmp("@@ -", line, 4)) {
 558                        struct fragment dummy;
 559                        if (parse_fragment_header(line, len, &dummy) < 0)
 560                                continue;
 561                        error("patch fragment without header at line %d: %.*s", linenr, len-1, line);
 562                }
 563
 564                if (size < len + 6)
 565                        break;
 566
 567                /*
 568                 * Git patch? It might not have a real patch, just a rename
 569                 * or mode change, so we handle that specially
 570                 */
 571                if (!memcmp("diff --git ", line, 11)) {
 572                        int git_hdr_len = parse_git_header(line, len, size, patch);
 573                        if (git_hdr_len < 0)
 574                                continue;
 575                        if (!patch->old_name && !patch->new_name)
 576                                die("git diff header lacks filename information");
 577                        *hdrsize = git_hdr_len;
 578                        return offset;
 579                }
 580
 581                /** --- followed by +++ ? */
 582                if (memcmp("--- ", line,  4) || memcmp("+++ ", line + len, 4))
 583                        continue;
 584
 585                /*
 586                 * We only accept unified patches, so we want it to
 587                 * at least have "@@ -a,b +c,d @@\n", which is 14 chars
 588                 * minimum
 589                 */
 590                nextlen = linelen(line + len, size - len);
 591                if (size < nextlen + 14 || memcmp("@@ -", line + len + nextlen, 4))
 592                        continue;
 593
 594                /* Ok, we'll consider it a patch */
 595                parse_traditional_patch(line, line+len, patch);
 596                *hdrsize = len + nextlen;
 597                linenr += 2;
 598                return offset;
 599        }
 600        return -1;
 601}
 602
 603/*
 604 * Parse a unified diff. Note that this really needs
 605 * to parse each fragment separately, since the only
 606 * way to know the difference between a "---" that is
 607 * part of a patch, and a "---" that starts the next
 608 * patch is to look at the line counts..
 609 */
 610static int parse_fragment(char *line, unsigned long size, struct patch *patch, struct fragment *fragment)
 611{
 612        int added, deleted;
 613        int len = linelen(line, size), offset;
 614        unsigned long pos[4], oldlines, newlines;
 615
 616        offset = parse_fragment_header(line, len, fragment);
 617        if (offset < 0)
 618                return -1;
 619        oldlines = fragment->oldlines;
 620        newlines = fragment->newlines;
 621
 622        if (patch->is_new < 0 && (pos[0] || oldlines))
 623                patch->is_new = 0;
 624        if (patch->is_delete < 0 && (pos[1] || newlines))
 625                patch->is_delete = 0;
 626
 627        /* Parse the thing.. */
 628        line += len;
 629        size -= len;
 630        linenr++;
 631        added = deleted = 0;
 632        for (offset = len; size > 0; offset += len, size -= len, line += len, linenr++) {
 633                if (!oldlines && !newlines)
 634                        break;
 635                len = linelen(line, size);
 636                if (!len || line[len-1] != '\n')
 637                        return -1;
 638                switch (*line) {
 639                default:
 640                        return -1;
 641                case ' ':
 642                        oldlines--;
 643                        newlines--;
 644                        break;
 645                case '-':
 646                        deleted++;
 647                        oldlines--;
 648                        break;
 649                case '+':
 650                        added++;
 651                        newlines--;
 652                        break;
 653                /* We allow "\ No newline at end of file" */
 654                case '\\':
 655                        break;
 656                }
 657        }
 658        patch->lines_added += added;
 659        patch->lines_deleted += deleted;
 660        return offset;
 661}
 662
 663static int parse_single_patch(char *line, unsigned long size, struct patch *patch)
 664{
 665        unsigned long offset = 0;
 666        struct fragment **fragp = &patch->fragments;
 667
 668        while (size > 4 && !memcmp(line, "@@ -", 4)) {
 669                struct fragment *fragment;
 670                int len;
 671
 672                fragment = xmalloc(sizeof(*fragment));
 673                memset(fragment, 0, sizeof(*fragment));
 674                len = parse_fragment(line, size, patch, fragment);
 675                if (len <= 0)
 676                        die("corrupt patch at line %d", linenr);
 677
 678                fragment->patch = line;
 679                fragment->size = len;
 680
 681                *fragp = fragment;
 682                fragp = &fragment->next;
 683
 684                offset += len;
 685                line += len;
 686                size -= len;
 687        }
 688        return offset;
 689}
 690
 691static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
 692{
 693        int hdrsize, patchsize;
 694        int offset = find_header(buffer, size, &hdrsize, patch);
 695
 696        if (offset < 0)
 697                return offset;
 698
 699        patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
 700
 701        return offset + hdrsize + patchsize;
 702}
 703
 704const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
 705const char minuses[]= "----------------------------------------------------------------------";
 706
 707static void show_stats(struct patch *patch)
 708{
 709        char *name = patch->old_name;
 710        int len, max, add, del;
 711
 712        if (!name)
 713                name = patch->new_name;
 714
 715        /*
 716         * "scale" the filename
 717         */
 718        len = strlen(name);
 719        max = max_len;
 720        if (max > 50)
 721                max = 50;
 722        if (len > max)
 723                name += len - max;
 724        len = max;
 725
 726        /*
 727         * scale the add/delete
 728         */
 729        max = max_change;
 730        if (max + len > 70)
 731                max = 70 - len;
 732        
 733        add = (patch->lines_added * max + max_change/2) / max_change;
 734        del = (patch->lines_deleted * max + max_change/2) / max_change;
 735        printf(" %-*s |%5d %.*s%.*s\n",
 736                len, name, patch->lines_added + patch->lines_deleted,
 737                add, pluses, del, minuses);
 738}
 739
 740static int check_patch(struct patch *patch)
 741{
 742        struct stat st;
 743        const char *old_name = patch->old_name;
 744        const char *new_name = patch->new_name;
 745
 746        if (old_name) {
 747                int pos = cache_name_pos(old_name, strlen(old_name));
 748                int changed;
 749
 750                if (pos < 0)
 751                        return error("%s: does not exist in index", old_name);
 752                if (patch->is_new < 0)
 753                        patch->is_new = 0;
 754                if (lstat(old_name, &st) < 0)
 755                        return error("%s: %s\n", strerror(errno));
 756                changed = ce_match_stat(active_cache[pos], &st);
 757                if (changed)
 758                        return error("%s: does not match index", old_name);
 759                if (!patch->old_mode)
 760                        patch->old_mode = st.st_mode;
 761        }
 762
 763        if (new_name && (patch->is_new | patch->is_rename | patch->is_copy)) {
 764                if (cache_name_pos(new_name, strlen(new_name)) >= 0)
 765                        return error("%s: already exists in index", new_name);
 766                if (!lstat(new_name, &st))
 767                        return error("%s: already exists in working directory", new_name);
 768                if (errno != ENOENT)
 769                        return error("%s: %s", new_name, strerror(errno));
 770        }
 771        return 0;
 772}
 773
 774static int check_patch_list(struct patch *patch)
 775{
 776        int error = 0;
 777
 778        for (;patch ; patch = patch->next)
 779                error |= check_patch(patch);
 780        return error;
 781}
 782
 783static void show_file(int c, unsigned int mode, const char *name)
 784{
 785        printf("%c %o %s\n", c, mode, name);
 786}
 787
 788static void show_file_list(struct patch *patch)
 789{
 790        for (;patch ; patch = patch->next) {
 791                if (patch->is_rename) {
 792                        show_file('-', patch->old_mode, patch->old_name);
 793                        show_file('+', patch->new_mode, patch->new_name);
 794                        continue;
 795                }
 796                if (patch->is_copy || patch->is_new) {
 797                        show_file('+', patch->new_mode, patch->new_name);
 798                        continue;
 799                }
 800                if (patch->is_delete) {
 801                        show_file('-', patch->old_mode, patch->old_name);
 802                        continue;
 803                }
 804                if (patch->old_mode && patch->new_mode && patch->old_mode != patch->new_mode) {
 805                        printf("M %o:%o %s\n", patch->old_mode, patch->new_mode, patch->old_name);
 806                        continue;
 807                }
 808                printf("M %o %s\n", patch->old_mode, patch->old_name);
 809        }
 810}
 811
 812static void stat_patch_list(struct patch *patch)
 813{
 814        int files, adds, dels;
 815
 816        for (files = adds = dels = 0 ; patch ; patch = patch->next) {
 817                files++;
 818                adds += patch->lines_added;
 819                dels += patch->lines_deleted;
 820                show_stats(patch);
 821        }
 822
 823        printf(" %d files changed, %d insertions(+), %d deletions(-)\n", files, adds, dels);
 824}
 825
 826static void patch_stats(struct patch *patch)
 827{
 828        int lines = patch->lines_added + patch->lines_deleted;
 829
 830        if (lines > max_change)
 831                max_change = lines;
 832        if (patch->old_name) {
 833                int len = strlen(patch->old_name);
 834                if (len > max_len)
 835                        max_len = len;
 836        }
 837        if (patch->new_name) {
 838                int len = strlen(patch->new_name);
 839                if (len > max_len)
 840                        max_len = len;
 841        }
 842}
 843
 844static int apply_patch(int fd)
 845{
 846        unsigned long offset, size;
 847        char *buffer = read_patch_file(fd, &size);
 848        struct patch *list = NULL, **listp = &list;
 849
 850        if (!buffer)
 851                return -1;
 852        offset = 0;
 853        while (size > 0) {
 854                struct patch *patch;
 855                int nr;
 856
 857                patch = xmalloc(sizeof(*patch));
 858                memset(patch, 0, sizeof(*patch));
 859                nr = parse_chunk(buffer + offset, size, patch);
 860                if (nr < 0)
 861                        break;
 862                patch_stats(patch);
 863                *listp = patch;
 864                listp = &patch->next;
 865                offset += nr;
 866                size -= nr;
 867        }
 868
 869        if ((check || apply) && check_patch_list(list) < 0)
 870                exit(1);
 871
 872        if (show_files)
 873                show_file_list(list);
 874
 875        if (diffstat)
 876                stat_patch_list(list);
 877
 878        free(buffer);
 879        return 0;
 880}
 881
 882int main(int argc, char **argv)
 883{
 884        int i;
 885        int read_stdin = 1;
 886
 887        if (read_cache() < 0)
 888                die("unable to read index file");
 889
 890        for (i = 1; i < argc; i++) {
 891                const char *arg = argv[i];
 892                int fd;
 893
 894                if (!strcmp(arg, "-")) {
 895                        apply_patch(0);
 896                        read_stdin = 0;
 897                        continue;
 898                }
 899                if (!strcmp(arg, "--no-merge")) {
 900                        merge_patch = 0;
 901                        continue;
 902                }
 903                if (!strcmp(arg, "--stat")) {
 904                        apply = 0;
 905                        diffstat = 1;
 906                        continue;
 907                }
 908                if (!strcmp(arg, "--check")) {
 909                        apply = 0;
 910                        check = 1;
 911                        continue;
 912                }
 913                if (!strcmp(arg, "--show-files")) {
 914                        show_files = 1;
 915                        continue;
 916                }
 917                fd = open(arg, O_RDONLY);
 918                if (fd < 0)
 919                        usage(apply_usage);
 920                read_stdin = 0;
 921                apply_patch(fd);
 922                close(fd);
 923        }
 924        if (read_stdin)
 925                apply_patch(0);
 926        return 0;
 927}