aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editors/patch.c35
-rw-r--r--include/usage.h15
-rwxr-xr-xtestsuite/patch.tests47
3 files changed, 82 insertions, 15 deletions
diff --git a/editors/patch.c b/editors/patch.c
index 4a9715144..580ee147c 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -78,12 +78,23 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
78 enum { 78 enum {
79 OPT_R = (1 << 2), 79 OPT_R = (1 << 2),
80 OPT_N = (1 << 3), 80 OPT_N = (1 << 3),
81 OPT_dry_run = (1 << 4) * ENABLE_LONG_OPTS,
81 }; 82 };
82 83
83 xfunc_error_retval = 2; 84 xfunc_error_retval = 2;
84 { 85 {
85 const char *p = "-1"; 86 const char *p = "-1";
86 const char *i = "-"; /* compat */ 87 const char *i = "-"; /* compat */
88#if ENABLE_LONG_OPTS
89 static const char patch_longopts[] ALIGN1 =
90 "strip\0" Required_argument "p"
91 "input\0" Required_argument "i"
92 "reverse\0" No_argument "R"
93 "forward\0" No_argument "N"
94 "dry-run\0" No_argument "\xff"
95 ;
96 applet_long_options = patch_longopts;
97#endif
87 opt = getopt32(argv, "p:i:RN", &p, &i); 98 opt = getopt32(argv, "p:i:RN", &p, &i);
88 if (opt & OPT_R) 99 if (opt & OPT_R)
89 plus = '-'; 100 plus = '-';
@@ -97,7 +108,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
97 FILE *dst_stream; 108 FILE *dst_stream;
98 //char *old_filename; 109 //char *old_filename;
99 char *new_filename; 110 char *new_filename;
100 char *backup_filename; 111 char *backup_filename = NULL;
101 unsigned src_cur_line = 1; 112 unsigned src_cur_line = 1;
102 unsigned dst_cur_line = 0; 113 unsigned dst_cur_line = 0;
103 unsigned dst_beg_line; 114 unsigned dst_beg_line;
@@ -131,16 +142,21 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
131 bb_make_directory(new_filename, -1, FILEUTILS_RECUR); 142 bb_make_directory(new_filename, -1, FILEUTILS_RECUR);
132 *slash = '/'; 143 *slash = '/';
133 } 144 }
134 backup_filename = NULL;
135 src_stream = NULL; 145 src_stream = NULL;
136 saved_stat.st_mode = 0644; 146 saved_stat.st_mode = 0644;
137 } else { 147 } else if (!(opt & OPT_dry_run)) {
138 backup_filename = xasprintf("%s.orig", new_filename); 148 backup_filename = xasprintf("%s.orig", new_filename);
139 xrename(new_filename, backup_filename); 149 xrename(new_filename, backup_filename);
140 src_stream = xfopen_for_read(backup_filename); 150 src_stream = xfopen_for_read(backup_filename);
151 } else
152 src_stream = xfopen_for_read(new_filename);
153
154 if (opt & OPT_dry_run) {
155 dst_stream = xfopen_for_write("/dev/null");
156 } else {
157 dst_stream = xfopen_for_write(new_filename);
158 fchmod(fileno(dst_stream), saved_stat.st_mode);
141 } 159 }
142 dst_stream = xfopen_for_write(new_filename);
143 fchmod(fileno(dst_stream), saved_stat.st_mode);
144 160
145 printf("patching file %s\n", new_filename); 161 printf("patching file %s\n", new_filename);
146 162
@@ -189,6 +205,11 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
189 patch_line = xmalloc_fgets(patch_file); 205 patch_line = xmalloc_fgets(patch_file);
190 if (patch_line == NULL) 206 if (patch_line == NULL)
191 break; /* EOF */ 207 break; /* EOF */
208 if (!*patch_line) {
209 /* whitespace-damaged patch with "" lines */
210 free(patch_line);
211 patch_line = xstrdup(" ");
212 }
192 if ((*patch_line != '-') && (*patch_line != '+') 213 if ((*patch_line != '-') && (*patch_line != '+')
193 && (*patch_line != ' ') 214 && (*patch_line != ' ')
194 ) { 215 ) {
@@ -244,7 +265,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
244 if (backup_filename) { 265 if (backup_filename) {
245 unlink(backup_filename); 266 unlink(backup_filename);
246 } 267 }
247 if ((dst_cur_line == 0) || (dst_beg_line == 0)) { 268 if (!(opt & OPT_dry_run)
269 && ((dst_cur_line == 0) || (dst_beg_line == 0))
270 ) {
248 /* The new patched file is empty, remove it */ 271 /* The new patched file is empty, remove it */
249 xunlink(new_filename); 272 xunlink(new_filename);
250 // /* old_filename and new_filename may be the same file */ 273 // /* old_filename and new_filename may be the same file */
diff --git a/include/usage.h b/include/usage.h
index d03ec2295..85561c558 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -898,7 +898,7 @@
898 "\n -d Daemonize" \ 898 "\n -d Daemonize" \
899 899
900#define dos2unix_trivial_usage \ 900#define dos2unix_trivial_usage \
901 "[OPTION] [FILE]" 901 "[OPTIONS] [FILE]"
902#define dos2unix_full_usage "\n\n" \ 902#define dos2unix_full_usage "\n\n" \
903 "Convert FILE in-place from DOS to Unix format.\n" \ 903 "Convert FILE in-place from DOS to Unix format.\n" \
904 "When no file is given, use stdin/stdout.\n" \ 904 "When no file is given, use stdin/stdout.\n" \
@@ -907,7 +907,7 @@
907 "\n -d unix2dos" \ 907 "\n -d unix2dos" \
908 908
909#define unix2dos_trivial_usage \ 909#define unix2dos_trivial_usage \
910 "[OPTION] [FILE]" 910 "[OPTIONS] [FILE]"
911#define unix2dos_full_usage "\n\n" \ 911#define unix2dos_full_usage "\n\n" \
912 "Convert FILE in-place from Unix to DOS format.\n" \ 912 "Convert FILE in-place from Unix to DOS format.\n" \
913 "When no file is given, use stdin/stdout.\n" \ 913 "When no file is given, use stdin/stdout.\n" \
@@ -3250,12 +3250,21 @@
3250 ) 3250 )
3251 3251
3252#define patch_trivial_usage \ 3252#define patch_trivial_usage \
3253 "[-p NUM] [-i DIFF] [-R] [-N]" 3253 "[OPTIONS] [ORIGFILE [PATCHFILE]]"
3254#define patch_full_usage "\n\n" \ 3254#define patch_full_usage "\n\n" \
3255 IF_LONG_OPTS( \
3256 " -p,--strip NUM Strip NUM leading components from file names" \
3257 "\n -i,--input DIFF Read DIFF instead of stdin" \
3258 "\n -R,--reverse Reverse patch" \
3259 "\n -N,--forward Ignore already applied patches" \
3260 "\n --dry-run Don't actually change files" \
3261 ) \
3262 IF_NOT_LONG_OPTS( \
3255 " -p NUM Strip NUM leading components from file names" \ 3263 " -p NUM Strip NUM leading components from file names" \
3256 "\n -i DIFF Read DIFF instead of stdin" \ 3264 "\n -i DIFF Read DIFF instead of stdin" \
3257 "\n -R Reverse patch" \ 3265 "\n -R Reverse patch" \
3258 "\n -N Ignore already applied patches" \ 3266 "\n -N Ignore already applied patches" \
3267 )
3259 3268
3260#define patch_example_usage \ 3269#define patch_example_usage \
3261 "$ patch -p1 < example.diff\n" \ 3270 "$ patch -p1 < example.diff\n" \
diff --git a/testsuite/patch.tests b/testsuite/patch.tests
index cfe69b76a..178048d2a 100755
--- a/testsuite/patch.tests
+++ b/testsuite/patch.tests
@@ -7,7 +7,7 @@
7# testing "test name" "options" "expected result" "file input" "stdin" 7# testing "test name" "options" "expected result" "file input" "stdin"
8 8
9testing "patch with old_file == new_file" \ 9testing "patch with old_file == new_file" \
10 "patch; echo $?; cat input" \ 10 'patch; echo $?; cat input' \
11"\ 11"\
12patching file input 12patching file input
130 130
@@ -15,7 +15,10 @@ qwe
15asd 15asd
16zxc 16zxc
17" \ 17" \
18 "qwe\nzxc\n" \ 18"\
19qwe
20zxc
21" \
19"\ 22"\
20--- input Jan 01 01:01:01 2000 23--- input Jan 01 01:01:01 2000
21+++ input Jan 01 01:01:01 2000 24+++ input Jan 01 01:01:01 2000
@@ -26,7 +29,7 @@ zxc
26" \ 29" \
27 30
28testing "patch with nonexistent old_file" \ 31testing "patch with nonexistent old_file" \
29 "patch; echo $?; cat input" \ 32 'patch; echo $?; cat input' \
30"\ 33"\
31patching file input 34patching file input
320 350
@@ -34,7 +37,10 @@ qwe
34asd 37asd
35zxc 38zxc
36" \ 39" \
37 "qwe\nzxc\n" \ 40"\
41qwe
42zxc
43" \
38"\ 44"\
39--- input.doesnt_exist Jan 01 01:01:01 2000 45--- input.doesnt_exist Jan 01 01:01:01 2000
40+++ input Jan 01 01:01:01 2000 46+++ input Jan 01 01:01:01 2000
@@ -45,14 +51,18 @@ zxc
45" \ 51" \
46 52
47testing "patch -R with nonexistent old_file" \ 53testing "patch -R with nonexistent old_file" \
48 "patch -R; echo $?; cat input" \ 54 'patch -R; echo $?; cat input' \
49"\ 55"\
50patching file input 56patching file input
510 570
52qwe 58qwe
53zxc 59zxc
54" \ 60" \
55 "qwe\nasd\nzxc\n" \ 61"\
62qwe
63asd
64zxc
65" \
56"\ 66"\
57--- input.doesnt_exist Jan 01 01:01:01 2000 67--- input.doesnt_exist Jan 01 01:01:01 2000
58+++ input Jan 01 01:01:01 2000 68+++ input Jan 01 01:01:01 2000
@@ -62,4 +72,29 @@ zxc
62 zxc 72 zxc
63" \ 73" \
64 74
75testing "patch detects already applied hunk" \
76 'patch 2>&1; echo $?; cat input' \
77"\
78patching file input
79patch: hunk #1 FAILED at 1
80patch: 1 out of 1 hunk FAILED
811
82abc
83def
84123
85" \
86"\
87abc
88def
89123
90" \
91"\
92--- input.old Jan 01 01:01:01 2000
93+++ input Jan 01 01:01:01 2000
94@@ -1,2 +1,3 @@
95 abc
96+def
97 123
98" \
99
65exit $FAILCOUNT 100exit $FAILCOUNT