#!/usr/bin/env bash
# shellcheck disable=SC2164
# SC2164: pushd/popd are redefined as functions that exit in common.sh

# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MIT

# This script constructs an appimage for vagrant, given a gemfile and a
# substrate. Appimage builds are supposed to be run from old versions of
# ubuntu, so in CI this is invoked via .ci/build-appimage-in-chroot. The
# substrate file should be a linux amd64 substrate.

# Load CI helpers
csource="${BASH_SOURCE[0]}"
while [ -h "$csource" ] ; do csource="$(readlink "$csource")"; done
root="$( cd -P "$( dirname "$csource" )/../" && pwd )"

. "${root}/.ci/load-ci.sh"

# Verify arguments
if [ "$#" -ne "3" ]; then
  failure "Expected three args: SUBSTRATE-FILE GEM-FILE OUTPUT-DIR"
fi

substrate_file="${1?Substrate file is required}"
gem_file="${2?Gem file is required}"
output_dir="${3?Directory for output file required}"

# If the script isn't being run as root, fail
debug "performing root user check"
if [ "$(id -u)" != "0" ]; then
    failure "Script must be run as root"
fi

# Validate our paramters
if [ ! -f "${substrate_file}" ]; then
    error "Invalid path for substrate file (%s)" "${substrate_file}"
fi

if [ ! -f "${gem_file}" ]; then
    error "Invalid path for vagrant gem file (%s)" "${gem_file}"
fi

mkdir -p "${output_dir}" ||
    error "Invalid path for output directory %s" "${output_dir}"
pushd "${output_dir}" > /dev/null || exit
output_dir="$(pwd)" || exit
popd > /dev/null || exit

WORK_DIR="$(mktemp -d tmp.XXXXXXXXX -p "$(pwd)")"
pushd "${WORK_DIR}" || failure "Could not enter work directory"

apt-get update ||
  failure "Failed to update local repositories"
apt-get install -y libcairo2-dev build-essential ca-certificates fuse libfuse2 ruby wget ||
  failure "Failed to install required packages"

# Get vagrant version
cp "${gem_file}" vagrant.gem ||
    failure "Failed to relocate Vagrant Gem (%s)" "${gem_file}"
gem unpack ./vagrant.gem || failure "Failed to unpack Vagrant gem"
VAGRANT_VERSION="$(<vagrant/version.txt)"
rm -rf ./vagrant

# Copy in our substrate asset
cp "${substrate_file}" ./substrate.zip ||
    failure "Failed to copy substrate asset (%s)" "${substrate_file}"

unzip ./substrate.zip ||
    failure "Failed to unpack substrate"
mkdir ./vagrant ||
    failure "Failed to create vagrant directory"
mv ./embedded ./vagrant/usr ||
    failure "Failed to rename substrate directory"
rm -f ./substrate.zip

pushd ./vagrant/usr/lib ||
    failure "Could not enter lib directory"

for f in ./*.so; do
    echo "Found shared library: ${f}"
    for ff in "${f}"*; do
        if [ "${f}" = "${ff}" ]; then
            continue
        fi
        echo "  ${f} -> ${ff}"
        rm "${ff}"
        ln -s "${f}" "${ff}"
    done
done
rm -f ./*.a

popd ||
    failure "Could not return to work directory"

# Copy in required files
appimg_dir="${root}/package/appimage"

cp "${appimg_dir}/vagrant.yml" vagrant.yml ||
    failure "Failed to relocate appimage config"
cp "${appimg_dir}/vagrant_wrapper.sh" vagrant_wrapper.sh ||
    failure "Failed to relocate vagrant wrapper script"


# Create our custom deb package
mkdir -p "vagrant/DEBIAN/"
cat <<EOF > vagrant/DEBIAN/control
Package: vagrant
Version: ${VAGRANT_VERSION}-1
Section: utils
Priority: important
Essential: yes
Architecture: amd64
Depends: ca-certificates
Maintainer: HashiCorp Vagrant Team <team-vagrant@hashicorp.com>
Description: Vagrant is a tool for building and distributing development environments.
EOF

dpkg-deb -b ./vagrant || failure "Failed to create Vagrant stub package"
rm -rf ./vagrant/
VAGRANT_DEB_FILE="${WORK_DIR}/vagrant_${VAGRANT_VERSION}-1.deb"
mv ./*.deb "${VAGRANT_DEB_FILE}"

export VAGRANT_VERSION
export WORK_DIR
export VAGRANT_DEB_FILE

# Build our appimage
"${appimg_dir}/pkg2appimage" ./vagrant.yml ||
    failure "Failed to build Vagrant appimage"

# Create the release asset
mkdir release-asset
mv out/* release-asset/vagrant ||
    failure "Failed to relocate Vagrant appimage for compression"
zip -j "vagrant_${VAGRANT_VERSION}_linux_amd64.zip" release-asset/* ||
    failure "Failed to create final Vagrant appimage asset"

# Place asset in original execution directory
mv ./*.zip "${output_dir}/" ||
    failure "Failed to move Vagrant appimage asset to destination"

# Exit the directory and clean it
# (we really don't care if this fails)
popd
rm -rf "${WORK_DIR}"
