#!/bin/sh # shellcheck disable=SC2039,SC2119,SC2120 # shellcheck source=../lib/load-configuration . "${0%/*}/../lib/load-configuration" # shellcheck disable=SC2016 usage() { >&2 echo '' >&2 echo 'modify-package-state [options] packages-file:' >&2 echo ' modify state of package(s).' >&2 echo '' >&2 echo 'possible options:' >&2 echo ' -b|--block: Block package(s).' >&2 echo ' -f|--faulty: Mark testing/tested package(s) as faulty.' >&2 echo ' -h|--help: Show this help and exit.' >&2 echo ' -n|--no-report: Do not report what packages were modified.' >&2 echo ' -t|--tested: Mark package(s) as tested.' >&2 echo ' -u|--unblock: Unblock package(s).' >&2 echo ' -w|--wait: Wait for lock if necessary.' >&2 echo '' >&2 echo 'Exactly one of -b|-f|-t|-u is needed for actual operation.' >&2 echo 'packages-file contains one line for each target.' >&2 echo 'for --faulty and --tested, the format is:' >&2 echo ' sha512sum pkgname-epoch:pkgver-pkgrel.sub_pkgrel-arch[".pkg.tar.zst"]' >&2 echo 'for --block and --unblock, the format is:' >&2 echo ' pkgbase.git_revision.mod_git_revision.repository.architecture' [ -z "$1" ] && exit 1 || exit "$1" } eval set -- "$( getopt -o bfhntuw \ --long block \ --long faulty \ --long help \ --long no-report \ --long tested \ --long unblock \ --long wait \ -n "$(basename "$0")" -- "$@" || \ echo usage )" action='' report=true wait_for_lock='-n' while true do case "$1" in -b|--block) if [ -n "${action}" ]; then >&2 echo 'Conflicting/redundand arguments.' usage fi action='block' ;; -f|--faulty) if [ -n "${action}" ]; then >&2 echo 'Conflicting/redundand arguments.' usage fi action='faulty' ;; -h|--help) usage 0 ;; -n|--no-report) report=false ;; -t|--tested) if [ -n "${action}" ]; then >&2 echo 'Conflicting/redundand arguments.' usage fi action='tested' ;; -u|--unblock) if [ -n "${action}" ]; then >&2 echo 'Conflicting/redundand arguments.' usage fi action='unblock' ;; -w|--wait) wait_for_lock='' ;; --) shift break ;; *) >&2 echo 'Whoops, forgot to implement option "'"$1"'" internally.' exit 42 ;; esac shift done if [ -z "${action}" ]; then >&2 echo 'Expected -b|-f|-t|-u.' usage fi if [ $# -ne 1 ]; then >&2 echo 'Too few or too many arguments.' usage fi input_file="$1" if ${report}; then if ! [ -w "${input_file}" ]; then >&2 printf \ 'Cannot open file "%s" for writing.\n' \ "${input_file}" exit 2 fi move_output() { cat "${output_file}" > "${input_file}" rm -f "${output_file}" } output_file=$(mktemp 'tmp.modify-package-state.XXXXXXXXXX' --tmpdir) trap 'move_output' EXIT else output_file='/dev/null' fi if ! [ -r "${input_file}" ]; then >&2 printf \ 'Cannot open file "%s" for reading.\n' \ "${input_file}" exit 2 fi exec 9> "${sanity_check_lock_file}" if ! verbose_flock -s ${wait_for_lock} 9; then >&2 echo 'Cannot get sanity-check lock.' exit fi exec 8> "${package_database_lock_file}" if ! verbose_flock ${wait_for_lock} 8; then >&2 echo 'Cannot get package-database lock.' exit fi if intentions_left ${wait_for_lock}; then >&2 echo 'There are still intentions in the queue.' exit fi while read -r a b; do case "${action}" in 'faulty'|'tested') # we expect a sha512sum and binary package identifier # (pkgname-epoch:pkgver-pkgrel.sub_pkgrel-arch[".pkg.tar.zst"]) # and we will only operate on packages in "testing" repositories # shellcheck disable=SC2016 combiner=$( printf '`binary_packages`' mysql_join_binary_packages_binary_packages_in_repositories mysql_join_binary_packages_in_repositories_repositories mysql_join_repositories_repository_stabilities mysql_join_binary_packages_architectures ) # shellcheck disable=SC2016,SC2031 selector=$( extract_pkgname_epoch_pkgver_pkgrel_sub_pkgrel_arch_from_package_name "${b}" printf 'WHERE `repository_stabilities`.`name`="testing"' printf ' AND `binary_packages`.`%s`=from_base64("%s")' \ 'pkgname' "$(printf '%s' "${pkgname}" | base64 -w0)" \ 'epoch' "$(printf '%s' "${epoch}" | base64 -w0)" \ 'pkgver' "$(printf '%s' "${pkgver}" | base64 -w0)" \ 'pkgrel' "$(printf '%s' "${pkgrel}" | base64 -w0)" \ 'sub_pkgrel' "$(printf '%s' "${sub_pkgrel}" | base64 -w0)" \ 'sha512sum' "$(printf '%s' "${a}" | base64 -w0)" printf ' AND `architectures`.`name`=from_base64("%s")' \ "$(printf '%s' "${arch}" | base64 -w0)" ) ;; 'block'|'unblock') # we expect a package source identifier (pkgbase.git_revision.mod_git_revision.repository.architecture) # and we will only operate on packages in "unbuilt" repositories # shellcheck disable=SC2016 combiner=$( printf '`build_assignments`' printf ' JOIN `architecture_compatibilities`' printf ' ON `architecture_compatibilities`.`runs_on`=`build_assignments`.`architecture`' printf ' AND `architecture_compatibilities`.`fully_compatible`' printf ' JOIN `architectures`' printf ' ON `architecture_compatibilities`.`built_for`=`architectures`.`id`' mysql_join_build_assignments_package_sources mysql_join_package_sources_upstream_repositories mysql_join_build_assignments_binary_packages mysql_join_binary_packages_binary_packages_in_repositories mysql_join_binary_packages_in_repositories_repositories mysql_join_repositories_repository_stabilities ) # shellcheck disable=SC2016 selector=$( arch="${a##*.}" pkgbase="${a%.*}" repository="${pkgbase##*.}" pkgbase="${pkgbase%.*}" mod_git_revision="${pkgbase##*.}" pkgbase="${pkgbase%.*}" git_revision="${pkgbase##*.}" pkgbase="${pkgbase%.*}" printf 'WHERE `repository_stabilities`.`name`="unbuilt"' printf ' AND `upstream_repositories`.`name`=from_base64("%s")' \ "$(printf '%s' "${repository}" | base64 -w0)" printf ' AND `architectures`.`name`=from_base64("%s")' \ "$(printf '%s' "${arch}" | base64 -w0)" printf ' AND `package_sources`.`%s`=from_base64("%s")' \ 'pkgbase' "$(printf '%s' "${pkgbase}" | base64 -w0)" \ 'git_revision' "$(printf '%s' "${git_revision}" | base64 -w0)" \ 'mod_git_revision' "$(printf '%s' "${mod_git_revision}" | base64 -w0)" ) ;; *) >&2 printf 'Whooops, action "%s" not implemented yet.\n' "${action}" exit 42 ;; esac case "${action}" in 'block') if [ -z "${b}" ]; then >&2 printf 'No reason is given for blocking package "%s".\n' "${a}" exit 2 fi tester='1' # shellcheck disable=SC2016 modifier=$( printf '`build_assignments`.`is_blocked`=from_base64("%s")' \ "$(printf '%s' "${b}" | base64 -w0)" ) ;; 'unblock') # shellcheck disable=SC2016 tester='NOT `build_assignments`.`is_blocked` IS NULL' # shellcheck disable=SC2016 modifier='`build_assignments`.`is_blocked`=NULL' ;; 'faulty') # shellcheck disable=SC2016 tester='`binary_packages`.`has_issues`=0' # shellcheck disable=SC2016 modifier='`binary_packages`.`is_tested`=0,`binary_packages`.`has_issues`=1' ;; 'tested') # shellcheck disable=SC2016 tester='`binary_packages`.`is_tested`=0' # shellcheck disable=SC2016 modifier='`binary_packages`.`is_tested`=1' ;; *) >&2 printf 'Whooops, action "%s" not implemented yet.\n' "${action}" exit 42 ;; esac if { printf 'SELECT 1' printf ' FROM %s %s AND %s LIMIT 1' "${combiner}" "${selector}" "${tester}" } | \ mysql_run_query | \ grep -qxF '1'; then # shellcheck disable=SC2016 { printf 'UPDATE %s SET %s %s' "${combiner}" "${modifier}" "${selector}" printf ';\n' } | \ mysql_run_query printf '%s %s\n' "${action}" "${a}" fi done \ < "${input_file}" \ > "${output_file}"