#!/bin/bash

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

set -x
set -o errexit
set -o nounset
set -o pipefail
set -o errtrace

true "INFO: Currently running script: ${BASH_SOURCE[0]} $*"

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

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

dist_build_source_run="true"

source pre
source variables

main() {
   sanity_tests "$@"
   gpg_key_create "$@"
   gpg_key_debugging "$@"
   signify_key_create "$@"
   openpgp_policy_setup "$@"
   true "INFO: END of ${FUNCNAME[0]}"
}

sanity_tests() {
   command -v sq >/dev/null
   command -v sq-git >/dev/null
   command -v sqop >/dev/null
   command -v signify-openbsd >/dev/null
   command -v sponge >/dev/null
}

gpg_key_create() {
   true "DEBEMAIL: $DEBEMAIL"
   ## Debugging.
   pwd

   if sq cert list --cert-email "$DEBEMAIL" &>/dev/null ; then
      true "INFO: OpenPGP key with uid DEBEMAIL $DEBEMAIL already exists. Skipping OpenPGP key creation, ok."
      return 0
   fi

   true "INFO: OpenPGP key with uid DEBEMAIL $DEBEMAIL does not exist yet. Generating OpenPGP key..."

   ## sq (stateful, gpg-agent) rather than sqop (stateless): Qubes
   ## split-gpg-2 routes via gpg-agent.
   ## --without-password / --expiration never: CI-friendly; humans
   ## who care about either generate the key manually.
   ## TODO: Debian forky: Drop or upgrade '--profile rfc9580' depending on availability.
   sq key generate --profile rfc9580 --own-key --email "$DEBEMAIL" --without-password --expiration never

   true "INFO: END of ${FUNCNAME[0]}"
}

gpg_key_debugging() {
   true "INFO: show OpenPGP key fingerprint for uid DEBEMAIL"
   ## Just output list of secret keys in that very folder in case that ever breaks and someone ever sends
   ## a build log, this will help with debugging.
   ## Idempotent.
   sq cert list --cert-email "$DEBEMAIL"
   sq cert lint --cert-email "$DEBEMAIL"
}

## Signify keys are used by 'dm-prepare-release' in package 'developer-meta-files'.
signify_key_create() {
   mkdir --parents -- "$signify_folder"
   chmod --recursive -- og-rwx "$signify_folder"

   if test -f "$signify_private_key" ; then
      true "INFO: signify_private_key $signify_private_key already exists. Skipping signify signing key generation, ok."
      test -r "$signify_private_key"
      return 0
   fi

   true "INFO: signify_private_key $signify_private_key does not exist yet. Generating signify signing key..."
   pushd -- "$signify_folder" >/dev/null
   ## Not idempotent. (Would generate different key.)
   signify-openbsd -n -G -p "$signify_public_key" -s "$signify_private_key" -c "derivative-maker"
   popd >/dev/null

   true "INFO: END of ${FUNCNAME[0]}"
}

## OpenPGP policy persistent setup. Derives an authorized policy from
## the shipped project policy plus the local maintainer's cert in
## ${binary_build_folder_dist}/sq-git-temp, then writes
## ${openpgp_policy_file_user} only when the derivation produced a
## real change AND no user-provided policy already exists (no
## clobber). The scratch cert / policy under sq-git-temp are
## reproducible on every run; persisting them under ~/buildconfig.d
## would duplicate data that already lives inline in the policy's
## keyring.
openpgp_policy_setup() {
   local sq_git_temp_dir cert_for_authorize cert_temp_file policy_temp_file

   if [ ! -r "${openpgp_policy_file_project}" ]; then
      true "INFO: ${openpgp_policy_file_project} not present; skipping openpgp-policy setup"
      return 0
   fi

   sq_git_temp_dir="${binary_build_folder_dist}/sq-git-temp"
   mkdir --parents -- "${sq_git_temp_dir}"
   chmod -- 0700 "${sq_git_temp_dir}"

   ## Email-scoped (vs --all): --all would authorize every cert in
   ## the local store (test, rotated, unrelated) as project-
   ## maintainer; in Qubes split-gpg-2 the cert store is shared and
   ## not curated.
   if [ -n "${openpgp_cert_file_resolved}" ]; then
      true "INFO: using pre-provisioned cert ${openpgp_cert_file_resolved}"
      cert_for_authorize="${openpgp_cert_file_resolved}"
   else
      cert_temp_file="${sq_git_temp_dir}/openpgp-cert-public-temp.pem"
      true "INFO: exporting local maintainer cert (DEBEMAIL=${DEBEMAIL}) -> ${cert_temp_file}"
      sq cert export --cert-email "${DEBEMAIL}" | sponge -- "${cert_temp_file}"
      chmod -- 0600 "${cert_temp_file}"
      cert_for_authorize="${cert_temp_file}"
   fi

   policy_temp_file="${sq_git_temp_dir}/openpgp-policy-public-temp.toml"
   cp -- "${openpgp_policy_file_project}" "${policy_temp_file}"
   chmod -- 0600 "${policy_temp_file}"

   true "INFO: authorizing local maintainer cert as project-maintainer in scratch ${policy_temp_file}"
   true "INFO:   --policy-file        ${policy_temp_file}"
   true "INFO:   --project-maintainer ${DEBFULLNAME} <${DEBEMAIL}>"
   true "INFO:   cert                 ${cert_for_authorize}"

   sq-git policy authorize \
      --policy-file "${policy_temp_file}" \
      --project-maintainer \
      "${DEBFULLNAME} <${DEBEMAIL}>" \
      "${cert_for_authorize}"

   if cmp --silent -- "${policy_temp_file}" "${openpgp_policy_file_project}"; then
      true "INFO: 'sq-git policy authorize' was a no-op; '${DEBFULLNAME} <${DEBEMAIL}>' is already covered by ${openpgp_policy_file_project}; not writing ${openpgp_policy_file_user}"
   elif [ -f "${openpgp_policy_file_user}" ]; then
      true "INFO: ${openpgp_policy_file_user} already exists; refusing to clobber. Delete to re-derive from scratch ${policy_temp_file}."
   else
      true "INFO: committing scratch policy -> ${openpgp_policy_file_user}"
      mkdir --parents -- "${openpgp_policy_dir_user}"
      chmod -- 0700 "${openpgp_policy_dir_user}"
      cp -- "${policy_temp_file}" "${openpgp_policy_file_user}"
      chmod -- 0600 "${openpgp_policy_file_user}"
   fi

   true "INFO: END of ${FUNCNAME[0]}"
}


main "$@"
