#!/bin/sh # move binary packages from staging to testing (if possible [1]) and # additionally tested packages from testing to the respective stable # repository (if possible [1]) # The condition [1] is explained in the stored function # calculate_maximal_moveable_set which is created in bin/bootsrap-mysql # TODO: make (all) locking less restrictive # TODO: intentionally break packages that failed to build for a certain time # TODO: -p seems to try to move stuff from community to community and from # extra to extra - which of course leads to problems. # shellcheck disable=SC2039,SC2119,SC2120 # shellcheck source=../lib/load-configuration . "${0%/*}/../lib/load-configuration" # shellcheck disable=SC2016 usage() { >&2 echo '' >&2 echo 'db-update [options] [packages]:' >&2 echo ' move tested packages from testing to stable.' >&2 echo ' move possible packages from staging to testing.' >&2 echo '' >&2 echo 'possible options:' >&2 echo ' -f|--force $arch/$repo/$pkgname:' >&2 echo ' Force movement of given package and move nothing else.' >&2 echo ' -h|--help:' >&2 echo ' Show this help and exit.' >&2 echo ' -i|--ignore-insanity:' >&2 echo ' Do not abort when insane.' >&2 echo ' -n|--no-action:' >&2 echo ' Only print what would be moved.' >&2 echo ' -o|--only $identifier:' >&2 echo ' Only try to move packages *from* the given' >&2 echo ' stability/architecture. $identifier must match one of' >&2 echo ' the regexes' >&2 echo ' (testing|staging)' >&2 echo ' !?(i486|i686|pentium4)' >&2 echo ' !?(i486|i686|pentium4)/(testing|staging)' >&2 echo ' where preceding exclamation mark negates the selection' >&2 echo ' of the architecture (but not the stability!).' >&2 echo ' Can be given multiple times to accumulate the selected' >&2 echo ' repositories.' >&2 echo ' -p|--progressive:' >&2 echo ' Move forward any package which replaces no package whose' >&2 echo ' dependencies are all available somewhere.' >&2 echo ' Note, that this _may_ move _less_ packages.' >&2 echo ' -w|--wait:' >&2 echo ' If necessary, wait for lock blocking.' [ -z "$1" ] && exit 1 || exit "$1" } eval set -- "$( getopt -o f:hino:pw \ --long force \ --long help \ --long ignore-insanity \ --long no-action \ --long only: \ --long progressive \ --long wait \ -n "$(basename "$0")" -- "$@" || \ echo usage )" block_flag='-n' ignore_insanity=false no_action_flag='' progressive=false force_pkgs='' only='' while true do case "$1" in -f|--force) shift force_pkgs=$( printf '%s' "$1" | \ base64 -w0 printf '\n%s' "${force_pkgs}" ) ;; -h|--help) usage 0 ;; -i|--ignore-insanity) ignore_insanity=true ;; -n|--no-action) no_action_flag='-n' ;; -o|--only) shift if ! printf '%s\n' "$1" \ | grep -qx '\(testing\|staging\)\|!\?\(i486\|i686\|pentium4\)\|!\?\(i486\|i686\|pentium4\)/\(testing\|staging\)'; then >&2 printf 'Syntax error, --only parameter "%s" does not match required regex.\n' "$1" usage fi only="$1 ${only}" ;; -p|--progressive) progressive=true >&2 echo 'Do not use this option, it is currently broken.' exit 42 ;; -w|--wait) block_flag='' ;; --) shift break ;; *) >&2 echo 'Whoops, forgot to implement option "'"$1"'" internally.' exit 42 ;; esac shift done if [ $# -ne 0 ]; then >&2 echo 'db-update: too many arguments' usage fi if ${progressive} && \ [ -n "${force_pkgs}" ]; then >&2 echo 'db-update: conflicting arguments' usage fi if [ -s "${work_dir}/build-master-sanity" ]; then >&2 echo 'Build master is not sane.' if ! ${ignore_insanity}; then exit fi fi if [ -n "${only}" ]; then only=$( printf '%s\n' "${only}" \ | tr ' ' '\n' ) only=$( printf '%s\n' "${only}" \ | grep '^[^!]' \ || true printf '%s\n' "${only}" \ | sed "$( for arch in i486 i686 pentium4; do printf 's@^!%s\\(/.\\+\\)\\?$@' \ "${arch}" for arch2 in i486 i686 pentium4; do if [ "${arch}" == "${arch2}" ]; then continue fi printf '%s\\1\\n' \ "${arch2}" done \ | sed 's/\\n$//' printf '@\nt\n' done )"' d ' ) fi if [ -z "${no_action_flag}" ]; then # Create lock. exec 9> "${package_database_lock_file}" # shellcheck disable=SC2086 if ! verbose_flock ${block_flag} 9; then >&2 echo 'come back (shortly) later - I cannot lock package database.' exit 0 fi # shellcheck disable=SC2086 if intentions_left ${block_flag}; then >&2 echo 'come back (shortly) later - There are still intentions in the queue.' exit 0 fi exec 8> "${sanity_check_lock_file}" # shellcheck disable=SC2086 if ! verbose_flock -s ${block_flag} 8; then >&2 echo 'come back (shortly) later - sanity-check currently running.' exit 0 fi # shellcheck disable=SC2016 { printf 'UPDATE `binary_packages`' printf ' JOIN (' printf 'SELECT `binary_packages_in_repositories`.`package`,' printf 'MIN(`binary_packages_in_repositories`.`last_moved`) AS `first_last_moved`' printf ' FROM `binary_packages_in_repositories`' mysql_join_binary_packages_in_repositories_repositories # shellcheck disable=SC2154 printf ' WHERE `repositories`.`stability`=%s' \ "${repository_stability_ids__testing}" printf ' GROUP BY `binary_packages_in_repositories`.`package`' printf ') AS `binary_packages_in_repositories`' printf ' ON `binary_packages_in_repositories`.`package`=`binary_packages`.`id`' printf ' SET `binary_packages`.`is_tested`=1' printf ' WHERE NOT `binary_packages`.`has_issues`' printf ' AND NOT `binary_packages`.`is_tested`' printf ' AND `binary_packages_in_repositories`.`first_last_moved`> \ "${tmp_dir}/${what}" done if [ ! -s "${tmp_dir}/repositories" ]; then >&2 printf 'Nothing to move here (from %s/%s).\n' \ "${arch}" \ "${source_stability}" continue fi touch \ "${tmp_dir}/mv" \ "${tmp_dir}/mv.id" \ "${tmp_dir}/rm" \ "${tmp_dir}/rm.id" perma_tmp_dir=$(mktemp -d "${work_dir}/tmp.db-update.permanent.XXXXXXXXXX") # shellcheck disable=SC2086 for s in "${tmp_dir}/"*; do sort -u "${s}" \ > "${perma_tmp_dir}/${s##*/}" done # receive the repository databases from the master mirror while read -r arch repo; do { printf 'mkdir -p "%s/dbs/%s/%s"\n' \ "${perma_tmp_dir}" \ "${arch}" \ "${repo}" printf 'failsafe_rsync' for suffix in 'db' 'files'; do printf ' "%s/%s/%s/%s.%s."*' \ "${master_mirror_rsync_directory}" \ "${arch}" \ "${repo}" \ "${repo}" \ "${suffix}" done printf ' "%s/dbs/%s/%s/"\n' \ "${perma_tmp_dir}" \ "${arch}" \ "${repo}" } \ | intent_something "${no_action_flag}" done < \ "${tmp_dir}/repositories" # remove to-be-deleted packages # shellcheck disable=SC2094 cut -d' ' -f2,3 < \ "${tmp_dir}/rm" | \ sort -u | \ while read -r arch repo; do { # TODO: sign repositories printf 'repo-remove -q "%s/dbs/%s/%s/%s.db.tar.gz" ' \ "${perma_tmp_dir}" \ "${arch}" \ "${repo}" \ "${repo}" grep " $(str_to_regex "${arch} ${repo}")\$" "${tmp_dir}/rm" \ | sed ' s/\(-[^-]\+\)\{3\} \S\+ \S\+$// ' \ | tr '\n' ' ' printf '\n' } \ | intent_something "${no_action_flag}" done # copy and delete moved packages # shellcheck disable=SC2094 cut -d' ' -f2,3,4,5 < \ "${tmp_dir}/mv" | \ sort -u | \ while read -r from_arch from_repo to_arch to_repo; do { printf '"%s/bin/repo-copy" ' \ "${base_dir}" printf '"%s/dbs/%s/%s/%s.db.tar.gz" ' \ "${perma_tmp_dir}" "${from_arch}" "${from_repo}" "${from_repo}" \ "${perma_tmp_dir}" "${to_arch}" "${to_repo}" "${to_repo}" grep " $(str_to_regex "${from_arch} ${from_repo} ${to_arch} ${to_repo}")\$" "${tmp_dir}/mv" \ | sed ' s/-[^-]\+\( \S\+\)\{4\}$// ' \ | tr '\n' ' ' printf '\n' printf 'repo-remove -q "%s/dbs/%s/%s/%s.db.tar.gz" ' \ "${perma_tmp_dir}" \ "${from_arch}" \ "${from_repo}" \ "${from_repo}" grep " $(str_to_regex "${from_arch} ${from_repo} ${to_arch} ${to_repo}")\$" "${tmp_dir}/mv" \ | sed ' s/\(-[^-]\+\)\{3\}\( \S\+\)\{4\}$// ' \ | tr '\n' ' ' printf '\n' } \ | intent_something "${no_action_flag}" done # create real file names of packages, because # mysql_query_and_delete_unneeded_binary_packages does so, too { printf 'sed -i '"'"'\n' printf ' s,^\\(\\S\\+\) \\(\\S\\+\\) \\(\\S\\+\\)$,\\2/\\3/\\1,\n' printf "'"' "%s/rm"\n' \ "${perma_tmp_dir}" } \ | intent_something "${no_action_flag}" # somewhat inaccurate { printf '{\n' printf ' mysql_run_query' printf ' | sort -u' printf ' >> "%s/rm"\n' \ "${perma_tmp_dir}" printf '} <