#!/bin/bash

# Record everything that is run from this script so appears in logs.

set -x

# Ensure that any failure within this script causes this script to fail
# immediately. This eliminates the need to check individual statuses for
# anything which is run and prematurely exit. Note that the feature of
# bash to exit in this way isn't foolproof. Ensure that you heed any
# advice in:
#
#   http://mywiki.wooledge.org/BashFAQ/105
#   http://fvue.nl/wiki/Bash:_Error_handling
#
# and use best practices to ensure that failures are always detected.
# Any user supplied scripts should also use this failure mode.

set -eo pipefail

# Set the umask to be '002' so that any files/directories created from
# this point are group writable. This does rely on any applications or
# installation scripts honouring the umask setting, which unfortunately
# not all do.

umask 002

# Create directory where additional packags will be installed.

WARPDRIVE_ROOT_DIR=${WARPDRIVE_ROOT_DIR:-/usr/local}

mkdir -p $WARPDRIVE_ROOT_DIR

# Validate that package version details are set in the Dockerfile.

test ! -z "$PYTHON_VERSION" || exit 1
test ! -z "$MOD_WSGI_VERSION" || exit 1

# Download source code for packages and unpack them.

WARPDRIVE_BUILD_DIR=${WARPDRIVE_BUILD_DIR:-/tmp/warpdrive-init.$$}

mkdir -p $WARPDRIVE_BUILD_DIR

curl -SL -o $WARPDRIVE_BUILD_DIR/python.tar.gz https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz

mkdir $WARPDRIVE_BUILD_DIR/python

tar -xC $WARPDRIVE_BUILD_DIR/python --strip-components=1 -f $WARPDRIVE_BUILD_DIR/python.tar.gz

# To be safe, force the C compiler to be used to be the 64 bit compiler.

CC=x86_64-linux-gnu-gcc
export CC

# Build Python from source code. Configure options used in part mirror
# what is used by Debian itself when it builds its own Python packages.
# We first install with a shared Python library, and then install the
# static library and statically linked 'python' executable.

cd $WARPDRIVE_BUILD_DIR/python

CONFIG_ARGS="--prefix=$WARPDRIVE_ROOT_DIR/python \
    --enable-ipv6 --with-dbmliborder=bdb:gdbm --with-system-expat \
    --with-system-ffi --with-fpectl"

case "$PYTHON_VERSION" in
    2.*)
        CONFIG_ARGS="$CONFIG_ARGS --enable-unicode=ucs4"
        ;;
    3.[012].*)
        CONFIG_ARGS="$CONFIG_ARGS --with-wide-unicode"
        ;;
esac

./configure $CONFIG_ARGS --enable-shared

LD_RUN_PATH=$WARPDRIVE_ROOT_DIR/python/lib
export LD_RUN_PATH

make
make install
make distclean

./configure $CONFIG_ARGS

make
make altbininstall

unset LD_RUN_PATH

cd $WARPDRIVE_ROOT_DIR/python/bin

case "$PYTHON_VERSION" in
    3.*)
        ln -s python3 python
        ;;
esac

# Set PATH to include bin directories for Python and Apache.

PATH=$WARPDRIVE_ROOT_DIR/python/bin:$PATH
export PATH

# Install additional common Python packages we want installed. This
# includes installing mod_wsgi-express as a fallback in case someone
# expects it to be available as part of the base image.

curl -SL 'https://bootstrap.pypa.io/get-pip.py' | python

if [ ! -f $WARPDRIVE_ROOT_DIR/python/bin/pip ]; then
    if [ -f $WARPDRIVE_ROOT_DIR/python/bin/pip3 ]; then
        ln -s pip3 $WARPDRIVE_ROOT_DIR/python/bin/pip
    fi
fi

pip install --no-cache-dir virtualenv

# Prune unwanted files from Python and Apache installations.

find $WARPDRIVE_ROOT_DIR/python/lib \
    \( -type d -and -name test -or -name tests \) -or \
    \( -type f -and -name '*.pyc' -or -name '*.pyo' \) | \
    xargs rm -rf

# Fixup group ownership and directory/file permissions for installation
# area so group writable by 'root'.

chgrp -R root $WARPDRIVE_ROOT_DIR

find $WARPDRIVE_ROOT_DIR -type d -exec chmod g+ws {} \;

find $WARPDRIVE_ROOT_DIR -perm 2755 -exec chmod g+w {} \;
find $WARPDRIVE_ROOT_DIR -perm 0644 -exec chmod g+w {} \;

# Clean up the temporary build area.

rm -rf $WARPDRIVE_BUILD_DIR

# Create a special user account under which any application should be
# run. This has group of 'root' with gid of '0' as it appears to be
# safest bet to allow file system permisions for everything to work.

WARPDRIVE_APP_ROOT=${WARPDRIVE_APP_ROOT:-/opt/app-root}

adduser --disabled-password --gecos "Warp Drive" --uid 1001 --gid 0 \
    --home ${WARPDRIVE_APP_ROOT} default

chmod g+ws ${WARPDRIVE_APP_ROOT}

# Create directories to be used as application directory etc. Ensure
# they are group writable, as we cannot be certain what uid application
# will run as. We do expect gid of '0' to be used though.

mkdir -p ${WARPDRIVE_APP_ROOT}/tmp
chmod g+ws ${WARPDRIVE_APP_ROOT}/tmp

WARPDRIVE_SRC_ROOT=${WARPDRIVE_SRC_ROOT:-$WARPDRIVE_APP_ROOT/src}

mkdir -p ${WARPDRIVE_SRC_ROOT}
chmod g+ws ${WARPDRIVE_SRC_ROOT}

# Create a Python virtual environment and ensure pip is up to date.
# Also install mod_wsgi as the default WSGI server.

virtualenv $WARPDRIVE_APP_ROOT

. $WARPDRIVE_APP_ROOT/bin/activate

pip install --no-cache-dir -U pip
pip install --no-cache-dir mod_wsgi==$MOD_WSGI_VERSION

find $WARPDRIVE_APP_ROOT -type d -exec chmod g+ws {} \;

find $WARPDRIVE_APP_ROOT -perm 2755 -exec chmod g+w {} \;
find $WARPDRIVE_APP_ROOT -perm 0644 -exec chmod g+w {} \;
