keep in sync with OGN upstream (SVN-326)
[ircu2.10.12-pk.git] / ircd-patch
1 #!/bin/sh
2 #
3 # IRC - Internet Relay Chat, ircd-patch
4 # Copyright (C) 2002 Alex Badea <vampire@p16.pub.ro>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 1, or (at your option)
9 # any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #
20 # $Id: ircd-patch,v 1.5.2.1 2005-12-29 03:41:56 entrope Exp $
21 #
22 #
23 # Experimental centralized patch system for ircu
24 # Run with no arguments to get help.
25 #
26 # Return codes:
27 #   0 - success
28 #   1 - at least one live patch failed
29 #   2 - at least one simulation (dry run) failed 
30 #   3 - invalid arguments (i.e. no such patch)
31 #   4 - invalid operation (i.e. tried to apply when already applied)
32 #
33
34 DIFFS=patches/diffs
35 MARKS=patches/marks
36 PLIST_FILE=include/patchlist.h
37
38 retcode=0
39 force=0
40
41
42 PLIST=""
43 for fname in $DIFFS/*.diff ; do
44         name=`basename $fname | sed -e 's/\.diff//'`
45         PLIST="$PLIST $name"
46 done
47
48 update_patchlist() {
49         list=""
50         for name in $PLIST ; do
51                 test -f $MARKS/$name && list="$list.$name"
52         done
53         echo "/* This file was automatically generated by ircd-patch */" > $PLIST_FILE
54         echo "#define PATCHLIST \"$list\"" >> $PLIST_FILE
55         echo "Updated $PLIST_FILE"
56 }
57
58 test -d $DIFFS || (echo "*** Missing $DIFFS, creating it" ; mkdir -p $DIFFS)
59 test -d $MARKS || (echo "*** Missing $MARKS, creating it" ; mkdir -p $MARKS)
60
61 dry_run() {
62         rejects=`patch -p0 -N -t --dry-run $2 < $1 | grep "hunk FAILED" | sed -e 's/.*to file /  /;s/\.rej$//'`
63         test -z "$rejects"
64 }
65
66 patch_list() {
67         echo "Available patches (* marks applied patches):"
68         for name in $PLIST ; do
69                 test -f $MARKS/$name && echo -n " * " || echo -n "   "
70                 echo $name
71         done
72         echo "Done."
73 }
74
75 patch_test() {
76         echo "Testing patches:"
77         list="$*"
78         test "z$list" = "z" && list=$PLIST
79         for name in $list ; do
80                 fname=$DIFFS/$name.diff
81                 echo -ne "  $name\t"
82                 if test ! -f $MARKS/$name ; then
83                         if dry_run "$fname" ; then
84                                 echo -n " OK"
85                         else
86                                 echo -n " PATCH FAILED"
87                                 retcode=2
88                         fi
89                 else
90                         echo -n " APPLIED"
91                         if dry_run "$fname" -R ; then
92                                 echo -n " OK"
93                         else
94                                 echo -n " REVERSE FAILED"
95                                 retcode=2
96                         fi
97                 fi
98                 echo
99         done
100         echo "Done."
101 }
102
103 patch_add() {
104         name=$1
105         fname="$DIFFS/$name.diff"
106         if test ! -f $fname ; then
107                 echo "Patch $name ($fname) does not exist"
108                 retcode=3
109                 return
110         fi
111
112         if test $force -lt 2 -a -f $MARKS/$name ; then
113                 echo "Patch $name seems already applied"
114                 retcode=4
115                 return
116         fi
117
118         if test $force -lt 1 ; then
119                 echo -n "Testing $fname... "
120                 if ! dry_run $fname ; then
121                         echo "Failed (use -f to force)."
122                         echo "The following files failed patching:"
123                         echo "$rejects"
124                         retcode=2
125                         return
126                 fi
127                 echo "seems ok."
128         fi
129
130         echo "Applying $fname..."
131         if patch -p0 -N -t < $fname ; then
132                 touch $MARKS/$name
133                 echo "Done."
134         else
135                 echo "Failed."
136                 retcode=1
137         fi
138 }
139
140 patch_del() {
141         name=$1
142         fname="$DIFFS/$name.diff"
143         if test ! -f $fname ; then
144                 echo "Patch $name ($fname) does not exist"
145                 retcode=3
146                 return
147         fi
148
149         if test $force -lt 2 -a ! -f $MARKS/$name ; then
150                 echo "Patch $name doesn't seem to be applied"
151                 retcode=4
152                 return
153         fi
154
155         if test $force -lt 1 ; then
156                 echo -n "Testing $fname... "
157                 if ! dry_run $fname -R ; then
158                         echo "Failed (use -f to force)."
159                         echo "The following files failed patching:"
160                         echo "$rejects"
161                         retcode=2
162                         return
163                 fi
164                 echo "seems ok."
165         fi
166         
167         echo "Reversing $fname..."
168         if patch -p0 -R -t < $fname ; then
169                 rm -f $MARKS/$name
170                 echo "Done."
171         else
172                 echo "Failed."
173                 retcode=1
174         fi
175 }
176
177 do_help() {
178         echo "Usage: $0 [-f [-f]] [args]"
179         echo "Arguments may be:"
180         echo "  help                Prints this help"
181         echo "  list                List available patches"
182         echo "  test [patch list]   Tests whether patches can be (un)applied correctly"
183         echo "  add  <patch list>   Applies a patch"
184         echo "  del  <patch list>   Reverses a patch"
185         echo "  update              Updates $PLIST_FILE with the currently applied patches"
186         echo "The -f option forces patching even if a dry run fails (effective on 'add'"
187         echo "and 'del' commands only). Using it twice will also skip checking whether"
188         echo "a patch is already applied."
189 }
190
191 while test "$1" = "-f" ; do
192         force=`expr $force + 1`
193         shift
194 done
195
196 case "$1" in
197         add)
198                 shift
199                 for name in $* ; do
200                         patch_add $name
201                 done
202                 update_patchlist
203                 ;;
204         del)
205                 shift
206                 for name in $* ; do
207                         patch_del $name
208                 done
209                 update_patchlist
210                 ;;
211         test)
212                 shift
213                 patch_test $*
214                 ;;
215         list)
216                 patch_list
217                 ;;
218         update)
219                 update_patchlist
220                 ;;
221         *)
222                 do_help
223                 ;;
224 esac
225
226 exit $retcode