Mercurial > hg > toybox
annotate toys/patch.c @ 339:157eab6dcdd2
Hello shouldn't be enabled in defconfig.
author | Rob Landley <rob@landley.net> |
---|---|
date | Wed, 14 Jan 2009 20:41:37 -0600 |
parents | 556c10abdff6 |
children | c7143968cea6 |
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 |
325
5d0fbdb2fc86
The epoch can also show up as 1970-01-01 (depending on timezone), so treat any year >0 and <= 1970 as meaning "file does not exist".
Rob Landley <rob@landley.net>
parents:
315
diff
changeset
|
43 A file compared against /dev/null (or with a date <= the epoch) is |
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
|
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 { | |
335
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
199 int reverse = toys.optflags & FLAG_REVERSE; |
209 | 200 if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY); |
201 TT.filein = TT.fileout = -1; | |
202 | |
203 // Loop through the lines in the patch | |
204 for(;;) { | |
205 char *patchline; | |
206 | |
207 patchline = get_line(TT.filepatch); | |
208 if (!patchline) break; | |
209 | |
210 // Are we processing a hunk? | |
211 if (TT.state >= 2) { | |
212 if (*patchline==' ' || *patchline=='+' || *patchline=='-') { | |
213 dlist_add(&TT.plines, patchline); | |
214 | |
219
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.oldlen--; |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
216 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
|
217 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
218 // Context line? |
209 | 219 if (*patchline==' ' && TT.state==2) TT.context++; |
220 else TT.state=3; | |
221 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
222 if (!TT.oldlen && !TT.newlen) apply_hunk(); |
209 | 223 continue; |
224 } | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
225 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
|
226 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
|
227 continue; |
209 | 228 } |
229 | |
230 // Open a new file? | |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
231 if (!strncmp("--- ", patchline, 4)) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
232 char *s; |
325
5d0fbdb2fc86
The epoch can also show up as 1970-01-01 (depending on timezone), so treat any year >0 and <= 1970 as meaning "file does not exist".
Rob Landley <rob@landley.net>
parents:
315
diff
changeset
|
233 int i; |
5d0fbdb2fc86
The epoch can also show up as 1970-01-01 (depending on timezone), so treat any year >0 and <= 1970 as meaning "file does not exist".
Rob Landley <rob@landley.net>
parents:
315
diff
changeset
|
234 |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
235 free(TT.oldname); |
209 | 236 |
237 // Trim date from end of filename (if any). We don't care. | |
238 for (s = patchline+4; *s && *s!='\t'; s++) | |
239 if (*s=='\\' && s[1]) s++; | |
325
5d0fbdb2fc86
The epoch can also show up as 1970-01-01 (depending on timezone), so treat any year >0 and <= 1970 as meaning "file does not exist".
Rob Landley <rob@landley.net>
parents:
315
diff
changeset
|
240 i = atoi(s); |
5d0fbdb2fc86
The epoch can also show up as 1970-01-01 (depending on timezone), so treat any year >0 and <= 1970 as meaning "file does not exist".
Rob Landley <rob@landley.net>
parents:
315
diff
changeset
|
241 if (i && i<=1970) |
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
|
242 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
|
243 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
|
244 *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
|
245 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
|
246 } |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
247 } else if (!strncmp("+++ ", patchline, 4)) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
248 int i = 0, del = 0; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
249 char *s, *start; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
250 |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
251 finish_oldfile(); |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
252 |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
253 // 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
|
254 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
|
255 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
|
256 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
|
257 *s = 0; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
258 |
335
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
259 if (reverse) { |
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
260 s = start; |
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
261 start = TT.oldname; |
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
262 } |
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
263 |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
264 // 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
|
265 if (!strcmp(start, "/dev/null")) { |
335
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
266 start = reverse ? s : TT.oldname; |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
267 del++; |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
268 } else start = patchline+4; |
335
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
269 |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
270 // handle -p path truncation. |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
271 for (s = start; *s;) { |
209 | 272 if ((toys.optflags & FLAG_PATHLEN) && TT.prefix == i) break; |
273 if (*(s++)=='/') { | |
274 start = s; | |
275 i++; | |
276 } | |
277 } | |
278 | |
331
9de39991c080
Two bugfixes for deleting files (-p and message)
Rob Landley <rob@landley.net>
parents:
325
diff
changeset
|
279 if (del) { |
9de39991c080
Two bugfixes for deleting files (-p and message)
Rob Landley <rob@landley.net>
parents:
325
diff
changeset
|
280 printf("removing %s\n", start); |
9de39991c080
Two bugfixes for deleting files (-p and message)
Rob Landley <rob@landley.net>
parents:
325
diff
changeset
|
281 xunlink(start); |
209 | 282 // If we've got a file to open, do so. |
331
9de39991c080
Two bugfixes for deleting files (-p and message)
Rob Landley <rob@landley.net>
parents:
325
diff
changeset
|
283 } else if (!(toys.optflags & FLAG_PATHLEN) || i <= TT.prefix) { |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
284 // 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
|
285 if (!strcmp(TT.oldname, "/dev/null")) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
286 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
|
287 s = strrchr(start, '/'); |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
288 if (s) { |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
289 *s = 0; |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
290 xmkpath(start, -1); |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
291 *s = '/'; |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
292 } |
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
|
293 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
|
294 } else { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
295 printf("patching %s\n", start); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
296 TT.filein = xopen(start, O_RDWR); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
297 } |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
298 TT.fileout = copy_tempfile(TT.filein, start, &TT.tempname); |
209 | 299 TT.state = 1; |
300 TT.context = 0; | |
301 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
|
302 TT.hunknum = 0; |
209 | 303 } |
304 | |
305 // 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
|
306 // 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
|
307 } 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
|
308 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
|
309 &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
|
310 { |
209 | 311 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
|
312 TT.hunknum++; |
209 | 313 TT.state = 2; |
314 continue; | |
315 } | |
316 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
317 // If we didn't continue above, discard this line. |
209 | 318 free(patchline); |
319 } | |
320 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
321 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
|
322 |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
323 if (CFG_TOYBOX_FREE) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
324 close(TT.filepatch); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
325 free(TT.oldname); |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
326 } |
209 | 327 } |