#!/bin/sh # delete obsolete binary packages # 1] Condition for deleting a package A is that: # a) nothing on the build-list (make|check|)depends on A and # b) no built package B which is not being deleted depends on A # "Package x depends on package y" means, that something needed by x # is provided by y and no other package which will not be deleted. # shellcheck disable=SC2039 # shellcheck source=conf/default.conf . "${0%/*}/../conf/default.conf" # TODO: delete other to-be-deleted packages if asked to do so # shellcheck disable=SC2016 usage() { >&2 echo '' >&2 echo 'delete-packages [options]:' >&2 echo ' delete obsolete binary packages.' >&2 echo '' >&2 echo 'possible options:' >&2 echo ' -b|--block: If necessary, wait for lock blocking.' >&2 echo ' -h|--help: Show this help and exit.' >&2 echo ' -n|--no-action: Only print what would be deleted.' [ -z "$1" ] && exit 1 || exit "$1" } eval set -- "$( getopt -o bhn \ --long block \ --long help \ --long no-action \ -n "$(basename "$0")" -- "$@" || \ echo usage )" block_flag='-n' no_action=false while true do case "$1" in -b|--block) block_flag='' ;; -h|--help) usage 0 ;; -n|--no-action) no_action=true ;; --) shift break ;; *) >&2 echo 'Whoops, forgot to implement option "'"$1"'" internally.' exit 42 ;; esac shift done if [ -s "${work_dir}/build-master-sanity" ]; then >&2 echo 'Build master is not sane.' exit fi # Create a lock file and a trap. if ! ${no_action}; then # exec 9> "${build_list_lock_file}" # if ! flock ${block_flag} 9; then # >&2 echo 'come back (shortly) later - I cannot lock build list.' # exit 0 # fi exec 8> "${package_database_lock_file}" if ! flock ${block_flag} 8; then >&2 echo 'come back (shortly) later - I cannot lock package database.' exit 0 fi exec 7> "${sanity_check_lock_file}" if ! flock -s ${block_flag} 7; then >&2 echo 'come back (shortly) later - sanity-check running.' exit 0 fi fi tmp_dir=$(mktemp -d "${work_dir}/tmp.delete-packages.XXXXXXXXXX") trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT # shellcheck disable=SC2016 { printf 'CREATE TEMPORARY TABLE `to_deletes` (`id` BIGINT, UNIQUE KEY (`id`));\n' printf 'INSERT IGNORE INTO `to_deletes`' printf ' SELECT `binary_packages`.`id`' printf ' FROM `binary_packages`' mysql_join_binary_packages_dependencies mysql_join_dependencies_dependency_types printf ' AND `dependency_types`.`relevant_for_binary_packages`' mysql_join_binary_packages_repositories printf ' AND `repositories`.`is_on_master_mirror`' printf ' WHERE `binary_packages`.`is_to_be_deleted`' printf ' AND NOT EXISTS (' printf 'SELECT * FROM `install_target_providers`' printf ' WHERE `install_target_providers`.`install_target`=`dependencies`.`depending_on`' printf ');\n' printf ' SELECT DISTINCT "repo",`repositories`.`name`' printf ' FROM `to_deletes`' printf ' JOIN `binary_packages` ON `to_deletes`.`id`=`binary_packages`.`id`' mysql_join_binary_packages_repositories printf ';\n' printf ' SELECT "package",`repositories`.`name`,`binary_packages`.`pkgname`' printf ' FROM `to_deletes`' printf ' JOIN `binary_packages` ON `to_deletes`.`id`=`binary_packages`.`id`' mysql_join_binary_packages_repositories printf ';\n' printf ' SELECT "package-id",`to_deletes`.`id`' printf ' FROM `to_deletes`' printf ';\n' } | \ mysql_run_query | \ sed ' y/\t/ / /^repo /{ s/^\S\+ // w '"${tmp_dir}"'/repositories d } /^package /{ s/^\S\+ // w '"${tmp_dir}"'/packages d } /^package-id /{ s/^\S\+ // w '"${tmp_dir}"'/package-ids d } ' if [ ! -s "${tmp_dir}/packages" ]; then printf 'Nothing to delete.\n' exit fi if ${no_action}; then printf 'I would delete the following packages:\n' sed ' y, ,/, s/^/ / ' "${tmp_dir}/packages" printf 'From these repositories:\n' sed ' s/^/ / ' "${tmp_dir}/repositories" exit fi mkdir "${tmp_dir}/repos" while read -r repo; do ${master_mirror_rsync_command} \ "${master_mirror_rsync_directory}/i686/${repo}/${repo}.db.tar.gz" \ "${master_mirror_rsync_directory}/i686/${repo}/${repo}.files.tar.gz" \ "${tmp_dir}/repos/" # shellcheck disable=SC2046 repo-remove "${tmp_dir}/repos/${repo}.db.tar.gz" \ $( grep "^$(str_to_regex "${repo}") " "${tmp_dir}/packages" | \ cut -d' ' -f2 ) ${master_mirror_rsync_command} \ "${tmp_dir}/repos/${repo}.db.tar.gz" \ "${tmp_dir}/repos/${repo}.files.tar.gz" \ "${master_mirror_rsync_directory}/i686/${repo}/" done < \ "${tmp_dir}/repositories" # shellcheck disable=SC2016 { printf 'CREATE TEMPORARY TABLE `to_deletes` (`id` BIGINT, UNIQUE KEY (`id`));\n' printf 'LOAD DATA LOCAL INFILE "%s" INTO TABLE `to_deletes`;\n' \ "${tmp_dir}/package-ids" printf 'DELETE `binary_packages` FROM `binary_packages` ' printf ' JOIN `to_deletes` ON `to_deletes`.`id`=`binary_packages`.`id`' mysql_join_binary_packages_repositories mysql_join_binary_packages_architectures printf ';\n' } | \ mysql_run_query tr ' ' '/' < \ "${tmp_dir}/packages" | \ sed ' p s/$/.sig/ ' | \ sed ' s,^,rm "i686/, s,$,", ' | \ ${master_mirror_sftp_command}