From 4c9b771fbe177710788273f792a220b756e7cad7 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 20 Dec 2019 10:37:42 -0800 Subject: patch: support [FILE [PATCH]] arguments. POSIX only mentions -i/stdin, but GNU patch -- and Larry Wall's patch 1.3, found via https://en.wikipedia.org/wiki/Patch_(Unix) -- also support supplying the name of the file to patch and the name of the patch file as optional arguments. The AOSP build makes use of this syntax to patch snakeyaml to remove references to java.beans.* stuff. --- toys/posix/patch.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/toys/posix/patch.c b/toys/posix/patch.c index 3234a1f0..27c25143 100644 --- a/toys/posix/patch.c +++ b/toys/posix/patch.c @@ -15,20 +15,19 @@ * * -E remove empty files --remove-empty-files * -F fuzz (number, default 2) - * [file] which file to patch -USE_PATCH(NEWTOY(patch, "(no-backup-if-mismatch)(dry-run)"USE_TOYBOX_DEBUG("x")"g#fulp#d:i:Rs(quiet)", TOYFLAG_USR|TOYFLAG_BIN)) +USE_PATCH(NEWTOY(patch, ">2(no-backup-if-mismatch)(dry-run)"USE_TOYBOX_DEBUG("x")"g#fulp#d:i:Rs(quiet)", TOYFLAG_USR|TOYFLAG_BIN)) config PATCH bool "patch" default y help - usage: patch [-d DIR] [-i file] [-p depth] [-Rlsu] [--dry-run] + usage: patch [-d DIR] [-i PATCH] [-p depth] [-Rlsu] [--dry-run] [FILE [PATCH]] Apply a unified diff to one or more files. -d Modify files in DIR - -i Input file (default=stdin) + -i Input patch file (default=stdin) -l Loose match (ignore whitespace) -p Number of '/' to strip from start of file paths (default=all) -R Reverse patch @@ -267,7 +266,7 @@ char *unquote_file(char *filename) { } else { ch = unescape(s[1]); *t++ = ch ? ch : s[1]; - s++; + s++; } } else *t++ = *s; } @@ -288,6 +287,7 @@ void patch_main(void) int reverse = FLAG(R), state = 0, patchlinenum = 0, strip = 0; char *oldname = NULL, *newname = NULL; + if (toys.optc == 2) TT.i = toys.optargs[1]; if (TT.i) TT.filepatch = xopenro(TT.i); TT.filein = TT.fileout = -1; @@ -388,12 +388,23 @@ void patch_main(void) oldsum = TT.oldline + TT.oldlen; newsum = TT.newline + TT.newlen; + // If an original file was provided on the command line, it overrides + // *all* files mentioned in the patch, not just the first. + if (toys.optc) { + char **which = reverse ? &oldname : &newname; + + free(*which); + *which = strdup(toys.optargs[0]); + // The supplied path should be taken literally with or without -p. + toys.optflags |= FLAG_p; + TT.p = 0; + } + name = reverse ? oldname : newname; // We're deleting oldname if new file is /dev/null (before -p) // or if new hunk is empty (zero context) after patching - if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) - { + if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) { name = reverse ? newname : oldname; del++; } -- cgit v1.2.3