#! /usr/bin/env bash

# Test examples from the into.
#
# Usage: install [options] <hello-repo>
#
# -t <toolchain>
#    Specify the build2 toolchain install/stage directory. The script will
#    use <toolchain>/bin/b and <toolchain>/bin/bpkd instead of just b and
#    bpkg.
#
# -c1
# -c2
# -c3
#    C++ compilers 1 (g++-5), 2 (clang++-3.6), and 3 (x86_64-w64-mingw32-g++).
#    If the value for 2 or 2 is empty, then this test is skipped.
#
# -h
#    The hello2 source directory, by default hello/hello2
#
# -s
#    Show the commands being executed.
#
# For example:
#
# intro https://pkg.cppget.org/1/hello
# intro /var/bpkg/1/hello
#
usage="usage: $0 [options] <hello-repo>"

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

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

tmp=/tmp
rep=
toolchain=
hello2=hello/hello2
show=n

c1=g++-5
c2=clang++-3.6
c3=x86_64-w64-mingw32-g++

while [ $# -gt 0 ]; do
  case $1 in
    -t)
      shift
      toolchain=${1%/}
      shift
      ;;
    -c1)
      shift
      c1=$1
      shift
      ;;
    -c2)
      shift
      c2=$1
      shift
      ;;
    -c3)
      shift
      c3=$1
      shift
      ;;
    -h)
      shift
      hello2=${1%/}
      shift
      ;;
    -s)
      show=y
      shift
      ;;
    *)
      rep=${1%/}
      break
      ;;
  esac
done

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

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

if [ ! -d "$hello2" ]; then
  error "hello2 directory $hello2 does not exist"
fi

if [ -n "$toolchain" ]; then
  export PATH="$toolchain/bin:$PATH"

  if [ "`which b`" != "$toolchain/bin/b" ]; then
    error "b does not appear to be in $toolchain/bin/"
  fi

  if [ "`which bpkg`" != "$toolchain/bin/bpkg" ]; then
    error "bpkg does not appear to be in $toolchain/bin/"
  fi
fi

if [ -z "`which tree`" ]; then
  tree="ls -1"
else
  tree=tree
fi

function show () # <cmd> ...
{
  if [ $show = "y" ]; then
    echo "$*"
    $*
    echo
  else
    $*
  fi
}

function create () # <dir> <bpkg-args>
{
  local d=$1; shift

  rm -rf $tmp/$d
  mkdir $tmp/$d
  cd $tmp/$d
  show bpkg create $*
}

function info () # stable|testing
{
  local d=$1; shift
  show bpkg rep-info $rep/$d
}

function add () # stable|testing
{
  local d=$1; shift
  show bpkg add $rep/$d
}

function fetch ()
{
  show bpkg fetch
}

function build () # <bpkg-args>
{
  show bpkg build -y $*
}

function drop () # <bpkg-args>
{
  show bpkg drop -y $*
}

function status () # <pkg> <expected>
{
  if [ $show = "y" ]; then
    echo "bpkg status $1"
  fi

  local s=`bpkg status $1`
  echo "$s"

  if [ "$s" != "$2" ]; then
    error "status $1: '"$s"', expected: '"$2"'"
  fi

  if [ $show = "y" ]; then
    echo
  fi
}

function clean () # <bpk>
{
  show bpkg clean $*
}

function update () # <bpk>
{
  show bpkg update $*
}

function test () # <bpk>
{
  show bpkg test $*
}

create hello-gcc5-release cxx config.cxx=$c1 config.cxx.coptions=-O3
info stable
add stable
fetch
build hello
drop hello
build -v hello
status libhello "configured 1.0.1"
status hello "configured 1.0.0 hold_package"
drop hello
status hello "available 1.0.0"
status libfoobar "unknown"

build hello
add testing
fetch
status libhello "configured 1.0.1; available 1.1.1 1.1.0"
build hello
build libhello
clean hello
update hello
build libhello/1.0.1

test libhello hello
show ls -1F
show ls -1F hello-1.0.0/
show hello-1.0.0/hello || true
show hello-1.0.0/hello World

show bpkg install config.install.root=/opt/hello \
     config.install.root.sudo=sudo \
     config.bin.rpath=/opt/hello/lib hello
show $tree -F /opt/hello/
show /opt/hello/bin/hello World
sudo rm -rf /opt/hello

show cd $hello2
show b config.cxx=$c1 config.import.libhello=$tmp/hello-gcc5-release
show $tree -F
show ./hello
show b config.cxx=$c1 config.import.libhello=$tmp/hello-gcc5-release clean # Extra.

show cd $tmp
rm -rf hello2-gcc5-release
show mkdir hello2-gcc5-release
show b config.cxx=$c1 config.cxx.coptions=-O3 \
  config.import.libhello=$tmp/hello-gcc5-release \
  "configure($hello2/@hello2-gcc5-release/)"
show b hello2-gcc5-release/
show cd hello2-gcc5-release/
show b
show b clean
show b -v

show cd $tmp
show b "configure($hello2/@$tmp/hello-gcc5-release/hello2/)"
show b $tmp/hello-gcc5-release/hello2/
show b "{clean disfigure}($tmp/hello-gcc5-release/hello2/)"

build -d $tmp/hello-gcc5-release $hello2/
build -d $tmp/hello-gcc5-release -L libhello
update -d $tmp/hello-gcc5-release hello2
show $tmp/hello-gcc5-release/hello2-1.0.0/hello

if [ -n "$c2" ]; then
  create hello-clang36-release cxx config.cxx=$c2 config.cxx.coptions=-O3
  add testing
  fetch
  build libhello/1.0.0 $hello2/
fi

if [ -n "$c3" ]; then
  create hello-mingw32 cxx \
    config.cxx=$c3         \
    config.bin.lib=static config.cxx.loptions=-static
  add stable
  fetch
  build hello
  export WINEDEBUG=fixme-all
  show wine hello-1.0.0/hello.exe Windows
fi