apply.con commit git-init-db: set up the full default environment (cad88fd)
   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
 339/*
 340 * This is normal for a diff that doesn't change anything: we'll fall through
 341 * into the next diff. Tell the parser to break out.
 342 */
 343static int gitdiff_unrecognized(const char *line, struct patch *patch)
 344{
 345        return -1;
 346}
 347
 348static char *git_header_name(char *line)
 349{
 350        int len;
 351        char *name, *second;
 352
 353        /*
 354         * Find the first '/'
 355         */
 356        name = line;
 357        for (;;) {
 358                char c = *name++;
 359                if (c == '\n')
 360                        return NULL;
 361                if (c == '/')
 362                        break;
 363        }
 364
 365        /*
 366         * We don't accept absolute paths (/dev/null) as possibly valid
 367         */
 368        if (name == line+1)
 369                return NULL;
 370
 371        /*
 372         * Accept a name only if it shows up twice, exactly the same
 373         * form.
 374         */
 375        for (len = 0 ; ; len++) {
 376                char c = name[len];
 377
 378                switch (c) {
 379                default:
 380                        continue;
 381                case '\n':
 382                        break;
 383                case '\t': case ' ':
 384                        second = name+len;
 385                        for (;;) {
 386                                char c = *second++;
 387                                if (c == '\n')
 388                                        return NULL;
 389                                if (c == '/')
 390                                        break;
 391                        }
 392                        if (second[len] == '\n' && !memcmp(name, second, len)) {
 393                                char *ret = xmalloc(len + 1);
 394                                memcpy(ret, name, len);
 395                                ret[len] = 0;
 396                                return ret;
 397                        }
 398                }
 399        }
 400        return NULL;
 401}
 402
 403/* Verify that we recognize the lines following a git header */
 404static int parse_git_header(char *line, int len, unsigned int size, struct patch *patch)
 405{
 406        unsigned long offset;
 407
 408        /* A git diff has explicit new/delete information, so we don't guess */
 409        patch->is_new = 0;
 410        patch->is_delete = 0;
 411
 412        /*
 413         * Some things may not have the old name in the
 414         * rest of the headers anywhere (pure mode changes,
 415         * or removing or adding empty files), so we get
 416         * the default name from the header.
 417         */
 418        patch->def_name = git_header_name(line + strlen("diff --git "));
 419
 420        line += len;
 421        size -= len;
 422        linenr++;
 423        for (offset = len ; size > 0 ; offset += len, size -= len, line += len, linenr++) {
 424                static const struct opentry {
 425                        const char *str;
 426                        int (*fn)(const char *, struct patch *);
 427                } optable[] = {
 428                        { "@@ -", gitdiff_hdrend },
 429                        { "--- ", gitdiff_oldname },
 430                        { "+++ ", gitdiff_newname },
 431                        { "old mode ", gitdiff_oldmode },
 432                        { "new mode ", gitdiff_newmode },
 433                        { "deleted file mode ", gitdiff_delete },
 434                        { "new file mode ", gitdiff_newfile },
 435                        { "copy from ", gitdiff_copysrc },
 436                        { "copy to ", gitdiff_copydst },
 437                        { "rename from ", gitdiff_renamesrc },
 438                        { "rename to ", gitdiff_renamedst },
 439                        { "similarity index ", gitdiff_similarity },
 440                        { "", gitdiff_unrecognized },
 441                };
 442                int i;
 443
 444                len = linelen(line, size);
 445                if (!len || line[len-1] != '\n')
 446                        break;
 447                for (i = 0; i < sizeof(optable) / sizeof(optable[0]); i++) {
 448                        const struct opentry *p = optable + i;
 449                        int oplen = strlen(p->str);
 450                        if (len < oplen || memcmp(p->str, line, oplen))
 451                                continue;
 452                        if (p->fn(line + oplen, patch) < 0)
 453                                return offset;
 454                        break;
 455                }
 456        }
 457
 458        return offset;
 459}
 460
 461static int parse_num(const char *line, unsigned long *p)
 462{
 463        char *ptr;
 464
 465        if (!isdigit(*line))
 466                return 0;
 467        *p = strtoul(line, &ptr, 10);
 468        return ptr - line;
 469}
 470
 471static int parse_range(const char *line, int len, int offset, const char *expect,
 472                        unsigned long *p1, unsigned long *p2)
 473{
 474        int digits, ex;
 475
 476        if (offset < 0 || offset >= len)
 477                return -1;
 478        line += offset;
 479        len -= offset;
 480
 481        digits = parse_num(line, p1);
 482        if (!digits)
 483                return -1;
 484
 485        offset += digits;
 486        line += digits;
 487        len -= digits;
 488
 489        *p2 = *p1;
 490        if (*line == ',') {
 491                digits = parse_num(line+1, p2);
 492                if (!digits)
 493                        return -1;
 494
 495                offset += digits+1;
 496                line += digits+1;
 497                len -= digits+1;
 498        }
 499
 500        ex = strlen(expect);
 501        if (ex > len)
 502                return -1;
 503        if (memcmp(line, expect, ex))
 504                return -1;
 505
 506        return offset + ex;
 507}
 508
 509/*
 510 * Parse a unified diff fragment header of the
 511 * form "@@ -a,b +c,d @@"
 512 */
 513static int parse_fragment_header(char *line, int len, struct fragment *fragment)
 514{
 515        int offset;
 516
 517        if (!len || line[len-1] != '\n')
 518                return -1;
 519
 520        /* Figure out the number of lines in a fragment */
 521        offset = parse_range(line, len, 4, " +", &fragment->oldpos, &fragment->oldlines);
 522        offset = parse_range(line, len, offset, " @@", &fragment->newpos, &fragment->newlines);
 523
 524        return offset;
 525}
 526
 527static int find_header(char *line, unsigned long size, int *hdrsize, struct patch *patch)
 528{
 529        unsigned long offset, len;
 530
 531        patch->is_rename = patch->is_copy = 0;
 532        patch->is_new = patch->is_delete = -1;
 533        patch->old_mode = patch->new_mode = 0;
 534        patch->old_name = patch->new_name = NULL;
 535        for (offset = 0; size > 0; offset += len, size -= len, line += len, linenr++) {
 536                unsigned long nextlen;
 537
 538                len = linelen(line, size);
 539                if (!len)
 540                        break;
 541
 542                /* Testing this early allows us to take a few shortcuts.. */
 543                if (len < 6)
 544                        continue;
 545
 546                /*
 547                 * Make sure we don't find any unconnected patch fragmants.
 548                 * That's a sign that we didn't find a header, and that a
 549                 * patch has become corrupted/broken up.
 550                 */
 551                if (!memcmp("@@ -", line, 4)) {
 552                        struct fragment dummy;
 553                        if (parse_fragment_header(line, len, &dummy) < 0)
 554                                continue;
 555                        error("patch fragment without header at line %d: %.*s", linenr, len-1, line);
 556                }
 557
 558                if (size < len + 6)
 559                        break;
 560
 561                /*
 562                 * Git patch? It might not have a real patch, just a rename
 563                 * or mode change, so we handle that specially
 564                 */
 565                if (!memcmp("diff --git ", line, 11)) {
 566                        int git_hdr_len = parse_git_header(line, len, size, patch);
 567                        if (git_hdr_len < 0)
 568                                continue;
 569                        if (!patch->old_name && !patch->new_name)
 570                                die("git diff header lacks filename information");
 571                        *hdrsize = git_hdr_len;
 572                        return offset;
 573                }
 574
 575                /** --- followed by +++ ? */
 576                if (memcmp("--- ", line,  4) || memcmp("+++ ", line + len, 4))
 577                        continue;
 578
 579                /*
 580                 * We only accept unified patches, so we want it to
 581                 * at least have "@@ -a,b +c,d @@\n", which is 14 chars
 582                 * minimum
 583                 */
 584                nextlen = linelen(line + len, size - len);
 585                if (size < nextlen + 14 || memcmp("@@ -", line + len + nextlen, 4))
 586                        continue;
 587
 588                /* Ok, we'll consider it a patch */
 589                parse_traditional_patch(line, line+len, patch);
 590                *hdrsize = len + nextlen;
 591                linenr += 2;
 592                return offset;
 593        }
 594        return -1;
 595}
 596
 597/*
 598 * Parse a unified diff. Note that this really needs
 599 * to parse each fragment separately, since the only
 600 * way to know the difference between a "---" that is
 601 * part of a patch, and a "---" that starts the next
 602 * patch is to look at the line counts..
 603 */
 604static int parse_fragment(char *line, unsigned long size, struct patch *patch, struct fragment *fragment)
 605{
 606        int added, deleted;
 607        int len = linelen(line, size), offset;
 608        unsigned long pos[4], oldlines, newlines;
 609
 610        offset = parse_fragment_header(line, len, fragment);
 611        if (offset < 0)
 612                return -1;
 613        oldlines = fragment->oldlines;
 614        newlines = fragment->newlines;
 615
 616        if (patch->is_new < 0 && (pos[0] || oldlines))
 617                patch->is_new = 0;
 618        if (patch->is_delete < 0 && (pos[1] || newlines))
 619                patch->is_delete = 0;
 620
 621        /* Parse the thing.. */
 622        line += len;
 623        size -= len;
 624        linenr++;
 625        added = deleted = 0;
 626        for (offset = len; size > 0; offset += len, size -= len, line += len, linenr++) {
 627                if (!oldlines && !newlines)
 628                        break;
 629                len = linelen(line, size);
 630                if (!len || line[len-1] != '\n')
 631                        return -1;
 632                switch (*line) {
 633                default:
 634                        return -1;
 635                case ' ':
 636                        oldlines--;
 637                        newlines--;
 638                        break;
 639                case '-':
 640                        deleted++;
 641                        oldlines--;
 642                        break;
 643                case '+':
 644                        added++;
 645                        newlines--;
 646                        break;
 647                /* We allow "\ No newline at end of file" */
 648                case '\\':
 649                        break;
 650                }
 651        }
 652        patch->lines_added += added;
 653        patch->lines_deleted += deleted;
 654        return offset;
 655}
 656
 657static int parse_single_patch(char *line, unsigned long size, struct patch *patch)
 658{
 659        unsigned long offset = 0;
 660        struct fragment **fragp = &patch->fragments;
 661
 662        while (size > 4 && !memcmp(line, "@@ -", 4)) {
 663                struct fragment *fragment;
 664                int len;
 665
 666                fragment = xmalloc(sizeof(*fragment));
 667                memset(fragment, 0, sizeof(*fragment));
 668                len = parse_fragment(line, size, patch, fragment);
 669                if (len <= 0)
 670                        die("corrupt patch at line %d", linenr);
 671
 672                fragment->patch = line;
 673                fragment->size = len;
 674
 675                *fragp = fragment;
 676                fragp = &fragment->next;
 677
 678                offset += len;
 679                line += len;
 680                size -= len;
 681        }
 682        return offset;
 683}
 684
 685static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
 686{
 687        int hdrsize, patchsize;
 688        int offset = find_header(buffer, size, &hdrsize, patch);
 689
 690        if (offset < 0)
 691                return offset;
 692
 693        patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
 694
 695        return offset + hdrsize + patchsize;
 696}
 697
 698const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
 699const char minuses[]= "----------------------------------------------------------------------";
 700
 701static void show_stats(struct patch *patch)
 702{
 703        char *name = patch->old_name;
 704        int len, max, add, del;
 705
 706        if (!name)
 707                name = patch->new_name;
 708
 709        /*
 710         * "scale" the filename
 711         */
 712        len = strlen(name);
 713        max = max_len;
 714        if (max > 50)
 715                max = 50;
 716        if (len > max)
 717                name += len - max;
 718        len = max;
 719
 720        /*
 721         * scale the add/delete
 722         */
 723        max = max_change;
 724        if (max + len > 70)
 725                max = 70 - len;
 726        
 727        add = (patch->lines_added * max + max_change/2) / max_change;
 728        del = (patch->lines_deleted * max + max_change/2) / max_change;
 729        printf(" %-*s |%5d %.*s%.*s\n",
 730                len, name, patch->lines_added + patch->lines_deleted,
 731                add, pluses, del, minuses);
 732}
 733
 734static int check_patch(struct patch *patch)
 735{
 736        struct stat st;
 737        const char *old_name = patch->old_name;
 738        const char *new_name = patch->new_name;
 739
 740        if (old_name) {
 741                int pos = cache_name_pos(old_name, strlen(old_name));
 742                int changed;
 743
 744                if (pos < 0)
 745                        return error("%s: does not exist in index", old_name);
 746                if (patch->is_new < 0)
 747                        patch->is_new = 0;
 748                if (lstat(old_name, &st) < 0)
 749                        return error("%s: %s\n", strerror(errno));
 750                changed = ce_match_stat(active_cache[pos], &st);
 751                if (changed)
 752                        return error("%s: does not match index", old_name);
 753                if (!patch->old_mode)
 754                        patch->old_mode = st.st_mode;
 755        }
 756
 757        if (new_name && (patch->is_new | patch->is_rename | patch->is_copy)) {
 758                if (cache_name_pos(new_name, strlen(new_name)) >= 0)
 759                        return error("%s: already exists in index", new_name);
 760                if (!lstat(new_name, &st))
 761                        return error("%s: already exists in working directory", new_name);
 762                if (errno != ENOENT)
 763                        return error("%s: %s", new_name, strerror(errno));
 764        }
 765        return 0;
 766}
 767
 768static int check_patch_list(struct patch *patch)
 769{
 770        int error = 0;
 771
 772        for (;patch ; patch = patch->next)
 773                error |= check_patch(patch);
 774        return error;
 775}
 776
 777static void show_file(int c, unsigned int mode, const char *name)
 778{
 779        printf("%c %o %s\n", c, mode, name);
 780}
 781
 782static void show_file_list(struct patch *patch)
 783{
 784        for (;patch ; patch = patch->next) {
 785                if (patch->is_rename) {
 786                        show_file('-', patch->old_mode, patch->old_name);
 787                        show_file('+', patch->new_mode, patch->new_name);
 788                        continue;
 789                }
 790                if (patch->is_copy || patch->is_new) {
 791                        show_file('+', patch->new_mode, patch->new_name);
 792                        continue;
 793                }
 794                if (patch->is_delete) {
 795                        show_file('-', patch->old_mode, patch->old_name);
 796                        continue;
 797                }
 798                if (patch->old_mode && patch->new_mode && patch->old_mode != patch->new_mode) {
 799                        printf("M %o:%o %s\n", patch->old_mode, patch->new_mode, patch->old_name);
 800                        continue;
 801                }
 802                printf("M %o %s\n", patch->old_mode, patch->old_name);
 803        }
 804}
 805
 806static void stat_patch_list(struct patch *patch)
 807{
 808        int files, adds, dels;
 809
 810        for (files = adds = dels = 0 ; patch ; patch = patch->next) {
 811                files++;
 812                adds += patch->lines_added;
 813                dels += patch->lines_deleted;
 814                show_stats(patch);
 815        }
 816
 817        printf(" %d files changed, %d insertions(+), %d deletions(-)\n", files, adds, dels);
 818}
 819
 820static void patch_stats(struct patch *patch)
 821{
 822        int lines = patch->lines_added + patch->lines_deleted;
 823
 824        if (lines > max_change)
 825                max_change = lines;
 826        if (patch->old_name) {
 827                int len = strlen(patch->old_name);
 828                if (len > max_len)
 829                        max_len = len;
 830        }
 831        if (patch->new_name) {
 832                int len = strlen(patch->new_name);
 833                if (len > max_len)
 834                        max_len = len;
 835        }
 836}
 837
 838static int apply_patch(int fd)
 839{
 840        unsigned long offset, size;
 841        char *buffer = read_patch_file(fd, &size);
 842        struct patch *list = NULL, **listp = &list;
 843
 844        if (!buffer)
 845                return -1;
 846        offset = 0;
 847        while (size > 0) {
 848                struct patch *patch;
 849                int nr;
 850
 851                patch = xmalloc(sizeof(*patch));
 852                memset(patch, 0, sizeof(*patch));
 853                nr = parse_chunk(buffer + offset, size, patch);
 854                if (nr < 0)
 855                        break;
 856                patch_stats(patch);
 857                *listp = patch;
 858                listp = &patch->next;
 859                offset += nr;
 860                size -= nr;
 861        }
 862
 863        if ((check || apply) && check_patch_list(list) < 0)
 864                exit(1);
 865
 866        if (show_files)
 867                show_file_list(list);
 868
 869        if (diffstat)
 870                stat_patch_list(list);
 871
 872        free(buffer);
 873        return 0;
 874}
 875
 876int main(int argc, char **argv)
 877{
 878        int i;
 879        int read_stdin = 1;
 880
 881        if (read_cache() < 0)
 882                die("unable to read index file");
 883
 884        for (i = 1; i < argc; i++) {
 885                const char *arg = argv[i];
 886                int fd;
 887
 888                if (!strcmp(arg, "-")) {
 889                        apply_patch(0);
 890                        read_stdin = 0;
 891                        continue;
 892                }
 893                if (!strcmp(arg, "--no-merge")) {
 894                        merge_patch = 0;
 895                        continue;
 896                }
 897                if (!strcmp(arg, "--stat")) {
 898                        apply = 0;
 899                        diffstat = 1;
 900                        continue;
 901                }
 902                if (!strcmp(arg, "--check")) {
 903                        apply = 0;
 904                        check = 1;
 905                        continue;
 906                }
 907                if (!strcmp(arg, "--show-files")) {
 908                        show_files = 1;
 909                        continue;
 910                }
 911                fd = open(arg, O_RDONLY);
 912                if (fd < 0)
 913                        usage(apply_usage);
 914                read_stdin = 0;
 915                apply_patch(fd);
 916                close(fd);
 917        }
 918        if (read_stdin)
 919                apply_patch(0);
 920        return 0;
 921}