#! /bin/bash

# Target to Photon OS version
VERSION=3

# Keep running container instance alive?
KEEP_SANDBOX_AFTER_FAILURE=1

# Draw spinner while waiting
DRAW_SPINNER=1

test "$#" -ne 1 && echo "Usage: $0 spec-file-to-build.spec" && exit 1

CONTAINER=build_spec
SPECPATH=$(readlink -m $1)
SPECFILE=$(basename $SPECPATH)
SPECDIR=$(dirname $SPECPATH)
mkdir -p $SPECDIR/stage/LOGS
LOGFILE=$SPECDIR/stage/LOGS/$(basename $SPECFILE .spec).log

# use &3 for user output
exec 3>&1
# redirect &1 and &2 to the log file
exec &>$LOGFILE

function wait_for_result() {
  local pid=$!
  if [ "$DRAW_SPINNER" -eq 1 ]; then
    local spin='-\|/'
    local i=0
    echo -n " " >&3
    while [ -d /proc/$pid ]; do
      sleep .25
      echo -ne "\b${spin:i++%4:1}" >&3
    done
    echo -ne "\b" >&3
  fi
  wait $pid
  if [ $? -eq 0 ]; then
    echo -e "\033[0;32mOK\033[0m" >&3
  else
    echo -e "\033[0;31mFAIL\033[0m" >&3
    fail
  fi
}

function run() {
  echo -ne "\t$1 " >&3
  shift
  echo "run: $@"
  $@ &
  wait_for_result
}

function in_sandbox() {
  docker exec $CONTAINER "$@"
}

function create_sandbox() {
  docker ps -f "name=$CONTAINER" && docker rm -f $CONTAINER
  docker inspect --format='{{.Created}}' photon_build_spec:$VERSION.0
  local status=$?
  local cdate=$(date --date=`docker inspect --format='{{.Created}}' photon_build_spec:$VERSION.0` '+%s')
  # image exists?
  if [ $status -eq 0 ]; then
    local vdate=$((`date '+%s'` - 1209600))
    # image is less then 2 weeks
    if [ $cdate -gt $vdate ]; then
      # use this image
      run "Use local build template image" docker run -d --name $CONTAINER --network="host" photon_build_spec:$VERSION.0 tail -f /dev/null
      return 0
    else
      # remove old image
      docker image rm photon_build_spec:$VERSION.0
    fi
  fi


  run "Pull photon image" docker run -d --name $CONTAINER --network="host" photon:$VERSION.0 tail -f /dev/null

  # replace toybox with coreutils and install default build tools
  run "Replace toybox with coreutils" in_sandbox tdnf remove -y toybox
  run "Install default build tools" in_sandbox tdnf install -y rpm-build build-essential tar sed findutils file gzip patch

  run "Create build template image for future use" docker commit `docker ps -q -f "name=$CONTAINER"` photon_build_spec:$VERSION.0
}

function prepare_buildenv() {
  run "Create source folder" in_sandbox mkdir -p /usr/src/photon/SOURCES
  run "Copy sources from $SPECDIR" docker cp $SPECDIR/. $CONTAINER:/usr/src/photon/SOURCES
  local br=`sed -n 's/BuildRequires://p' $SPECPATH | sed 's/ \(<\|\)= /=/g;s/>\(=\|\) [^ ]*//g'`
  if [ "$br" != "" ]; then
    run "Install build requirements" in_sandbox tdnf install -y $br 
  fi
}

function build() {
  echo -ne "\tRun rpmbuild " >&3
  docker exec $CONTAINER rpmbuild -bb --define "dist .ph$VERSION" /usr/src/photon/SOURCES/$SPECFILE &
  wait_for_result
}

function get_rpms() {
  run "Copy RPMS" docker cp $CONTAINER:/usr/src/photon/RPMS $SPECDIR/stage
  run "Copy SRPMS" docker cp $CONTAINER:/usr/src/photon/SRPMS $SPECDIR/stage
}

function destroy_sandbox() {
  run "Stop container" docker kill $CONTAINER
  run "Remove container" docker rm $CONTAINER
}

function clean_up() {
  echo "Post clean up" >&3
  docker ps -f "name=$CONTAINER" &>/dev/null && destroy_sandbox &>/dev/null
}

function fail() {
  test "$KEEP_SANDBOX_AFTER_FAILURE" -ne 1 && clean_up || \
    echo "Sandbox is preserved for analisys. Use 'docker exec -it $CONTAINER /bin/bash'" >&3
  echo "Build failed. See $LOGFILE for full output" >&3
  echo -e "\033[1;33m" >&3
  tail $LOGFILE >&3
  echo -e "\033[0m" >&3
  exit 1
}

trap clean_up SIGINT SIGTERM

echo "1. Create sandbox" >&3
create_sandbox

echo "2. Prepare build environment" >&3
prepare_buildenv

echo "3. Build" >&3
build

echo "4. Get binaries" >&3
get_rpms

echo "5. Destroy sandbox" >&3
destroy_sandbox

echo "Build completed. RPMS are in '$SPECDIR/stage' folder" >&3