#!/bin/sh
#
-# ircd-patch
+# 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
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
- [ -f $MARKS/$name ] && echo -n " * " || echo -n " "
+ test -f $MARKS/$name && echo -n " * " || echo -n " "
echo $name
done
echo "Done."
patch_test() {
echo "Testing patches:"
list="$*"
- [ -z "$list" ] && list=$PLIST
+ test "z$list" = "z" && list=$PLIST
for name in $list ; do
fname=$DIFFS/$name.diff
- echo -n " "
- if [ ! -f $MARKS/$name ] ; then
- echo -n " "
- if patch -p0 -N -t --dry-run >/dev/null < $fname ; then
- echo -n " "
+ echo -ne " $name\t"
+ if test ! -f $MARKS/$name ; then
+ if dry_run "$fname" ; then
+ echo -n " OK"
else
- echo -n "fail "
+ echo -n " PATCH FAILED"
+ retcode=2
fi
else
- echo -n "applied "
- if patch -p0 -R -t --dry-run >/dev/null < $fname ; then
- echo -n " "
+ echo -n " APPLIED"
+ if dry_run "$fname" -R ; then
+ echo -n " OK"
else
- echo -n "fail "
+ echo -n " REVERSE FAILED"
+ retcode=2
fi
fi
- echo " $name"
+ echo
done
echo "Done."
}
patch_add() {
name=$1
fname="$DIFFS/$name.diff"
- if [ ! -f $fname ]; then
+ if test ! -f $fname ; then
echo "Patch $name ($fname) does not exist"
- return 1
+ retcode=3
+ return
fi
- if [ -f $MARKS/$name ] ; then
+
+ if test $force -lt 2 -a -f $MARKS/$name ; then
echo "Patch $name seems already applied"
- return 1
+ 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 [ ! -f $fname ]; then
+ if test ! -f $fname ; then
echo "Patch $name ($fname) does not exist"
- return 1
+ retcode=3
+ return
fi
- if [ ! -f $MARKS/$name ] ; then
+
+ if test $force -lt 2 -a ! -f $MARKS/$name ; then
echo "Patch $name doesn't seem to be applied"
- return 1
+ 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 [args]"
+ 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 " 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
list)
patch_list
;;
+ update)
+ update_patchlist
+ ;;
*)
do_help
;;
esac
+
+exit $retcode