#!/bin/sh

# Copyright (c) 2016, Percona LLC and/or its affiliates. All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

BUILD_REVEL="${BUILD_REVEL:-"yes"}"
DIRTY_BUILD="${DIRTY_BUILD:-"no"}"
PKG="${PKG:-"yes"}"

if [ $# -eq 1 -a "$1" = "help" ]; then
   echo "Usage: $0"
   echo
   echo "This script must be ran from the root or scripts/ dir."
   echo "Binaries and packages are put in distro/."
   exit 0
fi

set -eu

err() {
   echo "ERROR: $@" >&2
   exit 1
}

BIN="percona-qan-api"

if [ -f "build" -a "install" -a "manage" ]; then
   cd ..
fi

if [ -d "app" -a -d "conf" -a -d "vendor" ]; then
   ROOT_DIR="$PWD"
else
   err "Run this script from the percona/qan-api root directory."
fi

if [ -z "$(which strings)" ]; then
   err "The 'strings' program is required. Install binutils."
fi

PLATFORM=`uname -m`
if [ "$PLATFORM" = "x86_64" ]; then
   ARCH="x86_64"  # no change
elif [ "$PLATFORM" = "i686" -o "$PLATFORM" = "i386" ]; then
   ARCH="i386"
else
   err "Unknown platform (uname -m): $PLATFORM (expected x86_64, i686, or i386)"
fi

cd "$ROOT_DIR"

# Determine if this is a dev or release build. A release build requires using
# the master branch that's tagged with the same version in conf/app.conf. Else,
# we presume dev build.
DEV="yes"
VER="$(grep app.version conf/app.conf | awk '{print $3}')"
REV="$(git log -n 1 --no-walk --pretty="%h")"
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
if [ "$BRANCH" = "master" ]; then
   # git log -n 1 --no-walk --tags --pretty="%h %d" --decorate=full
   # 1475390  (HEAD, tag: refs/tags/v1.0.0, refs/remotes/origin/master, refs/heads/master, refs/heads/foo)
   latestTag="$(git log -n 1 --no-walk --tags --pretty="%h %d" --decorate=full)"
   tagRev="$(echo "$latestTag" | awk '{print $1}')"
   tagVer="$(echo "$latestTag" | perl -n -e '/refs\/tags\/v([\d\.]+)/ && print $1')"
   if [ "$tagVer" -a "$tagRev" = "$REV" ]; then
      if [ "$tagVer" != "$VER" ]; then
         err "Version mismatch: conf/app.conf has v$VER, but git tag has v$tagVer"
      else
         dirty="$(git status --porcelain)"
         if [ "$dirty" ]; then
            if [ "$DIRTY_BUILD" = "no" ]; then
               err "Cannot do release build because this is the master branch with version" \
                  "tag v$tagVer but there are uncommitted changes or untracked files" \
                  "(see 'git status'). If the latest commit is not v$tagVer, remove the tag (git tag -d v$tagVer);" \
                  "else, add and commit all changes, then re-tag the latest commit" \
                  "(git tag -a v$tagVer -m \"v$tagVer\"). Or, specify DIRTY_BUILD=yes to force" \
                  "the release build (not recommended)."
            else
               echo "Dirty release build of master branch v$VER"
            fi
         else
            echo "Release build of master branch v$VER"
         fi
         DEV="no"
      fi
   else
      echo "Dev build of master branch @ $REV (latest commit has no version tag)"
   fi
else
   echo "Dev build of $BRANCH branch @ $REV"
fi

# To distinguish dev and release builds, we append "-date.revision" to dev builds,
# e.g. release 1.0.0 = "1.0.0", but dev 1.0.0 = "1.0.0-20150825.a73cd9e".
# Also, unless DEPS is set explicitly, dev builds don't use vendoring but release builds do.
if [ "$DEV" = "yes" ]; then
   ymd="$(TZ="UTC" date "+%Y%m%d")"
   VER="$VER-$ymd.$REV"
   DEPS="${DEPS:-"no"}"
else
   DEPS="${DEPS:-"yes"}"
fi

# Install/update deps (vendoring)
if [ "$DEPS" = "yes" ]; then
   govendor sync
fi

# Build binaries
BUILD_TARGET_DIR="/tmp/$BIN-$VER"
if [ "$BUILD_REVEL" = "yes" ]; then 
   echo "Building $BIN..."
   [ -d "$BUILD_TARGET_DIR" ] && rm -rf "$BUILD_TARGET_DIR"
   set +e
   APP_VERSION="$VER" revel build github.com/percona/qan-api "$BUILD_TARGET_DIR" > revel-build.log 2>&1
   if [ $? -ne 0 ]; then
     c=$?
     tail -n 20 "$ROOT_DIR/revel-build.log" >&2
     err "'revel build' failed (exit $c). See above or revel-build.log for the full log."
   fi
   set -e
fi

# Set up the distro dir
PKG_FILE="$BIN-$VER-$ARCH"
PKG_DIR="$ROOT_DIR/distro/$PKG_FILE"
[ ! -d "distro" ] && mkdir distro
[ -d "$PKG_DIR" ] && rm -rf "$PKG_DIR"

cp -R "$BUILD_TARGET_DIR" "$PKG_DIR"

# Rename binary so "ps | grep percona" shows all Percona procs.
cd "$PKG_DIR"
mkdir schema
mkdir bin
mv qan-api bin/$BIN

# Check that binary was compiled with pkgs from vendor dir.
if [ "$DEPS" = "yes" ]; then
   strings bin/$BIN | grep -q "vendor/github.com/go-sql-driver/mysql" \
      || err "$BIN not built with vendor deps (vendor)"
   strings bin/$BIN | grep -q "vendor/github.com/revel/revel" \
      || err "$BIN not built with vendor deps (vendor)"
fi

# Clean up the crap that Revel puts in the distro, i.e. the entire source tree. :-(
rm run.*
rm -rf ./src/github.com/percona/qan-api/*

# Put back in the distro only the dirs and files we need.
mkdir ./src/github.com/percona/qan-api/conf
mkdir -p ./src/github.com/percona/qan-api/app/views
mkdir -p ./src/github.com/percona/qan-api/service/query
cp -r "$ROOT_DIR/scripts"/* .
rm build
cp "$ROOT_DIR/conf/prod.conf" ./src/github.com/percona/qan-api/conf
cp "$ROOT_DIR/conf/app.conf"  ./src/github.com/percona/qan-api/conf
cp "$ROOT_DIR/conf/routes"    ./src/github.com/percona/qan-api/conf
cp "$ROOT_DIR/schema/"*       ./schema
cp "$ROOT_DIR/service/query/mini.pl" ./src/github.com/percona/qan-api/service/query

# Double check that there are no .go source files in the distro.
if [ "$(find ./src/github.com/percona -name \*.go -print)" ]; then
   err "There are .go source files in ./src/github.com/percona!"
fi

cd ..
[ "$PKG" = "yes" ] && tar cfz $PKG_FILE.tar.gz $PKG_FILE/ > /dev/null

echo
echo "Done building distro/$PKG_FILE.tar.gz"
echo
