From f481c3c11dfaea24ba1c429f73ad60b3657d4c80 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Mon, 6 Feb 2006 01:44:50 +0000 Subject: - 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. --- Makefile.in | 3 +- bin/patch-wrapper.in | 204 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/backup-files.c | 12 +-- quilt.changes | 12 +++ test/patch-wrapper.test | 74 ++++++++++++++++++ 5 files changed, 299 insertions(+), 6 deletions(-) create mode 100755 bin/patch-wrapper.in create mode 100644 test/patch-wrapper.test 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,3 +1,15 @@ +------------------------------------------------------------------- +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 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 -- cgit