#! /usr/bin/env bash

# Test installation of the build2 toolchain distribution. Essentially, this
# is an automated build2-toolchain/INSTALL.
#
# Usage: install [options] <build2-toolchain-archive> <build2-repo>
#
# -i <dir>
#    Target installation directory instead of default /tmp/build2-install.
#
# -l <dir>
#    Prerequisite library (libodb, libodb-sqlite) installation directory
#    instead of default /usr/local.
#
# -s
#    Use sudo when installing.
#
# -t
#    Install toolchain only.
#
# --cxx <path>
#    C++ compiler to use, g++ by default.
#
# --cxxflags <flags>
#    C++ compiler flags to use, -W -Wall -Wno-unknown-pragmas by default.
#
# --cppflags <flags>
#    Extra C++ preprocessor flags to use.
#
# For example:
#
# install /tmp/build2-toolchain-0.1.0.tar.gz https://pkg.cppget.org/1/alpha
#
usage="usage: $0 [options] <build2-toolchain-archive> <build2-repo>"

owd=`pwd`
trap "{ cd $owd; exit 1; }" ERR
set -o errtrace # Trap in functions.

function info () { echo "$*" 1>&2; }
function error () { info "$*"; exit 1; }

tca=
rep=
tmp=/tmp
lib="/usr/local"           # Library (libodb, etc) installation directory.
ins="$tmp/build2-install"  # Our installation directory.
sudo=
extras=brep                # Extras to build.
extras_show=brep-loader    # Extra programs (in bin/) to test with --version.
pmc="build2-toolchain"     # bpkg configuration directory
cxx="g++"
cxxflags="-W -Wall -Wno-unknown-pragmas"
cppflags=

while [ $# -gt 0 ]; do
  case $1 in
    -s)
      sudo=sudo
      shift
      ;;
    -i)
      shift
      ins=${1%/}
      shift
      ;;
    -l)
      shift
      lib=${1%/}
      shift
      ;;
    -t)
      extras=
      shift
      ;;
    --cxx)
      shift
      cxx=$1
      shift
      ;;
    --cxxflags)
      shift
      cxxflags="$1"
      shift
      ;;
    --cppflags)
      shift
      cppflags="$1"
      shift
      ;;
    *)
      if [ -z "$tca" ]; then
        tca=${1%/}; shift
      else
        rep=$1; break
      fi
      ;;
  esac
done

if [ -z "$tca" ]; then
  error $usage
fi

if [ -z "$rep" ]; then
  error $usage
fi

cd $tmp

# Download archive if it is an HTTP URL.
#
if [[ $tca == http://* || $tca == https://* ]]; then
  url=$tca
  tca=`echo "$url" | sed -e 's%^.*/\(.*\)$%\1%' -`
  if [ -z "$tca" ]; then
    error "unable to extract archive name from $url"
  fi
  rm -f $tca
  wget $url
elif [[ $tca != /* ]]; then
  tca=$owd/$tca
fi

if [[ ( $rep != http://* || $tca == https://* ) && $rep != /* ]]; then
  rep=$owd/$rep
fi

if [[ $ins != /* ]]; then
  ins=$owd/$ins
fi

# Warm sudo up so that the rest of this script can continue unattended.
#
if [ "$sudo" ]; then
  $sudo echo >/dev/null
fi

tcb=`basename $tca .tar.gz`

# Unpack.
#
rm -rf $tcb
rm -rf $tcb.disabled
tar xfz $tca

# Bootstrap.
#
cd $tcb/build2
./bootstrap --cxx $cxx --cxxflags "$cxxflags"
./build/b-boot                          \
  config.cxx=$cxx                       \
  config.cxx.coptions="$cxxflags"       \
  config.bin.rpath=$ins-boot/lib update
cd ..

./build2/build/b                                 \
  config.cxx=$cxx                                \
  config.cxx.coptions="$cxxflags"                \
  config.cxx.poptions="$cppflags -I$lib/include" \
  config.cxx.loptions=-L$lib/lib                 \
  config.bin.rpath="$ins-boot/lib $lib/lib"      \
  config.install.root=$ins-boot                  \
  config.install.root.sudo=$sudo                 \
  configure

./build2/build/b update

$sudo mkdir -p $ins-boot
$sudo rm -rf $ins-boot/*
./build2/build/b install

function show () # <dir> <prog>...
{
  local d=$1; shift
  for p in $*; do
    if [ `which $p` != "$d/bin/$p" ]; then
      error "wrong $p path: `which $p`"
    fi

    $p --version 1>&2
  done
}

# Disable any rpaths that may still be pointing inside the build directory.
#
cd $tmp
mv $tcb $tcb.disabled

OLDPATH="$PATH"
PATH="$ins-boot/bin:$OLDPATH"
show $ins-boot b bpkg

# Rebuild via the package manager.
#
mkdir -p $pmc
rm -rf $pmc/*
rm -rf $pmc.disabled
cd $pmc

bpkg create                                      \
  cxx                                            \
  config.cxx=$cxx                                \
  config.cxx.coptions="$cxxflags"                \
  config.cxx.poptions="$cppflags -I$lib/include" \
  config.cxx.loptions=-L$lib/lib                 \
  config.bin.rpath="$ins/lib $lib/lib"           \
  config.install.root=$ins                       \
  config.install.root.sudo=$sudo                 \

bpkg add $rep
bpkg fetch
bpkg build --yes build2 bpkg

$sudo mkdir -p $ins
$sudo rm -rf $ins/*
bpkg install build2 bpkg

cd $tmp
mv $pmc $pmc.disabled

PATH="$ins/bin:$OLDPATH"
show $ins b bpkg

mv $pmc.disabled $pmc

# Build extras using the bpkg-built toolchain.
#
if [ ! -z "$extras" ]; then
  cd $pmc
  bpkg build --yes $extras
  bpkg install $extras
  cd $tmp

  mv $pmc $pmc.disabled
  show $ins $extras_show
  mv $pmc.disabled $pmc
fi

mv $tcb.disabled $tcb

cd $owd