#!/usr/bin/env bash
# -*- vim: set expandtab tabstop=2 shiftwidth=2:
#
# Build a container ready to build the documentation be reading the dependencies
# listed in shell scripts in documentation/tools/host_packages_scripts, and
# start a documentation build in this container.
#
# Usage:
#
#   ./documentation/tools/build-docs-container <image> [<make target>]
#
# e.g.:
#
#   ./documentation/tools/build-docs-container ubuntu:24.04 html
#
# Will build the docs in an Ubuntu 24.04 container in html.
#
# The container engine can be selected by exporting CONTAINERCMD in the
# environment. The default is docker, but podman can also be used.

set -eu -o pipefail

SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
CONTAINERCMD=${CONTAINERCMD:-docker}
DOCS_DIR="$SCRIPT_DIR/../.."
INCLUDE_ESSENTIAL_PACKAGES=${INCLUDE_ESSENTIAL_PACKAGES:-0}

function usage()
{
  echo "$0 -- script to build documentation from within a container

$0 OCI_IMAGE [make arguments...]

   OCI_IMAGE is an image:tag of an OCI image hosted on hub.docker.com. It is one
   of:
     - almalinux:8
     - almalinux:9
     - centos:stream9
     - debian:12
     - debian:13
     - fedora:39
     - fedora:40
     - fedora:41
     - fedora:42
     - leap:15.5
     - leap:15.6
     - rockylinux:8
     - rockylinux:9
     - ubuntu:22.04
     - ubuntu:24.04
     - ubuntu:25.04
     - ubuntu:25.10

   [make arguments] is one or more argument to pass to the make command of
   documentation/Makefile, see that file for what's supported. This is typically
   intended to be used to provide specific make targets.
   Default: publish

   Environment variables:

   - CONTAINERCMD can be set to 'docker' or 'podman' to select the
     container engine (default: 'docker').

   - INCLUDE_ESSENTIAL_PACKAGES can be set to 0 or 1 to also include essential
     packages listed in documentation/tools/host_packages_scripts/*_essential.sh.
     This is not required to build the documentation but can be useful to validate
     the installation of packages listed in these files (default: 0).
"
}

main ()
{
  if [ "$#" -lt 1 ]; then
    usage
    exit 1
  fi

  local image="$1"
  shift

  OCI=$(which "$CONTAINERCMD")

  # docker build doesn't accept 2 colons, so "sanitize" the name
  local sanitized_dockername
  sanitized_dockername=$(echo "$image" | tr ':.' '-')

  local version
  version=$(echo "$image" | awk -F: '{print $NF}')

  # Default to docker.io unless overwritten below
  local repo=docker.io

  case $image in
    "almalinux:8"*|\
    "almalinux:9"*)
      containerfile=Containerfile.almalinux
      essential=almalinux_essential.sh
      docs=almalinux_docs.sh
      docs_pdf=tlmgr_docs_pdf.sh
      pip3=pip3_docs.sh
      ;;
    "centos:stream9"*)
      containerfile=Containerfile.stream
      essential=centosstream_essential.sh
      docs=centosstream_docs.sh
      docs_pdf=tlmgr_docs_pdf.sh
      pip3=pip3_docs.sh
      repo=quay.io/centos
      ;;
    # Missing python3-saneyaml
    # "debian:11"*|\
    "debian:12"*|\
    "debian:13"*)
      containerfile=Containerfile.debian
      essential=ubuntu_essential.sh
      docs=ubuntu_docs.sh
      docs_pdf=ubuntu_docs_pdf.sh
      ;;
    "fedora:39"*|\
    "fedora:40"*|\
    "fedora:41"*|\
    "fedora:42"*)
      containerfile=Containerfile.fedora
      essential=fedora_essential.sh
      docs=fedora_docs.sh
      docs_pdf=fedora_docs_pdf.sh
      pip3=pip3_docs.sh
      ;;
    "leap:15.5"*|\
    "leap:15.6"*)
      image=opensuse/leap:$version
      containerfile=Containerfile.zypper
      essential=opensuse_essential.sh
      docs=opensuse_docs.sh
      docs_pdf=opensuse_docs_pdf.sh
      pip3=pip3_docs.sh
      ;;
    "rockylinux:8"*|\
    "rockylinux:9"*)
      containerfile=Containerfile.rocky
      essential=rockylinux_essential.sh
      docs=rockylinux_docs.sh
      docs_pdf=tlmgr_docs_pdf.sh
      pip3=pip3_docs.sh
      ;;
    "ubuntu:22.04"*|\
    "ubuntu:24.04"*|\
    "ubuntu:25.04"*|\
    "ubuntu:25.10"*)
      containerfile=Containerfile.ubuntu
      essential=ubuntu_essential.sh
      docs=ubuntu_docs.sh
      docs_pdf=ubuntu_docs_pdf.sh
      ;;
    *)
      echo "$image not supported!"
      usage
      exit 1
      ;;
  esac

  $OCI build \
    --tag "yocto-docs-$sanitized_dockername:latest" \
    --build-arg ARG_FROM="$repo/$image" \
    --build-arg INCLUDE_ESSENTIAL_PACKAGES="${INCLUDE_ESSENTIAL_PACKAGES}" \
    --build-arg ESSENTIAL="host_packages_scripts/$essential" \
    --build-arg DOCS="host_packages_scripts/$docs" \
    --build-arg DOCS_PDF="host_packages_scripts/$docs_pdf" \
    --build-arg PIP3="host_packages_scripts/${pip3:-}" \
    --file "$SCRIPT_DIR/containerfiles/$containerfile" \
    "$SCRIPT_DIR"

  local -a args_run=(
    --rm
    --interactive
    --tty
    --volume="$DOCS_DIR:/docs:rw"
    --workdir=/docs
    --security-opt label=disable
  )

  if [ "$(basename "$OCI")" = "docker" ]; then
    args_run+=(
      --user="$(id -u)":"$(id -g)"
    )
  elif [ "$(basename "$OCI")" = "podman" ]; then
    # we need net access to fetch bitbake terms
    args_run+=(
      --cap-add=NET_RAW
      --userns=keep-id
    )
  fi

  $OCI run \
    "${args_run[@]}" \
    "yocto-docs-$sanitized_dockername" \
    "$@"
}

main "$@"
