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