#!/bin/sh # # IRC - Internet Relay Chat, ircd-patch # Copyright (C) 2002 Alex Badea # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 1, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # $Id: ircd-patch,v 1.5.2.1 2005-12-29 03:41:56 entrope Exp $ # # # Experimental centralized patch system for ircu # Run with no arguments to get help. # # Return codes: # 0 - success # 1 - at least one live patch failed # 2 - at least one simulation (dry run) failed # 3 - invalid arguments (i.e. no such patch) # 4 - invalid operation (i.e. tried to apply when already applied) # DIFFS=patches/diffs MARKS=patches/marks PLIST_FILE=include/patchlist.h retcode=0 force=0 PLIST="" for fname in $DIFFS/*.diff ; do name=`basename $fname | sed -e 's/\.diff//'` PLIST="$PLIST $name" done update_patchlist() { list="" for name in $PLIST ; do test -f $MARKS/$name && list="$list.$name" done echo "/* This file was automatically generated by ircd-patch */" > $PLIST_FILE echo "#define PATCHLIST \"$list\"" >> $PLIST_FILE echo "Updated $PLIST_FILE" } test -d $DIFFS || (echo "*** Missing $DIFFS, creating it" ; mkdir -p $DIFFS) test -d $MARKS || (echo "*** Missing $MARKS, creating it" ; mkdir -p $MARKS) dry_run() { rejects=`patch -p0 -N -t --dry-run $2 < $1 | grep "hunk FAILED" | sed -e 's/.*to file / /;s/\.rej$//'` test -z "$rejects" } patch_list() { echo "Available patches (* marks applied patches):" for name in $PLIST ; do test -f $MARKS/$name && echo -n " * " || echo -n " " echo $name done echo "Done." } patch_test() { echo "Testing patches:" list="$*" test "z$list" = "z" && list=$PLIST for name in $list ; do fname=$DIFFS/$name.diff echo -ne " $name\t" if test ! -f $MARKS/$name ; then if dry_run "$fname" ; then echo -n " OK" else echo -n " PATCH FAILED" retcode=2 fi else echo -n " APPLIED" if dry_run "$fname" -R ; then echo -n " OK" else echo -n " REVERSE FAILED" retcode=2 fi fi echo done echo "Done." } patch_add() { name=$1 fname="$DIFFS/$name.diff" if test ! -f $fname ; then echo "Patch $name ($fname) does not exist" retcode=3 return fi if test $force -lt 2 -a -f $MARKS/$name ; then echo "Patch $name seems already applied" retcode=4 return fi if test $force -lt 1 ; then echo -n "Testing $fname... " if ! dry_run $fname ; then echo "Failed (use -f to force)." echo "The following files failed patching:" echo "$rejects" retcode=2 return fi echo "seems ok." fi echo "Applying $fname..." if patch -p0 -N -t < $fname ; then touch $MARKS/$name echo "Done." else echo "Failed." retcode=1 fi } patch_del() { name=$1 fname="$DIFFS/$name.diff" if test ! -f $fname ; then echo "Patch $name ($fname) does not exist" retcode=3 return fi if test $force -lt 2 -a ! -f $MARKS/$name ; then echo "Patch $name doesn't seem to be applied" retcode=4 return fi if test $force -lt 1 ; then echo -n "Testing $fname... " if ! dry_run $fname -R ; then echo "Failed (use -f to force)." echo "The following files failed patching:" echo "$rejects" retcode=2 return fi echo "seems ok." fi echo "Reversing $fname..." if patch -p0 -R -t < $fname ; then rm -f $MARKS/$name echo "Done." else echo "Failed." retcode=1 fi } do_help() { echo "Usage: $0 [-f [-f]] [args]" echo "Arguments may be:" echo " help Prints this help" echo " list List available patches" echo " test [patch list] Tests whether patches can be (un)applied correctly" echo " add Applies a patch" echo " del Reverses a patch" echo " update Updates $PLIST_FILE with the currently applied patches" echo "The -f option forces patching even if a dry run fails (effective on 'add'" echo "and 'del' commands only). Using it twice will also skip checking whether" echo "a patch is already applied." } while test "$1" = "-f" ; do force=`expr $force + 1` shift done case "$1" in add) shift for name in $* ; do patch_add $name done update_patchlist ;; del) shift for name in $* ; do patch_del $name done update_patchlist ;; test) shift patch_test $* ;; list) patch_list ;; update) update_patchlist ;; *) do_help ;; esac exit $retcode