diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2003-01-31 12:45:37 +0000 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2003-01-31 12:45:37 +0000 |
commit | 21a15e55a81ea4bd2bc21729ceebe6be6a9ccd9b (patch) | |
tree | 150f25f9add7ecb5ae144ab63a62c3b43d25f378 /scripts/patchfns.in | |
parent | f07f43d191fe23209876061b7a31b5cb1e9a219d (diff) | |
download | quilt-21a15e55a81ea4bd2bc21729ceebe6be6a9ccd9b.tar.gz |
Install binary backup-files into /usr/lib/quilt and the remaining scripts under /usr/share/quilt/scripts.
Diffstat (limited to 'scripts/patchfns.in')
-rw-r--r-- | scripts/patchfns.in | 614 |
1 files changed, 614 insertions, 0 deletions
diff --git a/scripts/patchfns.in b/scripts/patchfns.in new file mode 100644 index 0000000..e17d164 --- /dev/null +++ b/scripts/patchfns.in @@ -0,0 +1,614 @@ +# 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. + +if [ -n "$PATCHSCRIPTS" ] +then + P=$PATCHSCRIPTS/ +else + unset P +fi + +if [ -e .pc/series ] +then + SERIES=.pc/series +elif [ -e series ] +then + SERIES=series +else + SERIES=${P}patches/series +fi + +DB=".pc/applied-patches" + +# Define where diffstat lives (may be missing) +DIFFSTAT=/usr/bin/diffstat + +quote_re() +{ + echo "$1" | sed -e 's:\([\^\$/.+*\[\\]\):\\\1:g' +} + +#basename() +#{ +# local path=${1%/} +# echo "${path/*\/}" +#} + +#dirname() +#{ +# local path=${1%/} +#} + +patch_file_name() +{ + local patch=$1 + + if [ -e $SERIES ] + then + awk '/^'"$(quote_re $patch)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \ + { printf "'"$P"'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=$(@MKTEMP@ /tmp/patch-scripts.XXXXXX) + 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 + rm -f $tmpfile + else + mv -f $tmpfile $SERIES + fi + 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=$(@MKTEMP@ /tmp/patch-scripts.XXXXXX) || 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 + mv -f $tmpfile $SERIES +} + +remove_from_series() +{ + local patch=$1 + + tmpfile=$(@MKTEMP@ /tmp/patch-scripts.XXXXXX) || return 1 + awk ' + ! /^'"$(quote_re $patch)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \ + { print } + ' $SERIES > $tmpfile + if [ $? -eq 0 ] + then + mv -f $tmpfile $SERIES + else + rm -f $tmpfile + return 1 + fi +} + +pc_file_name() +{ + while [ $# -gt 0 ] + do + echo ".pc/$1/.pc" + shift + done + +} + +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 -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 +} + +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 + grep -l -E "^$(quote_re $file)\$" \ + $(pc_file_name $patches_on_top) \ + | head -1 \ + | sed -e 's:^\.pc/::' -e 's:/\.pc$::' + fi + + #modified_files $file -- $patches_on_top \ + #| cut -d $'\t' -f2 \ + #| cut -d ' ' -f1 +} + +# Create a list of files and the patches that modify them. +refresh_patches_per_file() +{ + local pc_files=$(pc_file_name $(cat_series)) + local ex_pc_files pc_file + + if [ -e .pc/patches-per-file ] + then + local needs_refresh + for pc_file in pc_files + do + if [ .pc/patches-per-file -ot $pc_file ] + then + needs_refresh=1 + break + fi + done + if [ -z "$needs_refresh" ] + then + return 0 + fi + fi + + for pc_file in $pc_files + do + if [ -e $pc_file ] + then + ex_pc_files[${#ex_pc_files[@]}]=$pc_file + fi + done + + if [ ${#ex_pc_files[@]} -eq 0 ] + then + rm -f .pc/patches-per-file + return 0 + fi + + awk ' + ARGIND!=saved { sub(/^.pc\//, "", FILENAME) + sub(/\/\.pc/, "", FILENAME) + saved=ARGIND + } + { if (files[$0]) + files[$0]=files[$0] " " FILENAME + else + files[$0]=FILENAME + } + END { for (file in files) + printf "%s\t%s\n", file, files[file] + } + ' "${ex_pc_files[@]}" > .pc/patches-per-file +} + +# For a lists of patches and a list of files, compute which patches +# modify which files. Invoked as +# modified_files file ... [-- patch ...] +# +modified_files() +{ + if ! refresh_patches_per_file + then + return 1 + fi + + awk ' + BEGIN { no_files=1 + no_patches=1 + for (i=1; i<ARGC; i++) { + if (ARGV[i]=="--") + break + files[ARGV[i]]=1 + no_files=0 + } + for (i++; i<ARGC; i++) { + patches[ARGV[i]]=1 + no_patches=0 + } + split("", ARGV) # read from standard input + } + no_files || files[$1] { + if (no_patches) { + print + next + } + for (i=2; i<=NF; i++) + if ($i in patches) { + printf "%s\t%s", $1, $i + for (i++; i<=NF; i++) + if ($i in patches) + printf " %s", $i + printf "\n" + } + } + ' "$@" < .pc/patches-per-file +} + +add_to_db() +{ + echo $1 >> $DB +} + +remove_from_db() +{ + local patch=$1 + local tmpfile + if tmpfile=$(@MKTEMP@ /tmp/patch-scripts.XXXXXX) + 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/^'"$P"'patches\///' -e 's/^\.pc\///' \ + -e 's/\.gz$//' -e 's/\.bz2$//' \ + -e 's/\.patch$//' -e 's/\.diff\?$//' + fi +} + +file_in_patch() +{ + local file=$1 patch=$2 + files_in_patch $patch \ + | grep -q -E "^$(quote_re $file)\$" +} + +files_in_patch() +{ + local pc_file=$(pc_file_name $1) + if [ -e "$pc_file" ] + then + cat $pc_file + 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 + }' +} + +refresh_file_list() +{ + local patch=$1 + local pc_file=$(pc_file_name $patch) + local patch_file=$(patch_file_name $patch) + + if ! [ -e "$patch_file" ] + then + return 0 + fi + if [ ! -e $pc_file -o \ + $pc_file -ot $patch_file -o \ + $pc_file -ot $SERIES ] + then + local tmpfile status + if ! mkdir -p $(dirname $pc_file) || \ + ! tmpfile=$(@MKTEMP@ /tmp/patch-scripts.XXXXXX) + then + return 1 + fi + + if [ -e $pc_file ] + then + cat $pc_file >> $tmpfile + fi + if ! touched_by_patch $(patch_strip_level $patch) \ + $patch >> $tmpfile + then + return 1 + fi + sort $tmpfile | uniq > $pc_file + rm $tmpfile + return 0 + fi +} + +diff_file() +{ + local file=$1 suffix=$2 old_file=$3 new_file=$4 + local old_file new_file + + if [ ! -e "$old_file" -a ! -e "$new_file" ] + then + echo "File $file does not exist" >&2 + return 0 + fi + local old_hdr new_hdr + if [ $opt_strip_level -eq 0 ] + then + old_hdr=$file$suffix + new_hdr=$file + else + local dir=$(basename $PWD) + old_hdr=$dir$suffix/$file + new_hdr=$dir/$file + fi + + echo Index: $new_hdr + @DIFF@ -Nu $DIFF_OPTS $old_file $new_file | + fix_diff_header $old_hdr $new_hdr +} + +fix_diff_header() +{ + local from=$1 to=$2 + sed -e 's:^--- [^ \t]*:--- '"$from"':' \ + -e 's:^+++ [^ \t]*:+++ '"$to"':' +} + +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 } + $1 == "Index:" { eat = eat $0 + next } + $1 == "diff" { 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 +} +### Local Variables: +### mode: shell-script +### End: +# vim:filetype=sh |