summaryrefslogtreecommitdiffstats
path: root/lib/patchfns.in
diff options
context:
space:
mode:
Diffstat (limited to 'lib/patchfns.in')
-rw-r--r--lib/patchfns.in434
1 files changed, 319 insertions, 115 deletions
diff --git a/lib/patchfns.in b/lib/patchfns.in
index 63fae45..17c5b56 100644
--- a/lib/patchfns.in
+++ b/lib/patchfns.in
@@ -1,8 +1,10 @@
-debug()
-{
- #echo "$@" >&2
- true
-}
+#!/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.
if [ -n "$PATCHSCRIPTS" ]
then
@@ -23,20 +25,36 @@ 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?)([ \t]|$)/ \
- { printf "'"$P"'patches/%s\n", $1; exit }' \
- $SERIES
+ awk '/^'"$(quote_re $patch)"'(|\.patch|\.diff?)(|\.gz|\.bz2)([ \t]|$)/ \
+ { printf "'"$P"'patches/%s\n", $1
+ exit
+ }
+ ' $SERIES
fi
}
@@ -47,13 +65,16 @@ patch_args()
if [ -e $SERIES ]
then
- awk '/^'"$(quote_re $patch)"'(|\.patch|\.diff?)([ \t]|$)/ \
+ 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
+ print $i
+ else
+ print "-p1" ;
+ exit
+ }
+ ' $SERIES
fi
}
@@ -87,20 +108,24 @@ change_db_strip_level()
if [ -e $SERIES ]
then
- local tmp=$(mktemp /tmp/patch-scripts.XXXXXX)
- awk '/^'"$(quote_re $patch)"'(\.patch|\.diff?)([ \t]|$)/ \
- {for(i=2; i<=NF; i++)
- if ($i ~ /^-p/)
- {$i="'"$level"'" ; break}
- if (i > NF)
- $i="'"$level"'"}
- {print}' \
- $SERIES > $tmp
- if cmp $SERIES $tmp >/dev/null 2>/dev/null
+ 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 $tmp
+ rm -f $tmpfile
else
- mv -f $tmp $SERIES
+ mv -f $tmpfile $SERIES
fi
else
return 1
@@ -115,7 +140,7 @@ patch_in_series()
then
return 1
else
- grep -q '^'"$(quote_re $patch)"'\(\|\.patch\|.diff\?\)\([ \t]\|$\)' $SERIES
+ grep -q '^'"$(quote_re $patch)"'\(\|\.patch\|.diff\?\)\(\|\.gz\|\.bz2\)\([ \t]\|$\)' $SERIES
fi
}
@@ -123,31 +148,54 @@ patch_in_series()
insert_in_series()
{
local patch=$1 patch_args=$2
- local top=$(top_patch) tmp
+ local top=$(top_patch) tmpfile
if [ -n "$patch_args" ]
then
patch_args=" $patch_args"
fi
- tmp=$(mktemp /tmp/patch-scripts.XXXXXX) || return 1
+ tmpfile=$(mktemp /tmp/patch-scripts.XXXXXX) || return 1
+ mkdir -p $(dirname $SERIES)
if [ -n "$top" ]
then
- awk ' { print }
- /^'"$(quote_re $top)"'(|\.patch|\.diff?)([ \t]|$)/ \
- { print "'"$patch$patch_args"'" }' \
- < $SERIES \
- > $tmp \
- || return 1
+ 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 > $tmp
+ echo $patch$patch_args > $tmpfile
if [ -e $SERIES ]
then
- cat $SERIES >> $tmp
+ cat $SERIES >> $tmpfile
fi
fi
- mkdir -p $(dirname $SERIES)
- mv -f $tmp $SERIES
+ 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()
@@ -170,34 +218,23 @@ backup_file_name()
done
}
-__cat_series()
+cat_series()
{
- local series=$1
- if [ -e $series ]
+ if [ -e $SERIES ]
then
sed -e '/^#/d' -e 's/^[ \t]*//' -e 's/[ \t].*//' \
- -e 's/\.patch$//' -e 's/\.diff\?//' $series
+ -e 's/\.gz$//' -e 's/\.bz2$//' \
+ -e 's/\.patch$//' -e 's/\.diff\?$//' $SERIES
else
return 1
fi
}
-cat_series()
-{
- __cat_series $SERIES
-}
-
top_patch()
{
[ -e $DB ] && tail -1 $DB
}
-die()
-{
- echo "error: $*"
- exit 1
-}
-
is_numeric()
{
echo $1 | grep -q -e '^[0-9]*$'
@@ -219,17 +256,30 @@ is_applied()
patches_before()
{
local patch=$1
- cat_series \
- | awk '$0 == "'"$patch"'" { exit }
- { print }'
+
+ if [ -n "$patch" ]
+ then
+ cat_series \
+ | awk '
+ $0 == "'"$patch"'" { exit }
+ { print }
+ '
+ fi
}
patches_after()
{
local patch=$1
- cat_series \
- | awk 'seen { print }
- $0 == "'"$patch"'" { seen=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
@@ -237,8 +287,10 @@ patches_on_top_of()
{
local patch=$1
[ -e $DB ] || return
- awk '$0 == "'"$patch"'" { seen=1 ; next }
- seen { print }' $DB
+ awk '
+ $0 == "'"$patch"'" { seen=1 ; next }
+ seen { print }
+ ' $DB
}
# Print the name of the patch that modified the file $2 next after
@@ -255,30 +307,106 @@ next_patch_for_file()
| head -1 \
| sed -e 's:^\.pc/::' -e 's:/\.pc$::'
fi
+
+ #modified_files $file -- $patches_on_top \
+ #| cut -d $'\t' -f2 \
+ #| cut -d ' ' -f1
}
-can_apply()
+# Create a list of files and the patches that modify them.
+refresh_patches_per_file()
{
- local silent
- if [ "x$1" == "x-s" ]
+ local pc_files=$(pc_file_name $(cat_series))
+ local ex_pc_files pc_file
+
+ if [ -e .pc/patches-per-file ]
then
- silent=-s
- shift
+ 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
- local patch=$1
- patch -p1 --dry-run -f $silent -i $(patch_file_name $patch) < /dev/null
-}
-can_remove()
-{
- local silent
- if [ "x$1" == "x-s" ]
+ 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
- silent=-s
- shift
+ rm -f .pc/patches-per-file
+ return 0
fi
- local patch=$1
- patch -R -p1 --dry-run -f $silent -i $(patch_file_name $patch) < /dev/null
+
+ 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()
@@ -290,10 +418,13 @@ remove_from_db()
{
local patch=$1
local tmpfile
- tmpfile=$(mktemp /tmp/patch-scripts.XXXXXX)
- grep -v "^$patch\$" $DB > $tmpfile
- mv -f $tmpfile $DB
- [ -s $DB ] || rm -f $DB
+ if tmpfile=$(mktemp /tmp/patch-scripts.XXXXXX)
+ then
+ grep -v "^$(quote_re $patch)\$" $DB > $tmpfile
+ mv -f $tmpfile $DB
+ rm -f $tmpfile
+ [ -s $DB ] || rm -f $DB
+ fi
}
stripit()
@@ -303,6 +434,7 @@ stripit()
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
}
@@ -322,15 +454,19 @@ files_in_patch()
fi
}
-install_file_in_patch()
+touched_by_patch()
{
- local file=$1 patch=$2 bup_file=$(backup_file_name $patch $file)
-
- if ! echo $file  @LIB@/backup-file -s -B .pc/$patch/ || \
- ! echo $file >> $(pc_file_name $patch)
- then
- return 1
- fi
+ 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()
@@ -341,40 +477,103 @@ refresh_file_list()
if ! [ -e "$patch_file" ]
then
- echo "Patch file $patch_file does not exist"
- return 1
+ return 0
fi
- if [ ! -e $pc_file -o $pc_file -ot $patch_file ]
+ if [ ! -e $pc_file -o \
+ $pc_file -ot $patch_file -o \
+ $pc_file -ot $SERIES ]
then
- mkdir -p $(dirname $pc_file)
- echo "touched-by-patch $(patch_strip_level $patch) $patch_file > $pc_file" >&2
- @LIB@/touched-by-patch -p$(patch_strip_level $patch) \
- $patch_file > $pc_file
- if [ $? -ne 0 ]
+ 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
- return 2
+ sort $tmpfile | uniq > $pc_file
+ rm $tmpfile
+ return 0
fi
}
-directory_names()
+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()
{
- echo "$@" \
- | awk 'BEGIN {RS=" "}
- {sub(/\/?[^\/]*$/, "") ; printf "[%s]\n", $0}
- {if (last != $0)
- print last
- last = $0}
- END {print last}'
+ local from=$1 to=$2
+ sed -e 's:^--- [^ \t]*:--- '"$from"':' \
+ -e 's:^+++ [^ \t]*:+++ '"$to"':'
}
-need_file_there()
+cat_file()
{
- if [ ! -e $1 ]
+ 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
- echo "File $1 does not exist"
- exit 1
+ cat
+ else
+ case "$filename" in
+ *.gz|*.tgz)
+ gzip -c > "$filename" ;;
+ *.bz2)
+ bzip2 -c > "$filename" ;;
+ *)
+ cat > "$filename" ;;
+ esac
fi
}
@@ -384,10 +583,15 @@ patch_description()
if [ -e "$patch_file" ]
then
- awk '/^--- / {exit}
- diff {print diff ; diff=""}
- /^diff / {diff=$0 ; next}
- {print}' \
- $patch_file
+ awk '
+ /^--- / { exit }
+ diff_line { print diff_line
+ diff_line=""
+ }
+ /^diff / { diff_line=$0
+ next
+ }
+ { print }
+ ' $patch_file
fi
}