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

                                                                  





                                                                      
 


                       




                        
                           







                         
                                    



                        


                                                       
                                                       


                                                           

          
                                                              

 

          

                                

                          
 

         

                                




                                                
 





                         
                                                                                          
                                                              


                              









                                                                    
                       
                                                                                   

                                                       





                                                
































                                     
                                             
                       










                                                                                  
                                                                
                    
                                              
                  
                              












                           
                                                                                                    






                                      
                                      





                                         
                                           
                                   

                        
                       









                                                                                 
            
                                                   

                                 
                                               

                  

                              





                      
                                           
               


                                                                             
                       
            


                              

                              

 








                                                                             
                          
                         

                                
                       
            


                              

                              

 









                                    
            
 
                         
            


                                                                              




                        

           
                                   

 

            
                                    











                                    
                                              

 


















                                                 


                      



                            
                         



                                                 




                      


                            
                         





                                                  






                                                            
               


                                                 










                                                                  







                                                                  
          










                      
                                  
            
                                                                 



                                       






                         
                                           
                                                                   

                                                          





                              
                                 



                


                               
            

                                                                 


                                                 


          
                  
 

                                            
                  







                                            

 


                           

                                                                    

 

           
                                             
                                  
 


                                                
                               

                                     
                                  


                                          
                                       


                                  
                                                         


                                      
                                                                                          


                                                   

 
          
 






















                                                        
            









                                                 






                           
                                                   
            
                       
                                        
                                                
                                             


                                           

                                         

          










                                           











































                                                                
















                                              
                                



                  



                      
# This file contains the common functions used in all quilt script
# It is meant to be sourced by bash scripts.

#  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.

export TEXTDOMAIN=quilt
		

if [ -e $HOME/.quiltrc ]
then
	. $HOME/.quiltrc
fi

: ${QUILT_PATCHES:=patches}

if [ -e .pc/series ]
then
	SERIES=.pc/series
elif [ -e series ]
then
	SERIES=series
else
	SERIES=$QUILT_PATCHES/series
fi

DB=".pc/applied-patches"

# Quote a string for use in a basic regular expression.
quote_bre()
{
	echo "$1" | @SED@ -e 's:\([][^$/.*\\]\):\\\1:g'
}

# Quote a string for use in an extended regular expression.
quote_re()
{
	echo "$1" | @SED@ -e 's:\([][?{(|)}^$/.+*\\]\):\\\1:g'
}

basename()
{
        local path="${1//\/\//}"
        path="${path%%/}"
	echo "${path##*/}"
}

dirname()
{
        local path="${1//\/\//}"
        path="${path%%/}"
	local basename="${path##*/}"
	path="${path:0:${#path}-${#basename}}"
	[ x"$path" != x"/" ] && path="${path%/}"
	echo "${path:-.}"
}

patch_file_name()
{
	local patch=$1

	if [ -e $SERIES ]
	then
		@AWK@ '/^'"$(quote_re $patch)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \
			{ printf "'"$QUILT_PATCHES"'/%s\n", $1
			  exit
			}
		' $SERIES
	fi
}

# The -pN option and possibly others that should be passed to patch.
patch_args()
{
	local patch=$1

	if [ -e $SERIES ]
	then
		@AWK@ '
		/^'"$(quote_re $patch)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \
			{ if (NF >= 2)
				for (i=2; i <= NF; i++)
					print $i
			  else
				print "-p1" ;
			  exit
			}
		' $SERIES
	fi
}

patch_strip_level()
{
	local patch=$1 i
	for i in $(patch_args $patch)
	do
		case $i in
		-p)
			echo $2
			return ;;
		-p*)
			echo ${i:2}
			return ;;
		esac
	done
	echo "1"
}

change_db_strip_level()
{
	local level=$1 patch=$2

	if [ x$level != x-p1 ]
	then
		level="$level"
	else
		level=""
	fi

	if [ -e $SERIES ]
	then
		local tmpfile=$(gen_tempfile)
		@AWK@ '
		/^'"$(quote_re $patch)"'(\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \
			{ for(i=2; i<=NF; i++)
				if ($i ~ /^-p/) {
					$i="'"$level"'"
					break
				}
			  if (i > NF)
				 $i="'"$level"'"
			}
			{ print }
		' $SERIES > $tmpfile
		if ! cmp $SERIES $tmpfile >/dev/null 2>/dev/null
		then
			cat $tmpfile > $SERIES
		fi
		rm -f $tmpfile
	else
		return 1
	fi
}

patch_in_series()
{
	local patch=$1

	if ! [ -e $SERIES ]
	then
		return 1
	else
		grep -q -E '^'"$(quote_re $patch)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)' $SERIES
	fi
}

# Insert new patch after topmost patch
insert_in_series()
{
	local patch=$1 patch_args=$2
	local top=$(top_patch) tmpfile

	if [ -n "$patch_args" ]
	then
		patch_args=" $patch_args"
	fi

	tmpfile=$(gen_tempfile) || return 1
	mkdir -p $(dirname $SERIES)
	if [ -n "$top" ]
	then
		@AWK@ '
				{ print }
		/^'"$(quote_re $top)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \
				{ print "'"$patch$patch_args"'" }
		' $SERIES > $tmpfile
		status=$?
		if [ $status -ne 0 ]
		then
			rm -f $tmpfile
			return 1
		fi
	else
		echo "$patch$patch_args" > $tmpfile
		if [ -e $SERIES ]
		then
			cat $SERIES >> $tmpfile
		fi
	fi
	cat $tmpfile > $SERIES
	rm -f $tmpfile
}

remove_from_series()
{
	local patch=$1

	tmpfile=$(gen_tempfile) || return 1
	@AWK@ '
	! /^'"$(quote_re $patch)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \
				{ print }
	' $SERIES > $tmpfile
	if [ $? -ne 0 ]
	then
		rm -f $tmpfile
	   	return 1
	fi
	cat $tmpfile > $SERIES
	rm -f $tmpfile
}

rename_in_series()
{
	local from=$1 to=$2

	tmpfile=$(gen_tempfile) || return 1
	/usr/bin/gawk '
	/^'"$(quote_re $from)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \
		{ sub(/'"$(quote_re $from)(|\.patch|\.diff?)(|\.gz|\.bz2)"'/,
		      "'"${to//\"/\\\"}"'")
		  good=1 }
		{ print }
	END	{ exit(! good) }
	' $SERIES > $tmpfile
	if [ $? -ne 0 ]
	then
		rm -f $tmpfile
		return 1
	fi
	cat $tmpfile > $SERIES
	rm -f $tmpfile
}

backup_file_name()
{
	local patch=$1
	while [ $# -gt 1 ]
	do
		echo ".pc/$patch/$2"
		shift
	done
}

cat_series()
{
	if [ -e $SERIES ]
	then
		@SED@ -e '/^#/d' -e 's/^[ '$'\t'']*//' -e 's/[ '$'\t''].*//' \
		      -e 's/\.gz$//' -e 's/\.bz2$//' \
		      -e 's/\.patch$//' -e 's/\.diff\?$//' $SERIES
	else
		return 1
	fi
}

top_patch()
{
	[ -e $DB ] && tail -n 1 $DB
}

is_numeric()
{
	echo $1 | grep -q '^[0-9]*$'
}

is_applied_last()
{
	local patch=$1
	[ "$(top_patch)" == $patch ]
}

is_applied()
{
	local patch=$1
	[ -e $DB ] || return 1
	grep -q -E "^$(quote_re $patch)\$" $DB
}

applied_patches()
{
	[ -e $DB ] || return 1
	cat $DB
}

applied_before()
{
	local patch=$1

	if [ -n "$patch" ]
	then
		@AWK@ '
		$0 == "'"$patch"'"	{ exit }
					{ print }
		' $DB
	fi
}
		
patches_before()
{
	local patch=$1

	if [ -n "$patch" ]
	then
		cat_series \
		| @AWK@ '
		$0 == "'"$patch"'"	{ exit }
					{ print }
		'
	fi
}

patches_after()
{
	local patch=$1
	if [ -n "$patch" ]
	then
		cat_series \
		| @AWK@ '
		seen			{ print }
		$0 == "'"$patch"'"	{ seen=1 }
		'
	else
		cat_series
	fi
}

# List all patches that have been applied on top of patch $1
patches_on_top_of()
{
	local patch=$1
	[ -e $DB ] || return
	@AWK@ '
	$0 == "'"$patch"'"	{ seen=1 ; next }
	seen			{ print }
	' $DB
}

# Print the name of the patch that modified the file $2 next after
# patch $1, or print nothing if patch $1 is on top.
next_patch_for_file()
{
	local patch=$1 file=$2
	local patches_on_top=$(patches_on_top_of $patch)

	if [ -n "$patches_on_top" ]
	then
		for patch in $patches_on_top
		do
			if [ -f $(backup_file_name $patch $file) ]
			then
				echo $patch
				break
			fi
		done
	fi
}

add_to_db()
{
	echo $1 >> $DB
}

remove_from_db()
{
	local patch=$1
	local tmpfile
	if tmpfile=$(gen_tempfile)
	then
		grep -v -E "^$(quote_re $patch)\$" $DB > $tmpfile
		mv -f $tmpfile $DB
		rm -f $tmpfile
		[ -s $DB ] || rm -f $DB
	fi
}

stripit()
{
	if [ -n "$1" ]
	then
		echo $1 |
		@SED@ -e 's/^\(\.\/\)*//' \
		      -e 's/^'"$(quote_bre $QUILT_PATCHES)"'\///' \
		      -e 's/\.gz$//' -e 's/\.bz2$//' \
		      -e 's/\.patch$//' -e 's/\.diff\?$//'
	fi
}

file_in_patch()
{
	local file=$1 patch=$2
	[ -f ".pc/$patch/$file" ]
}

files_in_patch()
{
	local patch="$1"
	local path=".pc/$patch"
	if [ -d "$path" ]
	then
		for file in $(find "$path" -type f \
				   -a ! -path "$path/.timestamp")
		do
			echo "${file:${#path}+1}"
		done
	fi
}

touched_by_patch()
{
	local strip=$1 patch=$2
	cat_file $(patch_file_name $patch) \
	|  @AWK@ '
	/^\+\+\+[ \t]/ {
		sub(/^\+\+\+[ \t]/, "")
		sub(/[ \t].*/, "")
		sub(/^\/dev\/null/, "")
		for (i=0; i<'$strip'; i++)
			sub(/^[^\/]*\//, "")
		print
	}'
}

fix_diff_header()
{
	local from=$1 to=$2
	@SED@ -e 's/^--- [^ '$'\t'']*/--- '"$(quote_bre $from)"'/' \
	      -e 's/^+++ [^ '$'\t'']*/+++ '"$(quote_bre $to)"'/'
}

diff_file()
{
	local file=$1 old_file=$2 new_file=$3
	local old_hdr new_hdr line

	[ -s "$old_file" ] || old_file=/dev/null
	[ -s "$new_file" ] || new_file=/dev/null

	: ${opt_strip_level:=1}
	if [ $opt_strip_level -eq 0 ]
	then
		old_hdr=$file.orig
		new_hdr=$file
	else
		local dir=$(basename $PWD)
		old_hdr=$dir.orig/$file
		new_hdr=$dir/$file
	fi

	@DIFF@ -Nu $QUILT_DIFF_OPTS $old_file $new_file |
	if read line
	then
		echo "Index: $new_hdr"
		echo "==================================================================="
		(echo "$line" ; cat) \
		| fix_diff_header $old_hdr $new_hdr
	fi
}

cat_file()
{
	local filename
	
	for filename in "$@"
	do
		if [ -e "$filename" ]
		then
			case "$filename" in
			*.gz|*.tgz)
				gzip -cd "$filename" ;;
			*.bz2)
				bzip2 -cd "$filename" ;;
			*)
				cat "$filename" ;;
			esac
		fi
	done
}

cat_to_file()
{
	local filename="$1"

	if [ -z "$filename" ]
	then
		cat
	else
		case "$filename" in
		*.gz|*.tgz)
			gzip -c > "$filename" ;;
		*.bz2)
			bzip2 -c > "$filename" ;;
		*)
			cat > "$filename" ;;
		esac
	fi
}

patch_description()
{
	local patch_file=$1

	if [ -e "$patch_file" -o -z "$patch_file" ]
	then
		@AWK@ '
		$1 == "---"	{ exit }
               /^Index:[ \t]|^diff[ \t]|^==*$/ \
                               { eat = eat $0
				  next }
		eat		{ print eat
				  eat="" }
				{ print }
		' $patch_file
	fi
}

in_array()
{
	local a=$1
	while [ $# -gt 1 ]
	do
		shift
		[ "$a" = "$1" ] && return 0
	done
	return 1
}

gen_tempfile()
{
	# This is a substitute for the mktemp executable.
	internal_mktemp()
	{
		local try n
		if [ x"$1" = x"-d" ]
		then
			for ((n=0 ; $n<100 ; n++))
			do
				try=${2%XXXXXX}$RANDOM
				mkdir -m 700 $try 2>/dev/null \
				&& break
			done
		else
			local user_mask=$(umask)
			umask 077
			set -o noclobber
			for ((n=0 ; $n<100 ; n++))
			do
				try=${1%XXXXXX}$RANDOM
				echo -n "" 2> /dev/null > $try \
				&& break
			done
			set +o noclobber
			umask $user_mask
		fi
		if [ $n -lt 100 ]
		then
			echo $try
		else
			return 1
		fi
	}

	local dir
	if [ x"$1" = x"-d" ]
	then
		dir=-d
		shift
	fi
	@MKTEMP@ $dir ${1:-${TMPDIR:-/tmp}/quilt}.XXXXXX
}

first_modified_by()
{
	local file=$1 patch
	local -a patches
	if [ $# -eq 0 ]
	then
		patches=( $(applied_patches) )
	else
		shift
		patches=( "$@" )
	fi
	for patch in ${patches[@]}
	do
		if [ -f ".pc/$patch/$file" ]
		then
			echo $patch
			return 0
		fi
	done
	return 1
}
### Local Variables:
### mode: shell-script
### End:
# vim:filetype=sh