#!/bin/bash
# $Id$
set -e
# Pass trap handlers to functions
set -E

# VT100 colors
declare -r  BLACK=$'\e[1;30m'
declare -r  DK_GRAY=$'\e[0;30m'

declare -r  RED=$'\e[31m'
declare -r  GREEN=$'\e[32m'
declare -r  YELLOW=$'\e[33m'
declare -r  BLUE=$'\e[34m'
declare -r  MAGENTA=$'\e[35m'
declare -r  CYAN=$'\e[36m'
declare -r  WHITE=$'\e[37m'

declare -r  OFF=$'\e[0m'
declare -r  BOLD=$'\e[1m'
declare -r  REVERSE=$'\e[7m'
declare -r  HIDDEN=$'\e[8m'

declare -r  tab_=$'\t'
declare -r  nl_=$'\n'

declare -r   DD_BORDER="${BOLD}==============================================================================${OFF}"
declare -r   SD_BORDER="${BOLD}------------------------------------------------------------------------------${OFF}"
declare -r STAR_BORDER="${BOLD}******************************************************************************${OFF}"

# bold yellow > <  pair
declare -r R_arrow=$'\e[1;33m>\e[0m'
declare -r L_arrow=$'\e[1;33m<\e[0m'


#>>>>>>>>>>>>>>>ERROR TRAPPING >>>>>>>>>>>>>>>>>>>>
#-----------------------#
simple_error() {        # Basic error trap.... JUST DIE
#-----------------------#
  # If +e then disable text output
  if [[ "$-" =~ e ]]; then
    LASTLINE="$1"
    LASTERR="$2"
    LASTFUNC="$3"
    LASTSOURCE="$4"
#    echo -e "\n${RED}ERROR:${GREEN} basic error trapped!${OFF}\n" >&2
    echo -e "\n${RED}ERROR:${GREEN} Error $LASTERR at $LASTSOURCE line ${LASTLINE}!${OFF}\n" >&2
  fi
  exit $LASTERR
}

see_ya() {
    echo -e "\n${L_arrow}${BOLD}jhalfs-trunk${R_arrow} exit${OFF}\n"
}
##### Simple error TRAPS
# ctrl-c   SIGINT
# ctrl-y
# ctrl-z   SIGTSTP
# SIGHUP   1 HANGUP
# SIGINT   2 INTRERRUPT FROM KEYBOARD Ctrl-C
# SIGQUIT  3
# SIGKILL  9 KILL
# SIGTERM 15 TERMINATION
# SIGSTOP 17,18,23 STOP THE PROCESS
#####
set -e
trap see_ya 0
trap 'simple_error "${LINENO}" "$?" "${FUNCNAME}" "${BASH_SOURCE}"' ERR
trap 'echo -e "\n\n${RED}INTERRUPT${OFF} trapped\n" &&  exit 2'  1 2 3 15 17 18 23
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

version="
${BOLD}  \"jhalfs-trunk\"${OFF} builder tool (development) \$Rev$
  \$Date$

  Written by George Boudreau and Manuel Canales Esparcia,
  plus several contributions.

  Based on an idea from Jeremy Huntwork

  This set of files are published under the
  ${BOLD}Gnu General Public License, Version 2.${OFF}
"

case $1 in
  -v ) echo "$version" && exit 1 ;;
  run ) : ;;
  * )
    echo "${nl_}${tab_}${BOLD}${RED}This script cannot be called directly: EXITING ${OFF}${nl_}"
    exit 1
    ;;
esac

# If the user has not saved his configuration file, let's ask
# if he or she really wants to run this stuff
if [ $(ls -l --time-style='+%Y%m%d%H%M%S' configuration.old | cut -d' ' -f 6) \
 -ge $(ls -l --time-style='+%Y%m%d%H%M%S' configuration | cut -d' ' -f 6) ]
  then echo -n "Do you want to run jhalfs? yes/no (yes): "
  read ANSWER
  if [ x${ANSWER:0:1} = "xn" -o x${ANSWER:0:1} = "xN" ] ; then
    echo "${nl_}Exiting gracefully.${nl_}"
    exit
  fi
fi

# Change this to 0 to suppress almost all messages
VERBOSITY=1

[[ $VERBOSITY > 0 ]] && echo -n "Loading config params from <configuration>..."
source configuration
[[ $? > 0 ]] && echo "file: configuration did not load.." && exit 1
[[ $VERBOSITY > 0 ]] && echo "OK"

# These are boolean vars generated from Config.in.
# ISSUE: If a boolean parameter is not set to y(es) there
# is no variable defined by the menu app. This can
# cause a headache if you are not aware.
#  The following variables MUST exist. If they don't, the
#  default value is n(o).
RUNMAKE=${RUNMAKE:-n}
GETPKG=${GETPKG:-n}
COMPARE=${COMPARE:-n}
RUN_FARCE=${RUN_FARCE:-n}
RUN_ICA=${RUN_ICA:-n}
PKGMNGT=${PKGMNGT:-n}
WRAP_INSTALL=${WRAP_INSTALL:-n}
BOMB_TEST=${BOMB_TEST:-n}
STRIP=${STRIP:=n}
REPORT=${REPORT:=n}
VIMLANG=${VIMLANG:-n}
FULL_LOCALE=${FULL_LOCALE:-n}
GRSECURITY_HOST=${GRSECURITY_HOST:-n}
CUSTOM_TOOLS=${CUSTOM_TOOLS:-n}
REBUILD_MAKEFILE=${REBUILD_MAKEFILE:-n}
INSTALL_LOG=${INSTALL_LOG:-n}
CLEAN=${CLEAN:=n}
SET_SSP=${SET_SSP:=n}
SET_ASLR=${SET_ASLR:=n}
SET_PAX=${SET_PAX:=n}
SET_HARDENED_TMP=${SET_HARDENED_TMP:=n}
SET_WARNINGS=${SET_WARNINGS:=n}
SET_MISC=${SET_MISC:=n}
SET_BLOWFISH=${SET_BLOWFISH:=n}
UNICODE=${UNICODE:=n}

if [[ "${NO_PROGRESS_BAR}" = "y" ]] ; then
	NO_PROGRESS="#"
fi


# Sanity check on the location of $BUILDDIR / $JHALFSDIR
CWD=$(cd `dirname $0` && pwd)
if [[ $JHALFSDIR == $CWD ]]; then
    echo " The jhalfs source directory conflicts with the jhalfs build directory."
    echo " Please move the source directory or change the build directory."
    exit 2
fi

# Book sources envars
BRANCH_ID=${BRANCH_ID:=development}

case $BRANCH_ID in
  development )
    case $PROGNAME in
      clfs* ) TREE="" ;;
          * ) TREE=trunk/BOOK ;;
    esac
    LFSVRS=development
    ;;
  *EDIT* )  echo " You forgot to set the branch or stable book version."
            echo " Please rerun make and fix the configuration."
            exit 2 ;;
  branch-* )
    case $PROGNAME in
      lfs )
        LFSVRS=${BRANCH_ID}
        TREE=branches/${BRANCH_ID#branch-}
        if [ ${BRANCH_ID#branch-} = 6 ]; then
            TREE=${TREE}/BOOK
        fi
        ;;
      clfs* )
        LFSVRS=${BRANCH_ID}
        TREE=${BRANCH_ID#branch-}
        ;;
    esac
    ;;
  * )
    case $PROGNAME in
      lfs )
        LFSVRS=${BRANCH_ID}
        TREE=tags/${BRANCH_ID}
        if (( ${BRANCH_ID:0:1} < 7 )) ; then
            TREE=${TREE}/BOOK
        fi
        ;;
      hlfs )
        LFSVRS=${BRANCH_ID}
        TREE=tags/${BRANCH_ID}/BOOK
        ;;
      clfs* )
        LFSVRS=${BRANCH_ID}
        TREE=clfs-${BRANCH_ID}
        ;;
      * )
    esac
    ;;
esac

# Set the document location...
BOOK=${BOOK:=$JHALFSDIR/$PROGNAME-$LFSVRS}


#--- Envars not sourced from configuration
case $PROGNAME in
      clfs ) declare -r GIT="git://git.clfs.org/cross-lfs" ;;
      clfs2 ) declare -r GIT="git://git.clfs.org/clfs-sysroot" ;;
      clfs3 ) declare -r GIT="git://git.clfs.org/clfs-embedded" ;;
      *) declare -r SVN="svn://svn.linuxfromscratch.org" ;;
esac
declare -r LOG=000-masterscript.log
  # Needed for fetching BLFS book sources when building CLFS
declare -r SVN_2="svn://svn.linuxfromscratch.org"

# Set true internal variables
COMMON_DIR="common"
PACKAGE_DIR=$(echo $PROGNAME | tr '[a-z]' '[A-Z]')
MODULE=$PACKAGE_DIR/master.sh
PKGMNGTDIR="pkgmngt"
# The name packageManager.xml is hardcoded in *.xsl, so no variable.

[[ $VERBOSITY > 0 ]] && echo -n "Loading common-functions module..."
source $COMMON_DIR/common-functions
[[ $? > 0 ]] && echo " $COMMON_DIR/common-functions did not load.." && exit
[[ $VERBOSITY > 0 ]] && echo "OK"
[[ $VERBOSITY > 0 ]] && echo -n "Loading code module <$MODULE>..."
source $MODULE
[[ $? > 0 ]] && echo "$MODULE did not load.." && exit 2
[[ $VERBOSITY > 0 ]] && echo "OK"
#
[[ $VERBOSITY > 0 ]] && echo "${SD_BORDER}${nl_}"


#*******************************************************************#
[[ $VERBOSITY > 0 ]] && echo -n "Loading function <func_check_version.sh>..."
source $COMMON_DIR/libs/func_check_version.sh
[[ $? > 0 ]] && echo " function module did not load.." && exit 2
[[ $VERBOSITY > 0 ]] && echo "OK"

[[ $VERBOSITY > 0 ]] && echo -n "Loading function <func_validate_configs.sh>..."
source $COMMON_DIR/libs/func_validate_configs.sh
[[ $? > 0 ]] && echo " function module did not load.." && exit 2
[[ $VERBOSITY > 0 ]] && echo "OK"

[[ $VERBOSITY > 0 ]] && echo -n "Loading function <func_custom_pkgs>..."
source $COMMON_DIR/libs/func_custom_pkgs
[[ $? > 0 ]] && echo " function module did not load.." && exit 2
[[ $VERBOSITY > 0 ]] && echo "OK"


[[ $VERBOSITY > 0 ]] && echo "${SD_BORDER}${nl_}"

[[ $VERBOSITY > 0 ]] && echo Checking tools required for jhalfs
check_alfs_tools

[[ $VERBOSITY > 0 ]] && echo "${SD_BORDER}${nl_}"

# blfs-tool envars
BLFS_TOOL=${BLFS_TOOL:-n}
if [[ "${BLFS_TOOL}" = "y" ]] ; then
  [[ $VERBOSITY > 0 ]] && echo Checking supplementary tools for installing BLFS
  check_blfs_tools
  [[ $VERBOSITY > 0 ]] && echo "${SD_BORDER}${nl_}"
  BLFS_SVN=${BLFS_SVN:-n}
  BLFS_WORKING_COPY=${BLFS_WORKING_COPY:-n}
  BLFS_BRANCH=${BLFS_BRANCH:-n}
  if [[ "${BLFS_SVN}" = "y" ]]; then
    BLFS_BRANCH_ID=development
    BLFS_TREE=trunk/BOOK
  elif [[ "${BLFS_WORKING_COPY}" = "y" ]]; then
    [[ -d "$BLFS_WC_LOCATION" ]] &&
    [[ -d "$BLFS_WC_LOCATION/postlfs" ]] || {
      echo " BLFS tools: This is not a working copy: $BLFS_WC_LOCATION."
      echo " Please rerun make and fix the configuration."
      exit 2
      }
    BLFS_TREE=$(cd $BLFS_WC_LOCATION; svn info | grep '^URL' | sed 's@.*BLFS/@@')
    BLFS_BRANCH_ID=$(echo $BLFS_TREE | sed -e 's@trunk/BOOK@development@' \
                                           -e 's@branches/@branch-@' \
                                           -e 's@tags/@@' \
                                           -e 's@/BOOK@@')
  elif [[ "${BLFS_BRANCH}" = "y" ]] ; then
    case $BLFS_BRANCH_ID in
           *EDIT* )  echo " You forgot to set the BLFS branch or stable book version."
                     echo " Please rerun make and fix the configuration."
                     exit 2 ;;
   branch-systemd )  BLFS_TREE=branches/systemd ;;
         branch-* )  BLFS_TREE=branches/${BLFS_BRANCH_ID#branch-}/BOOK ;;
       6.2* | 7.* )  BLFS_TREE=tags/${BLFS_BRANCH_ID} ;;
                * )  BLFS_TREE=tags/${BLFS_BRANCH_ID}/BOOK ;;
    esac
  fi
  [[ $VERBOSITY > 0 ]] && echo -n "Loading blfs tools installation function..."
  source $COMMON_DIR/libs/func_install_blfs
  [[ $? > 0 ]] && echo "function module did not load.." && exit 1
  [[ $VERBOSITY > 0 ]] && echo "OK"
fi

###################################
###          MAIN               ###
###################################


validate_config
echo "${SD_BORDER}${nl_}"
echo -n "Are you happy with these settings? yes/no (no): "
read ANSWER
if [ x$ANSWER != "xyes" ] ; then
  echo "${nl_}Rerun make to fix the configuration options.${nl_}"
  exit
fi
echo "${nl_}${SD_BORDER}${nl_}"

# Load additional modules or configuration files based on global settings
# compare module
if [[ "$COMPARE" = "y" ]]; then
  [[ $VERBOSITY > 0 ]] && echo -n "Loading compare module..."
  source $COMMON_DIR/libs/func_compare.sh
  [[ $? > 0 ]] && echo "$COMMON_DIR/libs/func_compare.sh did not load.." && exit
  [[ $VERBOSITY > 0 ]] && echo "OK"
fi
#
# optimize module
if [[ "$OPTIMIZE" != "0" ]]; then
  [[ $VERBOSITY > 0 ]] && echo -n "Loading optimization module..."
  source optimize/optimize_functions
  [[ $? > 0 ]] && echo " optimize/optimize_functions did not load.." && exit
  [[ $VERBOSITY > 0 ]] && echo "OK"
  #
  # optimize configurations
  [[ $VERBOSITY > 0 ]] && echo -n "Loading optimization config..."
  source optimize/opt_config
  [[ $? > 0 ]] && echo " optimize/opt_config did not load.." && exit
  [[ $VERBOSITY > 0 ]] && echo "OK"
  # The number of parallel jobs is taken from configuration now
  MAKEFLAGS="-j${N_PARALLEL}"
  # Validate optimize settings, if required
  validate_opt_settings
fi
#

if [[ "$REBUILD_MAKEFILE" = "n" ]] ; then

  # If requested, clean the build directory
  clean_builddir

  if [[ ! -d $JHALFSDIR ]]; then
    mkdir -p $JHALFSDIR
  fi

  # Create $BUILDDIR/sources even though it could be created by get_sources()
  if [[ ! -d $BUILDDIR/sources ]]; then
    mkdir -p $BUILDDIR/sources
  fi
  #
  # Create the log directory
  if [[ ! -d $LOGDIR ]]; then
    mkdir $LOGDIR
  fi
  >$LOGDIR/$LOG
  #
  # Copy common helper files
  cp $COMMON_DIR/{makefile-functions,progress_bar.sh} $JHALFSDIR/
  # Copy needed stylesheets
  cp $COMMON_DIR/{packages.xsl,chroot.xsl} $JHALFSDIR/
  #
  # Fix the XSL book parser
  case $PROGNAME in
    clfs* ) sed 's,FAKEDIR,'${BOOK}/BOOK',' ${PACKAGE_DIR}/${XSL} > $JHALFSDIR/${XSL} ;;
    lfs | hlfs ) sed 's,FAKEDIR,'$BOOK',' $PACKAGE_DIR/$XSL > $JHALFSDIR/${XSL} ;;
    * ) ;;
  esac
  export XSL=$JHALFSDIR/${XSL}
  #

  # Copy packageManager.xml, if needed
  [[ "$PKGMNGT" = "y" ]] && [[ "$PROGNAME" = "lfs" ]] &&
    cp $PKGMNGTDIR/packageManager.xml  $JHALFSDIR/ &&
    cp $PKGMNGTDIR/packInstall.sh  $JHALFSDIR/
  #
  # Copy urls.xsl, if needed
  [[ "$GETPKG" = "y" ]] && cp $COMMON_DIR/urls.xsl  $JHALFSDIR/
  #
  # Create the test-log directory, if needed
  [[ "$TEST" != "0" ]] && [[ ! -d $TESTLOGDIR ]] && install -d -m 1777 $TESTLOGDIR
  #
  # Create the installed-files directory, if needed
  [[ "$INSTALL_LOG" = "y" ]] && [[ ! -d $FILELOGDIR ]] && install -d -m 1777 $FILELOGDIR
  #
  # Prepare report creation, if needed
  if [[ "$REPORT" = "y" ]]; then
    cp $COMMON_DIR/create-sbu_du-report.sh  $JHALFSDIR/
    # After making sure that all looks sane, dump the settings to a file
    # This file will be used to create the REPORT header
    validate_config > $JHALFSDIR/jhalfs.config
  fi
  #
  # Copy optimize files, if needed
  [[ "$OPTIMIZE" != "0" ]] && cp optimize/opt_override $JHALFSDIR/
  #
  # Copy compare files, if needed
  if [[ "$COMPARE" = "y" ]]; then
    mkdir -p $JHALFSDIR/extras
    cp extras/* $JHALFSDIR/extras
  fi
  #
  # Copy custom tools config files, if requested
  if [[ "${CUSTOM_TOOLS}" = "y" ]]; then
    echo "Copying custom tool scripts to $JHALFSDIR"
    mkdir -p $JHALFSDIR/custom-commands
    cp -f custom/config/* $JHALFSDIR/custom-commands
  fi
  #
  # Install blfs-tool, if requested.
  if [[ "${BLFS_TOOL}" = "y" ]] ; then
    echo Installing BLFS book and tools
    install_blfs_tools 2>&1 | tee -a $LOGDIR/$LOG
    [[ ${PIPESTATUS[0]} != 0 ]] && exit 1
  fi
  #

# Download or updates the book source
  get_book
  extract_commands
  echo "${SD_BORDER}${nl_}"

fi

# When regenerating the Makefile, we need to know also the
# canonical book version
if [[ "$REBUILD_MAKEFILE" = "y" ]] ; then
  case $PROGNAME in
    clfs* )
      VERSION=$(xmllint --noent $JHALFSDIR/$BOOK/prologue/$ARCH/bookinfo.xml 2>/dev/null | grep subtitle | sed -e 's/^.*ion //'  -e 's/<\/.*//') ;;
    lfs)
      if [[ "$INITSYS" = "sysv" ]] ; then
        VERSION=$(grep 'ENTITY version ' $JHALFSDIR/$BOOK/general.ent| cut -d\" -f2)
      else
        VERSION=$(grep 'ENTITY versiond' $JHALFSDIR/$BOOK/general.ent| cut -d\" -f2)
      fi
      ;;
    *)
      VERSION=$(xmllint --noent $JHALFSDIR/$BOOK/prologue/bookinfo.xml 2>/dev/null | grep subtitle | sed -e 's/^.*ion //'  -e 's/<\/.*//') ;;
  esac
fi

build_Makefile

echo "${SD_BORDER}${nl_}"

# Check for build prerequisites.
  echo
  cd $CWD
  check_prerequisites
  echo "${SD_BORDER}${nl_}"
# All is well, run the build (if requested)
run_make