#! @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 $QUILT_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 if [ -z $patch_file ] then echo "Waring: Can not find the $patch in your series file, the series file may changed" return 0 #can not find the patch in series fi local apply_ts=$(date -r $pc_file '+%s') ts for file in $(files_in_patch $patch) do if ! [ -e .pc/$patch/$file ] then echo "Warning: the backup files .pc/$patch/$file do not exist" echo "Check your backup files in .pc/$patch" echo "If pop did not success, please touch a empty .pc/$patch/$file and try again" touch .pc/$patch/$file return 1 # backup files is missing, we can not remove it with force fi done 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 echo $"Removing $patch" trap "" SIGINT files_may_have_changed $patch patch_may_changed=$? if [ "$opt_force" -eq 1 ] || \ ( [ "$opt_remove" -eq 0 ] && [ $patch_may_changed -eq 0 ] ) 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 } options=`getopt -o fRqvh -- "$@"` if [ $? -ne 0 ] then usage fi opt_force=0 opt_remove=0 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