]> git.decadent.org.uk Git - dak.git/blob - config/debian/cron.dinstall
local is nice for variables in functions
[dak.git] / config / debian / cron.dinstall
1 #!/bin/bash
2 # No way I try to deal with a crippled sh just for POSIX foo.
3
4 # Copyright (C) 2009-2012 Joerg Jaspert <joerg@debian.org>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; version 2.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 # Homer: Are you saying you're never going to eat any animal again? What
20 #        about bacon?
21 # Lisa: No.
22 # Homer: Ham?
23 # Lisa: No.
24 # Homer: Pork chops?
25 # Lisa: Dad, those all come from the same animal.
26 # Homer: Heh heh heh. Ooh, yeah, right, Lisa. A wonderful, magical animal.
27
28 # exit on errors
29 set -e
30 set -o pipefail
31 # make sure to only use defined variables
32 set -u
33 # ERR traps should be inherited from functions too. (And command
34 # substitutions and subshells and whatnot, but for us the functions is
35 # the important part here)
36 set -E
37
38 # import the general variable set.
39 export SCRIPTVARS=/srv/ftp-master.debian.org/dak/config/debian/vars
40 . $SCRIPTVARS
41
42 ########################################################################
43 # Functions                                                            #
44 ########################################################################
45 # common functions are "outsourced"
46 . "${configdir}/common"
47
48 # source the dinstall functions
49 . "${configdir}/dinstall.functions"
50
51 ########################################################################
52 ########################################################################
53
54 # Function to save which stage we are in, so we can restart an interrupted
55 # dinstall. Or even run actions in parallel, if we dare to, by simply
56 # backgrounding the call to this function. But that should only really be
57 # done for things we don't care much about.
58 #
59 # This should be called with the first argument being an array, with the
60 # members
61 #  - FUNC - the function name to call
62 #  - ARGS - Possible arguments to hand to the function. Can be the empty string
63 #  - TIME - The timestamp name. Can be the empty string
64 #  - ERR  - if this is the string false, then the call will be surrounded by
65 #           set +e ... set -e calls, so errors in the function do not exit
66 #           dinstall. Can be the empty string, meaning true.
67 #
68 # MAKE SURE TO KEEP THIS THE LAST FUNCTION, AFTER ALL THE VARIOUS ONES
69 # ADDED FOR DINSTALL FEATURES!
70 function stage() {
71     ARGS='GO[@]'
72     local "${!ARGS}"
73
74     local error=${ERR:-"true"}
75
76     ARGS=${ARGS:-""}
77
78     log "########## DINSTALL BEGIN: ${FUNC} ${ARGS} ##########"
79     local STAGEFILE="${stagedir}/${FUNC}_${ARGS}"
80     STAGEFILE=${STAGEFILE// /_}
81     if [ -f "${STAGEFILE}" ]; then
82         local stamptime=$(/usr/bin/stat -c %Z "${STAGEFILE}")
83         local unixtime=$(date +%s)
84         local difference=$(( $unixtime - $stamptime ))
85         if [ ${difference} -ge 14400 ]; then
86             log_error "Did already run ${FUNC}, stagefile exists, but that was ${difference} seconds ago. Please check."
87         else
88             log "Did already run ${FUNC}, not calling again..."
89         fi
90         return
91     fi
92
93     debug "Now calling function ${FUNC}. Arguments: ${ARGS}. Timestamp: ${TIME}"
94
95     # Make sure we are always at the same place. If a function wants to be elsewhere,
96     # it has to cd first!
97     cd ${configdir}
98
99     # Now redirect the output into $STAGEFILE.log. In case it errors out somewhere our
100     # errorhandler trap can then mail the contents of $STAGEFILE.log only, instead of a whole
101     # dinstall logfile. Short error mails ftw!
102     exec >> "${STAGEFILE}.log" 2>&1
103
104     if [ -f "${LOCK_STOP}" ]; then
105         log "${LOCK_STOP} exists, exiting immediately"
106         exit 42
107     fi
108
109     if [ "${error}" = "false" ]; then
110         set +e
111     fi
112     ${FUNC} ${ARGS}
113
114     # No matter what happened in the function, we make sure we have set -e default state back
115     set -e
116
117     # Make sure we are always at the same place.
118     cd ${configdir}
119
120     # We always use the same umask. If a function wants to do different, fine, but we reset.
121     umask 022
122
123     touch "${STAGEFILE}"
124
125     if [ -n "${TIME}" ]; then
126         ts "${TIME}"
127     fi
128
129     # And the output goes back to the normal logfile
130     exec >> "$LOGFILE" 2>&1
131
132     # Now we should make sure that we have a usable dinstall.log, so append the $STAGEFILE.log
133     # to it.
134     cat "${STAGEFILE}.log" >> "${LOGFILE}"
135     rm -f "${STAGEFILE}.log"
136
137     log "########## DINSTALL END: ${FUNC} ##########"
138
139     if [ -f "${LOCK_STOP}" ]; then
140         log "${LOCK_STOP} exists, exiting immediately"
141         exit 42
142     fi
143 }
144
145 ########################################################################
146
147 # We need logs.
148 LOGFILE="$logdir/dinstall.log"
149
150 exec >> "$LOGFILE" 2>&1
151
152 # And now source our default config
153 . "${configdir}/dinstall.variables"
154
155 # Make sure we start out with a sane umask setting
156 umask 022
157
158 # And use one locale, no matter what the caller has set
159 export LANG=C
160 export LC_ALL=C
161
162 touch "${DINSTALLSTART}"
163 ts "startup"
164 DINSTALLBEGIN="$(date -u +"%a %b %d %T %Z %Y (%s)")"
165 state "Startup"
166
167 lockfile -l 3600 "${LOCK_DAILY}"
168 trap onerror ERR
169 trap remove_daily_lock EXIT TERM HUP INT QUIT
170
171 touch "${LOCK_BRITNEY}"
172
173 # This loop simply wants to be fed by a list of values (see below)
174 # which consists of 5 values currently.
175 # The first four are the array values for the stage function, the
176 # fifths tells us if we should background the stage call.
177 #
178 #  - FUNC - the function name to call
179 #  - ARGS - Possible arguments to hand to the function. Can be the empty string
180 #  - TIME - The timestamp name. Can be the empty string
181 #  - ERR  - if this is the string false, then the call will be surrounded by
182 #           set +e ... set -e calls, so errors in the function do not exit
183 #           dinstall. Can be the empty string, meaning true.
184 #  - BG   - Background the function stage?
185 #
186 # ATTENTION: Spaces in arguments or timestamp names need to be escaped by \
187 #
188 # ATTENTION: There are two special values for the first column (FUNC).
189 #            STATE   - do not call stage function, call the state
190 #                      function to update the public statefile "where is dinstall"
191 #            NOSTAGE - do not call stage function, call the command directly.
192 while read FUNC ARGS TIME ERR BACKGROUND; do
193     debug "FUNC: $FUNC ARGS: $ARGS TIME: $TIME ERR: $ERR BG: $BACKGROUND"
194
195     # Empty values in the value list are the string "none" (or the
196     # while read loop won't work). Here we ensure that variables that
197     # can be empty, are empty if the string none is set for them.
198     for var in ARGS TIME; do
199         if [[ ${!var} == none ]]; then
200             typeset ${var}=''
201         fi
202     done
203
204     case ${FUNC} in
205         STATE)
206             state ${ARGS}
207         ;;
208         NOSTAGE)
209             ${ARGS}
210         ;;
211         *)
212             GO=(
213                 FUNC=${FUNC}
214                 TIME=${TIME}
215                 ARGS=${ARGS}
216                 ERR=${ERR}
217             )
218             if [[ ${BACKGROUND} == true ]]; then
219                 stage $GO &
220             else
221                 stage $GO
222             fi
223         ;;
224     esac
225 done < <(cat - <<EOF
226 savetimestamp          none                       none                       false   false
227 qa1                    none                       init                       true    true
228 pg_timestamp           predinstall                pg_dump1                   false   false
229 updates                none                       External\ Updates          false   false
230 i18n1                  none                       i18n\ 1                    false   false
231 dep11                  none                       dep11\ 1                   false   false
232 NOSTAGE                lockaccepted               none                       false   false
233 punew                  stable-new                 p-u-new                    false   false
234 opunew                 oldstable-new              o-p-u-new                  false   false
235 backports_policy       none                       backports-policy           false   false
236 cruft                  none                       cruft                      false   false
237 STATE                  indices                    none                       false   false
238 dominate               none                       dominate                   false   false
239 autocruft              unstable\ experimental     autocruft                  false   false
240 fingerprints           none                       import-keyring             false   false
241 overrides              none                       overrides                  false   false
242 mpfm                   none                       pkg-file-mapping           false   false
243 STATE                  packages/contents          none                       false   false
244 packages               none                       apt-ftparchive             false   false
245 STATE                  dists/                     none                       false   false
246 pdiff                  none                       pdiff                      false   false
247 release                none                       release\ files             false   false
248 dakcleanup             none                       cleanup                    false   false
249 STATE                  scripts                    none                       false   false
250 mkmaintainers          none                       mkmaintainers              false   false
251 copyoverrides          none                       copyoverrides              false   false
252 mklslar                none                       mklslar                    false   false
253 mkfilesindices         none                       mkfilesindices             false   false
254 mkchecksums            none                       mkchecksums                false   false
255 mirror                 none                       mirror\ hardlinks          false   false
256 ddaccess               none                       ddaccessible\ sync         false   false
257 NOSTAGE                remove_locks               none                       false   false
258 STATE                  postlock                   none                       false   false
259 changelogs             none                       changelogs                 false   true
260 pg_timestamp           postdinstall               pg_dump2                   false   false
261 expire                 none                       expire_dumps               false   true
262 transitionsclean       none                       transitionsclean           false   true
263 dm                     none                       none                       false   true
264 bts                    none                       none                       false   true
265 mirrorpush             none                       mirrorpush                 false   true
266 mirrorpush-backports   none                       mirrorpush-backports       false   true
267 i18n2                  none                       i18n\ 2                    false   true
268 stats                  none                       stats                      false   true
269 testingsourcelist      none                       none                       false   true
270 NOSTAGE                rm\ -f\ "\${LOCK_BRITNEY}" none                       false   false
271 cleantransactions      none                       none                       false   false
272 EOF
273         )
274
275 # we need to wait for the background processes before the end of dinstall
276 wait
277
278 log "Daily cron scripts successful, all done"
279
280 exec > "$logdir/afterdinstall.log" 2>&1
281
282 GO=(
283     FUNC="renamelogfile"
284     TIME=""
285     ARGS=""
286     ERR="false"
287 )
288 stage $GO
289 state "all done"
290
291
292 # Now, at the very (successful) end of dinstall, make sure we remove
293 # our stage files, so the next dinstall run will do it all again.
294 rm -f ${stagedir}/*
295 touch "${DINSTALLEND}"