#!/bin/sh # do some basic sanity checks # shellcheck source=conf/default.conf . "${0%/*}/../conf/default.conf" usage() { >&2 echo '' >&2 echo 'sanity-check [options] [checks]: check sanity of build master' >&2 echo '' >&2 echo 'possible options:' >&2 echo ' -h|--help: Show this help and exit.' >&2 echo ' -q|--quiet: Only print errors found.' >&2 echo ' -r|--really-quiet: Do not print anything.' [ -z "$1" ] && exit 1 || exit "$1" } i_am_insane() { echo 'build master is insane' > "${work_dir}/build-master-sanity" exit 1 } eval set -- "$( getopt -o hqr \ --long help \ --long quiet \ --long really-quiet \ -n "$(basename "$0")" -- "$@" || \ echo usage )" silence=0 while true do case "$1" in -h|--help) usage 0 ;; -q|--quiet) silence=1 ;; -r|--really-quiet) silence=2 ;; --) shift break ;; *) >&2 echo 'Whoops, forgot to implement option "'"$1"'" internally.' exit 42 ;; esac shift done tmp_dir=$(mktemp -d) trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT if [ $# -eq 0 ]; then set -- build-list repos package-database state-files fi while [ $# -gt 0 ]; do case "$1" in build-list) [ ${silence} -gt 0 ] || \ >&2 printf 'checking build-list ...' errors=$( grep -vn '^\S\+ [0-9a-f]\{40\} [0-9a-f]\{40\} \S\+$\|^break_loops$' "${work_dir}/build-list" ) || true if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following build orders are wrongly formatted:" echo "${errors}" fi i_am_insane fi errors=$( grep -vxF 'break_loops' "${work_dir}/build-list" | \ awk '{print $1}' | \ sort | \ uniq -d ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following packages have duplicate build orders:" echo "${errors}" fi i_am_insane fi errors=$( ( grep -vxF 'break_loops' "${work_dir}/build-list" | \ awk '{print $1}' cat "${work_dir}/deletion-list" ) | \ sort | \ uniq -d ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following packages appear on the build- and deletion-list:" echo "${errors}" fi i_am_insane fi [ ${silence} -gt 0 ] || \ >&2 echo ' passed.' ;; repos) [ ${silence} -gt 0 ] || \ >&2 printf 'checking repos on master mirror ...' repos='build-support community-staging community-testing community core extra gnome-unstable kde-unstable staging testing' errors=$( ( # shellcheck disable=SC2086 printf 'expected %s\n' ${repos} ls_master_mirror 'i686' | \ sed 's|^|found |' ) | \ sort -k2 | \ uniq -uf1 ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following repos are missing or obsolete on the mirror:" echo "${errors}" fi i_am_insane fi [ ${silence} -gt 0 ] || \ >&2 echo ' passed.' ;; package-database) for repo in ${repos}; do [ ${silence} -gt 0 ] || \ >&2 printf 'checking consistency of repository "%s" on the master mirror ...' "${repo}" packages=$( ls_master_mirror "i686/${repo}" | \ grep '\.pkg\.tar\.xz\(\.sig\)\?$' ) || true errors=$( echo "${packages}" | \ grep '\S' | \ sed ' s|^\(.*\.pkg\.tar\.xz\)$|package \1| s|^\(.*\.pkg\.tar\.xz\)\.sig$|signature \1| ' | \ sort -k2 | \ uniq -cf1 | \ grep -v '^\s*2\s' | \ awk '{print $2 " " $3}' ) || true if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following packages in ${repo} are missing a signature or vice versa:" echo "'${errors}'" fi i_am_insane fi ${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}/" errors=$( ( tar -tzf "${tmp_dir}/${repo}.db.tar.gz" | \ grep '/$' | \ sed ' s|/$|| s|^|in_database | ' echo "${packages}" | \ grep '\S' | \ sed ' s|-[^-]\+$|| s|^|in_repository | ' | \ sort -u ) | \ sort -k2 | \ uniq -uf1 ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following packages in ${repo} are missing from the database or vice versa:" echo "${errors}" fi i_am_insane fi errors=$( ( tar -tzf "${tmp_dir}/${repo}.files.tar.gz" | \ grep '/$' | \ sed ' s|/$|| s|^|in_database | ' echo "${packages}" | \ grep '\S' | \ sed ' s|-[^-]\+$|| s|^|in_repository | ' | \ sort -u ) | \ sort -k2 | \ uniq -uf1 ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following packages in ${repo} are missing from the file-database or vice versa:" echo "${errors}" fi i_am_insane fi rm -rf --one-file-system "${tmp_dir:?}/"* [ ${silence} -gt 0 ] || \ >&2 echo ' passed.' done ;; state-files) for status in 'staging:done' 'testing:testing'; do [ ${silence} -gt 0 ] || \ >&2 printf 'checking state-files of "%s" ...' "${status%:*}" errors=$( ( find "${work_dir}/package-states" -name "*.${status#*:}" -exec \ cat {} \; | \ sed 's|^|package-state-file |' ls_master_mirror 'i686' | \ grep "${status%:*}\$" | \ while read -r repo; do ls_master_mirror "i686/${repo}" done | \ grep '\.pkg\.tar\.xz$' | \ sed 's|^|package-file |' ) | \ sort -k2 | \ uniq -cf1 | \ grep -v '^\s*2\s' | \ awk '{print $2 " " $3}' ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then echo echo "The following ${status%:*} packages do not have state files or vice versa:" echo "${errors}" fi i_am_insane fi [ ${silence} -gt 0 ] || \ >&2 echo ' passed.' done ;; *) [ ${silence} -gt 1 ] || \ >&2 printf 'unknown sanity-check "%s".\n' "$1" exit 2 ;; esac shift done rm -f "${work_dir}/build-master-sanity"