Mercurial > hg > toybox
annotate toys/patch.c @ 315:aaac01796688
Upgrade patch to detect hunks that start after a false start.
Imagine a hunk that starts with a blank line, but the site to patch starts
with two blank lines. Before we'd read the first blank line, think it was the
start of the hunk and buffer it, read the second blank line, notice that it
didn't match the second line of the hunk, and discard _both_ buffered lines of
context (writing them to the output file) without checking that one of the
later context lines might have been the real start of the hunk.
Make it re-check the rest of the buffered context for matches each time it
discards a line of buffered context.
author | Rob Landley <rob@landley.net> |
---|---|
date | Thu, 23 Oct 2008 16:44:30 -0500 |
parents | d1a548bbd0dd |
children | 5d0fbdb2fc86 |
rev | line source |
---|---|
233
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
1 /* vi: set sw=4 ts=4: |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
2 * |
209 | 3 * patch.c - Apply a "universal" diff. |
4 * | |
233
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
5 * Copyright 2007 Rob Landley <rob@landley.net> |
209 | 6 * |
233
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
7 * see http://www.opengroup.org/onlinepubs/009695399/utilities/patch.html |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
8 * (But only does -u, because who still cares about "ed"?) |
209 | 9 * |
10 * TODO: | |
11 * -b backup | |
12 * -l treat all whitespace as a single space | |
13 * -N ignore already applied | |
14 * -d chdir first | |
15 * -D define wrap #ifdef and #ifndef around changes | |
16 * -o outfile output here instead of in place | |
17 * -r rejectfile write rejected hunks to this file | |
18 * | |
19 * -E remove empty files --remove-empty-files | |
20 * -f force (no questions asked) | |
21 * -F fuzz (number, default 2) | |
22 * [file] which file to patch | |
233
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
23 |
234
163498bf547b
Move NEWTOY() list from end of toylist.h to generated/newtoys.h.
Rob Landley <rob@landley.net>
parents:
233
diff
changeset
|
24 USE_PATCH(NEWTOY(patch, "up#i:R", TOYFLAG_USR|TOYFLAG_BIN)) |
163498bf547b
Move NEWTOY() list from end of toylist.h to generated/newtoys.h.
Rob Landley <rob@landley.net>
parents:
233
diff
changeset
|
25 |
233
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
26 config PATCH |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
27 bool "patch" |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
28 default y |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
29 help |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
30 usage: patch [-i file] [-p depth] [-Ru] |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
31 |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
32 Apply a unified diff to one or more files. |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
33 |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
34 -i Input file (defaults=stdin) |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
35 -p number of '/' to strip from start of file paths (default=all) |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
36 -R Reverse patch. |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
37 -u Ignored (only handles "unified" diffs) |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
38 |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
39 This version of patch only handles unified diffs, and only modifies |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
40 a file when all all hunks to that file apply. Patch prints failed |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
41 hunks to stderr, and exits with nonzero status if any hunks fail. |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
42 |
280
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
43 A file compared against /dev/null (or with a date in 1969) is |
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
44 created/deleted as appropriate. |
233
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
45 */ |
209 | 46 |
47 #include "toys.h" | |
48 | |
237
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
49 DEFINE_GLOBALS( |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
50 char *infile; |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
51 long prefix; |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
52 |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
53 struct double_list *plines, *flines; |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
54 long oldline, oldlen, newline, newlen, linenum; |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
55 int context, state, filein, fileout, filepatch, hunknum; |
237
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
56 char *tempname, *oldname; |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
57 ) |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
58 |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
59 #define TT this.patch |
209 | 60 |
61 #define FLAG_REVERSE 1 | |
62 #define FLAG_PATHLEN 4 | |
63 | |
64 static void do_line(void *data) | |
65 { | |
66 struct double_list *dlist = (struct double_list *)data; | |
67 | |
68 if (TT.state && *dlist->data != TT.state) | |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
69 fdprintf(TT.state == 2 ? 2 : TT.fileout, |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
70 "%s\n", dlist->data+(TT.state>2 ? 1 : 0)); |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
71 |
209 | 72 free(dlist->data); |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
73 free(data); |
209 | 74 } |
75 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
76 static void finish_oldfile(void) |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
77 { |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
78 if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
79 } |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
80 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
81 static void fail_hunk(void) |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
82 { |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
83 if (!TT.plines) return; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
84 TT.plines->prev->next = 0; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
85 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
86 fdprintf(2, "Hunk %d FAILED.\n", TT.hunknum); |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
87 toys.exitval = 1; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
88 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
89 // If we got to this point, we've seeked to the end. Discard changes to |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
90 // this file and advance to next file. |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
91 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
92 TT.state = 2; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
93 llist_free(TT.plines, do_line); |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
94 TT.plines = NULL; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
95 delete_tempfile(TT.filein, TT.fileout, &TT.tempname); |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
96 TT.filein = -1; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
97 } |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
98 |
209 | 99 static void apply_hunk(void) |
100 { | |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
101 struct double_list *plist, *buf = NULL, *check; |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
102 int i = 0, backwards = 0, matcheof = 0, |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
103 reverse = toys.optflags & FLAG_REVERSE; |
209 | 104 |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
105 // Break doubly linked list so we can use singly linked traversal function. |
209 | 106 TT.plines->prev->next = NULL; |
107 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
108 // Match EOF if there aren't as many ending context lines as beginning |
209 | 109 for (plist = TT.plines; plist; plist = plist->next) { |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
110 if (plist->data[0]==' ') i++; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
111 else i = 0; |
209 | 112 } |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
113 if (i < TT.context) matcheof++; |
209 | 114 |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
115 // Search for a place to apply this hunk. Match all context lines and |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
116 // lines to be removed. |
209 | 117 plist = TT.plines; |
118 buf = NULL; | |
119 i = 0; | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
120 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
121 // Start of for loop |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
122 if (TT.context) for (;;) { |
209 | 123 char *data = get_line(TT.filein); |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
124 |
209 | 125 TT.linenum++; |
126 | |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
127 // Skip lines of the hunk we'd be adding. |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
128 while (plist && *plist->data == "+-"[reverse]) { |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
129 if (data && !strcmp(data, plist->data+1)) { |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
130 if (++backwards == TT.context) |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
131 fdprintf(2,"Possibly reversed hunk %d at %ld\n", |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
132 TT.hunknum, TT.linenum); |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
133 } else backwards=0; |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
134 plist = plist->next; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
135 } |
209 | 136 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
137 // Is this EOF? |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
138 if (!data) { |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
139 // Does this hunk need to match EOF? |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
140 if (!plist && matcheof) break; |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
141 |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
142 // File ended before we found a place for this hunk. |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
143 fail_hunk(); |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
144 goto done; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
145 } |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
146 check = dlist_add(&buf, data); |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
147 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
148 // todo: teach the strcmp() to ignore whitespace. |
209 | 149 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
150 for (;;) { |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
151 // If we hit the end of a hunk that needed EOF and this isn't EOF, |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
152 // or next line doesn't match, flush first line of buffered data and |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
153 // recheck match until we find a new match or run out of buffer. |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
154 |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
155 if (!plist || strcmp(check->data, plist->data+1)) { |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
156 // First line isn't a match, write it out. |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
157 TT.state = 1; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
158 check = llist_pop(&buf); |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
159 check->prev->next = buf; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
160 buf->prev = check->prev; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
161 do_line(check); |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
162 plist = TT.plines; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
163 |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
164 // Out of buffered lines? |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
165 if (check==buf) { |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
166 buf = 0; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
167 break; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
168 } |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
169 check = buf; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
170 } else { |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
171 // This line matches. Advance plist, detect successful match. |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
172 plist = plist->next; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
173 if (!plist && !matcheof) goto out; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
174 check = check->next; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
175 if (check == buf) break; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
176 } |
209 | 177 } |
178 } | |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
179 out: |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
180 // Got it. Emit changed data. |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
181 TT.state = "-+"[reverse]; |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
182 llist_free(TT.plines, do_line); |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
183 TT.plines = NULL; |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
184 done: |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
185 TT.state = 0; |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
186 if (buf) { |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
187 buf->prev->next = NULL; |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
188 llist_free(buf, do_line); |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
189 } |
209 | 190 } |
191 | |
192 // state 0: Not in a hunk, look for +++. | |
193 // state 1: Found +++ file indicator, look for @@ | |
194 // state 2: In hunk: counting initial context lines | |
195 // state 3: In hunk: getting body | |
196 | |
197 void patch_main(void) | |
198 { | |
199 if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY); | |
200 TT.filein = TT.fileout = -1; | |
201 | |
202 // Loop through the lines in the patch | |
203 for(;;) { | |
204 char *patchline; | |
205 | |
206 patchline = get_line(TT.filepatch); | |
207 if (!patchline) break; | |
208 | |
209 // Are we processing a hunk? | |
210 if (TT.state >= 2) { | |
211 if (*patchline==' ' || *patchline=='+' || *patchline=='-') { | |
212 dlist_add(&TT.plines, patchline); | |
213 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
214 if (*patchline != '+') TT.oldlen--; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
215 if (*patchline != '-') TT.newlen--; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
216 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
217 // Context line? |
209 | 218 if (*patchline==' ' && TT.state==2) TT.context++; |
219 else TT.state=3; | |
220 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
221 if (!TT.oldlen && !TT.newlen) apply_hunk(); |
209 | 222 continue; |
223 } | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
224 fail_hunk(); |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
225 TT.state = 0; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
226 continue; |
209 | 227 } |
228 | |
229 // Open a new file? | |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
230 if (!strncmp("--- ", patchline, 4)) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
231 char *s; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
232 free(TT.oldname); |
209 | 233 |
234 // Trim date from end of filename (if any). We don't care. | |
235 for (s = patchline+4; *s && *s!='\t'; s++) | |
236 if (*s=='\\' && s[1]) s++; | |
280
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
237 if (!strncmp(s, "\t1969-12-31", 10)) |
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
238 TT.oldname = xstrdup("/dev/null"); |
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
239 else { |
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
240 *s = 0; |
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
241 TT.oldname = xstrdup(patchline+4); |
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
242 } |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
243 } else if (!strncmp("+++ ", patchline, 4)) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
244 int i = 0, del = 0; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
245 char *s, *start; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
246 |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
247 finish_oldfile(); |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
248 |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
249 // Trim date from end of filename (if any). We don't care. |
280
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
250 for (s = start = patchline+4; *s && *s!='\t'; s++) |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
251 if (*s=='\\' && s[1]) s++; |
280
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
252 if (!strncmp(s, "\t1969-12-31", 10)) start = "/dev/null"; |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
253 *s = 0; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
254 |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
255 // If new file is /dev/null (before -p), we're deleting oldname |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
256 if (!strcmp(start, "/dev/null")) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
257 start = TT.oldname; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
258 del++; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
259 } else start = patchline+4; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
260 |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
261 // handle -p path truncation. |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
262 for (s = start; *s;) { |
209 | 263 if ((toys.optflags & FLAG_PATHLEN) && TT.prefix == i) break; |
264 if (*(s++)=='/') { | |
265 start = s; | |
266 i++; | |
267 } | |
268 } | |
269 | |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
270 if (del) xunlink(TT.oldname); |
209 | 271 // If we've got a file to open, do so. |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
272 else if (!(toys.optflags & FLAG_PATHLEN) || i <= TT.prefix) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
273 // If the old file was null, we're creating a new one. |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
274 if (!strcmp(TT.oldname, "/dev/null")) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
275 printf("creating %s\n", start); |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
276 s = strrchr(start, '/'); |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
277 if (s) { |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
278 *s = 0; |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
279 xmkpath(start, -1); |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
280 *s = '/'; |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
281 } |
280
d1a548bbd0dd
Teach patch that a file dated 1969-12-31 means doesn't exist, and to fail
Rob Landley <rob@landley.net>
parents:
238
diff
changeset
|
282 TT.filein = xcreate(start, O_CREAT|O_EXCL|O_RDWR, 0666); |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
283 } else { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
284 printf("patching %s\n", start); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
285 TT.filein = xopen(start, O_RDWR); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
286 } |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
287 TT.fileout = copy_tempfile(TT.filein, start, &TT.tempname); |
209 | 288 TT.state = 1; |
289 TT.context = 0; | |
290 TT.linenum = 0; | |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
291 TT.hunknum = 0; |
209 | 292 } |
293 | |
294 // Start a new hunk? | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
295 // Test filein rather than state to report only the first failed hunk. |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
296 } else if (TT.filein!=-1 && !strncmp("@@ -", patchline, 4) && |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
297 4 == sscanf(patchline+4, "%ld,%ld +%ld,%ld", &TT.oldline, |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
298 &TT.oldlen, &TT.newline, &TT.newlen)) |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
299 { |
209 | 300 TT.context = 0; |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
301 TT.hunknum++; |
209 | 302 TT.state = 2; |
303 continue; | |
304 } | |
305 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
306 // If we didn't continue above, discard this line. |
209 | 307 free(patchline); |
308 } | |
309 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
310 finish_oldfile(); |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
311 |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
312 if (CFG_TOYBOX_FREE) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
313 close(TT.filepatch); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
314 free(TT.oldname); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
315 } |
209 | 316 } |