#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

## Intentional word-splitting of the optional COWBUILDER_PREFIX argument;
## quoting it would break the cowbuilder call.
# shellcheck disable=SC2086

## Host-side wrapper. All VBoxManage calls run inside the amd64 cowbuilder
## chroot set up by 'build-steps.d/*_cowbuilder-setup' so the build host
## does not need VirtualBox installed. This is required to build the
## arm64 ('Mac M1/M2') VirtualBox OVA on an arm64 Linux host (since
## VirtualBox is not available for arm64 Linux) and keeps the build host
## clean for amd64 builds too.

set -x
set -o errexit
set -o nounset
set -o pipefail
set -o errtrace
shopt -s inherit_errexit
shopt -s shift_verbose

true "INFO: Currently running script: ${BASH_SOURCE[0]} $*"

MYDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

cd "$MYDIR"
cd ..
cd help-steps

source pre
source variables

main() {
   if [ ! "${dist_build_virtualbox:-}" = "true" ]; then
      true "${green}INFO: Skipping ${BASH_SOURCE[0]}, because dist_build_virtualbox is not set to 'true'.${reset}"
      return 0
   fi

   ## Note on '$build_dry_run': deliberately NOT gated here. In dry-run
   ## mode '3200_create-raw-image' calls 'qemu-img create -f raw' (a
   ## valid sparse raw image, not an empty text file), so
   ## 'VBoxManage convertfromraw' succeeds and produces a near-empty VDI.
   ## The whole point of '--dry-run true' is (per 'help-steps/parse-cmd')
   ## to exercise 'dm-prepare-release' with minimum artifact, so 4600
   ## must still populate the VirtualBox registry.

   ## VirtualBox is installed into the amd64 chroot only (see
   ## 'build-steps.d/*_cowbuilder-setup'). Use the amd64 chroot regardless
   ## of $dist_build_target_arch: for an arm64 target we still use
   ## 'VBoxManage' from the amd64 chroot to wrap the arm64 .vdi into an
   ## .ova.
   local dist_build_multiarch_package_item
   dist_build_multiarch_package_item="amd64"
   export dist_build_multiarch_package_item

   ## Sets base_folder / cow_folder for the current
   ## $dist_build_multiarch_package_item.
   set_cowbuilder_folders

   if [ ! -d "$base_folder" ]; then
      error "base_folder '$base_folder' does not exist. Did the amd64 cowbuilder chroot fail to build?"
   fi

   ## Hand the chroot script its variables through the environment via the
   ## '--preserve-env' below, rather than serialising them to a file the chroot
   ## sources. Export each set entry of the curated allowlist
   ## '$env_vars_keep_list' from 'help-steps/variables' (several are in the
   ## list but not exported, so the '--preserve-env=' on '$SUDO_TO_ROOT' would
   ## otherwise skip them). Re-using the allowlist means there is no parallel
   ## hardcoded list to drift, and host-only state that is not in the list
   ## (SSH_AUTH_SOCK, GPG_AGENT_INFO, ANSIBLE_VAULT_PASSWORD, ...) is not
   ## exported here.
   local env_vars_var_keep_item
   for env_vars_var_keep_item in $env_vars_keep_list; do
      ## Skip variables unset in this run; an unset allowlist entry is not an
      ## error.
      [ -v "$env_vars_var_keep_item" ] || continue
      # shellcheck disable=SC2163  # dynamic export of the allowlisted name is intended
      export "$env_vars_var_keep_item"
   done

   local chroot_exec_script
   chroot_exec_script="$dist_source_help_steps_folder/pbuilder-chroot-script-create-vbox-vm"

   local bindmounts
   ## Keep host and chroot absolute paths identical so $binary_image_raw_file
   ## and $binary_build_folder_dist (passed through the environment) resolve
   ## correctly inside the chroot.
   ## Space-separated by design: pbuilder consumes BINDMOUNTS with an unquoted
   ## word-split ('for mnt in $BINDMOUNTS' in pbuilder-modules' mount loop), so a
   ## bind path containing whitespace is unsupported by pbuilder itself. Neither a
   ## bash array nor repeated '--bindmounts' flags help: each flag just appends to
   ## the same whitespace-split BINDMOUNTS string. These are controlled build
   ## paths with no spaces (help-steps/variables fails early otherwise).
   ## '$binary_image_vdi_dir' is bind-mounted as its OWN mount (not nested under
   ## '$binary_build_folder_dist') so the unprivileged chroot account
   ## 'dm-vbox-temp' can traverse to the VM disk; see 'binary_image_vdi_dir' in
   ## 'help-steps/variables'. The bind source must exist before cowbuilder
   ## mounts it.
   mkdir --parents -- "$binary_image_vdi_dir"
   bindmounts="$binary_build_folder_dist $source_code_folder_dist $binary_image_vdi_dir"

   local cowbuilder_exit_code
   cowbuilder_exit_code=0

   ## '--preserve-env' carries the variables exported above through cowbuilder
   ## into the chroot script's environment; no env file is passed.
   $SUDO_TO_ROOT \
      --preserve-env \
         ${COWBUILDER_PREFIX:-} \
            cowbuilder \
               --host-arch "$host_architecture" \
               --architecture "$dist_build_multiarch_package_item" \
               --configfile "$dist_build_pbuilder_config_file" \
               --execute \
               --basepath "$base_folder" \
               --buildplace "$cow_folder" \
               --save-after-login \
               --bindmounts "$bindmounts" \
               -- \
               "$chroot_exec_script" \
               || { cowbuilder_exit_code="$?" ; true; };

   if [ -d "$base_folder" ]; then
      $SUDO_TO_ROOT "$dist_source_help_steps_folder/umount_kill.sh" "$base_folder"
   fi

   if [ ! "${cowbuilder_exit_code:-}" = "0" ]; then
      error "cowbuilder --execute pbuilder-chroot-script-create-vbox-vm failed with exit code '$cowbuilder_exit_code'."
   fi

   sync
}

main "$@"
