summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in3
-rwxr-xr-xbin/patch-wrapper.in204
-rw-r--r--lib/backup-files.c12
-rw-r--r--quilt.changes12
-rw-r--r--test/patch-wrapper.test74
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