Mercurial > hg > toybox
annotate toys/posix/patch.c @ 688:9791e462855a
Fix reversed test: patch creates a file if /dev/null or dated the epoch _and_ first hunk being replaced is 0 lines at start of file, not one or the other.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 10 Nov 2012 14:34:01 -0600 |
parents | 7e846e281e38 |
children | a81cf364764d |
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 * |
656
6df4ccc0acbe
Regularize command headers, update links to standards documents.
Rob Landley <rob@landley.net>
parents:
653
diff
changeset
|
7 * see http://opengroup.org/onlinepubs/9699919799/utilities/patch.html |
233
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 |
670 | 24 USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"ulp#i:R", TOYFLAG_USR|TOYFLAG_BIN)) |
234
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) |
670 | 35 -l Loose match (ignore whitespace) |
36 -p Number of '/' to strip from start of file paths (default=all) | |
233
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
37 -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
|
38 -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
|
39 |
d4176f3f3835
Zap toys/Config.in and instead create generated/Config.in from contents of
Rob Landley <rob@landley.net>
parents:
219
diff
changeset
|
40 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
|
41 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
|
42 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
|
43 |
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
|
44 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
|
45 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
|
46 */ |
209 | 47 |
674
7e846e281e38
New build infrastructure to generate FLAG_ macros and TT alias, #define FOR_commandname before #including toys.h to trigger it. Rename DEFINE_GLOBALS() to just GLOBALS() (because I could never remember if it was DECLARE_GLOBALS). Convert existing commands to use new infrastructure, and replace optflag constants with FLAG_ macros where appropriate.
Rob Landley <rob@landley.net>
parents:
673
diff
changeset
|
48 #define FOR_patch |
209 | 49 #include "toys.h" |
50 | |
674
7e846e281e38
New build infrastructure to generate FLAG_ macros and TT alias, #define FOR_commandname before #including toys.h to trigger it. Rename DEFINE_GLOBALS() to just GLOBALS() (because I could never remember if it was DECLARE_GLOBALS). Convert existing commands to use new infrastructure, and replace optflag constants with FLAG_ macros where appropriate.
Rob Landley <rob@landley.net>
parents:
673
diff
changeset
|
51 GLOBALS( |
237
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
52 char *infile; |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
53 long prefix; |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
54 |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
55 struct double_list *current_hunk; |
377
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
56 long oldline, oldlen, newline, newlen; |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
57 long linenum; |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
58 int context, state, filein, fileout, filepatch, hunknum; |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
59 char *tempname; |
237
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
60 ) |
7cb15eae1664
Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS()
Rob Landley <rob@landley.net>
parents:
234
diff
changeset
|
61 |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
62 // Dispose of a line of input, either by writing it out or discarding it. |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
63 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
64 // state < 2: just free |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
65 // state = 2: write whole line to stderr |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
66 // state = 3: write whole line to fileout |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
67 // state > 3: write line+1 to fileout when *line != state |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
68 |
670 | 69 #define PATCH_DEBUG (CFG_TOYBOX_DEBUG && (toys.optflags & 32)) |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
70 |
209 | 71 static void do_line(void *data) |
72 { | |
73 struct double_list *dlist = (struct double_list *)data; | |
74 | |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
75 if (TT.state>1 && *dlist->data != TT.state) { |
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
76 char *s = dlist->data+(TT.state>3 ? 1 : 0); |
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
77 int i = TT.state == 2 ? 2 : TT.fileout; |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
78 |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
79 xwrite(i, s, strlen(s)); |
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
80 xwrite(i, "\n", 1); |
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
81 } |
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
82 |
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
83 if (PATCH_DEBUG) fprintf(stderr, "DO %d: %s\n", TT.state, dlist->data); |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
84 |
209 | 85 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
|
86 free(data); |
209 | 87 } |
88 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
89 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
|
90 { |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
91 if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname); |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
92 TT.fileout = TT.filein = -1; |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
93 } |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
94 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
95 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
|
96 { |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
97 if (!TT.current_hunk) return; |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
98 TT.current_hunk->prev->next = 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
|
99 |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
100 fprintf(stderr, "Hunk %d FAILED %ld/%ld.\n", |
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
101 TT.hunknum, TT.oldline, TT.newline); |
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 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
|
103 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
104 // 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
|
105 // 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
|
106 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
107 TT.state = 2; |
624
1e8b9acdafeb
Genericize llist code a bit: rename llist_free() to llist_traverse(), and no longer accept NULL as a synonym for free.
Rob Landley <rob@landley.net>
parents:
550
diff
changeset
|
108 llist_traverse(TT.current_hunk, do_line); |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
109 TT.current_hunk = 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
|
110 delete_tempfile(TT.filein, TT.fileout, &TT.tempname); |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
111 TT.state = 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
|
112 } |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
113 |
670 | 114 // Compare ignoring whitespace. Just returns |
115 static int loosecmp(char *aa, char *bb) | |
116 { | |
117 int a = 0, b = 0; | |
118 | |
119 for (;;) { | |
120 while (isspace(aa[a])) a++; | |
121 while (isspace(bb[b])) b++; | |
122 if (aa[a] != bb[b]) return 1; | |
123 if (!aa[a]) return 0; | |
673
c102f31a753e
Missing line in patch -l. Oops.
Rob Landley <rob@landley.net>
parents:
670
diff
changeset
|
124 a++, b++; |
c102f31a753e
Missing line in patch -l. Oops.
Rob Landley <rob@landley.net>
parents:
670
diff
changeset
|
125 } |
670 | 126 } |
127 | |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
128 // Given a hunk of a unified diff, make the appropriate change to the file. |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
129 // This does not use the location information, but instead treats a hunk |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
130 // as a sort of regex. Copies data from input to output until it finds |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
131 // the change to be made, then outputs the changed data and returns. |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
132 // (Finding EOF first is an error.) This is a single pass operation, so |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
133 // multiple hunks must occur in order in the file. |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
134 |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
135 static int apply_one_hunk(void) |
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 struct double_list *plist, *buf = NULL, *check; |
670 | 138 int matcheof = 0, reverse = toys.optflags & FLAG_R, backwarn = 0; |
139 int (*lcmp)(char *aa, char *bb); | |
140 | |
141 lcmp = (toys.optflags & FLAG_l) ? (void *)loosecmp : (void *)strcmp; | |
209 | 142 |
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 // Break doubly linked list so we can use singly linked traversal function. |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
144 TT.current_hunk->prev->next = NULL; |
209 | 145 |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
146 // Match EOF if there aren't as many ending context lines as beginning |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
147 for (plist = TT.current_hunk; plist; plist = plist->next) { |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
148 if (plist->data[0]==' ') matcheof++; |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
149 else matcheof = 0; |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
150 if (PATCH_DEBUG) fprintf(stderr, "HUNK:%s\n", plist->data); |
209 | 151 } |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
152 matcheof = matcheof < TT.context; |
209 | 153 |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
154 if (PATCH_DEBUG) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N'); |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
155 |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
156 // Loop through input data searching for this hunk. Match all context |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
157 // lines and all lines to be removed until we've found the end of a |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
158 // complete hunk. |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
159 plist = TT.current_hunk; |
209 | 160 buf = NULL; |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
161 if (TT.context) for (;;) { |
209 | 162 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
|
163 |
209 | 164 TT.linenum++; |
165 | |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
166 // Figure out which line of hunk to compare with next. (Skip lines |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
167 // 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
|
168 while (plist && *plist->data == "+-"[reverse]) { |
670 | 169 if (data && !lcmp(data, plist->data+1)) { |
391
56d07d82e691
Don't complain about "possibly reversed" hunks that merely moved later in the file, just give a potential reason if it failed to apply.
Rob Landley <rob@landley.net>
parents:
377
diff
changeset
|
170 if (!backwarn) backwarn = TT.linenum; |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
171 } |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
172 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
|
173 } |
209 | 174 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
175 // 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
|
176 if (!data) { |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
177 if (PATCH_DEBUG) fprintf(stderr, "INEOF\n"); |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
178 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
179 // 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
|
180 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
|
181 |
391
56d07d82e691
Don't complain about "possibly reversed" hunks that merely moved later in the file, just give a potential reason if it failed to apply.
Rob Landley <rob@landley.net>
parents:
377
diff
changeset
|
182 if (backwarn) |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
183 fprintf(stderr, "Possibly reversed hunk %d at %ld\n", |
391
56d07d82e691
Don't complain about "possibly reversed" hunks that merely moved later in the file, just give a potential reason if it failed to apply.
Rob Landley <rob@landley.net>
parents:
377
diff
changeset
|
184 TT.hunknum, TT.linenum); |
56d07d82e691
Don't complain about "possibly reversed" hunks that merely moved later in the file, just give a potential reason if it failed to apply.
Rob Landley <rob@landley.net>
parents:
377
diff
changeset
|
185 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
186 // 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
|
187 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
|
188 goto done; |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
189 } else if (PATCH_DEBUG) fprintf(stderr, "IN: %s\n", data); |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
190 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
|
191 |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
192 // Compare this line with next expected line of hunk. |
209 | 193 |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
194 // A match can fail because the next line doesn't match, or because |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
195 // we hit the end of a hunk that needed EOF, and this isn't EOF. |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
196 |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
197 // If match failed, flush first line of buffered data and |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
198 // recheck buffered data for a new match until we find one or run |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
199 // out of buffer. |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
200 |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
201 for (;;) { |
670 | 202 if (!plist || lcmp(check->data, plist->data+1)) { |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
203 // Match failed. Write out first line of buffered data and |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
204 // recheck remaining buffered data for a new match. |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
205 |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
206 if (PATCH_DEBUG) |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
207 fprintf(stderr, "NOT: %s\n", plist->data); |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
208 |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
209 TT.state = 3; |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
210 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
|
211 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
|
212 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
|
213 do_line(check); |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
214 plist = TT.current_hunk; |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
215 |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
216 // If we've reached the end of the buffer without confirming a |
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
217 // match, read more lines. |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
218 if (check==buf) { |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
219 buf = 0; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
220 break; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
221 } |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
222 check = buf; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
223 } else { |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
224 if (PATCH_DEBUG) |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
225 fprintf(stderr, "MAYBE: %s\n", plist->data); |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
226 // 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
|
227 plist = plist->next; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
228 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
|
229 check = check->next; |
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
230 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
|
231 } |
209 | 232 } |
233 } | |
315
aaac01796688
Upgrade patch to detect hunks that start after a false start.
Rob Landley <rob@landley.net>
parents:
280
diff
changeset
|
234 out: |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
235 // We have a match. Emit changed data. |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
236 TT.state = "-+"[reverse]; |
624
1e8b9acdafeb
Genericize llist code a bit: rename llist_free() to llist_traverse(), and no longer accept NULL as a synonym for free.
Rob Landley <rob@landley.net>
parents:
550
diff
changeset
|
237 llist_traverse(TT.current_hunk, do_line); |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
238 TT.current_hunk = NULL; |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
239 TT.state = 1; |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
240 done: |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
241 if (buf) { |
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
242 buf->prev->next = NULL; |
624
1e8b9acdafeb
Genericize llist code a bit: rename llist_free() to llist_traverse(), and no longer accept NULL as a synonym for free.
Rob Landley <rob@landley.net>
parents:
550
diff
changeset
|
243 llist_traverse(buf, do_line); |
216
5697a3f7c8cf
Make patch's file add actually work, including directory creating and
Rob Landley <rob@landley.net>
parents:
214
diff
changeset
|
244 } |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
245 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
246 return TT.state; |
209 | 247 } |
248 | |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
249 // Read a patch file and find hunks, opening/creating/deleting files. |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
250 // Call apply_one_hunk() on each hunk. |
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
251 |
209 | 252 // state 0: Not in a hunk, look for +++. |
253 // state 1: Found +++ file indicator, look for @@ | |
254 // state 2: In hunk: counting initial context lines | |
255 // state 3: In hunk: getting body | |
256 | |
257 void patch_main(void) | |
258 { | |
670 | 259 int reverse = toys.optflags&FLAG_R, state = 0, patchlinenum = 0, |
412
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
260 strip = 0; |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
261 char *oldname = NULL, *newname = NULL; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
262 |
209 | 263 if (TT.infile) TT.filepatch = xopen(TT.infile, O_RDONLY); |
264 TT.filein = TT.fileout = -1; | |
265 | |
266 // Loop through the lines in the patch | |
412
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
267 for (;;) { |
209 | 268 char *patchline; |
269 | |
270 patchline = get_line(TT.filepatch); | |
271 if (!patchline) break; | |
272 | |
351 | 273 // Other versions of patch accept damaged patches, |
274 // so we need to also. | |
412
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
275 if (strip || !patchlinenum++) { |
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
276 int len = strlen(patchline); |
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
277 if (patchline[len-1] == '\r') { |
550
b2194045c40e
Remove "feature test macros", replace non-portable fdprintf() with standard fprintf().
Rob Landley <rob@landley.net>
parents:
500
diff
changeset
|
278 if (!strip) fprintf(stderr, "Removing DOS newlines\n"); |
412
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
279 strip = 1; |
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
280 patchline[len-1]=0; |
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
281 } |
2b521c791e4e
Patch shouldn't be bothered by DOS newlines.
Rob Landley <rob@landley.net>
parents:
391
diff
changeset
|
282 } |
351 | 283 if (!*patchline) { |
284 free(patchline); | |
285 patchline = xstrdup(" "); | |
286 } | |
287 | |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
288 // Are we assembling a hunk? |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
289 if (state >= 2) { |
209 | 290 if (*patchline==' ' || *patchline=='+' || *patchline=='-') { |
362
d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
Rob Landley <rob@landley.net>
parents:
351
diff
changeset
|
291 dlist_add(&TT.current_hunk, patchline); |
209 | 292 |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
293 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
|
294 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
|
295 |
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
296 // Context line? |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
297 if (*patchline==' ' && state==2) TT.context++; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
298 else state=3; |
209 | 299 |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
300 // If we've consumed all expected hunk lines, apply the hunk. |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
301 |
376
35c8beb54800
For CFG_TOYBOX_DEBUG add -x option to patch to dump lots of debug output about the search and match.
Rob Landley <rob@landley.net>
parents:
375
diff
changeset
|
302 if (!TT.oldlen && !TT.newlen) state = apply_one_hunk(); |
209 | 303 continue; |
304 } | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
305 fail_hunk(); |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
306 state = 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
|
307 continue; |
209 | 308 } |
309 | |
310 // Open a new file? | |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
311 if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
312 char *s, **name = &oldname; |
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
|
313 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
|
314 |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
315 if (*patchline == '+') { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
316 name = &newname; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
317 state = 1; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
318 } |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
319 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
320 free(*name); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
321 finish_oldfile(); |
209 | 322 |
323 // Trim date from end of filename (if any). We don't care. | |
324 for (s = patchline+4; *s && *s!='\t'; s++) | |
325 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
|
326 i = atoi(s); |
375
9f4e5e15597c
One more little tweak to patch: unrecognized date format != delete file.
Rob Landley <rob@landley.net>
parents:
362
diff
changeset
|
327 if (i>1900 && i<=1970) |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
328 *name = xstrdup("/dev/null"); |
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
|
329 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
|
330 *s = 0; |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
331 *name = xstrdup(patchline+4); |
335
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
332 } |
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
333 |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
334 // We defer actually opening the file because svn produces broken |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
335 // patches that don't signal they want to create a new file the |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
336 // way the patch man page says, so you have to read the first hunk |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
337 // and _guess_. |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
338 |
377
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
339 // Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@ |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
340 // but a missing ,value means the value is 1. |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
341 } else if (state == 1 && !strncmp("@@ -", patchline, 4)) { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
342 int i; |
377
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
343 char *s = patchline+4; |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
344 |
377
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
345 // Read oldline[,oldlen] +newline[,newlen] |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
346 |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
347 TT.oldlen = TT.newlen = 1; |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
348 TT.oldline = strtol(s, &s, 10); |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
349 if (*s == ',') TT.oldlen=strtol(s+1, &s, 10); |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
350 TT.newline = strtol(s+2, &s, 10); |
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
351 if (*s == ',') TT.newlen = strtol(s+1, &s, 10); |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
352 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
353 TT.context = 0; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
354 state = 2; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
355 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
356 // If this is the first hunk, open the file. |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
357 if (TT.filein == -1) { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
358 int oldsum, newsum, del = 0; |
377
15ca7e49b6ff
The @@ -1,2 +3,4 @@ lines treat ,1 as implied, so the format isn't regular.
Rob Landley <rob@landley.net>
parents:
376
diff
changeset
|
359 char *name; |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
360 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
361 oldsum = TT.oldline + TT.oldlen; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
362 newsum = TT.newline + TT.newlen; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
363 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
364 name = reverse ? oldname : newname; |
335
556c10abdff6
Make patch work with -R when deleting files.
Rob Landley <rob@landley.net>
parents:
331
diff
changeset
|
365 |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
366 // We're deleting oldname if new file is /dev/null (before -p) |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
367 // or if new hunk is empty (zero context) after patching |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
368 if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
369 { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
370 name = reverse ? newname : oldname; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
371 del++; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
372 } |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
373 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
374 // handle -p path truncation. |
500
cd70270dbc51
Teach patch -p that consecutive /// counts as one path component.
Rob Landley <rob@landley.net>
parents:
412
diff
changeset
|
375 for (i = 0, s = name; *s;) { |
670 | 376 if ((toys.optflags & FLAG_p) && TT.prefix == i) break; |
500
cd70270dbc51
Teach patch -p that consecutive /// counts as one path component.
Rob Landley <rob@landley.net>
parents:
412
diff
changeset
|
377 if (*s++ != '/') continue; |
cd70270dbc51
Teach patch -p that consecutive /// counts as one path component.
Rob Landley <rob@landley.net>
parents:
412
diff
changeset
|
378 while (*s == '/') s++; |
cd70270dbc51
Teach patch -p that consecutive /// counts as one path component.
Rob Landley <rob@landley.net>
parents:
412
diff
changeset
|
379 name = s; |
cd70270dbc51
Teach patch -p that consecutive /// counts as one path component.
Rob Landley <rob@landley.net>
parents:
412
diff
changeset
|
380 i++; |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
381 } |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
382 |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
383 if (del) { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
384 printf("removing %s\n", name); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
385 xunlink(name); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
386 state = 0; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
387 // If we've got a file to open, do so. |
670 | 388 } else if (!(toys.optflags & FLAG_p) || i <= TT.prefix) { |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
389 // If the old file was null, we're creating a new one. |
688
9791e462855a
Fix reversed test: patch creates a file if /dev/null or dated the epoch _and_ first hunk being replaced is 0 lines at start of file, not one or the other.
Rob Landley <rob@landley.net>
parents:
674
diff
changeset
|
390 if (!strcmp(oldname, "/dev/null") && !oldsum) { |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
391 printf("creating %s\n", name); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
392 s = strrchr(name, '/'); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
393 if (s) { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
394 *s = 0; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
395 xmkpath(name, -1); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
396 *s = '/'; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
397 } |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
398 TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
399 } else { |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
400 printf("patching %s\n", name); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
401 TT.filein = xopen(name, O_RDWR); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
402 } |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
403 TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
404 TT.linenum = 0; |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
405 TT.hunknum = 0; |
209 | 406 } |
407 } | |
408 | |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
409 TT.hunknum++; |
209 | 410 |
411 continue; | |
412 } | |
413 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
414 // If we didn't continue above, discard this line. |
209 | 415 free(patchline); |
416 } | |
417 | |
219
cfa11e043e2b
Fix patch to use @@ values and match EOF when fewer trailing than starting
Rob Landley <rob@landley.net>
parents:
216
diff
changeset
|
418 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
|
419 |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
420 if (CFG_TOYBOX_FREE) { |
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
421 close(TT.filepatch); |
348
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
422 free(oldname); |
c7143968cea6
Rearchitect patch to handle more darn corner cases.
Rob Landley <rob@landley.net>
parents:
335
diff
changeset
|
423 free(newname); |
214
98820d1eaa79
Upgrade patch to understand creating and deleting files.
Rob Landley <rob@landley.net>
parents:
209
diff
changeset
|
424 } |
209 | 425 } |