diff options
author | Dieter Plaetinck <dieter@plaetinck.be> | 2008-11-16 19:06:21 +0100 |
---|---|---|
committer | Dieter Plaetinck <dieter@plaetinck.be> | 2008-11-16 19:06:21 +0100 |
commit | aef60a91f36974b2b054cd6f6296615a2553bf4c (patch) | |
tree | 5e38e127482fdf1de41924ec25668ad14407d85f /src/aif.sh | |
parent | d8b38a0768f6e71dec55d4d70d4dca74327a7420 (diff) |
updated HOWTO for install using packages, got rid of patch-install-cd script + renamed fifa into aif everywhere
Diffstat (limited to 'src/aif.sh')
-rwxr-xr-x | src/aif.sh | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/aif.sh b/src/aif.sh new file mode 100755 index 0000000..1e23708 --- /dev/null +++ b/src/aif.sh @@ -0,0 +1,275 @@ +#!/bin/bash + +###### Set some default variables or get them from the setup script ###### +TITLE="Arch Linux Installation Framework" +LOG="/dev/tty7" +LOGFILE=/home/arch/aif/runtime/aif.log #TODO: maybe we could use a flag to en/disable logging to a file. + + +###### Miscalleaneous functions ###### + +usage () +{ + #NOTE: you can't use dia mode here yet because lib-ui isn't sourced yet. But cli is ok for this anyway. + msg="$0 <procedurename>\n +If the procedurename starts with 'http://' it will be wget'ed. Otherwise it's assumed to be a procedure in the VFS tree +If the procedurename is prefixed with '<modulename>/' it will be loaded from user module <modulename>. See README\n +Available procedures on the filesystem: +`find /home/arch/aif/core/procedures -type f`\n +`find /home/arch/aif/user/*/procedures -type f 2>/dev/null`" + echo -e "$msg" + +} + +##### TMP functions that we need during early bootstrap but will be overidden with decent functions by libraries ###### + + +notify () +{ + echo -e "$@" +} + + +log () +{ + str="[LOG] `date +"%Y-%m-%d %H:%M:%S"` $@" + echo -e "$str" + echo -e "$str" > $LOG + echo -e "$str" >> $LOGFILE +} + + +debug () +{ + str="[DEBUG] $@" + if [ "$DEBUG" = "1" ] + then + echo -e "$str" + echo -e "$str" > $LOG + echo -e "$str" >> $LOGFILE + fi +} + + +###### Core functions ###### + + +# $1 module name +load_module () +{ + [ -z "$1" ] && die_error "load_module needs a module argument" + log "Loading module $1 ..." + path=/home/arch/aif/user/"$1" + [ "$1" = core ] && path=/home/arch/aif/core + + for submodule in lib #procedure don't load procedures automatically! + do + if [ ! -d "$path/${submodule}s" ] + then + # ignore this problem for not-core modules + [ "$1" = core ] && die_error "$path/${submodule}s does not exist. something is horribly wrong with this installation" + else + shopt -s nullglob + for i in "$path/${submodule}s"/* + do + load_${submodule} "$1" "`basename "$i"`" + done + fi + done + +} + + +# $1 module name +# $2 procedure name +load_procedure() +{ + [ -z "$1" ] && die_error "load_procedure needs a module as \$1 and procedure as \$2" + [ -z "$2" ] && die_error "load_procedure needs a procedure as \$2" + if [ "$1" = 'http:' ] + then + log "Loading procedure $2 ..." + procedure=/home/arch/aif/runtime/procedure-downloaded-`basename $2` + wget "$2" -q -O $procedure >/dev/null || die_error "Could not download procedure $2" + else + log "Loading procedure $1/procedures/$2 ..." + procedure=/home/arch/aif/user/"$1"/procedures/"$2" + [ "$1" = core ] && procedure=/home/arch/aif/core/procedures/"$2" + fi + [ -f "$procedure" ] && source "$procedure" || die_error "Something went wrong while sourcing procedure $procedure" +} + + +# $1 module name +# $2 library name +load_lib () +{ + [ -z "$1" ] && die_error "load_library needs a module als \$1 and library as \$2" + [ -z "$2" ] && die_error "load_library needs a library as \$2" + log "Loading library $1/libs/$2 ..." + lib=/home/arch/aif/user/"$1"/libs/"$2" + [ "$1" = core ] && lib=/home/arch/aif/core/libs/"$2" + source $lib || die_error "Something went wrong while sourcing library $lib" +} + + +# $1 phase/worker +# $2 phase/worker name +# $3... extra args for phase/worker (optional) +execute () +{ + [ -z "$1" -o -z "$2" ] && die_error "Use the execute function like this: execute <type> <name> with type=phase/worker" + [ "$1" != phase -a "$1" != worker ] && die_error "execute's first argument must be a valid type (phase/worker)" + PWD_BACKUP=`pwd` + object=$1_$2 + + if [ "$1" = worker ] + then + log "*** Executing worker $2" + if type -t $object | grep -q function + then + shift 2 + $object "$@" + ret=$? + exit_var=exit_$object + read $exit_var <<< $ret # maintain exit status of each worker + else + die_error "$object is not defined!" + fi + elif [ "$1" = phase ] + then + log "******* Executing phase $2" + exit_var=exit_$object + read $exit_var <<< 0 + # TODO: for some reason the hack below does not work (tested in virtualbox), even though it really should. Someday I must get indirect array variables working and clean this up... + # debug "\$1: $1, \$2: $2, \$object: $object, \$exit_$object: $exit_object" + # debug "declare: `declare | grep -e "^${object}=" | cut -d"=" -f 2-`" + # props to jedinerd at #bash for this hack. + # eval phase=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-) + #debug "\$phase: $phase - ${phase[@]}" + unset phase + [ "$2" = preparation ] && phase=( "${phase_preparation[@]}" ) + [ "$2" = basics ] && phase=( "${phase_basics[@]}" ) + [ "$2" = system ] && phase=( "${phase_system[@]}" ) + [ "$2" = finish ] && phase=( "${phase_finish[@]}" ) + # worker_str contains the name of the worker and optionally any arguments + for worker_str in "${phase[@]}" + do + debug "Loop iteration. \$worker_str: $worker_str" + execute worker $worker_str || read $exit_var <<< $? # assign last failing exit code to exit_phase_<phasename>, if any. + done + ret=${!exit_var} + fi + + debug "Execute(): $object exit state was $ret" + cd $PWD_BACKUP + return $ret +} + + +# check if a phase/worker executed sucessfully +# returns 0 if ok, the phase/workers' exit state otherwise (and returns 1 if not executed yet) +# $1 phase/worker +# $2 phase/worker name +ended_ok () +{ + [ -z "$1" -o -z "$2" ] && die_error "Use the ended_ok function like this: ended_ok <type> <name> with type=phase/worker" + [ "$1" != phase -a "$1" != worker ] && die_error "ended_ok's first argument must be a valid type (phase/worker)" + object=$1_$2 + exit_var=exit_$object + debug "Ended_ok? -> Exit state of $object was: ${!exit_var} (if empty. it's not executed yet)" + [ "${!exit_var}" = '0' ] && return 0 + [ "${!exit_var}" = '' ] && return 1 + return ${!exit_var} +} + + +depend_module () +{ + load_module "$1" +} + + +depend_procedure () +{ + load_procedure "$1" "$2" +} + + +start_process () +{ + execute phase preparation + execute phase basics + execute phase system + execute phase finish +} + + +show_report () #TODO: abstract UI method (cli/dia) +{ + echo "Execution Report:" + echo "-----------------" + for phase in preparation basics system finish + do + object=phase_$phase + exit_var=exit_$object + ret=${!exit_var} + echo -n "Phase $phase: " + [ "$ret" = "0" ] && echo "Success" || echo "Failed" + eval phase_array=$(declare | grep -e "^${object}=" | cut -d"=" -f 2-) + for worker_str in "${phase_array[@]}" + do + worker=${worker_str%% *} + exit_var=exit_worker_$worker + ret=${!exit_var} + echo -n " > Worker $worker: " + [ "$ret" = "0" ] && echo "Success" || echo "Failed" + done + done +} + + +# use this function to stop the installation procedure. +# $1 exit code (optional) +stop_installer () +{ + log "-------------- STOPPING INSTALLATION ----------" + exit $1 +} + + +###### perform actual logic ###### +echo "Welcome to $TITLE" +log "################## START OF INSTALLATION ##################" +[ -z "$1" ] && usage && exit 1 + +mount -o remount,rw / &>/dev/null + +# note that we allow procedures like http://foo/bar. module -> http:, procedure -> http://foo/bar. +if [[ $1 =~ ^http:// ]] +then + module=http + procedure="$1" +elif grep -q '\/' <<< "$1" +then + #user specified module/procedure + module=`dirname "$1"` + procedure=`basename "$1"` +else + module=core + procedure="$1" +fi + +load_module core +[ "$module" != core -a "$module" != http ] && load_module "$module" + +load_procedure "$module" "$procedure" + +# Set pacman vars. allow procedures to have set $var_TARGET_DIR (TODO: look up how delayed variable substitution works. then we can put this at the top again) +# flags like --noconfirm should not be specified here. it's up to the procedure to decide the interactivity +PACMAN=pacman +PACMAN_TARGET="pacman --root $var_TARGET_DIR --config /tmp/pacman.conf" + +start_process + +exit 0 |