Merge branch 'u2_10_12_branch' of git://git.code.sf.net/p/undernet-ircu/ircu2
[ircu2.10.12-pk.git] / ircd-patch
diff --git a/ircd-patch b/ircd-patch
new file mode 100755 (executable)
index 0000000..9637b89
--- /dev/null
@@ -0,0 +1,226 @@
+#!/bin/sh
+#
+# IRC - Internet Relay Chat, ircd-patch
+# Copyright (C) 2002 Alex Badea <vampire@p16.pub.ro>
+#
+# 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  <patch list>   Applies a patch"
+       echo "  del  <patch list>   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