summaryrefslogtreecommitdiffstats
path: root/scripts/rpatch.in
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@suse.de>2003-01-31 12:45:37 +0000
committerAndreas Gruenbacher <agruen@suse.de>2003-01-31 12:45:37 +0000
commit21a15e55a81ea4bd2bc21729ceebe6be6a9ccd9b (patch)
tree150f25f9add7ecb5ae144ab63a62c3b43d25f378 /scripts/rpatch.in
parentf07f43d191fe23209876061b7a31b5cb1e9a219d (diff)
downloadquilt-21a15e55a81ea4bd2bc21729ceebe6be6a9ccd9b.tar.gz
Install binary backup-files into /usr/lib/quilt and the remaining scripts under /usr/share/quilt/scripts.
Diffstat (limited to 'scripts/rpatch.in')
-rwxr-xr-xscripts/rpatch.in254
1 files changed, 254 insertions, 0 deletions
diff --git a/scripts/rpatch.in b/scripts/rpatch.in
new file mode 100755
index 0000000..afdf230
--- /dev/null
+++ b/scripts/rpatch.in
@@ -0,0 +1,254 @@
+#! @BASH@
+
+# This script is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# See the COPYING and AUTHORS files for more details.
+
+# Read in library functions
+if [ "$(type -t patch_file_name)" != function ]
+then
+ if ! [ -r @SCRIPTS@/patchfns ]
+ then
+ echo "Cannot read library @SCRIPTS@/patchfns" >&2
+ exit 1
+ fi
+ . @SCRIPTS@/patchfns
+fi
+
+usage()
+{
+ echo "Usage: $0 [-fRq] patchname"
+ exit 1
+}
+
+verify_removal()
+{
+ local patch=$1
+ local bup file status=0
+ local dir=$(basename $PWD) suffix=${patch//\//_}
+
+ # Check if all changes of the patch are undone
+ for file in $(files_in_patch $patch)
+ do
+ bup=$(backup_file_name $patch $file)
+ if ! [ -s $file -o -s $bup ] || \
+ cmp $file $bup > /dev/null 2> /dev/null
+ then
+ continue
+ fi
+
+ if [ $status -eq 0 ]
+ then
+ echo "Patch does not remove changes:"
+ fi
+
+ @DIFF@ -Nu $DIFF_OPTS $bup $file \
+ | sed -e 's:^--- [^ \t]*:--- '"$dir/$file.orig"':' \
+ -e 's:^+++ [^ \t]*:+++ '"$dir/$file"':'
+
+ status=1
+ done
+ return $status
+}
+
+files_may_have_changed()
+{
+ local patch=$1 file
+ local patch_file=$(patch_file_name $patch)
+ local pc_file=$(pc_file_name $patch)
+
+ if ! [ -e $pc_file ]
+ then
+ return 1
+ fi
+
+ local apply_ts=$(date -r $pc_file '+%s') ts
+
+ if [ -e "$patch_file" -a $pc_file -ot "$patch_file" ]
+ then
+ return 0
+ fi
+
+ for file in $(files_in_patch $patch)
+ do
+ if ! [ -e $file ]
+ then
+ return 0 # file is missing
+ fi
+
+ ts=$(date -r $file '+%s')
+ if [ $? -ne 0 -o $ts -gt $apply_ts ]
+ then
+ return 0 # file has changed
+ fi
+ done
+ return 1
+}
+
+rollback_patch()
+{
+ local patch=$1 pc_file=$(pc_file_name $patch)
+ @LIB@/backup-files $silent_unless_verbose \
+ -f $pc_file -z ~rpatch -r
+ rm -f $(files_in_patch $patch | sed -e 's/$/\.rej/')
+}
+
+interrupt()
+{
+ local patch=$1
+ rollback_patch $patch
+ echo "Interrupted by user; patch $patch was not removed."
+ exit 1
+}
+
+reverse_patch()
+{
+ local patch=$1
+ local patch_file=$(patch_file_name $patch)
+
+ if ! [ -s $patch_file ]
+ then
+ echo "Patch file $patch_file appears to be empty"
+ return 0
+ fi
+
+ if [ "x${patch_file:(-3)}" = "x.gz" ]
+ then
+ gzip -cd $patch_file \
+ | @PATCH@ $(patch_args $patch) --no-backup-if-mismatch \
+ -R -E $silent
+ elif [ "x${patch_file:(-4)}" = "x.bz2" ]
+ then
+ bzip2 -cd $patch_file \
+ | @PATCH@ $(patch_args $patch) --no-backup-if-mismatch \
+ -R -E $silent
+ else
+ @PATCH@ $(patch_args $patch) --no-backup-if-mismatch \
+ -R -E $silent -i $patch_file
+ fi
+}
+
+rpatch()
+{
+ local patch=$1 pc_file=$(pc_file_name $patch)
+
+ if ! [ -e $pc_file ]
+ then
+ echo "Patch $patch appears to be empty, removed"
+ remove_from_db $patch
+ return 0
+ fi
+
+ trap "" SIGINT
+ if [ -n "$opt_force" ] || \
+ ( [ -z "$opt_remove" ] && ! files_may_have_changed $patch )
+ then
+ # Optimize: Force remove if the patch has not been
+ # modified since it was applied. (Forced remove is
+ # faster!)
+
+ @LIB@/backup-files $silent -f $pc_file -B .pc/$patch/ -r
+ status=$?
+ remove_from_db $patch
+ rm -f $pc_file~refresh
+ if [ $status != 0 ]
+ then
+ exit $status
+ fi
+ else
+ if ! @LIB@/backup-files $silent_unless_verbose \
+ -f $pc_file -z ~rpatch
+ then
+ echo "Failed to create temporary files" >&2
+ return 1
+ fi
+
+ trap "interrupt $patch" SIGINT
+
+ reverse_patch $patch
+ status=$?
+
+ trap "" SIGINT
+
+ if [ $status -eq 0 ] && verify_removal $patch
+ then
+ @LIB@/backup-files $silent_unless_verbose \
+ -f $pc_file -z ~rpatch -x
+ @LIB@/backup-files $silent_unless_verbose \
+ -f $pc_file -B .pc/$patch/ -x
+
+ remove_from_db $patch
+ else
+ rollback_patch $patch
+ echo "Patch $patch does not remove (enforce with -f)"
+ return 1
+ fi
+ fi
+ trap - SIGINT
+
+ local top=$(top_patch) where
+ if [ -z "$top" ]
+ then
+ where="no patches applied"
+ else
+ where="now at $top"
+ fi
+ echo "Removed $patch, $where"
+}
+
+options=`getopt -o fRqvh -- "$@"`
+
+if [ $? -ne 0 ]
+then
+ usage
+fi
+
+eval set -- "$options"
+
+while true
+do
+ case "$1" in
+ -f)
+ opt_force=1
+ shift ;;
+ -R)
+ opt_remove=1 # remove properly with patch -R; no tricks
+ unset opt_force
+ shift ;;
+ -q)
+ opt_quiet=1
+ shift ;;
+ -v)
+ opt_verbose=1
+ shift ;;
+ -h)
+ usage -h ;;
+ --)
+ shift
+ break ;;
+ esac
+done
+
+if [ $# -ne 1 ]
+then
+ usage
+fi
+
+patch=$(stripit $1)
+[ -n "$opt_quiet" ] && silent=-s
+[ -z "$opt_verbose" ] && silent_unless_verbose=-s
+
+top=$(top_patch)
+if [ -n "$top" -a -e $(pc_file_name $top)~refresh -a -z "$opt_force" ]
+then
+ echo "The topmost patch $top needs to be refreshed first."
+ exit 1
+fi
+
+rpatch "$patch" || exit 1
+### Local Variables:
+### mode: shell-script
+### End:
+# vim:filetype=sh