diff options
-rw-r--r-- | Makefile.in | 3 | ||||
-rwxr-xr-x | bin/patch-wrapper.in | 204 | ||||
-rw-r--r-- | lib/backup-files.c | 12 | ||||
-rw-r--r-- | quilt.changes | 12 | ||||
-rw-r--r-- | test/patch-wrapper.test | 74 |
5 files changed, 299 insertions, 6 deletions
diff --git a/Makefile.in b/Makefile.in index b30eedd..84bd5b8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,7 +67,7 @@ SRC += COPYING AUTHORS TODO Makefile.in configure.ac \ bash_completion quilt.quiltrc aclocal.m4 DIRT += quilt.spec -BIN_IN := quilt guards +BIN_IN := quilt guards patch-wrapper BIN_SRC := $(BIN_IN:%=%.in) BIN := $(BIN_IN) SRC += $(BIN_SRC:%=bin/%) @@ -374,6 +374,7 @@ endif # (test|check) quilt/refresh :: quilt/scripts/remove-trailing-ws quilt/mail :: quilt/scripts/edmail +test/.patch-wrapper.ok : bin/patch-wrapper # Include a run-time generated list of dependencies for each test case test/.depend : Makefile $(TESTS) diff --git a/bin/patch-wrapper.in b/bin/patch-wrapper.in new file mode 100755 index 0000000..4d6b108 --- /dev/null +++ b/bin/patch-wrapper.in @@ -0,0 +1,204 @@ +#! @BASH@ + +# This is a wrapper to GNU patch that recognizes the most common +# options and mimics GNU patch's behavior and output, and creates the +# quilt metadata as if quilt push was used to apply the patches. When +# options are used that this wrapper does not recognize, GNU patch is +# used directly, and no quilt metadata will get created. + +PATCH=patch +original_options=("$@") + +# GNU patch recognizes these environment variables +if [ -n "$SIMPLE_BACKUP_SUFFIX" ] +then + set -- --suffix "$SIMPLE_BACKUP_SUFFIX" "$@" +fi +if [ -n "$PATCH_VERSION_CONTROL" ] +then + set -- --version-control "$PATCH_VERSION_CONTROL" "$@" +elif [ -n "$VERSION_CONTROL" ] +then + set -- --version-control "$VERSION_CONTROL" "$@" +fi +if [ -n "$POSIXLY_CORRECT" ] +then + set -- --posix "$@" +fi + +backup_files() { + declare dir=${QUILT_PC:-.pc}/$patch + + if [ "$backup_mode" = --backup-if-mismatch ] + then + awk ' + /^patching file / \ + { file=$0 + sub(/^patching file /, "", file) + } + /^Hunk #[0-9]* / \ + { if (! file in backup) + print file > "/dev/stderr" + backup[file] = 1 + #print "ln "dir"/"file" "prefix file suffix \ + # > "/dev/stderr" + system("ln "dir"/"file" "prefix file suffix) + } + { if (!silent) + print + } + ' dir="${dir//\\/\\\\}" \ + prefix="${opt_prefix//\\/\\\\}" \ + suffix="${opt_suffix//\\/\\\\}" \ + silent="${opt_silent:+1}" + elif [ -n "$opt_silent" ]; then + cat > /dev/null + fi + if [ "$backup_mode" = --backup ] + then + for file in $(find "$dir" -type f -a ! -path "$path/.timestamp") + do + dest=$opt_prefix${file#$dir/}$opt_suffix + mkdir -p $(dirname "$dest") + ln $file $dest + done + fi +} + +options=`getopt -q -o bsB:z:i:p:d: \ + --long quiet,silent,backup,backup-if-mismatch \ + --long no-backup-if-mismatch,prefix: \ + --long suffix:,posix,input:,strip:,directory: -- "$@"` +if [ $? -ne 0 ] +then + cannot_handle=1 +elif [[ ! ${LC_ALL:-${LC_MESSAGES:-${LANG}}} =~ "^$|^C$|^POSIX$|^en" ]] +then + cannot_handle=1 +else + eval set -- "$options" + + backup_mode=--backup-if-mismatch + opt_prefix= + opt_suffix= + opt_silent= + opt_input= + opt_strip= + opt_directory=$PWD + + while : + do + case "$1" in + -b|--backup) + backup_mode=--backup + ;; + --backup-if-mismatch) + backup_mode=--backup-if-mismatch + ;; + -d|--directory) + cd "$2" || exit 1 + shift + ;; + -i|--input) + opt_input=$2 + new_options[${#new_options[@]}]=$1 + new_options[${#new_options[@]}]=$2 + shift + ;; + --no-backup-if-mismatch) + backup_mode=--no-backup-if-mismatch + ;; + -B|--prefix) + opt_prefix=$2 + new_options[${#new_options[@]}]=$1 + new_options[${#new_options[@]}]=$2 + shift + ;; + -s|--silent|--quiet) + opt_silent=--silent + ;; + -p|--strip) + opt_strip=-p$2 + new_options[${#new_options[@]}]=-p$2 + shift + ;; + -z|--suffix) + opt_suffix=$2 + new_options[${#new_options[@]}]=$1 + new_options[${#new_options[@]}]=$2 + shift + ;; + --posix) + backup_mode=--no-backup-if-mismatch + new_options[${#new_options[@]}]=$1 + ;; + --) + shift + break + ;; + *) + new_options[${#new_options[@]}]=$1 + ;; + esac + shift + done + + [ -n "$opt_prefix$opt_suffix" ] || opt_suffix=.orig + if [ -z "$opt_strip" -o $# -ne 0 ] + then + cannot_handle=1 + fi +fi + +if [ -n "$cannot_handle" ] +then + $PATCH "${original_options[@]}" + exit +fi + +if [ -n "$opt_input" ] +then + patch=$opt_input +else + patch=$(readlink /proc/self/fd/0) +fi +patch=${patch#$PWD/} + +quilt_patches=${QUILT_PATCHES:-patches} +if [ ! -e "$quilt_patches/$patch" ] +then + dir=$(dirname "$quilt_patches/$patch") + mkdir -p "$dir" + updir=../ + while ! [ "$dir/$updir$patch" -ef "$patch" ] + do + updir=$updir../ + done + ln -s "$updir$patch" "$quilt_patches/$patch" +fi + +if [ "$opt_strip" = -p1 ]; then + echo "$patch" +else + echo "$patch $opt_strip" +fi \ +>> $quilt_patches/series + +$PATCH "${new_options[@]}" --backup --prefix ${QUILT_PC:-.pc}/$patch/ \ + | backup_files +status=${PIPESTATUS[0]} +if [ $status -eq 0 ] +then + dir=${QUILT_PC:-.pc}/$patch + if [ ! -e "$dir" ] + then + mkdir -p "$dir" + fi + echo -n "" > $dir/.timestamp + if [ ! -e ${QUILT_PC:-.pc}/.version ] + then + echo 2 > ${QUILT_PC:-.pc}/.version + fi + echo $patch >> "${QUILT_PC:-.pc}/applied-patches" +fi +exit $status diff --git a/lib/backup-files.c b/lib/backup-files.c index 268fb49..4d6d137 100644 --- a/lib/backup-files.c +++ b/lib/backup-files.c @@ -471,7 +471,7 @@ walk(const char *path, const struct stat *st) int main(int argc, char *argv[]) { - int opt, status=0; + int opt, status = 0; progname = argv[0]; @@ -557,15 +557,17 @@ main(int argc, char *argv[]) } for (; optind < argc; optind++) { if (strcmp(argv[optind], "-") == 0) { + struct stat st; char *dir = strdup(opt_prefix), *d = strrchr(dir, '/'); if (d) *d = '\0'; else d = "."; - status = foreachdir(dir, walk); - if (status == -1) - perror(dir); - + if (stat(dir, &st) == 0) { + status = foreachdir(dir, walk); + if (status == -1) + perror(dir); + } free(dir); } else status = process_file(argv[optind]); diff --git a/quilt.changes b/quilt.changes index d1c52c7..e470a87 100644 --- a/quilt.changes +++ b/quilt.changes @@ -1,4 +1,16 @@ ------------------------------------------------------------------- +Mon Feb 6 02:41:10 CET 2006 - agruen@suse.de + +- bin/patch-wrapper.in: A wrapper to GNU patch that recognizes the + most common options and mimics GNU patch's behavior and output, + and creates the quilt metadata as if quilt push was used to + apply the patch. When options are used that this wrapper does + not recognize, GNU patch is used directly, and no quilt metadata + will get created. +- lib/backup-files.c: Don't fail if a directory specified with + -B does not exist. + +------------------------------------------------------------------- Sat Feb 4 08:37:47 CET 2006 - agruen@suse.de - make dist: Add the missing aclocal.m4 to the tarball. diff --git a/test/patch-wrapper.test b/test/patch-wrapper.test new file mode 100644 index 0000000..32c80bb --- /dev/null +++ b/test/patch-wrapper.test @@ -0,0 +1,74 @@ +$ rm -rf d +$ mkdir -p d/somewhere +$ cd d + +$ cat > foo.orig +< 1 +< +< 3 +< +< 5 +$ sed -e 's/3/3a/' foo.orig > foo +$ diff -u foo.orig foo > foo.diff +$ mv foo.orig foo + +$ patch-wrapper -s -p0 < foo.diff +$ quilt pop -q +> Removing patch patches/foo.diff +> No patches applied +$ rm -rf ${QUILT_PATCHES:-patches} ${QUILT_PC:-.pc} + +$ patch-wrapper --backup -B xxx/ -s -p0 < foo.diff +$ find xxx -type f +> xxx/foo +$ quilt pop -q +> Removing patch patches/foo.diff +> No patches applied +$ rm -rf ${QUILT_PATCHES:-patches} ${QUILT_PC:-.pc} + +$ patch-wrapper -s -p0 -i foo.diff +$ quilt pop -q +> Removing patch patches/foo.diff +> No patches applied +$ rm -rf ${QUILT_PATCHES:-patches} ${QUILT_PC:-.pc} + +$ patch-wrapper -p0 < foo.diff +> patching file foo +$ quilt pop -q +> Removing patch patches/foo.diff +> No patches applied +$ rm -rf ${QUILT_PATCHES:-patches} ${QUILT_PC:-.pc} + +$ mv foo.diff somewhere/ +$ patch-wrapper -p0 < somewhere/foo.diff +> patching file foo +$ quilt pop -q +> Removing patch patches/somewhere/foo.diff +> No patches applied +$ rm -rf ${QUILT_PATCHES:-patches} ${QUILT_PC:-.pc} + +$ patch-wrapper -p0 -i somewhere/foo.diff +> patching file foo +$ quilt pop -q +> Removing patch patches/somewhere/foo.diff +> No patches applied +$ rm -rf ${QUILT_PATCHES:-patches} ${QUILT_PC:-.pc} + +$ sed -e 's/5/5b/' foo > foo.new +$ mv foo.new foo +$ patch-wrapper -p0 < somewhere/foo.diff +> patching file foo +> Hunk #1 succeeded at 1 with fuzz 1. +$ cat foo.orig +> 1 +> +> 3 +> +> 5b +$ quilt pop -q +> Removing patch patches/somewhere/foo.diff +> No patches applied +$ rm -rf ${QUILT_PATCHES:-patches} ${QUILT_PC:-.pc} + +$ cd .. +$ rm -rf d |