#! /usr/bin/env bash

# Stage or queue one or more projects from the same group.
#
# -c
#    Cleanup (remove) previous versions.
#
# -d
#    Distribute only without regenerating or publishing the repository.
#
# -g
#    Distribute and regenerate only without publishing the repository.
#    In this mode of no packages is specified, then just regenerate.
#
# -p
#    Publish only without distributing and regenerating the repository.
#
# -q
#    Put packages into the queue instead of staging. Implies -d.
#
# -Q <section>
#    Put packages into staging queue's specified section instead of staging.
#
# --min-bpkg-version <ver>
#
#    Pass --min-bpkg-version to bpkg-rep-create.
#
usage="usage: etc/stage-pkg [<options>] <group> <dir>..."

rsync_ops="--progress"

owd=`pwd`
trap "{ cd $owd; exit 1; }" ERR
set -o errtrace # Trap in functions.

function info () { echo "$*" 1>&2; }
function error () { info "$*"; exit 1; }

# Make sure the build2 tools are runnable.
#
b    --version >/dev/null
bpkg --version >/dev/null
bdep --version >/dev/null

repo_name="STAGE.BUILD2.ORG"
repo_root="staging/repository/1"
repo_dir="$repo_root"
repo_host1="stage.build2.org:/var/bpkg/1"
repo_host2=

clean=
dist_only=
gen_only=
pub_only=
group=
dirs=()
rep_create_ops=()

while [ $# -gt 0 ]; do
  case $1 in
    -c)
      clean=true
      shift
      ;;
    -d)
      dist_only=true
      shift
      ;;
    -g)
      gen_only=true
      shift
      ;;
    -p)
      pub_only=true
      shift
      ;;
    -q)
      #repo_name="CPPGET.ORG/QUEUE"
      repo_root="cppget.org/queue/1"
      repo_dir="$repo_root/alpha"
      #repo_host1="cppget.org:/var/bpkg/1/queue"
      #repo_host2="queue.cppget.org:/var/bpkg/1/queue"
      dist_only=true
      shift
      ;;
    -Q)
      shift
      repo_name="QUEUE.STAGE.BUILD2.ORG"
      repo_root="staging/queue/1"
      repo_dir="$repo_root/$1"
      repo_host1="stage.build2.org:/var/pkg/1"
      shift
      ;;
    --min-bpkg-version)
      shift
      rep_create_ops+=(--min-bpkg-version "$1")
      shift
      ;;
    *)
      if [ -z "$group" ]; then
	group="$1"
      else
	dirs+=("${1%/}")
      fi
      shift
      ;;
  esac
done

if [ -z "$pub_only" ]; then

  # In the -g mode skip distributing if no packages are specified.
  #
  if [ -z "$gen_only" -o -n "$group" ]; then

    if [ -z "$group" -o "${#dirs[@]}" -eq 0 ]; then
      error "$usage"
    fi

    mkdir -p /tmp/dist

    # Dist individual packages into the repository.
    #
    function dist() # <group> <dir>
    {
      local o="$repo_dir/$1"
      local b="$(basename $2)"
      local d="$2-default"

      # If *-default/ exists, use that (old style out of tree configuration).
      # Otherwise, use the source directory itself (new style forwarded
      # configuration).
      #
      if ! test -d "$d"; then
	d="$2"
	if ! test -d "$d"; then
	  error "neither $2-default nor $2 exist"
	fi
      fi

      mkdir -p "$o"

      # Clean up old packages.
      #
      if [ -n "$clean" ]; then
	rm -f "$o/$b"-*
      fi

      b "dist($d/)" config.dist.root=/tmp/dist "config.dist.archives=$owd/$o/tar.gz"
    }

    for d in "${dirs[@]}"; do
      dist "$group" "$d"
    done
  fi

  if [ -n "$dist_only" ]; then
    exit 0
  fi

  # Regenerate the repository.
  #
  # --key "label_SIGN key" (OpenSSL 2)
  #
  info "Insert $repo_name signing key and press Enter"
  read
  etc/rep-update "$repo_root/" "${rep_create_ops[@]}"  \
    --openssl-option -engine --openssl-option pkcs11  \
    --openssl-option -keyform --openssl-option engine \
    --key "pkcs11:token=name:**build2.org;object=SIGN%20key"

  if [ -n "$gen_only" ]; then
    exit 0
  fi

fi # !pub_only

# Sync repository.
#
info "Press Enter to start package upload"
read

etc/rep-publish "$repo_root/" "$repo_host1/" $rsync_ops

if [ -n "$repo_host2" ]; then
  etc/rep-publish "$repo_root/" "$repo_host2/" $rsync_ops
fi