/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	#---------------------------------------------------------------------