enum {
OPT_R = (1 << 2),
OPT_N = (1 << 3),
+ OPT_dry_run = (1 << 4) * ENABLE_LONG_OPTS,
};
xfunc_error_retval = 2;
{
const char *p = "-1";
const char *i = "-"; /* compat */
+#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 "\xff"
+ ;
+ applet_long_options = patch_longopts;
+#endif
opt = getopt32(argv, "p:i:RN", &p, &i);
if (opt & OPT_R)
plus = '-';
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;
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);
+ } else
+ src_stream = xfopen_for_read(new_filename);
+
+ if (opt & OPT_dry_run) {
+ dst_stream = xfopen_for_write("/dev/null");
+ } else {
+ dst_stream = xfopen_for_write(new_filename);
+ fchmod(fileno(dst_stream), saved_stat.st_mode);
}
- dst_stream = xfopen_for_write(new_filename);
- fchmod(fileno(dst_stream), saved_stat.st_mode);
printf("patching file %s\n", new_filename);
patch_line = xmalloc_fgets(patch_file);
if (patch_line == NULL)
break; /* EOF */
+ if (!*patch_line) {
+ /* whitespace-damaged patch with "" lines */
+ free(patch_line);
+ patch_line = xstrdup(" ");
+ }
if ((*patch_line != '-') && (*patch_line != '+')
&& (*patch_line != ' ')
) {
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 */
"\n -d Daemonize" \
#define dos2unix_trivial_usage \
- "[OPTION] [FILE]"
+ "[OPTIONS] [FILE]"
#define dos2unix_full_usage "\n\n" \
"Convert FILE in-place from DOS to Unix format.\n" \
"When no file is given, use stdin/stdout.\n" \
"\n -d unix2dos" \
#define unix2dos_trivial_usage \
- "[OPTION] [FILE]"
+ "[OPTIONS] [FILE]"
#define unix2dos_full_usage "\n\n" \
"Convert FILE in-place from Unix to DOS format.\n" \
"When no file is given, use stdin/stdout.\n" \
)
#define patch_trivial_usage \
- "[-p NUM] [-i DIFF] [-R] [-N]"
+ "[OPTIONS] [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 --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" \
+ )
#define patch_example_usage \
"$ patch -p1 < example.diff\n" \
# testing "test name" "options" "expected result" "file input" "stdin"
testing "patch with old_file == new_file" \
- "patch; echo $?; cat input" \
+ 'patch; echo $?; cat input' \
"\
patching file input
0
asd
zxc
" \
- "qwe\nzxc\n" \
+"\
+qwe
+zxc
+" \
"\
--- input Jan 01 01:01:01 2000
+++ input Jan 01 01:01:01 2000
" \
testing "patch with nonexistent old_file" \
- "patch; echo $?; cat input" \
+ 'patch; echo $?; cat input' \
"\
patching file input
0
asd
zxc
" \
- "qwe\nzxc\n" \
+"\
+qwe
+zxc
+" \
"\
--- input.doesnt_exist Jan 01 01:01:01 2000
+++ input Jan 01 01:01:01 2000
" \
testing "patch -R with nonexistent old_file" \
- "patch -R; echo $?; cat input" \
+ 'patch -R; echo $?; cat input' \
"\
patching file input
0
qwe
zxc
" \
- "qwe\nasd\nzxc\n" \
+"\
+qwe
+asd
+zxc
+" \
"\
--- input.doesnt_exist Jan 01 01:01:01 2000
+++ input Jan 01 01:01:01 2000
zxc
" \
+testing "patch detects already applied hunk" \
+ 'patch 2>&1; echo $?; cat input' \
+"\
+patching file input
+patch: hunk #1 FAILED at 1
+patch: 1 out of 1 hunk FAILED
+1
+abc
+def
+123
+" \
+"\
+abc
+def
+123
+" \
+"\
+--- input.old Jan 01 01:01:01 2000
++++ input Jan 01 01:01:01 2000
+@@ -1,2 +1,3 @@
+ abc
++def
+ 123
+" \
+
exit $FAILCOUNT