git-apply: don't try to be clever about filenames and the index
[git.git] / apply.c
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 //
27 static int merge_patch = 1;
28 static int diffstat = 0;
29 static int check = 0;
30 static int apply = 1;
31 static int show_files = 0;
32 static 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  */
39 static 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  */
46 static int linenr = 1;
47
48 struct fragment {
49         unsigned long oldpos, oldlines;
50         unsigned long newpos, newlines;
51         const char *patch;
52         int size;
53         struct fragment *next;
54 };
55
56 struct 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
68 static 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
103 static 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
114 static 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
122 static 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
132 static 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  */
185 static 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
211 static 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  */
225 static 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;
251 absolute_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
260 static 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
266 static 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
272 static int gitdiff_oldmode(const char *line, struct patch *patch)
273 {
274         patch->old_mode = strtoul(line, NULL, 8);
275         return 0;
276 }
277
278 static int gitdiff_newmode(const char *line, struct patch *patch)
279 {
280         patch->new_mode = strtoul(line, NULL, 8);
281         return 0;
282 }
283
284 static 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
291 static 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
298 static 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
305 static 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
312 static 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
319 static 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
326 static int gitdiff_similarity(const char *line, struct patch *patch)
327 {
328         return 0;
329 }
330
331 static 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  */
340 static int gitdiff_unrecognized(const char *line, struct patch *patch)
341 {
342         return -1;
343 }
344
345 static 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 */
401 static 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
459 static 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
469 static 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  */
511 static 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
525 static 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  */
602 static 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
655 static 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
683 static 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
696 const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
697 const char minuses[]= "----------------------------------------------------------------------";
698
699 static void show_stats(struct patch *patch)
700 {
701         char *name = patch->old_name;
702         int len, max, add, del;
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 * max + max_change/2) / max_change;
726         del = (patch->lines_deleted * max + max_change/2) / max_change;
727         printf(" %-*s |%5d %.*s%.*s\n",
728                 len, name, patch->lines_added + patch->lines_deleted,
729                 add, pluses, del, minuses);
730 }
731
732 static int check_patch(struct patch *patch)
733 {
734         struct stat st;
735         const char *old_name = patch->old_name;
736         const char *new_name = patch->new_name;
737
738         if (old_name) {
739                 int pos = cache_name_pos(old_name, strlen(old_name));
740                 int changed;
741
742                 if (pos < 0)
743                         return error("%s: does not exist in index", old_name);
744                 if (patch->is_new < 0)
745                         patch->is_new = 0;
746                 if (lstat(old_name, &st) < 0)
747                         return error("%s: %s\n", strerror(errno));
748                 changed = ce_match_stat(active_cache[pos], &st);
749                 if (changed)
750                         return error("%s: does not match index", old_name);
751                 if (!patch->old_mode)
752                         patch->old_mode = st.st_mode;
753         }
754
755         if (new_name && (patch->is_new | patch->is_rename | patch->is_copy)) {
756                 if (cache_name_pos(new_name, strlen(new_name)) >= 0)
757                         return error("%s: already exists in index", new_name);
758                 if (!lstat(new_name, &st))
759                         return error("%s: already exists in working directory", new_name);
760                 if (errno != ENOENT)
761                         return error("%s: %s", new_name, strerror(errno));
762         }
763         return 0;
764 }
765
766 static int check_patch_list(struct patch *patch)
767 {
768         int error = 0;
769
770         for (;patch ; patch = patch->next)
771                 error |= check_patch(patch);
772         return error;
773 }
774
775 static void show_file(int c, unsigned int mode, const char *name)
776 {
777         printf("%c %o %s\n", c, mode, name);
778 }
779
780 static void show_file_list(struct patch *patch)
781 {
782         for (;patch ; patch = patch->next) {
783                 if (patch->is_rename) {
784                         show_file('-', patch->old_mode, patch->old_name);
785                         show_file('+', patch->new_mode, patch->new_name);
786                         continue;
787                 }
788                 if (patch->is_copy || patch->is_new) {
789                         show_file('+', patch->new_mode, patch->new_name);
790                         continue;
791                 }
792                 if (patch->is_delete) {
793                         show_file('-', patch->old_mode, patch->old_name);
794                         continue;
795                 }
796                 if (patch->old_mode && patch->new_mode && patch->old_mode != patch->new_mode) {
797                         printf("M %o:%o %s\n", patch->old_mode, patch->new_mode, patch->old_name);
798                         continue;
799                 }
800                 printf("M %o %s\n", patch->old_mode, patch->old_name);
801         }
802 }
803
804 static void stat_patch_list(struct patch *patch)
805 {
806         int files, adds, dels;
807
808         for (files = adds = dels = 0 ; patch ; patch = patch->next) {
809                 files++;
810                 adds += patch->lines_added;
811                 dels += patch->lines_deleted;
812                 show_stats(patch);
813         }
814
815         printf(" %d files changed, %d insertions(+), %d deletions(-)\n", files, adds, dels);
816 }
817
818 static void patch_stats(struct patch *patch)
819 {
820         int lines = patch->lines_added + patch->lines_deleted;
821
822         if (lines > max_change)
823                 max_change = lines;
824         if (patch->old_name) {
825                 int len = strlen(patch->old_name);
826                 if (len > max_len)
827                         max_len = len;
828         }
829         if (patch->new_name) {
830                 int len = strlen(patch->new_name);
831                 if (len > max_len)
832                         max_len = len;
833         }
834 }
835
836 static int apply_patch(int fd)
837 {
838         unsigned long offset, size;
839         char *buffer = read_patch_file(fd, &size);
840         struct patch *list = NULL, **listp = &list;
841
842         if (!buffer)
843                 return -1;
844         offset = 0;
845         while (size > 0) {
846                 struct patch *patch;
847                 int nr;
848
849                 patch = xmalloc(sizeof(*patch));
850                 memset(patch, 0, sizeof(*patch));
851                 nr = parse_chunk(buffer + offset, size, patch);
852                 if (nr < 0)
853                         break;
854                 patch_stats(patch);
855                 *listp = patch;
856                 listp = &patch->next;
857                 offset += nr;
858                 size -= nr;
859         }
860
861         if ((check || apply) && check_patch_list(list) < 0)
862                 exit(1);
863
864         if (show_files)
865                 show_file_list(list);
866
867         if (diffstat)
868                 stat_patch_list(list);
869
870         free(buffer);
871         return 0;
872 }
873
874 int main(int argc, char **argv)
875 {
876         int i;
877         int read_stdin = 1;
878
879         if (read_cache() < 0)
880                 die("unable to read index file");
881
882         for (i = 1; i < argc; i++) {
883                 const char *arg = argv[i];
884                 int fd;
885
886                 if (!strcmp(arg, "-")) {
887                         apply_patch(0);
888                         read_stdin = 0;
889                         continue;
890                 }
891                 if (!strcmp(arg, "--no-merge")) {
892                         merge_patch = 0;
893                         continue;
894                 }
895                 if (!strcmp(arg, "--stat")) {
896                         apply = 0;
897                         diffstat = 1;
898                         continue;
899                 }
900                 if (!strcmp(arg, "--check")) {
901                         apply = 0;
902                         check = 1;
903                         continue;
904                 }
905                 if (!strcmp(arg, "--show-files")) {
906                         show_files = 1;
907                         continue;
908                 }
909                 fd = open(arg, O_RDONLY);
910                 if (fd < 0)
911                         usage(apply_usage);
912                 read_stdin = 0;
913                 apply_patch(fd);
914                 close(fd);
915         }
916         if (read_stdin)
917                 apply_patch(0);
918         return 0;
919 }