#!/bin/bash

# report back on a build assignment
# either on success via:
#   "$0 $package $revision $mod_revision $repository" and tar'ed packages (= a tar of
#   package(s) and signature(s)) on stdin
# or on failure via:
#   "$0 $package $revision $mod_revision $repository ERROR"

# exit codes:
#  0: ok
#  1: another instance was already running
#  2: outdated package
#  3: signature error
#  4: package error (e.g. wrong packages sent)

# TODO:
#  fix signing of database

. "${0%/*}/../conf/default.conf"

# Create a lock file and a trap.

exec 9> "${build_list_lock_file}"
if ! flock -n 9; then
  >&2 echo 'come back (shortly) later - I cannot lock build list.'
  exit 1
fi

function clean_up_lock_file {
  rm -f "${build_list_lock_file}"
}

trap clean_up_lock_file EXIT

if [ "$5" == 'ERROR' ]; then
# the build failed on the build slave

  if [ ! -f "${work_dir}/package-states/$1.$2.$3.$4.locked" ]; then
    # too late, package already outdated -> ignore error report
    exit 0
  fi

  mv "${work_dir}/package-states/$1.$2.$3.$4."{locked,broken}

  # unlock every loop this package would have broken and which is not
  # broken by another locked package
  locked_packages="$(
    ls "${work_dir}/package-states/" | \
      grep '\.locked$' | \
      sed 's@^.*/\([^/]\+\)\.\([0-9a-f]\{40\}\.\)\{2\}[^.]\+\.locked$@\1@'
  )"
  grep "^${1//./\\.}\$" "${work_dir}/build-list.loops/loop_"* 2> /dev/null | \
    cut -d: -f1 | \
    while read -r loop; do
      if [ -z "$(
          (
            echo "${locked_packages}"
            cat "${loop}"
          ) | \
            sort | \
            uniq -d
        )" ]; then
        rm -f "${loop}.locked"
      fi
    done

  exit 0

fi

# the build was successful on the build slave

if ! grep -q "^${1//./\\.} $2 $3 $4\$" "${work_dir}/build-list"; then
  >&2 echo 'Sorry, the sent package is outdated.'
  exit 2
fi

function clean_up_tmp_dir {
  popd > /dev/null
  rm -rf --one-file-system "${tmp_dir}"
  clean_up_lock_file
}

tmp_dir="$(mktemp -d)"
pushd "${tmp_dir}" > /dev/null
trap clean_up_tmp_dir EXIT

# extract package(s)
tar -x

# check if all packages are signed and all signatures belong to a package
signature_errors="$(
  ls -1 *.pkg.tar.xz{,.sig} | \
    sed 's|\.sig$||' | \
    sort | \
    uniq -c | \
    grep -v '^\s*2\s' | \
    awk '{print $2}'
)"

if [ -n "${signature_errors}" ]; then
  >&2 echo 'The following packages lack a signature or vice versa:'
  >&2 echo "${signature_errors}"
  exit 3
fi

# check if the sent packages are the expected ones
packages=(*.pkg.tar.xz)
package_errors="$(
  (
    echo "${packages[@]}" | \
      tr ' ' '\n' | \
      sed '
        s@\(-[^-]\+\)\{2\}-\([^-]\+\)\.pkg\.tar\.xz@ \2@
        / any$/{s|any$|i686|}
      '
    sed 's|$| i686|' "${work_dir}/package-infos/$1.$2.$3.packages"
  ) | \
    sort | \
    uniq -u
)"

if [ -n "${package_errors}" ]; then
  >&2 echo 'The following packages should have been built but are missing or vice versa:'
  >&2 echo "${package_errors}"
  exit 4
fi

# move packages
mkdir -p "${master_mirror_directory}/i686/$4-staging/"
mv *.pkg.tar.xz{,.sig} "${master_mirror_directory}/i686/$4-staging/"

(
  cd "${master_mirror_directory}/i686/$4-staging"
  repo-add "$4-staging.db.tar.gz" "${packages[@]}"
  # repo-add -v -s -k "${repo_key}" "$4-staging.db.tar.gz" "${packages[@]}"

  # remove old versions of same packages
  for package in "${packages[@]}"; do
    pkgname="${package%-*-*-*.pkg.tar.xz}"
    ls | \
      grep "^${pkgname//./\\.}\(-[^-]\+\)\{3\}\.pkg\.tar\.xz\(\.sig\)\?\$" | \
      grep -v "^${package//./\\.}\(\.sig\)\?\$" | \
      xargs -rn1 rm
  done
)

# remove all loops which are broken by this package
grep "^${1//./\\.}\$" "${work_dir}/build-list.loops/loop_"* 2> /dev/null | \
  cut -d: -f1 | \
  xargs -rn1 rm

# remove package from build list
sed -i "/^${1//./\\.} $2 $3 $4\$/d" "${work_dir}/build-list"

# remove package lock file
rm "${work_dir}/package-states/$1.$2.$3.$4.locked"