#!/bin/bash

# stop on any unhandled error
set -e

# @TODO: pipefail not in POSIX
set -o pipefail

# show commands (debug)
#set -x

# shellcheck source=src/container/output.inc.sh
source "/output.inc.sh"

# This has no confirmed effect but setting just to be sure as some dpkg-* tools
# are supposed to use it
export DPKG_COLORS="always"

# Prepare stats and cache
BUILD_START_TIME="$EPOCHSECONDS"

# shellcheck source=src/container/cache.inc.sh
source "/cache.inc.sh"

# Instead of the debuild-style '<package>_<version>_<arch>.build' filename use
# plain 'build.log' for consistency across builds and directory diffs
BUILD_LOG="build.log"

# Normal builds in Debian are full binary releases with sources
if [ -n "$DEBCRAFT_FULL_BUILD" ]
then
  # Parse upstream version to extract pristine-tar only when doing full builds
  # that need the upstream source tarball. Skip this for binary-only builds
  # (--skip-sources) to save time.
  # shellcheck source=src/container/pristine-tar.inc.sh
  source "/pristine-tar.inc.sh"

  # Empty means full build, both source and binaries
  DPKG_BUILDPACKAGE_ARGS=""
  # Check if orig tarball already exists (from pristine-tar or copied by build.inc.sh)
  # If it exists, prevent gbp from creating a duplicate. If not, let gbp create it.
  PACKAGE_NAME="$(dpkg-parsechangelog --show-field=source)"
  ORIG_TARBALL_EXISTS=false
  for ext in gz xz bz2 lzma zst
  do
    if [ -f "../${PACKAGE_NAME}_${UPSTREAM_VERSION}.orig.tar.${ext}" ]
    then
      ORIG_TARBALL_EXISTS=true
      break
    fi
  done
  if [ "$ORIG_TARBALL_EXISTS" = true ]
  then
    log_info "Using existing orig tarball, preventing gbp from creating a new one"
    GBP_ARGS="--git-no-create-orig"
  else
    log_info "No orig tarball found, allowing gbp to create one from upstream tag"
    GBP_ARGS=""
  fi
else
  # Skip generating source package to make (binary) build faster by default
  DPKG_BUILDPACKAGE_ARGS="--build=any,all"
  GBP_ARGS="--git-no-create-orig --git-ignore-new"

  # Normally dpkg-source applies the patches, but when running a binary-only
  # build directly in the Debian packaging git repository dpkg-source will be
  # skipped and sources will remain unpatched unless they are explicitly patched
  # with Quilt
  if [ -f debian/patches/series ]
  then
    SKIP_PATCHES=false

    # Skip applying patches if on a gbp patch-queue branch where patches are
    # already applied as git commits. Attempting to apply them again with Quilt
    # would fail as the changes already exist in the working tree.
    if [ -d ".git" ]
    then
      CURRENT_BRANCH="$(git branch --show-current 2>/dev/null || git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
      if [[ "$CURRENT_BRANCH" == patch-queue/* ]]
      then
        log_info "On patch-queue branch '$CURRENT_BRANCH' - patches already applied, skipping Quilt"
        SKIP_PATCHES=true
      fi
    fi

    if [ "$SKIP_PATCHES" = false ]
    then
      log_info "Apply patches with Quilt"
      export QUILT_PATCHES=debian/patches
      # If all patches have already been applied, attempting to push any more results
      # in an exit status of 2.  As this is not an error, it should be ignored.
      quilt push -a || [ $? -eq 2 ]
    fi
  fi
fi

if [ -n "$HOST_ARCH" ] && ! dpkg-architecture -e "$HOST_ARCH"
then
  # Apply host architecture to build process if not the same as build architecture
  DPKG_BUILDPACKAGE_ARGS="$DPKG_BUILDPACKAGE_ARGS --host-arch $HOST_ARCH"
  # Set default variables so cross compiling is easier. DEB_BUILD_* properties
  # are only set here if not already set prior.  This matches what sbuild does
  # when it performs a cross build.
  # https://salsa.debian.org/debian/sbuild/-/blob/archive/debian/0.89.0/lib/Sbuild/Build.pm?ref_type=tags#L2886-2895
  # https://salsa.debian.org/debian/sbuild/-/blob/archive/debian/0.89.0/lib/Sbuild/Conf.pm?ref_type=tags#L167-177
  export CONFIG_SITE=/etc/dpkg-cross/cross-config.$HOST_ARCH
  export DEB_BUILD_OPTIONS=${DEB_BUILD_OPTIONS:-nocheck}
  export DEB_BUILD_PROFILES=${DEB_BUILD_PROFILES:-cross nocheck}
fi

# Use environment if set, otherwise use nice defaults
log_info "DEB_BUILD_OPTIONS set as '$DEB_BUILD_OPTIONS'"

# Teach user what is done and why
log_info "Running 'dpkg-buildpackage --build=any,all' to create .deb packages"

if [ -d ".git" ]
then
  # Always use git-buildpackage if possible
  #
  # Don't use default build system which is debuild, as sanitizes environment
  # variables while we intentionally want to keep e.g. CCACHE_DIR and it also runs
  # Lintian and signs packages, which we specifically want to do separately.
  # Instead use dpkg-buildpackage directly (debuild would use it anyway) and also
  # instruct it to only build binary packages, skipping source package generation
  # and skipping related cleanup steps.
  log_info "Running 'gbp buildpackage $GBP_ARGS' to create .deb packages from git repository"
  log_info "followed by './debian/rules clean' to ensure source directory is clean"
  # shellcheck disable=SC2086 # intentionally pass variable that can be multiple arguments
  # Capture both stdout and stderr to build.log, while also isolating stderr to
  # build.err.log for quick troubleshooting. Process substitution (2> >(...))
  # creates a background process that handles stderr separately from stdout.
  #
  # stderr flow: build command -> tee build.err.log (captures just stderr) ->
  #              append to build.log (mixes with stdout) -> back to terminal >&2
  # stdout flow:  build command -> tee build.log (appends to same file)
  gbp buildpackage --git-ignore-branch \
    --git-builder="dpkg-buildpackage --post-clean --no-sign $DPKG_BUILDPACKAGE_ARGS" \
    $GBP_ARGS 2> >(tee -a "../build.err.log" "../$BUILD_LOG" >&2) | tee -a "../$BUILD_LOG"
else
  # Fall-back to plain dpkg-buildpackage if no git repository
  log_info "Running 'dpkg-buildpackage $DPKG_BUILDPACKAGE_ARGS' to create .deb packages from plain sources directory"
  # shellcheck disable=SC2086 # intentionally pass variable that can be multiple arguments
  # Capture both stdout and stderr to build.log, while also isolating stderr to
  # build.err.log for quick troubleshooting. Process substitution (2> >(...))
  # creates a background process that handles stderr separately from stdout.
  #
  # stderr flow: build command -> tee build.err.log (captures just stderr) ->
  #              append to build.log (mixes with stdout) -> back to terminal >&2
  # stdout flow:  build command -> tee build.log (appends to same file)
  dpkg-buildpackage --post-clean --no-sign $DPKG_BUILDPACKAGE_ARGS 2> >(tee -a "../build.err.log" "../$BUILD_LOG" >&2) | tee -a "../$BUILD_LOG"
fi
# @TODO: Test building just binaries to make build faster, and later also
# test skipping rules/clean steps with '--no-pre-clean --no-post-clean'
# or run in parallel with '--jobs=auto'
#
# @TODO: At least for MariaDB seems rebuild needs 'debian/rules clean' target to run
# otherwise dh_install fails, thus using '--no-pre-clean --no-post-clean'  is not
# compatible with MariaDB
#   dh_install: warning: Cannot find (any matches for) "usr/lib/mysql/plugin/ha_archive.so" (tried in ., debian/tmp)

# Older ccache does not support '--verbose' but will print stats anyway, just
# followed by help section. Newer ccache 4.0+ (Ubuntu 22.04 "Focal", Debian 12
# "Bullseye") however require '--verbose' to show any cache hit stats at all.
log_info "Cache stats: ccache"
ccache --show-stats --verbose || true

if command -v sccache > /dev/null
then
  log_info "Cache stats: sccache"
  sccache --show-stats
  # --show-adv-stats available only in Debian 13 "Trixie" and newer
fi

# After the build, run the analyzer
# shellcheck source=src/container/debcraft-analyzer.sh
source "/debcraft-analyzer.sh"
