#!/bin/bash
################################################################################
set -eEuo pipefail
err=0
trap 'err=$?' ERR
trap 'cleanup' EXIT

epoch=$(date +%s.%3N)
today=$(date +%Y-%m-%d-T%H%M)

badarg() {
    echo -n "$(basename $0): " >&2
    echo "$1" >&2
    echo "Try '$(basename $0) -h' for more information." >&2
    exit 2
}

cleanup() {
    if [[ $err -eq 0 || $opt_debug -eq 0 ]]; then
        podman rm -i -f tmp-$epoch 2>&1 > /dev/null
    fi
}

help="Usage: $(basename $0) [-sdh] [-t tag] [directory] [name]
Builds an image from files in a directory, and assigns it a name.

Files used are 'Containerfile' and optionally 'Systemdfile'. If first argument
is omitted, script assumes files can be found in the current working directory.
If second argument is omitted, the directory where the files were found is used
as the image name.

Options:
  -s        Squash all layers in the image into a single layer
  -r        Redo build from scratch instead of using cached layers
  -d        Debug mode: don't delete the temporary container created by the script
            when encountering an error
  -t [tag]  Tag the image with the given string. Can be used multiple times to assign
            multiple tags
  -h        Display this help and exit"

# Handle options
opt_squash=0
opt_redo=0
opt_debug=0
opt_tags=()
while getopts ':srdt:h' arg; do
    case $arg in
        s) opt_squash=1;;
        r) opt_redo=1;;
        d) opt_debug=1;;
        t) opt_tags+=("${OPTARG}");;
        h) echo "$help"; exit 0;;
        :) badarg "Argument missing for option '-$OPTARG'";;
        ?) badarg "Invalid option '-$OPTARG'";;
    esac
done
shift $((OPTIND -1))

# Handle non-option arguments
if [[ $# -gt 2 ]]; then
    badarg "Too many arguments"
fi

if [[ $# -ge 1 ]]; then
    directory="$1"
else
    directory=$(pwd)
fi


if [[ $# -ge 2 ]]; then
    name="$2"
else
    name=$(basename "$directory")
fi

# Main
if [[ ! -d "$directory" ]]; then
    echo "Error: directory '$directory' not found"
    exit 1
else
    cd "$directory"
fi

buildopts=""
if [[ $opt_squash -eq 1 ]]; then
    buildopts="$buildopts --squash-all"
fi
if [[ $opt_redo -eq 1 ]]; then
    buildopts="$buildopts --no-cache"
fi

# tell buildah to build images in docker format instead of the default OCI format
# because only docker-format images can use the SHELL directive in Containerfiles
export BUILDAH_FORMAT=docker

# build image
echo "Building image ..."
podman build -f Containerfile -t tmp-$epoch $buildopts

# Systemdfile is for commands that need systemd to execute
if [[ -f Systemdfile ]]; then
    echo "Running build steps that require systemd ..."
    echo "Creating temporary container ..."
    podman create --name tmp-$epoch tmp-$epoch
    podman start tmp-$epoch
    echo "Copying script to container ..."
    podman cp Systemdfile tmp-$epoch:/root/
    echo "Running script ..."
    podman exec tmp-$epoch bash -c "chmod +x /root/Systemdfile && /root/Systemdfile"
    echo "Committing container to image ..."
    podman commit tmp-$epoch "$name:$today"
else
   echo "Systemdfile not found, skipping temporary container step ..."
   # tag image we already built with appropriate tag, and untag with tmp
   podman tag tmp-$epoch "$name:$today"
   podman rmi tmp-$epoch
fi

# tag image as latest
podman tag "$name:$today" "$name:latest"

# assign any extra tags
for tag in "${opt_tags[@]}"; do
    podman tag "$name:$today" "$name:$tag"
done

echo "Done!"