blob: afca43c3f4b3e665a58698262873008bdf0dc569 (
plain) (
tree)
|
|
# 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.
ORIGINAL_LANG=$LANG
export LANG=POSIX
export TEXTDOMAIN=quilt
export QUILT_PATCHES QUILT_PC SUBDIR SERIES DB
: ${QUILT_PATCHES:=patches}
: ${QUILT_PC:=.pc}
if [ -e "$QUILTRC" ]
then
source "$QUILTRC"
fi
#
# If the working directory does not contain a $QUILT_PATCHES directory,
# quilt searches for its base directory up the directory tree. If no
# $QUILT_PATCHES directory exists, the quilt operations that create
# patches will create $QUILT_PATCHES in the current working directory.
#
# When quilt is invoked from a directory below the base directory, it
# changes into the base directory, and sets $SUBDIR to the relative
# path from the base directory to the directory in which it was
# invoked. (e.g., if quilt is invoked in /usr/src/linux/drivers/net
# and the base direcory is /usr/src/linux, $SUBDIR is set to
# drivers/net/.
unset SUBDIR
if ! [ -d "$QUILT_PATCHES" ]
then
basedir=$PWD
while [ -n "$basedir" ]
do
basedir=${basedir%/*}
if [ -d "$basedir/$QUILT_PATCHES" ]
then
SUBDIR="${PWD#$basedir/}/"
if ! cd $basedir/
then
echo "Cannot change into parent directory $basedir/" >&2
exit 1
fi
break
fi
done
unset basedir
fi
if [ -n "$QUILT_SERIES" ]
then
SERIES=$QUILT_SERIES
elif [ -e $QUILT_PC/series ]
then
SERIES=$QUILT_PC/series
elif [ -e series ]
then
SERIES=series
else
SERIES=$QUILT_PATCHES/series
fi
DB="$QUILT_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
echo "$QUILT_PATCHES/$1"
}
# The -pN option and possibly others that should be passed to patch.
patch_args()
{
local patch=$1
if [ -e $SERIES ]
then
@AWK@ '
$1 == "'"$patch"'" \
{ 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)"'([ \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)([ \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)"'([ \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)"'([ \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
@AWK@ '
/^'"$(quote_re $from)"'([ \t]|$)/ \
{ sub(/'"$(quote_re $from)"'/, "'"${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
}
rename_in_db()
{
local from=$1 to=$2
local tmpfile
tmpfile=$(gen_tempfile) || return 1
/usr/bin/gawk '
/^'"$(quote_re $from)"'$/ \
{ sub(/'"$(quote_re $from)"'/, "'"${to//\"/\\\"}"'")
print
good=1 }
END { exit(! good) }
' $DB > $tmpfile
if [ $? -eq 0 ]
then
mv -f $tmpfile $DB
else
rm -f $tmpfile
return 1
fi
}
backup_file_name()
{
local patch=$1
while [ $# -gt 1 ]
do
echo "$QUILT_PC/$patch/$2"
shift
done
}
cat_series()
{
if [ -e $SERIES ]
then
@SED@ -e '/^$/d' -e '/^#/d' -e 's/^[ '$'\t'']*//' \
-e 's/[ '$'\t''].*//' $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
}
find_patch()
{
set -- $*
if [ $# -eq 1 -a -n "$1" -a -e "$SERIES" ]
then
local patch="${1#$QUILT_PATCHES/}"
local bre=$(quote_bre "$patch")
set -- $(@SED@ -e "/^$bre\(\|\.patch\|\.diff\?\)\(\|\.gz\|\.bz2\)\([ \t]\|$\)/!d" \
-e 's/[ \t].*//' $SERIES)
if [ $# -eq 1 ]
then
echo $1
return 0
else
# We may have an exact match, which overrides
# extension expansion
while [ $# -gt 0 ]
do
if [ $1 = "$patch" ]
then
echo $1
return 0
fi
shift
done
fi
fi
return 1
}
file_in_patch()
{
local file=$1 patch=$2
[ -f "$QUILT_PC/$patch/$file" ]
}
files_in_patch()
{
local patch="$1"
local path="$QUILT_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 z
[ -n "$QUILT_NO_DIFF_TIMESTAMPS" ] && z='.*'
@SED@ -e 's/^--- [^ '$'\t'']*'$z'/--- '"$(quote_bre $from)"'/' \
-e 's/^+++ [^ '$'\t'']*'$z'/+++ '"$(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 "$QUILT_PC/$patch/$file" ]
then
echo $patch
return 0
fi
done
return 1
}
### Local Variables:
### mode: shell-script
### End:
# vim:filetype=sh
|