summaryrefslogtreecommitdiffstats
path: root/lib/rpatch.in
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rpatch.in')
-rwxr-xr-xlib/rpatch.in202
1 files changed, 202 insertions, 0 deletions
diff --git a/lib/rpatch.in b/lib/rpatch.in
new file mode 100755
index 0000000..d25695b
--- /dev/null
+++ b/lib/rpatch.in
@@ -0,0 +1,202 @@
+#!/bin/sh
+
+if ! [ -r @LIB@/patchfns ]
+then
+ echo "Cannot read library @LIB@/patchfns" >&2
+ exit 1
+fi
+. @LIB@/patchfns
+
+usage()
+{
+ echo "Usage: rpatch [-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 pc_file=$(pc_file_name $patch)
+ local apply_ts=$(date -r $pc_file '+%s') ts
+
+ if [ $pc_file -ot $(patch_file_name $patch) ]
+ 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
+}
+
+abort_patch()
+{
+ local pc_file=$(pc_file_name $1)
+ @LIB@/backup-files -s -f $pc_file -z ~rpatch -r
+ exit 1
+}
+
+interrupt()
+{
+ local patch=$1
+ abort_patch $patch
+ echo "rpatch interrupted by user"
+ exit 1
+}
+
+do_remove()
+{
+ local patch=$1 pc_file=$(pc_file_name $patch)
+
+ 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_name $patch)~forced
+ return $status
+ else
+ local patch_file=$(patch_file_name $patch)
+ if ! [ -e "$patch_file" ]
+ then
+ echo "No patch named $patch found."
+ return 1
+ fi
+
+ trap "interrupt $patch" SIGINT
+ #if [ ! -e $patch_file ] || grep -q '^%patch$' $patch_file
+ #then
+ # @LIB@/parse-patch -s patch $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
+ status=$?
+ trap "" SIGINT
+ if [ $status -eq 0 ] && verify_removal $patch
+ then
+ @LIB@/backup-files -s -f $pc_file -z ~rpatch -x
+ @LIB@/backup-files -s -f $pc_file -B .pc/$patch/ -x
+
+ remove_from_db $patch
+ else
+ @LIB@/backup-files -s -f $pc_file -z ~rpatch -r
+ echo "Patch $patch does not remove cleanly"
+ return 1
+ fi
+ fi
+ trap - SIGINT
+}
+
+options=`getopt -o fRqh -- "$@"`
+
+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 ;;
+ -h)
+ usage -h ;;
+ --)
+ shift
+ break ;;
+ esac
+done
+
+if [ $# -ne 1 ]
+then
+ usage
+fi
+
+patch=$(stripit $1)
+[ -n "$opt_quiet" ] && silent=-s
+
+top=$(top_patch)
+if [ -n "$top" -a -e $(pc_file_name $top)~forced -a -z "$opt_force" ]
+then
+ echo "The topmost patch $top was force applied. Please run" \
+ "refpatch before removing it."
+ exit 1
+fi
+
+#if is_applied "$patch"
+#then
+ do_remove "$patch" || exit 1
+#else
+# echo "Patch $patch is not applied"
+# exit 1
+#fi
+
+top=$(top_patch)
+if [ -z "$top" ]
+then
+ where="no patches applied"
+else
+ where="now at $top"
+fi
+echo "Removed $patch, $where"
+