#!/bin/sh

short_options='ot:p:i:'
long_options='print-output,trigger:,pin-packages:,run-id:'

usage() {
  cat <<EOF
usage: debci test [OPTIONS] srcpkg

Options:
  -o, --print-output
      print output directory after test finished
  -t TRIGGER, --trigger TRIGGER
      Records TRIGGER as being the trigger for this test run. The trigger will
      be written to a file in the output directory, so that it can be retrieved
      later
  -p RELEASE=pkgname,src:srcname,...
  --pin-packages RELEASE=pkgname,src:srcname,...
      Force specific packages to be installed from the given RELEASE. The
      format is the same as the --pin-packages option from autopkgtest. RELEASE
      will be automatically addded to the testbed APT sources.
  -i ID, --run-id ID
      Use the specific ID as the run id for this test run, instead of
      generating one based on the current date.
$@
EOF
}

set -eu

debci_base_dir=$(readlink -f $(dirname $(readlink -f $0))/..)
. $debci_base_dir/lib/environment.sh
. $debci_base_dir/lib/functions.sh

process_package() {
  local pkgname
  case "$pkg" in
    .*|*/*)
      # a local pathname
      if [ -d "$pkg" ]; then
        pkgname="$(basename $(readlink -f "$pkg"))"
      else
        echo "E: $pkg is not a valid package"
        exit 1
      fi
      ;;
    *)
      pkgname="$pkg"
      ;;
  esac

  # output directory for test-package/autopkgtest
  local base_dir="$(autopkgtest_incoming_dir_for_package "$pkgname")"

  if [ -n "${run_id:-}" ]; then
    adt_out_dir="${base_dir}/${run_id}"
  else
    run_id=$(date +%Y%m%d_%H%M%S)
    adt_out_dir="${base_dir}/${run_id}"

    inc=0
    orig_run_id="$run_id"
    while [ -d "$adt_out_dir" ]; do
      # this in *very* unlikely to happen in production, but we need this for the
      # test suite
      run_id="${orig_run_id}.${inc}"
      adt_out_dir="${base_dir}/${run_id}"
    done
  fi

  mkdir -p "$(dirname $adt_out_dir)"
  start_timestamp=$(date +%s)


  # these variables can be considered as an API by backends/*/test-package and
  # debci-autopkgtest
  export debci_suite
  export debci_arch
  export debci_autopkgtest_args
  export debci_test_package="$pkgname"
  export debci_test_outputdir="$adt_out_dir"


  ########################################################################
  # XXX This is a hack to handle the fact that the --add-apt-source option
  # has spaces in it. $options is separated by | with a bogus first item
  # (to avoid an empty first argument; it is split on | into "$@", then
  # the first item is dicarded. "$@" is then used when calling the backend
  # test-package command
  ########################################################################
  old_IFS="$IFS"
  IFS='|'
  set -- $options
  shift
  IFS="$old_IFS"
  ########################################################################


  if [ "$debci_quiet" = 'true' ]; then
    test-package "$@" --output-dir "$adt_out_dir" "$pkg" \
      >/dev/null 2>&1 || true
  else
    test-package "$@" --output-dir "$adt_out_dir" "$pkg" || true
  fi

  if [ ! -d "$adt_out_dir" ]; then
    return
  fi

  finish_timestamp=$(date +%s)

  # remove redundant logs
  rm -f "${adt_out_dir}"/*-stdout
  rm -f "${adt_out_dir}"/*-stderr

  # cap main log
  log=${adt_out_dir}/log
  if [ -f "${log}" ]; then
    limit=20 # in MB
    limit_bytes=$((limit*1024*1024)) # 5MB
    if [ "$(stat --format=%s "${log}")" -gt "$limit_bytes" ]; then
      logtail="$(sed -e '/^autopkgtest .* summary$/,$ !d' "$log")"
      truncate --size "$limit_bytes" "${log}"
      (
        echo
        echo "----------------8<----------------8<----------------8<-----------------"
        echo ""
        echo "WARNING: log file truncated at ${limit} MB (before compression)"
        echo ""
        echo "----------------8<----------------8<----------------8<-----------------"
        echo "${logtail}"
      ) >> "${log}"
    fi
    gzip "${log}"
  fi

  if [ -f "${adt_out_dir}/duration".in ]; then
    cp "${adt_out_dir}/duration".in "${adt_out_dir}/duration"
  else
    echo $(($finish_timestamp - $start_timestamp)) > "$adt_out_dir/duration"
  fi

  if [ -n "$trigger" ]; then
    echo "$trigger" > "$adt_out_dir/trigger"
  fi

  if [ -n "$print_output" ]; then
      echo "$adt_out_dir"
  fi
}

get_buildd_suite() {
  (debci-generate-apt-sources --buildd "$1" | grep buildd) || true
}


# defaults
index=''
print_output=''
trigger=''
options=':'

while true; do
  opt="$1"
  shift
  case "$opt" in
    -o|--print-output)
      print_output=true
      ;;
    -t|--trigger)
      trigger="$1"
      shift
      ;;
    -p|--pin-packages)
      pin="$1"
      shift
      release=$(echo "$pin" | cut -d = -f 1)
      apt_source=$(get_buildd_suite "$release")
      if [ -n "$apt_source" ]; then
        options="$options|--add-apt-source=$apt_source"
      fi
      options="$options|--add-apt-release=$release|--pin-packages=$pin"
      ;;
    -i|--run-id)
      run_id="$1"
      if echo "$run_id" | grep -q -e '^[0-9]\{8\}_[0-9]\{6\}$' -e '^[0-9]*$' ; then
        : ok
      else
        echo "E: invalid run-id: $run_id (format needs to be YYYYMMDD_HHMMSS)"
        exit 1
      fi
      shift
      ;;
    --)
      break
      ;;
  esac
done

if [ $# -eq 1 ]; then
  pkg="$1"
  process_package
else
  usage
  exit 1
fi
