Hi,
I was having trouble with our patch.
It didn't warn about previously applied hunks, like:
$ dmesg | tail | tee mess > mess.orig
$ echo new line >> mess
$ diff -u mess.orig mess > xxx
$ #NOT mv mess.orig mess
$ patch -i xxx
There is -N to allow to skip them (complaining loud).
And we didn't have --dry-run.
I've picked the short-option -z for --dry-run out of the blue to
facilitate !getopt_long usage of patch.
A few points though:
- The size increase is absolutely intolerable.
(rephrase hunk handling)
- for --dry-run we should just not write anything to dst_stream
and get rid of any temporary file in due course.
I currently don't have more time for patch, so it would be great if
somebody steps up and either applies it as a fix in it's current state
or look a bit into it before committing it.
thanks,
diff --git a/editors/patch.c b/editors/patch.c
index 4a97151..226096a 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -75,16 +75,27 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
int ret = 0;
char plus = '+';
unsigned opt;
+#if ENABLE_LONG_OPTS
+static const char patch_longopts[] ALIGN1 =
+ "strip\0" Required_argument "p"
+ "input\0" Required_argument "i"
+ "reverse\0" No_argument "R"
+ "forward\0" No_argument "N"
+ "dry-run\0" No_argument "z"
+ ;
+#endif
enum {
OPT_R = (1 << 2),
OPT_N = (1 << 3),
+ OPT_dry_run = (1 << 4),
};
xfunc_error_retval = 2;
{
const char *p = "-1";
const char *i = "-"; /* compat */
- opt = getopt32(argv, "p:i:RN", &p, &i);
+ IF_LONG_OPTS(applet_long_options = patch_longopts;)
+ opt = getopt32(argv, "p:i:RNz", &p, &i);
if (opt & OPT_R)
plus = '-';
patch_level = xatoi(p); /* can be negative! */
@@ -97,7 +108,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
FILE *dst_stream;
//char *old_filename;
char *new_filename;
- char *backup_filename;
+ char *backup_filename = NULL;
unsigned src_cur_line = 1;
unsigned dst_cur_line = 0;
unsigned dst_beg_line;
@@ -131,15 +142,20 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
bb_make_directory(new_filename, -1, FILEUTILS_RECUR);
*slash = '/';
}
- backup_filename = NULL;
src_stream = NULL;
saved_stat.st_mode = 0644;
- } else {
+ } else if (!(opt & OPT_dry_run)) {
backup_filename = xasprintf("%s.orig", new_filename);
xrename(new_filename, backup_filename);
src_stream = xfopen_for_read(backup_filename);
- }
- dst_stream = xfopen_for_write(new_filename);
+ } else
+ src_stream = xfopen_for_read(new_filename);
+ if (opt & OPT_dry_run) {
+ backup_filename = xasprintf("/tmp/.%s", basename(new_filename));//FIXME: tidy up
+ copy_file(new_filename, backup_filename, 0);
+ dst_stream = xfopen_for_write(backup_filename);
+ } else
+ dst_stream = xfopen_for_write(new_filename);
fchmod(fileno(dst_stream), saved_stat.st_mode);
printf("patching file %s\n", new_filename);
@@ -152,6 +168,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
unsigned hunk_offset_start;
unsigned src_last_line = 1;
unsigned dst_last_line = 1;
+ char *src_line = NULL;
if ((sscanf(patch_line, "@@ -%d,%d +%d,%d", &src_beg_line, &src_last_line, &dst_beg_line, &dst_last_line) < 3)
&& (sscanf(patch_line, "@@ -%d +%d,%d", &src_beg_line, &dst_beg_line, &dst_last_line) < 2)
@@ -187,39 +204,44 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
while (1) {
free(patch_line);
patch_line = xmalloc_fgets(patch_file);
- if (patch_line == NULL)
- break; /* EOF */
- if ((*patch_line != '-') && (*patch_line != '+')
- && (*patch_line != ' ')
- ) {
- break; /* End of hunk */
- }
- if (*patch_line != plus) { /* '-' or ' ' */
- char *src_line = NULL;
- if (src_cur_line == src_last_line)
- break;
- if (src_stream) {
- src_line = xmalloc_fgets(src_stream);
- if (src_line) {
+ if (patch_line == NULL || (*patch_line != '+'
+ && *patch_line != '-' && *patch_line != ' '))
+ break; /* EOF or End of hunk */
+ if (src_stream && !src_line) {
+ src_line = xmalloc_fgets(src_stream);
+ if (src_line) {
+ src_cur_line++;
+ if (*patch_line != plus) {
int diff = strcmp(src_line, patch_line + 1);
- src_cur_line++;
free(src_line);
if (diff)
src_line = NULL;
}
}
- /* Do not patch an already patched hunk with -N */
- if (src_line == 0 && (opt & OPT_N)) {
+ }
+ if (*patch_line != plus && !src_line) {
+ bb_error_msg("hunk #%u FAILED at %u",
+ hunk_count, hunk_offset_start);
+ bad_hunk:
+ bad_hunk_count++;
+ break;
+ }
+ if (src_cur_line > src_last_line) {
+ static char msg[] =
+ "Reversed (or previously applied) "
+ "hunk #%u at %u detected! Skipping.";
+ if (opt & OPT_N) {
+ bb_error_msg(msg, hunk_count, hunk_offset_start);
continue;
}
- if (!src_line) {
- bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start);
- bad_hunk_count++;
- break;
- }
- if (*patch_line != ' ') { /* '-' */
+ msg[57] = '\0';
+ bb_error_msg(msg, hunk_count, hunk_offset_start);
+ goto bad_hunk;
+ }
+ if (*patch_line != plus) {
+ src_line = NULL;
+ if (*patch_line != ' ') /* '-' */
continue;
- }
}
if (dst_cur_line == dst_last_line)
break;
@@ -244,7 +266,8 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
if (backup_filename) {
unlink(backup_filename);
}
- if ((dst_cur_line == 0) || (dst_beg_line == 0)) {
+ if (!(opt & OPT_dry_run)
+ && ((dst_cur_line == 0) || (dst_beg_line == 0))) {
/* The new patched file is empty, remove it */
xunlink(new_filename);
// /* old_filename and new_filename may be the same file */
diff --git a/include/usage.h b/include/usage.h
index 8316c43..05cbb50 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -3240,12 +3240,22 @@
)
#define patch_trivial_usage \
- "[-p NUM] [-i DIFF] [-R] [-N]"
+ "[OPTION]... [ORIGFILE [PATCHFILE]]"
#define patch_full_usage "\n\n" \
+ IF_LONG_OPTS( \
+ " -p,--strip NUM Strip NUM leading components from file names" \
+ "\n -i,--input DIFF Read DIFF instead of stdin" \
+ "\n -R,--reverse Reverse patch" \
+ "\n -N,--forward Ignore already applied patches" \
+ "\n -z,--dry-run Don't actually change files" \
+ ) \
+ IF_NOT_LONG_OPTS( \
" -p NUM Strip NUM leading components from file names" \
"\n -i DIFF Read DIFF instead of stdin" \
"\n -R Reverse patch" \
"\n -N Ignore already applied patches" \
+ "\n -z Dry run, don't actually change files" \
+ )
#define patch_example_usage \
"$ patch -p1 < example.diff\n" \
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox