summaryrefslogblamecommitdiffstats
path: root/lib/apatch.in
blob: 3a13238c4d2c92ed0e67ad80203af66c78f8b310 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
           





                                                                      
 

                                               
    





                                                             
  


       
                                         


              




                                                        



                                                                    

 

           

                                                                 




              


























                                                                      

                                            

                         

                                     
            
                                               


                        






                                                                








                                                                            

                                                          




                                      

                          
                 
 

                      
                                                        








                                                              
                                              
                    

                                                                     

                  

                                                                    




                      
                                                     
















                           


                             


                                   













                                
                                                 



                   
                                                   
    
                                                                  


              
             
#!/bin/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 @LIB@/patchfns ]
	then
		echo "Cannot read library @LIB@/patchfns" >&2
		exit 1
	fi
	. @LIB@/patchfns
fi

usage()
{
	echo "Usage: $0 [-fqv] patchname"
	exit 1
}

rollback_patch()
{
	local patch=$1 pc_file=$(pc_file_name $patch)
	@LIB@/backup-files $silent_unless_verbose \
			   -f $pc_file -B .pc/$patch/ -r
	if [ -z "$opt_leave_rejects" ]
	then
		rm -f $(files_in_patch $patch | sed -e 's/$/\.rej/')
	fi
}

interrupt()
{
	rollback_patch $1
	echo "Interrupted by user; patch $patch was not applied."
	exit 1
}

apply_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 \
			-E $silent
	elif [ "x${patch_file:(-4)}" = "x.bz2" ]
	then
		bzip2 -cd $patch_file \
		| patch $(patch_args $patch) --no-backup-if-mismatch \
			-E $silent
	else
		patch $(patch_args $patch) --no-backup-if-mismatch \
			-E $silent -i $patch_file
	fi
}

apatch()
{
	local patch=$(stripit $1)
	local pc_file=$(pc_file_name $patch)
	local file status

	trap "" SIGINT
	if ! refresh_file_list $patch
	then
		echo "refresh_file_list failed"
		return 1
	fi

	if ! [ -e $pc_file ]
	then
		echo "Patch $patch appears to be empty, applied"
		add_to_db $patch
		return 0
	fi
	
	status=$?
	if [ $status -eq 2 ]
	then
		[ -z "$opt_quiet" ] && echo "Recreated file list for $patch"
	elif [ $status -ne 0 ]
	then
		return 1
	fi

	if ! @LIB@/backup-files $silent_unless_verbose \
				-f $pc_file -B .pc/$patch/
	then
		exit 1
	fi
	
	trap "interrupt $patch" SIGINT

	apply_patch $patch
	status=$?

	trap "" SIGINT

	# Remember date/time of applying so that pop can
	# avoid reverse applying the patch in the usual cases.
	touch $pc_file

	if [ $status -eq 0 -o -n "$opt_force" ]
	then
		add_to_db $patch
		if [ $status -eq 0 ]
		then
			echo "Applied $patch"
			rm -f $pc_file~refresh
		else
			touch $pc_file~refresh
			echo "Applied $patch (forced; needs refresh)"
		fi
	else
		rollback_patch $patch
		echo "Patch $patch does not apply (enforce with -f)"
	fi
	trap - SIGINT
	return $status
}

options=`getopt -o fqvh --long leave-rejects -- "$@"`

if [ $? -ne 0 ]
then
	usage
fi

eval set -- "$options"

while true
do
	case "$1" in
	-f)
		opt_force=1
		shift ;;
	-q)
		opt_quiet=1
		shift ;;
	-v)
		opt_verbose=1
		shift ;;
	--leave-rejects)
		opt_leave_rejects=1
		shift ;;
	-h)
		usage -h ;;
	--)
		shift
		break ;;
	esac
done

if [ $# -ne 1 ]
then
	usage
fi

[ -n "$opt_quiet" ] && silent=-s
[ -z "$opt_verbose" ] && silent_unless_verbose=-s

patch=$(stripit $1)

top=$(top_patch)
if [ -n "$top" -a -e $(pc_file_name $top)~refresh ]
then
	echo "The topmost patch $top needs to be refreshed first."
	exit 1
fi

apatch $patch