/usr/sbin/delve
1 #!/bin/bash
2 #---------------------------------------------------------------------
3 ## @Synopsis Delve is a tool for running individual spell files during the
4 ## @Synopsis build and install phase. This can be used as a debugging tool or to
5 ## @Synopsis "force" a spell to be installed. Use with caution and keep your hands
6 ## @Synopsis off if you dont know what you are doing.
7 ##
8 ## @Copyright 2004 the Source Mage Team
9 ## @Author Andrew Stitt
10 #---------------------------------------------------------------------
11
12 function help">help">help() {
13
14 cat << EOF
15 Delve allows the running of single spell files in the build/install phase
16
17 NOTE: this is a low level tool and should not be necessary in normal
18 situations. It is a bit of a big hammer not everything is a nail :)
19 You can do serious harm to your box if used improperly, also little
20 sanity checking is done because it is intended to circumvent some of
21 the normal restrictions of cast. Please use with care or not at all.
22
23 Usage:
24
25 delve spellname SPELL_FILE [... SPELL_FILE]
26 delve spellname success|failure
27 delve spellname all
28
29 Parameters
30
31 -f | --force Continue running files even if one fails
32 (use with caution!)
33
34 -g | --grimoire [...] Use only the specified grimoires for this cast
35 NOTE: If there are any cross-grimoire
36 dependencies on unspecified grimoires they
37 will not work. The target spell will
38 not be found. To avoid this, specify all
39 relevant grimoires to the -g parameter
40 in the order you wish them to be searched.
41
42 -c | --continue start end Run all the files from start to end:
43
44 delve -c start BUILD spellname
45 will run everything for spellname from begining through building
46
47 delve -c INSTALL end spellname
48 will run everything for spellname from INSTALL to success or fail
49
50 Spell file names and other values:
51 start, PRE_BUILD, config_loc, BUILD, PRE_INSTALL, INSTALL, POST_BUILD,
52 POST_INSTALL, FINAL, TRIGGERS, end, success, failure, all.
53
54 "start" and "end" are place holders for the start/end of the process,
55 mostly only meaningful with the -c option.
56
57 "config_loc" is the phase of cast where it asks you about adding stuff to
58 ./configure
59
60 "end" can be either success or failure depending on the return value of
61 the previous state (note, without -f delve will bail out immediatly).
62
63 "all" runs all the states for a given spell.
64
65 All other files should be self evident
66
67 Delve is conscious of build api versions and will refuse to run files
68 that do not exist in the spell's api. The -c option will file in the
69 appropriate files for the spell.
70
71 EOF
72
73 exit 1
74
75 }
76
77 #---------------------------------------------------------------------------
78 ## Loads OPTS and all the other log files to provide the appropriate
79 ## environment for spell files
80 #---------------------------------------------------------------------------
81 function delve_log_helper() {
82
83 if ! [[ "$__DELVE_IN_CAST" ]] ; then
84 # must declare OPTS before sourcing config
85 local OPTS
86 run_spell_config
87
88 get_uncommitted_depends_file $SPELL spell_depends
89 lock_file $ABANDONED_DEPENDS/$SPELL
90 if test -e $spell_depends && test -e $ABANDONED_DEPENDS/$SPELL ; then
91 cp $ABANDONED_DEPENDS/$SPELL $spell_depends
92 fi
93 unlock_file $ABANDONED_DEPENDS/$SPELL
94 test -e $spell_depends &&
95 OPTS="$OPTS $(get_depends_options $spell_depends $SPELL)"
96 fi
97
98 save_bin_lib_paths
99
100 # these have to go somewhere where future delves can find them
101 C_LOG=${C_LOG:="/tmp/sorcery/delve/$SPELL.compile.log"}
102 CASTFS_DBGLOG=${CASTFS_DBGLOG:="/tmp/sorcery/delve/$SPELL.iwdbglog"}
103 C_FIFO=${C_FIFO:="/dev/stdout"}
104 IW_LOG=${IW_LOG:="/tmp/sorcery/delve/$SPELL.iw"}
105 VOYEUR_STDOUT=${VOYEUR_STDOUT:="/dev/stdout"}
106 VOYEUR_STDERR=${VOYEUR_STDERR:="/dev/stderr"}
107 S_PWD=${S_PWD:="/tmp/sorcery/delve/$SPELL.pwd"}
108 touch $C_LOG
109
110 }
111
112 #---------------------------------------------------------------------------
113 ## Determines if a step is valid for the current spell
114 ## @param name of step
115 ## @param all the remaining parameters are numbers for which the step is valid
116 ## @stdout a complaint if the step is not valid
117 ##
118 ## if the BUILD_API number is not found in the parameter list complain
119 ## and return 1
120 #---------------------------------------------------------------------------
121 function delve_is_valid_step() {
122 local STEP=$1
123 local found
124 shift
125 for api in $@; do
126 if [ "$BUILD_API" == "$api" ] ; then
127 found=yes
128 break
129 fi
130 done
131 if [[ ! $found ]] ; then
132 message "Refusing to run $STEP for build api $BUILD_API"
133 return 1
134 fi
135 return 0
136 }
137
138 function delve_pre_build() {
139 debug "delve" "Running $FUNCNAME"
140 delve_is_valid_step PRE_BUILD 1 2 || return 1
141 run_pre_build">run_pre_build
142 }
143
144 function delve_config_loc() {
145 debug "delve" "Running $FUNCNAME"
146 delve_is_valid_step config_loc 1 2 || return 1
147 run_config_loc
148 }
149
150 function delve_build() {
151 debug "delve" "Running $FUNCNAME"
152 delve_is_valid_step BUILD 1 2 || return 1
153 delve_log_helper
154 (
155 run_build">run_build
156 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
157 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
158 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
159 }
160
161 function delve_pre_install() {
162 debug "delve" "Running $FUNCNAME"
163 delve_is_valid_step PRE_INSTALL 2 || return 1
164 delve_log_helper
165 (
166 run_pre_install
167 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
168 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
169 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
170 }
171
172 function delve_install() {
173 debug "delve" "Running $FUNCNAME"
174
175 delve_is_valid_step INSTALL 2 || return 1
176 delve_log_helper
177 if [[ "$STAGED_INSTALL" != "off" ]]
178 then
179 if [[ -z "$CHROOT_CHECK" ]]
180 then
181 prepare_stage_root &&
182 invoke_stage_root &&
183 export CHROOT_CHECK="true"
184 CHROOT_CMD="chroot ${STAGE_DIRECTORY}/MOUNT"
185 fi
186 INSTALL_ROOT=""
187 else
188 invoke_installwatch
189 fi
190 (
191 if [[ -z "$CHROOT_CMD" ]]
192 then
193 run_install || return 2
194 else
195 $CHROOT_CMD delve $SPELL INSTALL
196 fi
197 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
198 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
199 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
200 local rc=$?
201 if [[ $CHROOT_CMD ]]
202 then
203 devoke_stage_root
204 fi &&
205 return $rc
206 }
207
208 function delve_install_extras() {
209 debug "delve" "Running $FUNCNAME"
210
211 delve_is_valid_step INSTALL_EXTRAS 2 || return 1
212 delve_log_helper
213 if [[ "$STAGED_INSTALL" != "off" ]]
214 then
215 if [[ -z "$CHROOT_CHECK" ]]
216 then
217 invoke_stage_root &&
218 export CHROOT_CHECK="true"
219 CHROOT_CMD="chroot ${STAGE_DIRECTORY}/MOUNT"
220 fi
221 INSTALL_ROOT=""
222 else
223 invoke_installwatch
224 fi
225 (
226 if [[ -z "$CHROOT_CMD" ]]
227 then
228 run_install_extras || return 2
229 else
230 $CHROOT_CMD delve $SPELL INSTALL_EXTRAS
231 fi
232 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
233 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
234 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
235 local rc=$?
236 if [[ $CHROOT_CMD ]]
237 then
238 devoke_stage_root
239 fi &&
240 return $rc
241 }
242
243 function delve_post_build() {
244 debug "delve" "Running $FUNCNAME"
245
246 delve_is_valid_step POST_BUILD 1 || return 1
247 delve_log_helper
248 [ -d $SOURCE_DIRECTORY ] || {
249 message "Ack! there is no $SOURCE_DIRECTORY"
250 return 1
251 }
252 cd $SOURCE_DIRECTORY
253 (
254 run_post_build
255 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
256 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
257 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
258 }
259
260 function delve_post_install() {
261 debug "delve" "Running $FUNCNAME"
262 delve_is_valid_step POST_INSTALL 1 2 || return 1
263 delve_log_helper
264 (
265 run_post_install">run_post_install
266 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
267 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
268 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
269 }
270
271 function delve_transfer() {
272 debug "delve" "Running $FUNCNAME"
273 delve_is_valid_step TRANSFER 2 || return 1
274 delve_log_helper
275 (
276 run_transfer
277 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
278 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
279 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
280 }
281
282 function delve_final() {
283 debug "delve" "Running $FUNCNAME"
284 delve_is_valid_step FINAL 2 || return 1
285 delve_log_helper
286 devoke_installwatch &&
287 STAGED_INSTALL=off
288 (
289 run_final
290 ) 3> >(tee -a $C_LOG >> /dev/stdout) \
291 2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
292 > >(tee -a $C_LOG > $VOYEUR_STDOUT)
293
294 }
295
296 function delve_triggers() {
297 debug "delve" "Running $FUNCNAME"
298 delve_is_valid_step TRIGGERS 1 2 || return 1
299 run_triggers
300 }
301
302 function delve_spell_success() {
303 debug "delve" "Running $FUNCNAME"
304 SUCCESS_LIST=/dev/null
305 cd /
306 delve_log_helper
307 run_spell_success
308 }
309
310 function delve_spell_failure() {
311 debug "delve" "Running $FUNCNAME"
312 FAILED_LIST=/dev/null
313 delve_log_helper
314 run_spell_failure 2
315 }
316
317 #---------------------------------------------------------------------------
318 ## @param begin state
319 ## @param end state
320 ## @global BUILD_API
321 ## fill in the states from begin to end from the given BUILD_API
322 #---------------------------------------------------------------------------
323 function delve_make_continuation() {
324 local begin=$1
325 local end=$2
326 local API1="start PRE_BUILD config_loc BUILD POST_BUILD POST_INSTALL TRIGGERS end"
327 local API2="start PRE_BUILD config_loc BUILD PRE_INSTALL INSTALL INSTALL_EXTRAS POST_INSTALL TRANSFER FINAL TRIGGERS end"
328 local THIS_API
329 case $BUILD_API in
330 1) THIS_API=$API1 ;;
331 2) THIS_API=$API2 ;;
332 *) message "Unknown api for spell $SPELL: \"$BUILD_API\"" ; return 1;;
333 esac
334 local phase=0
335 local state
336 local states
337 for state in $THIS_API; do
338 case $phase in
339 0)
340 if [ "$state" == "$begin" ]; then
341 phase=1
342 fi
343 states="$state"
344 ;;
345 1)
346 states="$states $state"
347 if [ "$state" == "$end" ]; then
348 phase=2
349 break
350 fi
351 ;;
352 esac
353 done
354 if [ $phase != 2 ] ; then
355 message "Error making continuation"
356 return 1
357 fi
358 echo $states
359 return 0
360 }
361
362 #---------------------------------------------------------------------------
363 ## fills in STATES, continue_start, continue_end, and FORCE as applicable
364 #---------------------------------------------------------------------------
365 function process_parameters">process_parameters">process_parameters() {
366 for param in $@ ; do
367 case $param in
368 -f|--force) FORCE=on ;;
369 -c|--continue) continue_start=$2
370 continue_end=$3
371 shift 2
372 ;;
373 -g|--grimoire*) override_grimoires "$2";
374 shift 2 ;;
375 start) ;;
376 PRE_BUILD) STATES="$STATES $param" ;;
377 config_loc) STATES="$STATES $param" ;;
378 BUILD) STATES="$STATES $param" ;;
379 PRE_INSTALL) STATES="$STATES $param" ;;
380 INSTALL) STATES="$STATES $param" ;;
381 POST_BUILD) STATES="$STATES $param" ;;
382 INSTALL_EXTRAS) STATES="$STATES $param" ;;
383 POST_INSTALL) STATES="$STATES $param" ;;
384 TRANSFER) STAGES="$STAGES $param" ;;
385 FINAL) STATES="$STATES $param" ;;
386 TRIGGERS) STATES="$STATES $param" ;;
387 success) STATES="$STATES $param" ;;
388 failure) STATES="$STATES $param" ;;
389 end) STATES="$STATES $param" ;;
390 all) ALL=on ;;
391 -*) help">help">help ;;
392 *) SPELL=$param ;;
393 esac
394 done
395 }
396
397 #---------------------------------------------------------------------------
398 ## This is obviously the main">main">main">main">main function of delve, it loads the spell
399 ## figures out what states to run and then loops through them.
400 #---------------------------------------------------------------------------
401 function main">main">main">main">main() {
402
403 local STATES STATE
404 local FORCE ALL SPELL
405 local continue_start continue_end
406 process_parameters">process_parameters">process_parameters $@
407
408 if [[ $OVERRIDE_GRIMOIRES ]] ; then
409 codex_set_grimoires $OVERRIDE_GRIMOIRES
410 fi
411
412 codex_does_spell_exist $SPELL || return 1
413 codex_set_current_spell_by_name $SPELL
414 load_build_api
415 if [[ $continue_start ]] && [[ $continue_end ]] ; then
416 STATES=$(delve_make_continuation $continue_start $continue_end)
417 elif [[ $ALL ]] ; then
418 STATES=$(delve_make_continuation start end)
419 fi
420
421 if [[ -z $CHROOT_CHECK ]]
422 then
423 if [[ -z $STAGED_INSTALL ]]
424 then
425 if ! is_castfs_installed
426 then
427 STAGED_INSTALL=off
428 else
429 STAGED_INSTALL=on
430 fi
431 fi
432 fi
433
434 local last_rc=0
435 for STATE in $STATES; do
436 case $STATE in
437 start) ;;
438 PRE_BUILD) delve_pre_build ;;
439 config_loc) delve_config_loc ;;
440 BUILD) delve_build ;;
441 PRE_INSTALL) delve_pre_install ;;
442 INSTALL) delve_install ;;
443 POST_BUILD) delve_post_build ;;
444 INSTALL_EXTRAS) delve_install_extras ;;
445 POST_INSTALL) delve_post_install ;;
446 TRANSFER) delve_transfer ;;
447 FINAL) delve_final ;;
448 TRIGGERS) delve_triggers ;;
449 success) delve_spell_success ;;
450 failure) delve_spell_failure ;;
451 end)if [[ $last_rc == 0 ]] ; then
452 delve_spell_success
453 else
454 delve_spell_failure
455 fi ;;
456 esac
457 last_rc=$?
458 if [[ $last_rc != 0 ]] && [ "$FORCE" != 1 ] ; then
459 message "$STATE failed!"
460 return 1
461 fi
462 done
463 }
464
465 . /etc/sorcery/config
466 if [ $# -eq 0 ]; then help">help">help | $PAGER
467 elif [[ $1 == -h ]] || [[ $1 == --help ]] ; then help">help">help
468 elif [ "$UID" -gt 0 ]; then
469 # validate the parameters before su-ing, since we may still drop out
470 process_parameters">process_parameters">process_parameters "$@"
471
472 echo "Enter the root password, please."
473 PARAMS=$(consolidate_params "$@")
474 exec su -c "delve $PARAMS" root
475 else
476 # Make a nice dir structure to put stuff in, this exits if it fails
477 mk_tmp_dirs delve
478 main">main">main">main">main "$@"
479 rc=$?
480 cleanup_tmp_dir $TMP_DIR
481 exit $rc
482 fi
483
484 debug "delve" "exiting..."
485
486 #---------------------------------------------------------------------
487 ##=back
488 ##
489 ##=head1 LICENSE
490 ##
491 ## This software is free software; you can redistribute it and/or modify
492 ## it under the terms of the GNU General Public License as published by
493 ## the Free Software Foundation; either version 2 of the License, or
494 ## (at your option) any later version.
495 ##
496 ## This software is distributed in the hope that it will be useful,
497 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
498 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
499 ## GNU General Public License for more details.
500 ##
501 ## You should have received a copy of the GNU General Public License
502 ## along with this software; if not, write to the Free Software
503 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
504 ##
505 #---------------------------------------------------------------------