#!/bin/sh # $Id: apply,v 1.4 2003/06/30 12:49:09 herbert Exp $ set -e length=50 die() { echo "E: $@" >&2 exit 1 } warn() { echo "W: $@" >&2 } uncompress_patch() { patch=$1 case "$patch" in *.bz2) bzcat $patch ;; *.gz) zcat $patch ;; *) cat $patch ;; esac } find_patch() { patch=$1 if [ -f "$patch" ]; then echo "$patch" elif [ -f "$patch.bz2" ]; then echo "$patch.bz2" elif [ -f "$patch.gz" ]; then echo "$patch.gz" else die "$patch is in the series, but doesn't exist!" fi } apply_patch() { patch=$(find_patch $home/$1) base=$1 if uncompress_patch "$patch" | patch -p1 -f -s -t --no-backup-if-mismatch; then printf "%-${length}s\tOK (+)\n" "$base" else printf "%-${length}s\tFAIL (+)\n" "$base" exit 1 fi } deapply_patch() { patch=$(find_patch $home/$1) base=$1 if uncompress_patch "$patch" | patch -p1 -f -s -t -R --no-backup-if-mismatch; then printf "%-${length}s\tOK (-)\n" "$base" else printf "%-${length}s\tFAIL (-)\n" "$base" exit 1 fi } unpatch_series() { series=$1 [ -f "$series" ] || die "I wasn't passed a series: $series" tac $series | while read action patch; do case "$action" in +) deapply_patch $patch ;; -) apply_patch $patch ;; X) bakfile="$(dirname $patch)/.$(basename $patch).bak" if [ -f "$bakfile" ]; then mv -f "$bakfile" "$patch" printf "%-${length}s\tRESTORED (X)\n" "$patch" else printf "%-${length}s\tNO BACKUP (X)\n" "$patch" fi ;; esac done echo "--> $(basename $series) fully unapplied." } patch_series() { series=$1 [ -f "$series" ] || die "I wasn't passed a series: $series" while read action patch; do case "$action" in +) apply_patch $patch ;; -) deapply_patch $patch ;; X) bakfile="$(dirname $patch)/.$(basename $patch).bak" if [ -f "$patch" ]; then mv -f "$patch" "$bakfile" printf "%-${length}s\tREMOVED (X)\n" "$patch" else printf "%-${length}s\tNO FILE (X)\n" "$patch" fi ;; esac done < $series echo "--> $(basename $series) fully applied." } bubble_sort () { DIR=$1 shift SORTED=$@ SWAPED=1 while [ $SWAPED = 1 ]; do X=0 A="" SWAPED=0 NEW="" for i in $SORTED; do if [ -z "$A" ]; then A="$i" continue fi B="$i" if dpkg --compare-versions "$A" "$DIR" "$B"; then SWAPED=1 NEW="$NEW $B" else NEW="$NEW $A" A="$B" fi X=$(($X + 1)) done SORTED="$NEW $A" done echo $SORTED } bubble_sort_fwd () { bubble_sort "lt" $@ } bubble_sort_rev () { bubble_sort "gt" $@ } if ! [ -d Documentation ] || ! [ -d kernel ]; then die 'Not in kernel top level directory. Exiting' exit 1 fi # for THIS particular version of the source package version=${override_version:-@version@} upstream=${version%-*} revision=${version#*-} home=${home:-/usr/src/kernel-patches/all/$upstream/debian} if [ -f version.Debian ]; then current=$(cat version.Debian) current_rev=${current#*-} current_up=${current%-*} if [ "$current" = "$upstream" ]; then current_rev=0 fi else warn "No version.Debian file, assuming pristine Linux $upstream" current=$upstream current_rev=0 fi target=${1:-$version} target_rev=${target#*-} target_up=${target%-*} # Sanity checks if dpkg --compare-versions "$target_up" ne "$upstream"; then die "Upstream $target_up doesn't match $upstream!" # We don't have that version out yet! elif [ ! -n "$target_rev" ] || ( dpkg --compare-versions "$target_rev" ne "$target" && dpkg --compare-versions "$target_rev" gt "$revision" ); then year=$(($(date +%Y) + 1)) die "Can't patch to nonexistent revision $target_rev (wait until $year)" fi # At this point, we must handle three cases. # 1. $target_rev is greater than $current_rev. We must patch forward for this. # 2. $target_rev is less than $current_rev. We must reverse the list of series, # reverse each used series (tac) and unapply applied patches and vice versa. # 3. $target_rev is undefined, and $target is $upstream. # Revert to upstream. if [ "$target_rev" = "$target" ]; then # already reverted if [ "$current" = "$target" ]; then echo "Nothing to do, exiting." exit 0 fi for base in $(cd $home/series/ && bubble_sort_fwd $(ls -d *)); do srev=${base#*-} if [ -n "$srev" ]; then if dpkg --compare-versions $srev "<=" $current_rev; then unpatch_series $home/series/$base fi else die "Series doesn't have a revision!" fi done elif dpkg --compare-versions "$current_rev" eq "$upstream" || dpkg --compare-versions "$target_rev" gt "$current_rev"; then for base in $(cd $home/series/ && bubble_sort_rev $(ls -d *)); do srev=${base#*-} if [ -n "$srev" ]; then if dpkg --compare-versions "$srev" gt "$current_rev" && dpkg --compare-versions "$srev" le "$target_rev"; then patch_series $home/series/$base fi else die "Series doesn't have a revision!" fi done elif dpkg --compare-versions "$target_rev" eq "$current_rev"; then echo "Nothing to do, exiting." exit 0 elif dpkg --compare-versions "$target_rev" lt "$current_rev"; then for base in $(cd $home/series/ && bubble_sort_fwd $(ls -d *)); do srev=${base#*-} if [ -n "$srev" ]; then # -gt because you don't want to unapply the target series if dpkg --compare-versions "$srev" le "$current_rev" && dpkg --compare-versions "$srev" gt "$target_rev"; then unpatch_series $home/series/$base fi else die "Series doesn't have a revision!" fi done fi echo $target > version.Debian # vim:noet:ai:ts=4