#!/bin/bash

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

## example usage:

#make_cross_build_platform_list="armel armhf i386 amd64 arm64" ./build-steps.d/*_cowbuilder-setup --allow-untagged true --allow-uncommitted true --flavor internal --target root

set -x
set -e

true "INFO: Currently running script: $BASH_SOURCE $@"

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

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

source pre
source colors
source variables

cd "$MYDIR"
cd ..

source_date_epoch_test() {
   if [ "$SOURCE_DATE_EPOCH" = "" ]; then
      error "SOURCE_DATE_EPOCH is still unset!"
   fi
   true "INFO: SOURCE_DATE_EPOCH: $SOURCE_DATE_EPOCH"
}

cowbuilder_setup() {
   if cowbuilder_setup_do ; then
      true "$FUNCNAME: success"
   else
      true "$FUNCNAME: try again"
      cowbuilder_setup_do
   fi
}

cowbuilder_setup_do() {
   true "${bold}${green}INFO${reset}: Setting up cowbuilder..."

   dist_build_sources_list_primary_contents="$(cat -- "$dist_build_sources_list_primary")"
   export dist_build_sources_list_primary_contents

   if [ "$dist_build_unsafe_io" = "true" ]; then
      eatmydata_maybe_install="eatmydata"
   fi

   if [ "$dist_build_unsafe_io" = "true" ]; then
      if [ "$DOCKER" = "true" ]; then
         ## https://forums.whonix.org/t/docker-container-that-builds-whonix-images/17494/21
         true "INFO: Skip re-mounting /var/cache/pbuilder as tmpfs because DOCKER=true, ok."
      else
         if $SUDO_TO_ROOT mount | grep -- /var/cache/pbuilder | grep -- tmpfs ; then
            true "INFO: /var/cache/pbuilder already tmpfs."
         else
            $SUDO_TO_ROOT mount -t tmpfs -o size=2G none /var/cache/pbuilder
         fi
      fi
   fi

   ## Debugging.
   $SUDO_TO_ROOT cat -- "$dist_build_pbuilder_config_file"

   make_cross_build_platform_list_including_host_architecture+=" $make_cross_build_platform_list "

   if [ "$dist_build_virtualbox" = "true" ]; then
      if [ "$dist_build_target_arch" = "arm64" ]; then
         true "${cyan}INFO: '--target virtualbox' and '--arch arm64', therefore also building a AMD64 chroot, because at time of writing VirtualBox is available only on ARM64 macOS but not for ARM64 Linux.${reset}"
         make_cross_build_platform_list_including_host_architecture+=" amd64 "
      fi
   fi

   ## cowbuilder chroot also required for host_architecture so local dependencies can be built.
   make_cross_build_platform_list_including_host_architecture+=" $host_architecture "

   ## Remove duplicates in case we have just set this for example to "amd64 amd64".
   make_cross_build_platform_list_including_host_architecture=$(printf "%s\n" "$make_cross_build_platform_list_including_host_architecture" | tr ' ' '\n' | sort | uniq | tr '\n' ' ')

   for dist_build_multiarch_package_item in $make_cross_build_platform_list_including_host_architecture ; do
      true "dist_build_multiarch_package_item: $dist_build_multiarch_package_item"
      export dist_build_multiarch_package_item

      ## Implemented in help-steps/variables.
      ## sets:
      ## cow_folder
      ## base_folder
      set_cowbuilder_folders

      ## For development. Skipping base cowbuilder chroot creation during cowbuilder_execute_script development.
      #skip=true

      if [ "$skip" = "true" ]; then
         true "${cyan}INFO: Skipping cowbuilder chroot creation.${reset}"
      else
         if [ -d "$base_folder" ]; then
            $SUDO_TO_ROOT "$dist_source_help_steps_folder/umount_kill.sh" "$base_folder"
            $SUDO_TO_ROOT safe-rm --recursive --force -- "$base_folder"
         fi

         local cowbuilder_exit_code
         cowbuilder_exit_code=0

         ## '--mirror "$dist_build_apt_sources_mirror"' should be only cosmetic,
         ## because of mmdebstrap wrapper and hooks.
         ##
         ## Duplicate --extrapackages to prevent removal by pbuilder.
         $SUDO_TO_ROOT \
            $COWBUILDER_PREFIX \
               cowbuilder \
                  --architecture "$dist_build_multiarch_package_item" \
                  --configfile "$dist_build_pbuilder_config_file" \
                  --create \
                  --basepath "$base_folder" \
                  --buildplace "$cow_folder" \
                  --distribution "$dist_build_apt_stable_release" \
                  --mirror "$dist_build_apt_sources_mirror" \
                  --debootstrap "$dist_source_help_steps_folder/mmdebstrap" \
                  --hookdir "$dist_source_help_steps_folder/pbuilder-hooks" \
                  --extrapackages "sudo devscripts debhelper strip-nondeterminism fakeroot apt-transport-tor eatmydata aptitude cowdancer fasttrack-archive-keyring adduser" \
                  || { 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
            return "$cowbuilder_exit_code"
         fi
      fi

      true "INFO: Disable needless initramfs builds inside cowbuilder chroot (not supposed to get booted)."
      $SUDO_TO_ROOT mkdir --parents -- "$base_folder/etc/dracut.conf.d"
      $SUDO_TO_ROOT -- cp --verbose -- "$source_dracut_disable_config_snippet" "$base_folder/etc/dracut.conf.d"

      ## help-steps/pbuilder-hooks/G10sources_list_restore.bsh should have restored it already.
      ## `pbuilder` component `/usr/lib/pbuilder/pbuilder-createbuildenv`
      ## unfortunately runs function `installaptlines` after `${DEBOOTSTRAP}`,
      ## which uses a different sources list. This pbuilder hook script restores
      ## derivative-maker build APT sources list.
      ##
      ## Out-commented. No longer necessary in Trixie as we now use deb822
      ## format sources files and delete sources.list.
      #true "INFO: Sanity test. Security critical. Comparing derivative-maker build sources list with chroot sources list."
      #$SUDO_TO_ROOT diff -- "$dist_build_sources_list_primary" "$base_folder/etc/apt/sources.list.d/derivative.sources"
      #$SUDO_TO_ROOT cp -- "$dist_build_sources_list_primary" "$base_folder/etc/apt/sources.list.d/derivative.sources"

      $SUDO_TO_ROOT mkdir --parents -- "$base_folder/home/$user_name"
      $SUDO_TO_ROOT cp -- "$dist_build_pbuilder_config_file" "$base_folder/home/$user_name/pbuilder_config_file"

      ## virtualbox-installer / dist-installer-cli
      dist_installer_cli_file_name="$(basename -- "$binary_image_installer_dist_source")"
      ## example dist_installer_cli_file_name:
      ## dist-installer-cli-standalone

      ## copy dist-installer-cli-standalone into chroot home folder
      ## Might not be required for all platforms but depending on '"$dist_build_virtualbox" = "true"'
      ## might cause issues with reproducibility. Has no effect if not used.
      ## Copy unconditionally for simplicity.
      $SUDO_TO_ROOT cp -- "$binary_image_installer_dist_source" "$base_folder/usr/bin/$dist_installer_cli_file_name"
      $SUDO_TO_ROOT chmod o+rx -- "$base_folder/usr/bin/$dist_installer_cli_file_name"
      $SUDO_TO_ROOT chown --recursive -- "$user_name:$user_name" "$base_folder/home/$user_name"

      cowbuilder_script_list=()
      cowbuilder_script_list+=("$dist_build_pbuilder_main_chroot_script")

      if [ "$dist_build_virtualbox" = "true" ]; then
         ## Install VirtualBox inside the chroot using 'dist-installer-cli'.
         ## Useful for running 'vboxmanage' inside a clean 'cowbuilder' chroot.
         ## TODO: Enable after running 'build-steps.d/*_create-vbox-vm' inside chroot.
         #cowbuilder_script_list+=("$dist_build_pbuilder_virtualbox_chroot_script")
         true "INFO: Not yet installing VirtualBox inside chroot (TODO)."
      fi

      for cowbuilder_execute_script in "${cowbuilder_script_list[@]}"; do
         cowbuilder_exit_code=0
         $SUDO_TO_ROOT \
            $COWBUILDER_PREFIX \
               cowbuilder \
                  --architecture "$dist_build_multiarch_package_item" \
                  --configfile "$dist_build_pbuilder_config_file" \
                  --execute \
                  --basepath "$base_folder" \
                  --buildplace "$cow_folder" \
                  --save-after-login \
                  -- \
                  "$cowbuilder_execute_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
            break
         fi
      done

      if [ ! "$cowbuilder_exit_code" = "0" ]; then
         return "$cowbuilder_exit_code"
      fi
   done

   true "${bold}${green}INFO${reset}: cowbuilder setup done."
}

main() {
   source_date_epoch_test "$@"

   ## Not possible because we need *_local-dependencies build step.
   #if [ "$build_dry_run" = "true" ]; then
      #true "${bold}${cyan}INFO: dry-run, skipping $BASH_SOURCE. ${reset}"
      #return 0
   #fi

   cowbuilder_setup "$@"
}

main "$@"
