#!/bin/bash
#---------------------------------------------------------------------
##
##=head1 SYNOPSIS
##
## Functions for dealing with the actual compiling/installation of spells
## and walking through casts 'pass 4' pipeline.
##
##=head1 DESCRIPTION
##
## Contains functions for the build api version 2
## which has the following steps:
## PRE_BUILD -> BUILD -> PRE_INSTALL -> INSTALL -> POST_INSTALL ->
## FINAL -> TRIGGERS
##
##=head1 COPYRIGHT
##
## Copyright (C) 2002 The Source Mage Team <http://www.sourcemage.org>
##
##=head1 FUNCTIONS
#---------------------------------------------------------------------

#---------------------------------------------------------------------
## This runs through the phase 4 pipeline of building and installing
## a spell for BUILD_API 2.
#---------------------------------------------------------------------
run_build_spell() {
  debug "build_api2" "run_build_spell"

  local CHROOT_CHECK=""

  export C_LOG=$TMP_DIR/$SPELL.compile.log
  export CASTFS_DBGLOG=$C_LOG.castfs.dbglog
  export C_FIFO=/dev/stdout # not needed for api2 anymore, but just in case
  export S_PWD=$TMP_DIR/build.saved.pwd
  export VOYEUR_STDOUT VOYEUR_STDERR
  export __DELVE_IN_CAST=on

  rm  -f $CASTFS_DBGLOG
  touch $CASTFS_DBGLOG
  rm  -f $C_LOG
  touch $C_LOG

  if [[ $SCREEN_NAME ]] ; then
    screen_new_window "$SCREEN_NAME" $SCREEN_CAST_WIN "cast $SPELL" \
      tail -f -s 0.1 $C_LOG
    screen_switch_window "$SCREEN_NAME" $SCREEN_MAIN_WIN

    VOYEUR_STDOUT=/dev/null
    VOYEUR_STDERR=/dev/null
  elif [ "$VOYEUR" == "on" -a -z "$SILENT" ] ; then
    VOYEUR_STDOUT=/dev/stdout
    VOYEUR_STDERR=/dev/stderr
  else
    VOYEUR_STDOUT=/dev/null
    VOYEUR_STDERR=/dev/null
  fi

  if [[ -z $STAGED_INSTALL ]]
  then
    if ! is_castfs_installed
    then
      export STAGED_INSTALL=off
    else
      export STAGED_INSTALL=on
    fi
  fi

  if [[ $STAGED_INSTALL == on ]] && ! run_castfs_sanity
  then
    message "${PROBLEM_COLOR}CastFS failed the sanity check, staging disabled!"
    message -n "$DEFAULT_COLOR"
    export STAGED_INSTALL=off
  fi

  local PROTECT_SORCERY=yes
  local rs
  (
    run_pre_build                           || return 1
    run_config_loc                          || return 2
    (
      run_build                             &&
      run_pre_install                       &&
      if [[ $STAGED_INSTALL == off ]]
      then
        invoke_installwatch
      fi                                    &&
      delve ${OVERRIDE_GRIMOIRES+-g "$OVERRIDE_GRIMOIRES"} $SPELL INSTALL &&
      delve ${OVERRIDE_GRIMOIRES+-g "$OVERRIDE_GRIMOIRES"} $SPELL INSTALL_EXTRAS &&
      run_post_install                      || return 2
      run_transfer                          &&
      devoke_installwatch                   &&
      STAGED_INSTALL=off                    &&
      run_final | append_to_notice_log      || return 3
    ) 3> >(tee -a $C_LOG >> /dev/stdout) \
      2> >(tee -a $C_LOG 1>&2 >> $VOYEUR_STDERR) \
       > >(tee -a $C_LOG >> $VOYEUR_STDOUT) \
  )
  rs=$?
  unset __DELVE_IN_CAST
  if [[ $SCREEN_NAME ]] && [ $rs -gt 0 ] ; then
    screen_move_window "$SCREEN_NAME" $SCREEN_CAST_WIN $SCREEN_LAST_FAILED_CAST_WIN
    screen_name_window "$SCREEN_NAME" $SCREEN_LAST_FAILED_CAST_WIN "Failed $SPELL"
    screen_kill_window "$SCREEN_NAME" $SCREEN_CAST_WIN
    screen_notify "$SCREEN_NAME" "Last failed cast at $SCREEN_LAST_FAILED_CAST_WIN"
  elif [[ $SCREEN_NAME ]] ; then
    screen_kill_window "$SCREEN_NAME" $SCREEN_CAST_WIN
  fi

  # triggers don't run in the window
  [ $rs -gt 0 ] && return $rs

  run_triggers || return 4

  return 0
}

#---------------------------------------------------------------------
## This phase of casting involves unpacking the source into the
## source directories. If a PRE_BUILD file exists in SCRIPT_DIRECTORY
## and is executable it is run in preference to the default_pre_build.
#---------------------------------------------------------------------
run_pre_build() {

  debug "build_api2" "run_pre_build()"
  message  "${MESSAGE_COLOR}Preparing" \
           "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}"

  rm_source_dir || return 1
  mkdir -p $BUILD_DIRECTORY
  cd  "$BUILD_DIRECTORY"

  verify_sources &&
  run_spell_file PRE_BUILD pre_build
}


#---------------------------------------------------------------------
## Starts up the compile logs, turns on the various environment
## settings that need to be on, eventually gets around to running
## BUILD or default_build.
#---------------------------------------------------------------------
run_build()  {

  debug "build_api2" "Starting run_compile()"

  echo  "Compile log for $SPELL $VERSION Built on $(date  -u)"  >  $C_LOG
  echo  "Using gcc version: $(gcc -dumpversion)" >> $C_LOG
  message  "${MESSAGE_COLOR}Building"  \
           "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" >&3

  if [  -d  "$SOURCE_DIRECTORY"  ] ; then
    cd "$SOURCE_DIRECTORY"
  else
    cd "$BUILD_DIRECTORY"
  fi &&

  invoke_build_dir
  invoke_gcc

  message -n "Building in dir: "
  pwd
  message "$SPELL    $VERSION"
  message

  if ! run_spell_file BUILD build optimize; then
    message  "${PROBLEM_COLOR}"      \
             "! Problem Detected !"  \
             "${DEFAULT_COLOR}"
    return 1
  fi
  pwd > $S_PWD
}


#---------------------------------------------------------------------
## Turns all the various logs back on that were turned off from after
## run_build finished, then runs PRE_INSTALL or default_pre_install
#---------------------------------------------------------------------
run_pre_install() {
  debug "build_api2" "Starting run_pre_install()"

  if [ -f $S_PWD ] ; then
    cd "$(cat $S_PWD)"
  elif [ -d $SOURCE_DIRECTORY ] ; then
    cd "$SOURCE_DIRECTORY"
  else
    cd "$BUILD_DIRECTORY"
  fi

  run_spell_file PRE_INSTALL pre_install
  local rc=$?
  echo  "Compile log for $SPELL $VERSION Completed Build on $(date  -u)"  >>  $C_LOG
  pwd > $S_PWD
  return $rc
}


#---------------------------------------------------------------------
## load persistent vars, then runs INSTALL or default_install
## Along with other stuff that needs to be transplanted elsewhere.
## NOTE: this function is run from delve so installwatch can be invoked
## around an execed bash shell, this is needed for installwatch to
## stage root properly
#---------------------------------------------------------------------
run_install() {
  debug "build_api2" "Starting run_install()"

  message "${MESSAGE_COLOR}Installing" \
          "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" \
	  "(staging: $STAGED_INSTALL)" >&3

  if [ -f $S_PWD ] ; then
    cd "$(cat $S_PWD)"
  elif [ -d $SOURCE_DIRECTORY ] ; then
    cd "$SOURCE_DIRECTORY"
  else
    cd "$BUILD_DIRECTORY"
  fi

  if ! run_spell_file INSTALL install; then
    message  "${PROBLEM_COLOR}"      \
             "Problem Detected!"     \
             "${DEFAULT_COLOR}"
    false
  fi
}

run_install_extras() {

  debug "build_api2" "Starting run_install_extras()"
  run_spell_file INSTALL_EXTRAS install_extras
}

#---------------------------------------------------------------------
## Checks for a POST_INSTALL file in SCRIPT_DIRECTORY, and if it is
## executable, runs it. This file is run after INSTALL and before
## FINAL. Its purpose is to manipulate the installed files in the stage
## root and install other tracked files.
## NOTE: this function is run from delve so installwatch can be invoked
## around an execed bash shell, this is needed for installwatch to
## stage root properly
#---------------------------------------------------------------------
run_post_install() {
  debug "build_api2" "Starting run_post_install()"
  persistent_load &&
  if [[ $STAGED_INSTALL != off ]]
  then
    cd "$STAGE_DIRECTORY/"
  else
    cd "${INSTALL_ROOT:-/}"
  fi &&
  run_spell_file POST_INSTALL post_install
  unlock_resources "libgrimoire" "install"
}

#--------------------------------------------------------------------
## Checks against STAGED_INSTALL and installs the staged spell
## accordingly
#--------------------------------------------------------------------
run_transfer() {
  if [[ "$STAGED_INSTALL" != "off" ]]
  then
    message "${MESSAGE_COLOR}Installing"              \
            "${SPELL_COLOR}${SPELL}${MESSAGE_COLOR}"  \
            "into the system${DEFAULT_COLOR}" >&3
    run_spell_file TRANSFER transfer
  fi
}

#---------------------------------------------------------------------
## Checks for a FINAL file in SCRIPT_DIRECTORY, and if it is
## executable, runs it. This file is used for extra files that need
## to be installed, but not tracked by installwatch.
#---------------------------------------------------------------------
run_final() {

  debug "build_api2" "Starting run_final()"
  run_spell_file FINAL final
}

#---------------------------------------------------------------------
## @Type API
## Creates the source directory and unpacks the source package into it.
## Used if no PRE_BUILD script is found for a spell.
##
#---------------------------------------------------------------------
real_default_sorcery_pre_build() {

  debug "libgrimoire" "default_pre_build() - SOURCE=$SOURCE SOURCE_DIRECTORY=$SOURCE_DIRECTORY"
  mk_source_dir        $SOURCE_DIRECTORY  &&
  unpack_file

}


#---------------------------------------------------------------------
## @Type API
## Used if no BUILD script is found
## Default build is:
## <pre>
##  ./configure  --build=$BUILD        \
##               --prefix=/usr         \
##               --sysconfdir=/etc     \
##               --localstatedir=/var  \
##               $OPTS                 &&
##  make
## </pre>
##
#---------------------------------------------------------------------
real_default_sorcery_build() {
  debug "build_api2" "real_default_sorcery_build"

  OPTS="$OPTS --build=${BUILD}"
  #If these switches are used, they _may_ stop distcc and ccache from working
  # for some spells (bug 3798)
  #  We could write wrappers for all of the possible binaries
  [[ $CROSS_INSTALL == on ]] && OPTS="$OPTS --host=${HOST}"

  ./configure --prefix=${INSTALL_ROOT}/usr  \
          --sysconfdir=${INSTALL_ROOT}/etc  \
       --localstatedir=${INSTALL_ROOT}/var  \
              --mandir=${INSTALL_ROOT}/usr/share/man   \
             --infodir=${INSTALL_ROOT}/usr/share/info  \
                       $OPTS                 &&
  make

}

#---------------------------------------------------------------------
## @Type API
## Used if no PRE_INSTALL script is found
## Default pre_install is:
## <pre>
##  prepare_install
## </pre>
##
#---------------------------------------------------------------------
real_default_sorcery_pre_install() {
  debug "build_api2" "Starting real_default_sorcery_pre_install"
  prepare_install >&3
}

#---------------------------------------------------------------------
## @Type API
## Used if no INSTALL script is found
## Default install is:
## <pre>
##  make    install
## </pre>
##
#---------------------------------------------------------------------
real_default_sorcery_install() {
  debug "build_api2" "Starting real_default_sorcery_install"
  make    install
}


#---------------------------------------------------------------------
## @Type API
## Installs configuration files and documentation.  Stops installwatch.
## Used if no POST_INSTALL script is found for a spell.
##
## This is identical to api1's post_build
#---------------------------------------------------------------------
real_default_sorcery_install_extras() {

  debug "build_api2" "Starting real_default_sorcery_install_extras"
  install_xinetd
  install_initd
  install_pam_confs
  install_desktop_files
  gather_docs
  init_post_install
  case "$STAGED_INSTALL:$HOST" in
    (off:*-gnu) ldconfig ;;
  esac
  # release_saved_libraries
  cd  /
}

real_default_sorcery_transfer() {

  debug "build_api2" "Starting real_default_sorcery_transfer"
  transfer_staged_spell
}

#---------------------------------------------------------------------
## @License
##
## This software is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This software is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this software; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##
#---------------------------------------------------------------------
