#!/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"