Author: Alex Badea <vampire@p16.pub.ro>
[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.4 2002-04-09 22:40:56 vampire 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                 [ -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 [ ! -d $DIFFS ] && (echo "*** Missing $DIFFS, creating it" ; mkdir -p $DIFFS)
59 [ ! -d $MARKS ] && (echo "*** Missing $MARKS, creating it" ; mkdir -p $MARKS)
60
61 dry_run() {
62         patch -p0 -N -t --dry-run $2 >/dev/null < $1
63 }
64
65 patch_list() {
66         echo "Available patches (* marks applied patches):"
67         for name in $PLIST ; do
68                 [ -f $MARKS/$name ] && echo -n " * " || echo -n "   "
69                 echo $name
70         done
71         echo "Done."
72 }
73
74 patch_test() {
75         echo "Testing patches:"
76         list="$*"
77         [ -z "$list" ] && list=$PLIST
78         for name in $list ; do
79                 fname=$DIFFS/$name.diff
80                 echo -ne "  $name\t"
81                 if [ ! -f $MARKS/$name ] ; then
82                         if dry_run "$fname" ; then
83                                 echo -n " OK"
84                         else
85                                 echo -n " PATCH FAILED"
86                                 retcode=2
87                         fi
88                 else
89                         echo -n " APPLIED"
90                         if dry_run "$fname" -R ; then
91                                 echo -n " OK"
92                         else
93                                 echo -n " REVERSE FAILED"
94                                 retcode=2
95                         fi
96                 fi
97                 echo
98         done
99         echo "Done."
100 }
101
102 patch_add() {
103         name=$1
104         fname="$DIFFS/$name.diff"
105         if [ ! -f $fname ]; then
106                 echo "Patch $name ($fname) does not exist"
107                 retcode=3
108                 return
109         fi
110
111         if [ $force -lt 2 -a -f $MARKS/$name ] ; then
112                 echo "Patch $name seems already applied"
113                 retcode=4
114                 return
115         fi
116
117         if [ $force -lt 1 ]; then
118                 echo -n "Testing $fname... "
119                 if ! dry_run $fname ; then
120                         echo "Failed (use -f to force)."
121                         retcode=2
122                         return
123                 fi
124                 echo "seems ok."
125         fi
126
127         echo "Applying $fname..."
128         if patch -p0 -N -t < $fname ; then
129                 touch $MARKS/$name
130                 echo "Done."
131         else
132                 echo "Failed."
133                 retcode=1
134         fi
135 }
136
137 patch_del() {
138         name=$1
139         fname="$DIFFS/$name.diff"
140         if [ ! -f $fname ]; then
141                 echo "Patch $name ($fname) does not exist"
142                 retcode=3
143                 return
144         fi
145
146         if [ $force -lt 2 -a ! -f $MARKS/$name ] ; then
147                 echo "Patch $name doesn't seem to be applied"
148                 retcode=4
149                 return
150         fi
151
152         if [ $force -lt 1 ]; then
153                 echo -n "Testing $fname... "
154                 if ! dry_run $fname -R ; then
155                         echo "Failed (use -f to force)."
156                         retcode=2
157                         return
158                 fi
159                 echo "seems ok."
160         fi
161         
162         echo "Reversing $fname..."
163         if patch -p0 -R -t < $fname ; then
164                 rm -f $MARKS/$name
165                 echo "Done."
166         else
167                 echo "Failed."
168                 retcode=1
169         fi
170 }
171
172 do_help() {
173         echo "Usage: $0 [-f [-f]] [args]"
174         echo "Arguments may be:"
175         echo "  help                Prints this help"
176         echo "  list                List available patches"
177         echo "  test [patch list]   Tests whether patches can be (un)applied correctly"
178         echo "  add  <patch list>   Applies a patch"
179         echo "  del  <patch list>   Reverses a patch"
180         echo "  update              Updates $PLIST_FILE with the currently applied patches"
181         echo "The -f option forces patching even if a dry run fails (effective on 'add'"
182         echo "and 'del' commands only). Using it twice will also skip checking whether"
183         echo "a patch is already applied."
184 }
185
186 while [ "$1" == "-f" ]; do
187         force=$[$force + 1]
188         shift
189 done
190
191 case "$1" in
192         add)
193                 shift
194                 for name in $* ; do
195                         patch_add $name
196                 done
197                 update_patchlist
198                 ;;
199         del)
200                 shift
201                 for name in $* ; do
202                         patch_del $name
203                 done
204                 update_patchlist
205                 ;;
206         test)
207                 shift
208                 patch_test $*
209                 ;;
210         list)
211                 patch_list
212                 ;;
213         update)
214                 update_patchlist
215                 ;;
216         *)
217                 do_help
218                 ;;
219 esac
220
221 exit $retcode