diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-24 18:18:03 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-24 18:18:03 +0000 |
commit | 64a76d7b447eeaf2a50606c04f87cec8ef535efb (patch) | |
tree | dc3d21b070c99fe9043b4259f27cec4e6ae2f308 | |
parent | c4c2cd44d2befc5c1153cd54e1ceb93b88fee243 (diff) | |
download | busybox-w32-64a76d7b447eeaf2a50606c04f87cec8ef535efb.tar.gz busybox-w32-64a76d7b447eeaf2a50606c04f87cec8ef535efb.tar.bz2 busybox-w32-64a76d7b447eeaf2a50606c04f87cec8ef535efb.zip |
patch: support for patches without dates and generated with -U1; shrink
function old new delta
extract_filename - 92 +92
extract_filename_and_free_line 70 - -70
patch_main 1096 1009 -87
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 0/1 up/down: 92/-157) Total: -65 bytes
-rw-r--r-- | editors/patch.c | 136 |
1 files changed, 67 insertions, 69 deletions
diff --git a/editors/patch.c b/editors/patch.c index e0fb58f87..7b391603d 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -44,23 +44,23 @@ static unsigned copy_lines(FILE *src_stream, FILE *dest_stream, unsigned lines_c | |||
44 | * returns malloc'ed filename | 44 | * returns malloc'ed filename |
45 | * NB: frees 1st argument! | 45 | * NB: frees 1st argument! |
46 | */ | 46 | */ |
47 | static char *extract_filename_and_free_line(char *line, int patch_level) | 47 | static char *extract_filename(char *line, int patch_level, const char *pat) |
48 | { | 48 | { |
49 | char *temp, *filename_start_ptr = line + 4; | 49 | char *temp = NULL, *filename_start_ptr = line + 4; |
50 | 50 | ||
51 | /* Terminate string at end of source filename */ | 51 | if (strncmp(line, pat, 4) == 0) { |
52 | temp = strchrnul(filename_start_ptr, '\t'); | 52 | /* Terminate string at end of source filename */ |
53 | *temp = '\0'; | 53 | line[strcspn(line,"\t\n\r")] = '\0'; |
54 | 54 | ||
55 | /* Skip over (patch_level) number of leading directories */ | 55 | /* Skip over (patch_level) number of leading directories */ |
56 | while (patch_level--) { | 56 | while (patch_level--) { |
57 | temp = strchr(filename_start_ptr, '/'); | 57 | temp = strchr(filename_start_ptr, '/'); |
58 | if (!temp) | 58 | if (!temp) |
59 | break; | 59 | break; |
60 | filename_start_ptr = temp + 1; | 60 | filename_start_ptr = temp + 1; |
61 | } | ||
62 | temp = xstrdup(filename_start_ptr); | ||
61 | } | 63 | } |
62 | |||
63 | temp = xstrdup(filename_start_ptr); | ||
64 | free(line); | 64 | free(line); |
65 | return temp; | 65 | return temp; |
66 | } | 66 | } |
@@ -100,30 +100,26 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
100 | /* Skip everything upto the "---" marker | 100 | /* Skip everything upto the "---" marker |
101 | * No need to parse the lines "Only in <dir>", and "diff <args>" | 101 | * No need to parse the lines "Only in <dir>", and "diff <args>" |
102 | */ | 102 | */ |
103 | while (strncmp(patch_line, "--- ", 4) != 0) { | 103 | do { |
104 | free(patch_line); | 104 | /* Extract the filename used before the patch was generated */ |
105 | original_filename = extract_filename(patch_line, patch_level, "--- "); | ||
105 | patch_line = xmalloc_getline(patch_file); | 106 | patch_line = xmalloc_getline(patch_file); |
106 | if (!patch_line) | 107 | if (!patch_line) goto quit; |
107 | bb_error_msg_and_die("invalid patch"); | 108 | } while (!original_filename); |
108 | } | ||
109 | |||
110 | /* Extract the filename used before the patch was generated */ | ||
111 | original_filename = extract_filename_and_free_line(patch_line, patch_level); | ||
112 | 109 | ||
113 | patch_line = xmalloc_getline(patch_file); | 110 | new_filename = extract_filename(patch_line, patch_level, "+++ "); |
114 | if (!patch_line || strncmp(patch_line, "+++ ", 4) != 0) | 111 | if (!new_filename) { |
115 | bb_error_msg_and_die("invalid patch"); | 112 | bb_error_msg_and_die("invalid patch"); |
116 | new_filename = extract_filename_and_free_line(patch_line, patch_level); | 113 | } |
117 | 114 | ||
118 | /* Get access rights from the file to be patched, -1 file does not exist */ | 115 | /* Get access rights from the file to be patched */ |
119 | if (stat(new_filename, &saved_stat) != 0) { | 116 | if (stat(new_filename, &saved_stat) != 0) { |
120 | char *line_ptr; | 117 | char *slash = strrchr(new_filename, '/'); |
121 | /* Create leading directories */ | 118 | if (slash) { |
122 | line_ptr = strrchr(new_filename, '/'); | 119 | /* Create leading directories */ |
123 | if (line_ptr) { | 120 | *slash = '\0'; |
124 | *line_ptr = '\0'; | ||
125 | bb_make_directory(new_filename, -1, FILEUTILS_RECUR); | 121 | bb_make_directory(new_filename, -1, FILEUTILS_RECUR); |
126 | *line_ptr = '/'; | 122 | *slash = '/'; |
127 | } | 123 | } |
128 | backup_filename = NULL; | 124 | backup_filename = NULL; |
129 | saved_stat.st_mode = 0644; | 125 | saved_stat.st_mode = 0644; |
@@ -134,10 +130,16 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
134 | dst_stream = xfopen(new_filename, "w"); | 130 | dst_stream = xfopen(new_filename, "w"); |
135 | fchmod(fileno(dst_stream), saved_stat.st_mode); | 131 | fchmod(fileno(dst_stream), saved_stat.st_mode); |
136 | src_stream = NULL; | 132 | src_stream = NULL; |
137 | 133 | if (backup_filename && stat(original_filename, &saved_stat) == 0) { | |
138 | if (backup_filename && !stat(original_filename, &saved_stat)) { | 134 | // strcmp() is never 0! Otherwise: |
139 | src_stream = xfopen((strcmp(original_filename, new_filename)) ? | 135 | // original_filename == new_filename, |
140 | original_filename : backup_filename, "r"); | 136 | // stat(original_filename) == stat(new_filename), |
137 | // stat(new_filename) == 0, | ||
138 | // but we renamed new_filename if it existed! | ||
139 | // stat() must fail! | ||
140 | //src_stream = xfopen((strcmp(original_filename, new_filename)) ? | ||
141 | // original_filename : backup_filename, "r"); | ||
142 | src_stream = xfopen(original_filename, "r"); | ||
141 | } | 143 | } |
142 | 144 | ||
143 | printf("patching file %s\n", new_filename); | 145 | printf("patching file %s\n", new_filename); |
@@ -147,16 +149,12 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
147 | while (patch_line) { | 149 | while (patch_line) { |
148 | unsigned count; | 150 | unsigned count; |
149 | unsigned src_beg_line; | 151 | unsigned src_beg_line; |
150 | unsigned unused; | 152 | unsigned hunk_offset_start; |
151 | unsigned hunk_offset_start = 0; | 153 | unsigned src_last_line = 1; |
152 | smallint hunk_error = 0; | 154 | |
153 | 155 | if ((sscanf(patch_line, "@@ -%d,%d +%d", &src_beg_line, &src_last_line, &dest_beg_line) != 3) | |
154 | /* This bit should be improved */ | 156 | && (sscanf(patch_line, "@@ -%d +%d", &src_beg_line, &dest_beg_line) != 2) |
155 | if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, &unused, &dest_beg_line, &unused) != 4) | 157 | ) { /* No more hunks for this file */ |
156 | && (sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, &unused, &dest_beg_line) != 3) | ||
157 | && (sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, &dest_beg_line, &unused) != 3) | ||
158 | ) { | ||
159 | /* No more hunks for this file */ | ||
160 | break; | 158 | break; |
161 | } | 159 | } |
162 | hunk_count++; | 160 | hunk_count++; |
@@ -172,14 +170,22 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
172 | dest_cur_line += count; | 170 | dest_cur_line += count; |
173 | copy_trailing_lines_flag = 1; | 171 | copy_trailing_lines_flag = 1; |
174 | } | 172 | } |
175 | hunk_offset_start = src_cur_line; | 173 | src_last_line += hunk_offset_start = src_cur_line; |
176 | 174 | ||
177 | while (1) { | 175 | while (1) { |
178 | free(patch_line); | 176 | free(patch_line); |
179 | patch_line = xmalloc_fgets(patch_file); | 177 | patch_line = xmalloc_fgets(patch_file); |
180 | if (patch_line == NULL) break; | 178 | if (patch_line == NULL) |
181 | if ((*patch_line == '-') || (*patch_line == ' ')) { | 179 | break; /* EOF */ |
180 | if ((*patch_line != '-') && (*patch_line != '+') | ||
181 | && (*patch_line != ' ') | ||
182 | ) { | ||
183 | break; /* End of hunk */ | ||
184 | } | ||
185 | if (*patch_line != '+') { /* '-', ' ' or '\n' */ | ||
182 | char *src_line = NULL; | 186 | char *src_line = NULL; |
187 | if (src_cur_line == src_last_line) | ||
188 | break; | ||
183 | if (src_stream) { | 189 | if (src_stream) { |
184 | src_line = xmalloc_fgets(src_stream); | 190 | src_line = xmalloc_fgets(src_stream); |
185 | if (src_line) { | 191 | if (src_line) { |
@@ -188,26 +194,19 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
188 | free(src_line); | 194 | free(src_line); |
189 | if (diff) src_line = NULL; | 195 | if (diff) src_line = NULL; |
190 | } | 196 | } |
191 | if (!src_line) { | ||
192 | bb_error_msg("hunk #%d FAILED at %d", hunk_count, hunk_offset_start); | ||
193 | hunk_error = 1; | ||
194 | break; | ||
195 | } | ||
196 | } | 197 | } |
197 | if (*patch_line == ' ') { | 198 | if (!src_line) { |
198 | fputs(patch_line + 1, dst_stream); | 199 | bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start); |
199 | dest_cur_line++; | 200 | bad_hunk_count++; |
201 | break; | ||
202 | } | ||
203 | if (*patch_line == '-') { | ||
204 | continue; | ||
200 | } | 205 | } |
201 | } else if (*patch_line == '+') { | ||
202 | fputs(patch_line + 1, dst_stream); | ||
203 | dest_cur_line++; | ||
204 | } else { | ||
205 | break; | ||
206 | } | 206 | } |
207 | fputs(patch_line + 1, dst_stream); | ||
208 | dest_cur_line++; | ||
207 | } /* end of while loop handling one hunk */ | 209 | } /* end of while loop handling one hunk */ |
208 | if (hunk_error) { | ||
209 | bad_hunk_count++; | ||
210 | } | ||
211 | } /* end of while loop handling one file */ | 210 | } /* end of while loop handling one file */ |
212 | 211 | ||
213 | /* Cleanup last patched file */ | 212 | /* Cleanup last patched file */ |
@@ -217,9 +216,7 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
217 | if (src_stream) { | 216 | if (src_stream) { |
218 | fclose(src_stream); | 217 | fclose(src_stream); |
219 | } | 218 | } |
220 | if (dst_stream) { | 219 | fclose(dst_stream); |
221 | fclose(dst_stream); | ||
222 | } | ||
223 | if (bad_hunk_count) { | 220 | if (bad_hunk_count) { |
224 | ret = 1; | 221 | ret = 1; |
225 | bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); | 222 | bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count); |
@@ -232,11 +229,12 @@ int patch_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
232 | if ((dest_cur_line == 0) || (dest_beg_line == 0)) { | 229 | if ((dest_cur_line == 0) || (dest_beg_line == 0)) { |
233 | /* The new patched file is empty, remove it */ | 230 | /* The new patched file is empty, remove it */ |
234 | xunlink(new_filename); | 231 | xunlink(new_filename); |
235 | if (strcmp(new_filename, original_filename) != 0) | 232 | /* original_filename and new_filename may be the same file */ |
236 | xunlink(original_filename); | 233 | unlink(original_filename); |
237 | } | 234 | } |
238 | } | 235 | } |
239 | } /* end of "while there are patch lines" */ | 236 | } /* end of "while there are patch lines" */ |
237 | quit: | ||
240 | 238 | ||
241 | /* 0 = SUCCESS | 239 | /* 0 = SUCCESS |
242 | * 1 = Some hunks failed | 240 | * 1 = Some hunks failed |