#!/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: separate locks for staging, testing (and stable) # 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 $package-id:' >&2 echo ' Force movement of Package with given id and move nothing else.' >&2 echo ' -h|--help:' >&2 echo ' Show this help and exit.' >&2 echo ' -n|--no-action:' >&2 echo ' Only print what would be moved.' >&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:hnpw \ --long force \ --long help \ --long no-action \ --long progressive \ --long wait \ -n "$(basename "$0")" -- "$@" || \ echo usage )" block_flag='-n' no_action=false progressive=false force_ids='' while true do case "$1" in -f|--force) shift force_ids=$( printf '%s' "$1" | \ base64 -w0 printf '\n%s' "${force_ids}" ) ;; -h|--help) usage 0 ;; -n|--no-action) no_action=true ;; -p|--progressive) progressive=true ;; -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_ids}" ]; then >&2 echo 'db-update: conflicting arguments' usage fi if [ -s "${work_dir}/build-master-sanity" ]; then >&2 echo 'Build master is not sane.' exit fi if ! ${no_action}; then # Create lock. exec 9> "${package_database_lock_file}" if ! verbose_flock ${block_flag} 9; then >&2 echo 'come back (shortly) later - I cannot lock package database.' exit 0 fi exec 8> "${sanity_check_lock_file}" 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 (%s).\n' "${source_stability}" continue fi touch \ "${tmp_dir}/mv" \ "${tmp_dir}/mv.id" \ "${tmp_dir}/rm" \ "${tmp_dir}/rm.id" # shellcheck disable=SC2086 for s in "${tmp_dir}/"*; do sort -u "${s}" | \ sponge "${s}" done # receive the repository databases from the master mirror mkdir "${tmp_dir}/dbs" while read -r arch repo; do mkdir -p "${tmp_dir}/dbs/${arch}/${repo}" # shellcheck disable=SC2086 ${master_mirror_rsync_command} \ "${master_mirror_rsync_directory}/${arch}/${repo}/${repo}.db."* \ "${master_mirror_rsync_directory}/${arch}/${repo}/${repo}.files."* \ "${tmp_dir}/dbs/${arch}/${repo}/" 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 grep " $(str_to_regex "${arch} ${repo}")\$" "${tmp_dir}/rm" | \ sed ' s/\(-[^-]\+\)\{3\} \S\+ \S\+$// ' | \ xargs -r repo-remove -q "${tmp_dir}/dbs/${arch}/${repo}/${repo}.db.tar.gz" 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 grep " $(str_to_regex "${from_arch} ${from_repo} ${to_arch} ${to_repo}")\$" "${tmp_dir}/mv" | \ sed ' s/-[^-]\+\( \S\+\)\{4\}$// ' | \ xargs -r "${base_dir}/bin/repo-copy" \ "${tmp_dir}/dbs/${from_arch}/${from_repo}/${from_repo}.db.tar.gz" \ "${tmp_dir}/dbs/${to_arch}/${to_repo}/${to_repo}.db.tar.gz" grep " $(str_to_regex "${from_arch} ${from_repo} ${to_arch} ${to_repo}")\$" "${tmp_dir}/mv" | \ sed ' s/\(-[^-]\+\)\{3\}\( \S\+\)\{4\}$// ' | \ xargs -r repo-remove -q \ "${tmp_dir}/dbs/${from_arch}/${from_repo}/${from_repo}.db.tar.gz" done # create real file names of packages, because # mysql_query_and_delete_unneeded_binary_packages does so, too sed -i ' s,^\(\S\+\) \(\S\+\) \(\S\+\)$,\2/\3/\1, ' "${tmp_dir}/rm" # somewhat inaccurate if ! ${no_action}; then # shellcheck disable=SC2016 { printf 'CREATE TEMPORARY TABLE `replaced_bpir` (`id` BIGINT, UNIQUE KEY (`id`));\n' printf 'CREATE TEMPORARY TABLE `moved_bpir` (`id` BIGINT, `new_repository` MEDIUMINT, UNIQUE KEY (`id`));\n' printf 'LOAD DATA LOCAL INFILE "%s" INTO TABLE `%s` COLUMNS TERMINATED BY " ";\n' \ "${tmp_dir}/mv.id" 'moved_bpir' \ "${tmp_dir}/rm.id" 'replaced_bpir' printf 'DELETE `binary_packages_in_repositories` FROM `binary_packages_in_repositories`' printf ' JOIN `replaced_bpir` ON `binary_packages_in_repositories`.`id`=`replaced_bpir`.`id`;\n' mysql_query_and_delete_unneeded_binary_packages printf 'UPDATE `binary_packages_in_repositories`' printf ' JOIN `moved_bpir` ON `binary_packages_in_repositories`.`id`=`moved_bpir`.`id`' printf ' SET `binary_packages_in_repositories`.`repository`=`moved_bpir`.`new_repository`,' printf '`binary_packages_in_repositories`.`last_moved`=NOW()' printf ' WHERE `binary_packages_in_repositories`.`repository`!=`moved_bpir`.`new_repository`;\n' } | \ mysql_run_query | \ sort -u >> \ "${tmp_dir}/rm" fi # move the packages remotely via sftp { sed ' s/^/rm "/ s/$/"/ p s/"$/.sig"/ ' "${tmp_dir}/rm" sed ' s,^\(\S\+\) \(\S\+\) \(\S\+\) \(\S\+\) \(\S\+\)$,rename "\2/\3/\1" "\4/\5/\1"\nrename "\2/\3/\1.sig" "\4/\5/\1.sig", ' "${tmp_dir}/mv" echo 'quit' } | \ if ${no_action}; then sed 's|^|sftp: |' else ${master_mirror_sftp_command} fi if ${no_action}; then continue fi # and push our local *.db.tar.gz via rsync while read -r arch repo; do recompress_gz \ "${tmp_dir}" \ "${tmp_dir}/dbs/${arch}/${repo}/${repo}."*".tar.gz" \ "${tmp_dir}/dbs/${arch}/${repo}/${repo}."*".tar.gz.old" # shellcheck disable=SC2086 ${master_mirror_rsync_command} \ "${tmp_dir}/dbs/${arch}/${repo}/${repo}.db."* \ "${tmp_dir}/dbs/${arch}/${repo}/${repo}.files."* \ "${master_mirror_rsync_directory}/${arch}/${repo}/" done < \ "${tmp_dir}/repositories" done trigger_mirror_refreshs