#! /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
# -c4
#    C++ compilers 1 (g++-5), 2 (clang++-3.6), 3 (x86_64-w64-mingw32-g++), and
#    4 (cl-14). If the value for 2, 3, 4 is empty, then this test is skipped.
#
# -h
#    The hello2 source directory, by default hello/hello2
#
# -s
#    Show the commands being executed.
#
# -p
#    Prompt for confirmations.
#
# 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
prompt=-y
trust="--trust FF:DF:7D:38:67:4E:C3:82:65:7E:EE:1F:D4:80:EC:56:C4:33:5B:65:3F:9B:29:9A:30:56:B9:77:B9:F2:01:94"

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

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
      ;;
    -c4)
      shift
      c4="$1"
      shift
      ;;
    -h)
      shift
      hello2=${1%/}
      shift
      ;;
    -s)
      show=y
      shift
      ;;
    -p)
      prompt=
      trust=
      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 $trust $rep/$d
}

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

function fetch ()
{
  show bpkg fetch $trust
}

function build () # <bpkg-args>
{
  show bpkg build $prompt "${@}"
}

function drop () # <bpkg-args>
{
  show bpkg drop $prompt "${@}"
}

function status () # <pkg> <expected> [<args>]
{
  local p="$1"
  shift
  local e="$1"
  shift

  if [ $show = "y" ]; then
    echo "bpkg status $* $p"
  fi

  local s="$(bpkg status "${@}" $p)"
  echo "$s"

  if [ "$s" != "$e" ]; then
    error "status $1: '"$s"', expected: '"$e"'"
  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
if [ -n "$c2" ]; then
  create hello-vc14-release cxx config.cxx="$c4" config.cxx.coptions=/O2
fi
create hello-gcc5-release cc config.cxx="$c1" config.cc.coptions=-O3

info stable
add stable
fetch
build hello
drop hello
build -v -y hello

status libhello "configured 1.0.0; available sys:?"
status hello "configured 1.0.0 hold_package; available sys:?"
drop -y hello
status hello "available 1.0.0 sys:?"
status libfoobar "unknown"




build -y hello
add testing
fetch
status libhello "configured 1.0.0; available 1.1.0 sys:?"
build -y hello
build libhello
clean hello
update hello
build libhello/1.0.0

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.sudo=sudo        \
     config.bin.rpath=/opt/hello/lib \
     hello
show $tree -F /opt/hello/
show /opt/hello/bin/hello World

show bpkg uninstall                  \
     config.install.root=/opt/hello  \
     config.install.sudo=sudo        \
     config.bin.rpath=/opt/hello/lib \
     hello
show ls /opt/hello || true

show cd $hello2
show b config.cxx=$c1 config.import.libhello=$tmp/hello-gcc5-release
show $tree -F
show ./hello
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.cc.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/
status hello2 "unknown" -d $tmp/hello-gcc5-release
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 cc config.cxx=$c2 config.cc.coptions=-O3
  add testing
  fetch
  build libhello/1.0.0 $hello2/
fi

if [ -n "$c3" ]; then
  create hello-mingw64 cc config.cxx=$c3
  add stable
  fetch
  build -y hello
  export WINEDEBUG=fixme-all
  show wine hello-1.0.0/hello.exe Windows
  test libhello hello
fi