summaryrefslogblamecommitdiffstats
path: root/scripts/rpatch.in
blob: e4dfefb00f3cd4dccafbea0caf710096c3132d98 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
         





                                                                      
 

                                               
    
                                      
            
                                                                 

                      
                            
  


       
                                          


              


                           
                                                  
        


                                                                 



                        
                                                                        

                                            


                                                      



                


                                                                            
 
                                 
                                                  

                                                       
 
                                  
            
                                                                    
                                                      












                                                                           

          
                             
            









                                                                           
                                                    














                                                                       
            

                                                                               
          



                       


        
 
                                                       
 


                                                                   
            
                                                                 



                                     
                      

                                                                    
            

                                                                     
 


                                       

                                                                              

                                     
                                              
          
                      
                     
                      

 
                                 




















                                                                        


                             














                                
                                                 

                
                                                                
    
                                                                   


              
                         



                      
#! @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
}

files_may_have_changed()
{
	local patch=$1 file
	local patch_file=$(patch_file_name $patch)
	
	if [ $? -ne 0 -o ! -e "$patch_file" \
	     -o ! -e "$QUILT_PC/$patch/.timestamp" \
	     -o "$QUILT_PC/$patch/.timestamp" -ot "$patch_file" ]
	then
		return 0
	fi
	
	local apply_ts=$(date -r "$QUILT_PC/$patch/.timestamp" '+%s') ts
	for file in $(files_in_patch $patch)
	do
		ts=$(date -r $file '+%s' 2> /dev/null)
		[ -z "$ts" ] && return 0
		[ "$ts" -gt $apply_ts ] && return 0
	done
	return 1
}

# Check if all changes have been folded back into the patch (quilt refresh),
# and report any pending changes.
check_for_pending_changes()
{
	local patch=$1 pc_file=$2
	local patch_file=$(patch_file_name $patch)
	local patch_args=$(patch_args $patch)
	local workdir=$(gen_tempfile -d quilt) status=0

	if [ -d $QUILT_PC/$patch ]
	then
		if ! rmdir $workdir ||  # note that this is racey...
		   ! cp -rl $QUILT_PC/$patch $workdir/
		then
			echo $"Failed to copy files to temporary directory"
			rm -rf $workdir
			return 1
		fi

		# Now we may have some zero-size files that have no
		# permissions (which represent files that the patch
		# creates). Those may have been created in the meantime,
		# but patch would refuse to touch them: We must remove
		# them here.
		find $workdir -type f -size 0 -exec rm -f '{}' ';'

	fi
	
	if [ -s $patch_file ]
	then
		if ! cat_file $patch_file \
		     | @PATCH@ -d $workdir $patch_args \
			       --no-backup-if-mismatch -E \
			       >/dev/null 2>/dev/null
		then
			# If a patch was force applied (and therefore needs
			# refreshing), we know that patching the temporary
			# files won't succeed, either. So, ignore the error
			# in that particular case.
			
			if ! [ -e $QUILT_PC/$patch ]
			then
				echo $"Failed to patch temporary files"
				rm -rf $workdir
				return 1
			fi
		fi
	fi
	
	local remains=$(gen_tempfile)
	while read file
	do
		diff_file $file $workdir/$file $file >> $remains
	done < $pc_file
	
	if [ -s $remains ]
	then
		echo $"Patch $patch does not remove cleanly (enforce with -f)."
		status=1
	fi
	rm -f $remains
	rm -rf $workdir

	return $status
}

rpatch()
{
	local patch=$1 pc_file=$(gen_tempfile) status=0

	# FIXME backup-files should scan the directory tree itself.
	files_in_patch $patch > $pc_file
	if ! [ -s $pc_file ]
	then
		echo $"Patch $patch appears to be empty, removed"
		remove_from_db $patch
		return 0
	fi

	trap "" SIGINT
	if [ -z "$opt_force" ] && \
	   ( [ -n "$opt_remove" ] || files_may_have_changed $patch )
	then
		check_for_pending_changes $patch $pc_file || status=1
	fi

	if [ $status -eq 0 ]
	then
		echo $"Removing $patch"
		rm -f "$QUILT_PC/$patch/.timestamp"
		@LIB@/backup-files $silent -f $pc_file -B $QUILT_PC/$patch/ -r
		status=$?
		remove_from_db $patch
		rm -f $QUILT_PC/$patch~refresh
	fi
	rm -f $pc_file
	trap - SIGINT
	return $status
}

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 $QUILT_PC/$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