index : builder | |
Archlinux32 build system | gitolite user |
summaryrefslogtreecommitdiff |
-rwxr-xr-x | bin/build-master-status | 2 | ||||
-rwxr-xr-x | bin/build-packages | 188 | ||||
-rwxr-xr-x | bin/change-git-remotes | 2 | ||||
-rwxr-xr-x | bin/check-mirrors | 32 | ||||
-rwxr-xr-x | bin/check-opcodes | 199 | ||||
-rwxr-xr-x | bin/cleanup | 11 | ||||
-rwxr-xr-x | bin/create-build-support-package | 6 | ||||
-rwxr-xr-x | bin/db-update | 14 | ||||
-rwxr-xr-x | bin/delete-packages | 3 | ||||
-rwxr-xr-x | bin/generate-key-graph | 2 | ||||
-rwxr-xr-x | bin/get-assignment | 32 | ||||
-rwxr-xr-x | bin/get-package-updates | 450 | ||||
-rwxr-xr-x | bin/get-source-info | 83 | ||||
-rwxr-xr-x | bin/harvest-commit-times | 65 | ||||
-rwxr-xr-x | bin/ii-watch | 2 | ||||
-rwxr-xr-x | bin/interpret-mail | 2 | ||||
-rwxr-xr-x | bin/local-build-package | 220 | ||||
-rwxr-xr-x | bin/manage-slaves | 37 | ||||
-rwxr-xr-x | bin/manual-fix | 55 | ||||
-rwxr-xr-x | bin/nit-picker | 6 | ||||
-rwxr-xr-x | bin/opcode | 293 | ||||
-rwxr-xr-x | bin/ping-to-master | 5 | ||||
-rwxr-xr-x | bin/prioritize-build-list | 2 | ||||
-rwxr-xr-x | bin/return-assignment | 48 | ||||
-rwxr-xr-x | bin/sanity-check | 68 | ||||
-rwxr-xr-x | bin/schedule-for-rebuild (renamed from bin/seed-build-list) | 428 | ||||
-rwxr-xr-x | bin/strict-bashism-check | 15 | ||||
-rwxr-xr-x | bin/watch-build-logs | 26 |
diff --git a/bin/build-master-status b/bin/build-master-status index 7a17923..b66ba2b 100755 --- a/bin/build-master-status +++ b/bin/build-master-status @@ -18,7 +18,7 @@ if ! verbose_flock -n 9; then fi # update todos -find "${base_dir}/bin/" "${base_dir}/conf/" "${base_dir}/lib/" -type f \ +find "${base_dir}/bin/" "${conf_dir}/" "${base_dir}/lib/" -type f \ -exec grep -nHF '' '{}' \; | \ sed 's,^'"$(str_to_regex "${base_dir}")"'/,,' | \ sed -n ' diff --git a/bin/build-packages b/bin/build-packages index 9c5ab03..b39546d 100755 --- a/bin/build-packages +++ b/bin/build-packages @@ -21,7 +21,7 @@ # TODO: the following things need proper locking and/or proper handling of # external locks: # - `git` on the package source -# - `archbuild` (e.g. /var/lib/archbuilds/staging-i686-build/root.lock) +# - `archbuild` (e.g. /var/lib/archbuilds/extra-staging-i686-build/root.lock) # - `find ... -exec umount` on the build chroot # TODO: releave some locking conditions - meta goal: be able to run multiple @@ -38,12 +38,6 @@ usage() { >&2 echo 'build-packages: build package(s) on the build-list' >&2 echo '' >&2 echo 'possible options:' - >&2 echo ' -d|--diff source-directory:' - >&2 echo ' Apply the diff between $source-directory/PKGBUILD and' - >&2 echo ' $source-directory/../../trunk/PKGBUILD before building.' - >&2 echo ' This option is intended for building from trunk where minor' - >&2 echo ' fixes did not get released yet. Hence, it conflicts intentionally' - >&2 echo ' with -n, -l, -t or -x and it requires -p.' >&2 echo ' -h|--help: Show this help and exit.' >&2 echo ' -l|--local pkgname.git-revision.git-mod-revision.repository.architecture:' >&2 echo ' Build the given package without asking / reporting to the' @@ -74,10 +68,10 @@ usage() { >&2 echo ' clean the chroot before building' >&2 echo ' :haskell_without_check:' >&2 echo ' try with :without_check: iff this is a haskell-*, python-* or python2-* package' - >&2 echo ' :mirrored_source:' - >&2 echo ' compile from source tarbal from sources.archlinux.org if possible' >&2 echo ' :mirrored_source_by_hash:' >&2 echo ' download sources from sources.archlinux32.org by hash if possible' + >&2 echo ' :on_x86_64:' + >&2 echo ' build any package with x86_64 arch' >&2 echo ' :without_check:' >&2 echo ' run makepkg with "--no-check"' >&2 echo ' :without_systemd_nspawn:' @@ -90,8 +84,7 @@ usage() { } eval set -- "$( - getopt -o d:hl:n:p:s:t:ux \ - --long diff: \ + getopt -o hl:n:p:s:t:ux \ --long help \ --long local: \ --long prefer: \ @@ -102,7 +95,6 @@ eval set -- "$( )" unset count -unset diff_source_dir unset forced_package unset forced_straws unset prefered_package @@ -112,14 +104,6 @@ timeout=0 while true do case "$1" in - -d|--diff) - shift - if [ -n "${diff_source_dir}" ]; then - >&2 echo 'Option -d, --diff can be given only once.' - usage - fi - diff_source_dir="$1" - ;; -h|--help) usage 0 ;; @@ -173,17 +157,6 @@ if [ $# -ne 0 ]; then usage fi -if [ -n "${diff_source_dir}" ]; then - if [ -n "${count}" ] || \ - [ -n "${forced_package}" ] || \ - [ "${timeout}" -ne 0 ] || \ - ${exit_after_failure} || \ - [ -z "${prefered_package}" ]; then - >&2 echo 'Conflicting flags.' - usage - fi -fi - if [ -n "${forced_package}" ]; then if [ -n "${count}" ] || \ [ "${timeout}" -ne 0 ] || \ @@ -222,6 +195,14 @@ checksum=$( while [ "${count}" -ne 0 ] && \ [ "$(calculate_script_checksum)" = "${checksum}" ]; do + if [ -f '/tmp/do-not-run-build-slave' ]; then + >&2 echo 'build slave is on halt.' + >&2 echo 'I will terminate the loop and stop now.' + # non-zero exit code to signal systemctl that the process should not + # be restarted automatically + exit 1 + fi + if [ "${timeout}" -ne 0 ] && [ "${timeout}" -lt "$(date +%s)" ]; then break @@ -249,7 +230,7 @@ while [ "${count}" -ne 0 ] && \ if [ -z "${forced_package}" ]; then package=$( # shellcheck disable=SC2029 - ssh \ + ssh -o PasswordAuthentication=No \ -i "${master_build_server_identity}" \ -p "${master_build_server_port}" \ "${master_build_server_user}@${master_build_server}" \ @@ -277,7 +258,7 @@ while [ "${count}" -ne 0 ] && \ # 0: ok, I gave you an assignment 0) - [ ${count} -gt 0 ] && \ + [ "${count}" -gt 0 ] && \ count=$((count-1)) arch="${package##* }" package="${package% *}" @@ -291,19 +272,9 @@ while [ "${count}" -ne 0 ] && \ package="${package% *}" if [ "${arch}" = 'any' ]; then arch="${my_arch}" - fi - - if [ -n "${diff_source_dir}" ] && - [ "${prefered_package}" != "${package}" ]; then - >&2 echo 'The prefered package was not handed out.' - >&2 echo 'Because -d was given, I will abort.' - # shellcheck disable=SC2029 - ssh \ - -i "${master_build_server_identity}" \ - -p "${master_build_server_port}" \ - "${master_build_server_user}@${master_build_server}" \ - 'return-assignment' 'ABORT' - exit 2 + assignment_was_any=true + else + assignment_was_any=false fi if [ "${git_revision##*-}" = 'HEAD' ]; then @@ -376,14 +347,10 @@ while [ "${count}" -ne 0 ] && \ tmp_dir=$(mktemp -d "${work_dir}/tmp.build-packages.XXXXXX") trap bail_out EXIT - if ! git_repo=$(find_repository_with_commit "${git_revision}") || \ - [ -z "${git_repo}" ] || \ - ! find_pkgbuilds "${package}" "${repository}" "${git_repo}" "${git_revision}" "${mod_git_revision}" || \ - ! extract_source_directory "${git_repo}" "${git_revision}" "${mod_git_revision}" "${tmp_dir}" "${sub_pkgrel}" || \ - ! apply_trunk_patch "${tmp_dir}" "${diff_source_dir}"; then + if ! extract_source_directory "${package}" "${repository}" "${git_revision}" "${mod_git_revision}" "${tmp_dir}" "${sub_pkgrel}"; then # report local failure (probably a missing commit) to build-master # shellcheck disable=SC2029 - ssh \ + ssh -o PasswordAuthentication=No \ -i "${master_build_server_identity}" \ -p "${master_build_server_port}" \ "${master_build_server_user}@${master_build_server}" \ @@ -394,17 +361,21 @@ while [ "${count}" -ne 0 ] && \ continue fi + if [ -d "${tmp_dir}/keys/pgp" ]; then + find "${tmp_dir}/keys/pgp" -type f -exec gpg --import {} + + fi + cd "${tmp_dir}" echo 'nothing' > "${tmp_dir}/.ping-build-master" if [ -z "${forced_package}" ]; then - # we get a lock on "${work_dir}/ping-build-master.lock", + # we get a lock on "${tmp_dir}/ping-build-master.lock", # if we release that lock, ping-to-master should stop _immediately_ - exec 9> "${work_dir}/ping-build-master.lock" + exec 9> "${tmp_dir}/ping-build-master.lock" if ! verbose_flock -n 9; then >&2 echo 'ERROR: Cannot lock ping-to-master - this should not happen.' exit 2 fi - "${base_dir}/bin/ping-to-master" "$$" "${tmp_dir}" & + "${base_dir}/bin/ping-to-master" "$$" "${tmp_dir}" "${tmp_dir}/ping-build-master.lock" & fi success=false @@ -448,7 +419,7 @@ while [ "${count}" -ne 0 ] && \ if echo "${straw}" | \ grep -qF ':with_build_support:'; then - build_command='staging-with-build-support-'"${arch}"'-build' + build_command="${repository}-staging-with-build-support-${arch}-build" elif echo "${straw}" | \ grep -qF ':without_systemd_nspawn:'; then if [ -z "${prefered_package}" ]; then @@ -459,7 +430,7 @@ while [ "${count}" -ne 0 ] && \ >&2 echo 'The prefered package was not handed out.' >&2 echo 'Because straw :without_systemd_nspawn: is active, I will abort.' # shellcheck disable=SC2029 - ssh \ + ssh -o PasswordAuthentication=No \ -i "${master_build_server_identity}" \ -p "${master_build_server_port}" \ "${master_build_server_user}@${master_build_server}" \ @@ -485,8 +456,30 @@ while [ "${count}" -ne 0 ] && \ outerParameters="${innerParameters} -fcrs --asdeps --noconfirm --holdver" middleParameters='' innerParameters='' + elif echo "${straw}" | \ + grep -qF ':on_x86_64:'; then + if [ -z "${prefered_package}" ]; then + >&2 echo 'straw :on_x86_64: only allowed with -p' + exit 2 + fi + if [ "${prefered_package}" != "${package}" ]; then + >&2 echo 'The prefered package was not handed out.' + >&2 echo 'Because straw :on_x86_64: is active, I will abort.' + # shellcheck disable=SC2029 + ssh -o PasswordAuthentication=No \ + -i "${master_build_server_identity}" \ + -p "${master_build_server_port}" \ + "${master_build_server_user}@${master_build_server}" \ + 'return-assignment' 'ABORT' + exit 2 + fi + if ! ${assignment_was_any}; then + >&2 printf 'Can only build "any" packages with :on_x86_64:, but got a "%s" package.\n' "${arch}" + exit 2 + fi + build_command="${repository}-staging-x86_64-build" else - build_command='staging-'"${arch}"'-build' + build_command="${repository}-staging-${arch}-build" fi find . -maxdepth 1 -type f \( \ @@ -501,13 +494,13 @@ while [ "${count}" -ne 0 ] && \ echo 'checking-source' > "${tmp_dir}/.ping-build-master" success=false verifysource_trial=0 - while [ ${verifysource_trial} -lt 5 ]; do + while [ ${verifysource_trial} -lt 4 ]; do verifysource_trial=$((verifysource_trial + 1)) log_file="${tmp_dir}/$( date -u --iso-8601=seconds | \ cut -d+ -f1 ).build-log" - if CARCH="${arch}" makepkg --verifysource 2> "${log_file}"; then + if GIT_TERMINAL_PROMPT=0 CARCH="${arch}" makepkg --verifysource 2> "${log_file}"; then success=true rm "${log_file}" break @@ -557,53 +550,8 @@ while [ "${count}" -ne 0 ] && \ verifysource_trial=$((verifysource_trial + 1)) fi - # try to download source from sources.archlinux.org/sources/$repo/$source - if [ ${verifysource_trial} -eq 3 ]; then - if echo "${straw}" | \ - grep -qF ':mirrored_source:'; then - source_name=$( - makepkg --printsrcinfo | \ - sed -n ' - /^\s*\(epoch\|pkg\(base\|ver\|rel\)\) = /{s|^\s\+||;p} - /^pkgname = /q - ' | \ - sed ' - s|^pkgbase = \(.*\)$|0 \1-| - s|^epoch = \(.*\)$|1 \1:| - s|^pkgver = \(.*\)$|2 \1-| - s|^pkgrel = \([^.]*\)\(\..*\)\?$|3 \1.src.tar.gz| - ' | \ - sort -k1n,1 | \ - sed ' - s|^[0-9] || - :a - N - s|\n[0-9] \(\S\+\)$|\1| - ta - ' - ) - if wget -q --timeout=15 -nc -nd "https://sources.archlinux.org/sources/${git_repo}/${source_name}"; then - # shellcheck disable=SC2046 - tar -zst --overwrite \ - -f "${source_name}" \ - --exclude PKGBUILD \ - $( - if [ -n "${PKGBUILD_mod}" ]; then - git -C "${repo_paths__archlinux32}/${PKGBUILD_mod%/*}" archive "${mod_git_revision}" -- . | \ - tar -t | \ - sed 's/^/--exclude /' - fi - ) \ - --strip-components=1 \ - || true - continue - fi - fi - verifysource_trial=$((verifysource_trial + 1)) - fi - # try to download source from sources.archlinux32.org by its hash - if [ ${verifysource_trial} -eq 4 ]; then + if [ ${verifysource_trial} -eq 3 ]; then if echo "${straw}" | \ grep -qF ':mirrored_source_by_hash:'; then if download_sources_by_hash; then @@ -730,13 +678,22 @@ while [ "${count}" -ne 0 ] && \ } | \ sort | \ uniq -u | \ - while read -r unexpected_package; do - >&2 printf 'removing unexpected build artifact "%s"\n' \ - "${unexpected_package}" - rm "${unexpected_package}"* - done + { + removed_something_unexpected=false + while read -r unexpected_package; do + >&2 printf 'removing unexpected build artifact "%s"\n' \ + "${unexpected_package}" + rm "${unexpected_package}"* + removed_something_unexpected=true + done + if "${removed_something_unexpected}"; then + >&2 printf 'I was only expecting:\n%s\n' \ + "${expected_packages}" + fi + } fi >&2 printf 'signing package(s)\n' + mv "${log_file}" "${tar_content_dir}/" find . -maxdepth 1 -type f -name '*.pkg.tar.zst' \ -execdir gpg --local-user="${package_key}" --detach-sign '{}' \; \ -execdir mv '{}' '{}.sig' '{}-namcap.log' "${tar_content_dir}/" \; \ @@ -977,7 +934,8 @@ while [ "${count}" -ne 0 ] && \ \( \ -name '*.pkg.tar.zst-namcap.log' -o \ -name '*.pkg.tar.zst.so.needs' -o \ - -name '*.pkg.tar.zst.so.provides' \ + -name '*.pkg.tar.zst.so.provides' -o \ + -name '*.build-log' \ \) \ -execdir gzip '{}' \; else @@ -1015,7 +973,7 @@ while [ "${count}" -ne 0 ] && \ while ${upload_to_build_master}; do err=0 # shellcheck disable=SC2029 - ssh \ + ssh -o PasswordAuthentication=No \ -i "${master_build_server_identity}" \ -p "${master_build_server_port}" \ "${master_build_server_user}@${master_build_server}" \ @@ -1078,7 +1036,7 @@ while [ "${count}" -ne 0 ] && \ while true; do err=0 # shellcheck disable=SC2029 - ssh \ + ssh -o PasswordAuthentication=No \ -i "${master_build_server_identity}" \ -p "${master_build_server_port}" \ "${master_build_server_user}@${master_build_server}" \ @@ -1174,7 +1132,7 @@ while [ "${count}" -ne 0 ] && \ done -# remove the slave switch file if it exists (and if we are runnig on a slave) +# remove the slave switch file if it exists (and if we are running on a slave) if ! ${i_am_the_master}; then SLAVE=$(whoami) [ -f "/tmp/do-not-run-build-slave.$SLAVE" ] && rm "/tmp/do-not-run-build-slave.$SLAVE" diff --git a/bin/change-git-remotes b/bin/change-git-remotes index 9f9e4a5..fc50b7a 100755 --- a/bin/change-git-remotes +++ b/bin/change-git-remotes @@ -68,7 +68,7 @@ fi printf '%s\n' \ 'git://github.com/archlinux/svntogit-'"${git_name}" \ 'https://github.com/archlinux/svntogit-'"${git_name}" \ - 'https://git.archlinux.org/'"${git_name}" + 'git://git.archlinux.org/svntogit/'"${git_name}"'.git' ) ;; *) diff --git a/bin/check-mirrors b/bin/check-mirrors index d106201..d0b626c 100755 --- a/bin/check-mirrors +++ b/bin/check-mirrors @@ -5,6 +5,16 @@ if [ $# -eq 0 ]; then +# Create a lock file. + + exec 9> "${check_mirrors_lock_file}" + if ! verbose_flock 9; then + >&2 echo 'come back (shortly) later - I cannot lock check-mirrors.' + exit + fi + + echo 'updating mirrors from git...' >&2 + if [ -d "${releng_directory}/.git" ]; then git -C "${releng_directory}" remote update else @@ -54,6 +64,8 @@ if [ $# -eq 0 ]; then parallel -j10 "$0" "{}" > \ "${tmp_file}" + echo 'loading mirror data into database...' >&2 + # shellcheck disable=SC2016 { printf 'LOAD DATA LOCAL INFILE "%s" INTO TABLE `mirror_statuses` (' \ @@ -83,6 +95,8 @@ if [ $# -eq 0 ]; then } | \ mysql_run_query + echo 'done' >&2 + elif [ $# -eq 1 ]; then # check a single mirror url="$1" @@ -143,14 +157,16 @@ elif [ $# -eq 1 ]; then cnt=$( curl -s "${ip_flag}" "${url}archisos/" ) || has_isos=0 - for suffix in 'i686' 'dual'; do - # shellcheck disable=SC2059 - if ! printf '%s\n' "${cnt}" | \ - grep -qF "$(printf "$(date '+archlinux-%Y.%m.%%02d-'"${suffix}"'.iso\n')" $(seq 31))" -; then - has_isos=0 - break - fi - done +# doesn't really work: dual doesn't exist anymore and the other test sometimes fails, sometimes succeeds? +# let's assume the precense of the 'archisos' directory is enough +# for suffix in 'i686' 'dual'; do +# # shellcheck disable=SC2059 +# if ! printf '%s\n' "${cnt}" | \ +# grep -qF "$(printf "$(date '+archlinux-%Y.%m.%%02d-'"${suffix}"'.iso\n')" $(seq 31))" -; then +# has_isos=0 +# break +# fi +# done else has_isos=0 last_sync='0' diff --git a/bin/check-opcodes b/bin/check-opcodes deleted file mode 100755 index e8bb807..0000000 --- a/bin/check-opcodes +++ /dev/null @@ -1,199 +0,0 @@ -#!/bin/sh - -# shellcheck disable=SC2086,SC2119,SC2120 - -# shellcheck source=../lib/load-configuration -. "${0%/*}/../lib/load-configuration" - -usage( ) { - >&2 cat <<EOF - -check_opcodes: [options] [ -a <arch> ] <package> - -possible optons: - -h|--help: Show this help page - -a|--architecture: architecture family to check against, one of - i486, i686, pentium3 (meaning target architecture - the package should be runnable on) - -v|--verbose: Verbose output, print result of check for logs - -d|--debug: Debug output, used for development and testing - -EOF - exit 1 -} - -VERBOSE=0 -DEBUG=0 -EXIT_CODE=0 - -verbose( ) { - if test $VERBOSE = 1; then - echo "$@" - fi -} - -debug( ) { - if test $DEBUG = 1; then - echo "$@" - fi -} - -err( ) { - echo "ERROR: $*" - EXIT_CODE=1 -} - -tmp_dir=$(mktemp -d "${work_dir}/tmp.check-opcodes.XXXXXX") -trap 'rm -rf --one-file-system "${tmp_dir:?}"' EXIT - -ARCH=i686 - -while getopts ":vda:h-:" opt; do - case $opt in - -) - case "$OPTARG" in - help) - usage - ;; - verbose) - VERBOSE=1 - ;; - debug) - DEBUG=1 - ;; - *) - echo "ERROR: Invalid option: --$OPTARG" >&2 - usage - ;; - esac - ;; - h) - usage - ;; - v) - VERBOSE=1 - ;; - d) - DEBUG=1 - ;; - a) - ARCH=$OPTARG - ;; - \?) - echo "ERROR: Invalid option: -$OPTARG" >&2 - usage - ;; - esac -done - -shift $((OPTIND-1)) - -PACKAGE=$1 - -if test "$PACKAGE" = ""; then - echo "ERROR: Filename of a package required as argument" >&2 - usage - exit 1 -fi - -OPCODE_ARGS="" -case $ARCH in - i486) - OPCODE_ARGS='-r -a 386 -v' - ;; - i686) - OPCODE_ARGS='-s MMX -s SSE' - ;; -# TODO: pentium4 - pentium3) - OPCODE_ARGS='-s SSE2 -s SSE3' - ;; - *) - echo "ERROR: architecture must currently be one of i486, i686 and pentium3" >&2 - usage - exit 1 -esac - -debug "Unpacking $PACKAGE to $tmp_dir.." -bsdtar --no-fflags -x -C $tmp_dir -f $PACKAGE - -debug "Checking for architecture: $ARCH ($OPCODE_ARGS).." - -# shellcheck disable=SC2044 -for absfile in $(find $tmp_dir \( -regextype grep -regex '.*\.so\(\.[0-9.]\+\)\?' -type f \) -o \( -executable -type f \) ); do - file=$(basename $absfile) - relfile=${absfile#$tmp_dir} - debug "Checking file: $relfile" - if ! readelf -a $absfile > $tmp_dir/$file.elf 2>/dev/null; then - debug "readelf failed, ignoring file" - continue - fi - if ! objdump -f $absfile > $tmp_dir/$file.objdump 2>/dev/null; then - debug "objdump failed, ignoring file" - continue - fi - file $absfile > $tmp_dir/$file.file - - arch=$(grep ^architecture $tmp_dir/$file.objdump | sed 's/^architecture: //g' | cut -f 1 -d ,) - case $arch in - i386:x86-64) - arch='x86_64' - ;; - i386) - arch='x86' - ;; - *) - arch='unknown' - ;; - esac - debug " Objdump architecture: $arch" - - archelf=$(grep '^ \+Class' $tmp_dir/$file.elf | cut -f 2 -d : | tr -d ' ') - case $archelf in - ELF64) - archelf='x86_64' - ;; - ELF32) - archelf='x86' - ;; - *) - archelf='unknown' - ;; - esac - debug " Readelf architecture: $archelf" - - if test $arch != $archelf; then - err "ERROR: $file ambigous architecture information (objdump: $arch, ELF: $archelf)" - fi - - if test $arch = "x86_64"; then - err "ERROR: $file is a 64-bit library!" - continue - fi - - objdump -M intel -d $absfile > $tmp_dir/$file.asm - bad_opcodes=$(${base_dir}/bin/opcode $OPCODE_ARGS -m 1 < $tmp_dir/$file.asm | wc -l) - if test $bad_opcodes != 0; then - case $ARCH in - i486) - err "$relfile is not built for plain i486 opcodes" - ;; - i686) - err "$relfile contains MMX, SSE or newer opcodes" - ;; - pentium3) - err "$relfile contains SSE2 or newer opcodes" - ;; - esac - if test $DEBUG = 1; then - ${base_dir}/bin/opcode $OPCODE_ARGS -B 2 -A 2 < $tmp_dir/$file.asm - fi - else - if test $VERBOSE = 1; then - verbose "OK: $relfile fullfills architecture constraint for $ARCH" - fi - fi - -done - -exit $EXIT_CODE diff --git a/bin/cleanup b/bin/cleanup index 57c4e07..14d08ac 100755 --- a/bin/cleanup +++ b/bin/cleanup @@ -19,6 +19,14 @@ if [ -s "${work_dir}/build-master-sanity" ]; then exit fi +# Lock the database - we should not run in parallel with db-update. +exec 9> "${package_database_lock_file}" +# shellcheck disable=SC2086 +if ! verbose_flock -n 9; then + >&2 echo 'come back (shortly) later - I cannot lock package database.' + exit 0 +fi + # only keep newest logs per failed package and fail_reason # shellcheck disable=SC2016 @@ -68,6 +76,9 @@ fi rm "${build_log_directory}/error/${file}" done +# Release database lock. +flock -u 9 || true + # only keep namcap logs of last 2 weeks for succeeded packages find "${build_log_directory}/success" -maxdepth 1 -type f -mtime +14 \ -not -exec zgrep -q '^+.*ELF file .* has text relocations' '{}' \; \ diff --git a/bin/create-build-support-package b/bin/create-build-support-package index 09374ec..d786dcc 100755 --- a/bin/create-build-support-package +++ b/bin/create-build-support-package @@ -7,6 +7,10 @@ # TODO: use the intention-queue +# TODO: add the possibility to add an "external" package - TBD: How to +# create / Where to take from database information (e.g. +# package_sources). + # shellcheck disable=SC2016 usage() { >&2 echo 'usage:' @@ -169,7 +173,7 @@ if [ -n "${source_package}" ]; then fi new_pkg="${pkg%-*-*-*}" - new_pkg="${new_pkg}-shim${pkg#${new_pkg}}" + new_pkg="${new_pkg}-shim${pkg#"${new_pkg}"}" failsafe_rsync \ "${master_mirror_rsync_directory}/pool/${pkg}" \ diff --git a/bin/db-update b/bin/db-update index 88c567d..2d0f50e 100755 --- a/bin/db-update +++ b/bin/db-update @@ -683,12 +683,10 @@ mysql_query_update_replaced_bpir() { # somewhat inaccurate { - printf '{\n' - printf ' mysql_run_query' - printf ' | sort -u' - printf ' >> "%s/rm"\n' \ + printf 'mysql_run_query' + printf ' >> "%s/rm"' \ "${perma_tmp_dir}" - printf '} <<END_OF_MYSQL_QUERY\n' + printf ' <<END_OF_MYSQL_QUERY\n' 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' @@ -738,8 +736,10 @@ mysql_query_update_replaced_bpir() { # and push our local *.db.tar.gz via rsync while read -r arch repo; do { - printf 'recompress_gz "%s"' \ - "${tmp_dir}" + printf 'mkdir -p "%s/recompress_gz.tmp"\n' \ + "${perma_tmp_dir}" + printf 'recompress_gz "%s/recompress_gz.tmp"' \ + "${perma_tmp_dir}" for suffix in '' '.old'; do printf ' "%s/dbs/%s/%s/%s."*".tar.gz%s"' \ "${perma_tmp_dir}" \ diff --git a/bin/delete-packages b/bin/delete-packages index 2bb3072..0026c88 100755 --- a/bin/delete-packages +++ b/bin/delete-packages @@ -160,7 +160,8 @@ export TMPDIR="${tmp_dir}" mysql_join_binary_packages_in_repositories_binary_packages mysql_join_binary_packages_in_repositories_repositories mysql_join_repositories_architectures - printf ' WHERE CONCAT(' + printf ' WHERE `repositories`.`is_on_master_mirror`' + printf ' AND CONCAT(' printf '`architectures`.`name`,"/",' printf '`repositories`.`name`,"/",' printf '`binary_packages`.`pkgname`' diff --git a/bin/generate-key-graph b/bin/generate-key-graph index 3c5063f..b409d42 100755 --- a/bin/generate-key-graph +++ b/bin/generate-key-graph @@ -23,7 +23,7 @@ trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT # shellcheck disable=SC2046 ${master_mirror_rsync_command} $( ls_master_mirror pool \ - | grep '^archlinux32-keyring\(-transition\)\?\(-[^-]\+\)\{3\}\.pkg\.tar\.zst$' \ + | grep '^archlinux32-keyring\(-[^-]\+\)\{3\}\.pkg\.tar\.zst$' \ | sed 's#^#'"${master_mirror_rsync_directory}"'/pool/#' ) "${tmp_dir}/" diff --git a/bin/get-assignment b/bin/get-assignment index 6abfaef..8b399a3 100755 --- a/bin/get-assignment +++ b/bin/get-assignment @@ -96,6 +96,7 @@ if ! verbose_flock -s -n 8; then fi clean_up() { + # shellcheck disable=SC2317 rm -rf --one-file-system "${tmp_dir}" } @@ -200,16 +201,15 @@ while [ -s "${work_dir}/forced-package-builds.${slave}" ]; do fi done -# a package with [all dependencies met (or unsuccessfully built) or which is part of a loop] -# and which is currently not being built, ordered by: +# a package with [all dependencies met (or unsuccessfully built) or which is part of a loop], +# which is currently not being built and which has the highest priority, ordered by: # 1: we requested it # 2: tool chain priority -# 3: its priority -# 4: was built the least times -# 5: architecture matches (or the slave is from the majority architecture) -# 6: is part of a loop -# 7: has the oldes package source -# 8: build_assignment id +# 3: was built the least times +# 4: architecture matches (or the slave is from the majority architecture) +# 5: is part of a loop +# 6: has the oldes package source +# 7: build_assignment id next_building=$( # shellcheck disable=SC2016 { @@ -260,6 +260,21 @@ next_building=$( printf ' AND `architectures`.`name` = from_base64("%s");\n' \ "${arch}" + printf 'SET @`max_priority`=(' + printf 'SELECT MAX(`build_assignments`.`priority`)' + printf ' FROM `considered_build_assignments`' + printf ' JOIN `build_assignments`' + printf ' ON `build_assignments`.`id`=`considered_build_assignments`.`id`' + printf ');\n' + + printf 'DELETE `considered_build_assignments`' + printf ' FROM `considered_build_assignments`' + printf ' JOIN `build_assignments`' + printf ' ON `build_assignments`.`id`=`considered_build_assignments`.`id`' + printf ' WHERE `build_assignments`.`priority`<@`max_priority`' + printf ';\n' + + printf 'INSERT IGNORE INTO `considered_build_assignments_2` (`id`)' printf ' SELECT `considered_build_assignments`.`id`' printf ' FROM `considered_build_assignments`;\n' @@ -539,7 +554,6 @@ next_building=$( # 1: in toolchain, should be built later # 2: not in toolchain printf 'IFNULL(`toolchain_query`.`priority`,2),' - printf '`build_assignments`.`priority` DESC,' printf 'IFNULL(`latest_failed_builds`.`count`,0),' printf 'IF(' printf '`architectures`.`id`=%s' \ diff --git a/bin/get-package-updates b/bin/get-package-updates index 8e7e4ef..b067233 100755 --- a/bin/get-package-updates +++ b/bin/get-package-updates @@ -21,7 +21,12 @@ usage() { >&2 echo ' (yyyy-mm-ddThh:mm:ss). Conflicts -n.' >&2 echo ' -h|--help: Show this help and exit.' >&2 echo ' -i|--ignore-insanity:' - >&2 echo ' Do not abort when insane.' + >&2 echo ' Do not abort when insane.' + >&2 echo ' -m|--max-upstream-packages $number:' + >&2 echo ' Do not update more than $number upstream packages.' + >&2 echo ' Do not update git head of state repository.' + >&2 echo ' USE WITH CAUTION: This may remove packages, if they' + >&2 echo ' were moved. Always do a final run without -m.' >&2 echo ' -n|--no-pull: Do not pull git repos, merely reorder build list.' >&2 echo ' Conflicts -d.' >&2 echo ' -r|--recent-modifications:' @@ -33,10 +38,11 @@ usage() { } eval set -- "$( - getopt -o d:hinrw \ + getopt -o d:him:nrw \ --long date: \ --long help \ --long ignore-insanity \ + --long max-upstream-packages: \ --long no-pull \ --long recent-modifications \ --long wait \ @@ -47,6 +53,7 @@ eval set -- "$( block_flag='-n' date_time='' ignore_insanity=false +max_upstream_packages='' pull=true recent_modifications=false @@ -63,6 +70,10 @@ do -i|--ignore-insanity) ignore_insanity=true ;; + -m|--max-upstream-packages) + shift + max_upstream_packages="$1" + ;; -n|--no-pull) pull=false ;; @@ -106,16 +117,22 @@ if [ -s "${work_dir}/build-master-sanity" ]; then fi fi -# delete_package arch package +# delete_package arch package repository # mark $arch/$package for deletion + +# shellcheck disable=SC3043 delete_package() { + local architecture="$1" + local pkgbase="$2" + local repository="$3" + >&2 printf 'delete_package %s %s %s\n' "${architecture}" "${pkgbase}" "${repository}" # shellcheck disable=SC2016 query_delete_packages=$( printf '`architectures` AS `d_a`' printf ' JOIN `architecture_compatibilities` AS `a_c`' printf ' ON `a_c`.`runs_on`=`d_a`.`id`' printf ' AND `d_a`.`name`=from_base64("%s")' \ - "$(printf '%s' "$1" | base64 -w0)" + "$(printf '%s' "${architecture}" | base64 -w0)" printf ' JOIN `build_assignments`' printf ' ON (`a_c`.`built_for`=`build_assignments`.`architecture`' # "any" references all architectures, but this is not represented @@ -125,9 +142,12 @@ delete_package() { printf ' OR `d_a`.`name`="any")' mysql_join_build_assignments_package_sources printf ' AND `package_sources`.`pkgbase`=from_base64("%s")' \ - "$(printf '%s' "$2" | base64 -w0)" + "$(printf '%s' "${pkgbase}" | base64 -w0)" mysql_join_build_assignments_binary_packages mysql_join_binary_packages_binary_packages_in_repositories + mysql_join_package_sources_upstream_repositories + printf ' AND `upstream_repositories`.`name` LIKE from_base64("%s")' \ + "$(printf '%s' "${repository}" | base64 -w0)" ) # shellcheck disable=SC2016 { @@ -165,6 +185,8 @@ delete_package() { printf 'COMMIT;\n' + # no need to remove the binary_package, because it is now on the + # deletion-lists printf 'DELETE `binary_packages_in_repositories`' printf ' FROM %s' "${query_delete_packages}" mysql_join_binary_packages_in_repositories_repositories @@ -186,11 +208,16 @@ something_new=false for repo in ${repo_names}; do eval repo_path='"${repo_paths__'"${repo}"'}"' - # Update git repositories (official packages, community packages and the repository of package customizations). + if [ "${repo}" = 'archlinux32' ]; then + branch='master' + else + branch='main' + fi + # Update git repositories (upstream state and our package customizations). if [ -d "${repo_path}/.git" ]; then git -C "${repo_path}" pull --ff-only else - git -C "${repo_path}" fetch origin master:master + git -C "${repo_path}" fetch origin "${branch}:${branch}" fi || \ true # read previous git revision numbers from database. @@ -238,18 +265,9 @@ if ${pull} && \ exit fi -# Create a lock file for build list. - -exec 9> "${build_list_lock_file}" -# shellcheck disable=SC2086 -if ! verbose_flock ${block_flag} 9; then - >&2 echo 'come back (shortly) later - I cannot lock build list.' - exit -fi - -exec 8> "${sanity_check_lock_file}" +exec 9> "${sanity_check_lock_file}" # shellcheck disable=SC2086 -if ! verbose_flock -s ${block_flag} 8; then +if ! verbose_flock -s ${block_flag} 9; then >&2 echo 'come back (shortly) later - sanity-check running.' exit fi @@ -272,227 +290,203 @@ echo 'Check modified packages from the last update, and put them to the build li # If a package is deleted, remove from the rebuild list, and add it to the deletion list. # If a new package is added, then ensure that it's not on the deletion list. -# shellcheck disable=SC2016 -{ - printf 'SELECT DISTINCT' - printf ' `package_sources`.`pkgbase`,' - printf '`upstream_repositories`.`name`,' - printf 'IF(`build_assignments`.`architecture`=%s,"any","x86_64")' \ - "${architecture_ids__any}" - printf ' FROM `binary_packages`' - mysql_join_binary_packages_binary_packages_in_repositories - mysql_join_binary_packages_build_assignments - mysql_join_build_assignments_package_sources - mysql_join_package_sources_upstream_repositories - printf ' WHERE `binary_packages_in_repositories`.`repository`=%s;\n' \ - "${repository_ids__any_build_list}" -} | \ - mysql_run_query | \ - sed ' - s@^\(\S*\)\t\(\S*\)\t\(\S*\)$@s,^\\(.\\t\1/repos/\2-\3/\\)[^/]\\+$,\\1PKGBUILD,\ns,^\\(.\\t\2/\1/\\)[^/]\\+$,\\1PKGBUILD,@ - ' > \ - "${tmp_dir}/trigger-rebuild-on-any-file-sed-expression" - { - # trigger rebuild of packages removed from blacklist + directories=$( + # shellcheck disable=SC2154 + git -C "${repo_paths__state}" archive "${new_repo_revisions__state}" \ + | tar -t \ + | cut -d/ -f1 \ + | grep -vF -- '-testing-' \ + | grep -vF -- '-staging-' \ + | sort -u + ) # shellcheck disable=SC2016 { - printf 'SELECT `package_sources`.`pkgbase`,`upstream_repositories`.`name`,`git_repositories`.`name`' + printf 'SELECT DISTINCT `package_sources`.`pkgbase`,' + printf '`package_sources`.`git_revision`,' + printf '`upstream_repositories`.`name`' printf ' FROM `package_sources`' mysql_join_package_sources_upstream_repositories - mysql_join_upstream_repositories_git_repositories - printf ' WHERE `package_sources`.`pkgbase` IN (' + mysql_join_package_sources_build_assignments + mysql_join_build_assignments_binary_packages + mysql_join_binary_packages_binary_packages_in_repositories + printf ' AND NOT `binary_packages_in_repositories`.`is_to_be_deleted`' + } \ + | mysql_run_query \ + | tr '\t' ' ' \ + | sort -u \ + > "${tmp_dir}/mysql-packages" + for directory in ${directories}; do # shellcheck disable=SC2154 - git -C "${repo_paths__archlinux32}" diff --name-status "${old_repo_revisions__archlinux32}" "${new_repo_revisions__archlinux32}" -- 'blacklist' | \ - sed ' - s@^D\tblacklist/[^/]\+/[^/]\+/@@ - t - d - ' | \ - base64_encode_each | \ - sed ' - s/^/from_base64("/ - s/$/")/ - ' | \ - tr '\n' ',' - printf '"");\n' - } | \ - mysql_run_query | \ - while read -r pkgbase repository git_repository; do - eval 'git_rev="${new_repo_revisions__'"${git_repository}"'}"' - eval 'git_dir="${repo_paths__'"${git_repository}"'}"' - # TODO: maybe, we want to exclude our own packages here, too? But why - # would they be black listed in the first place? - # shellcheck disable=SC2154 - if git -C "${git_dir}" archive "${git_rev}" -- "${pkgbase}/repos" \ - | tar -tf - \ - | grep -q -- '-\(any\|x86_64\)/PKGBUILD$'; then - printf 'A %s %s %s\n' \ - "${pkgbase}" \ - "${git_rev}" \ - "${repository}" - fi - done - # actual updates/removes - for repo in ${repo_names}; do - eval repo_path='"${repo_paths__'"${repo}"'}"' - eval old_repo_revision='"${old_repo_revisions__'"${repo}"'}"' - eval new_repo_revision='"${new_repo_revisions__'"${repo}"'}"' - # if old revision unknown, mimic "git diff"-output + git -C "${repo_paths__state}" archive "${new_repo_revisions__state}" -- "${directory}" \ + | tar -Ox \ + | grep -v '^\S\+\( \S\+\)\1\1$' \ + | grep ' [0-9a-f]\{40\}$' \ + | cut -d' ' -f1,4 \ + | sed ' + s@$@ '"${directory%-*}"'@ + ' + done \ + | grep -v '^lib32-' \ + | sort -u \ + > "${tmp_dir}/upstream-packages" + diff "${tmp_dir}/mysql-packages" "${tmp_dir}/upstream-packages" \ + | grep '^>' \ + | awk '{print $3 " " $2 " " $4}' \ + | sort -k2,2 -k3,3 \ + | uniq -uf1 \ + | while read -r git_revision pkgbase repository; do # shellcheck disable=SC2154 - if [ "${old_repo_revision}" = "NONE" ]; then - git -C "${repo_path}" archive --format=tar HEAD | \ - tar -t | \ - sed 's|^|A\t|' + if git -C "${repo_paths__archlinux32}" archive "${new_repo_revisions__archlinux32}" -- "${repository}/${pkgbase}" >/dev/null 2>&1; then + mod_git_revision="${new_repo_revisions__archlinux32}" else - git -C "${repo_path}" diff --no-renames --name-status "${old_repo_revision}" "${new_repo_revision}" - fi | \ - # rename any file to "PKGBUILD" for packages on the build-list - sed -f "${tmp_dir}/trigger-rebuild-on-any-file-sed-expression" | \ - # only track changes in PKGBUILDs - grep '/PKGBUILD$' | \ - if [ "${repo}" = "archlinux32" ]; then - # modify the directory structure from the modifiaction-repository - # to the one of an original source repository - # shellcheck disable=SC2016 - sed 's|^\(.\t\)\([^/]\+\)/\([^/]\+\)/\(.\+\)$|\2 \1\3/repos/\2-x86_64/\4|' | \ - while read -r pkg_repo rest; do - repo=$(find_git_repository_to_package_repository "${pkg_repo}") - eval 'printf '"'"'%s %s\n'"'" \ - "$(printf '"${new_repo_revisions__%s}"' "${repo}")" \ - "'${rest}'" - done - else - sed "s|^|${new_repo_revision} |" - fi | \ - grep '^\S\+ .\s[^/]\+/repos/[^/]\+/PKGBUILD$' | \ - # ignore i686 - grep -- '-\(any\|x86_64\)/PKGBUILD$' | \ - # ignore staging and testing - grep -v -- '[-/]\(staging\|testing\|unstable\)-[^/]\+/PKGBUILD$' | \ - sed 's|^\(\S\+\) \(.\)\t\([^/]\+\)/repos/\([^/]\+\)-[^/-]\+/PKGBUILD$|\2 \3 \1 \4|' - done | \ - sort -u | \ - sed ' - s|^D\s|0 \0| - t - s|^[AM]\s|1 \0| - t - s|^|2 | - ' | \ - sort -k1,1 | \ - sed 's|^[012] ||' -} | \ - while read -r mode package git_revision repository; do - if [ "${mode}" = 'D' ]; then - # deleted PKGBUILD - # shellcheck disable=SC2154 - git_revision="${new_repo_revisions__archlinux32}" - found_package=false - # we need to test archlinux32 last, because otherwise - # find_package_repository_to_package might look in the wrong git - # repository of a package w/o upstream - for repository in ${repo_names} archlinux32; do - eval 'repo_path="${repo_paths__'"${repository}"'}"' - if [ "${repository}" = "archlinux32" ]; then - if git -C "${repo_path}" archive "${new_repo_revisions__archlinux32}" 2> /dev/null | \ - tar -t 2> /dev/null | \ - grep -q '^[^/]\+/'"$(str_to_regex "${package}")"'/PKGBUILD$'; then - found_package=true - fi - else - # shellcheck disable=SC2154 - if eval 'git -C "${repo_path}" archive "${new_repo_revisions__'"${repository}"'}" -- "${package}/repos"' 2> /dev/null | \ - tar -t --wildcards "${package}/repos/*/PKGBUILD" 2> /dev/null | \ - cut -d/ -f3 | \ - grep -v 'staging\|testing\|-unstable' | \ - grep -vq -- '-i686$'; then - eval 'git_revision="${new_repo_revisions__'"${repository}"'}"' - found_package=true - break - fi - fi - done - if ${found_package}; then - mode='M' - repository=$( - find_package_repository_to_package "${package}" "${repository}" "${git_revision}" - ) - else - delete_package 'any' "${package}" - continue - fi + mod_git_revision='0000000000000000000000000000000000000000' fi - if [ "${mode}" = 'A' ] || [ "${mode}" = 'M' ]; then - # shellcheck disable=SC2016 - { - # delete old binary packages which are not yet built or on the - # deletion list - mysql_query_delete_packages \ - '`package_sources`.`pkgbase`=from_base64("'"$( - printf '%s' "${package}" | \ - base64 -w0 - )"'")' \ - '`repositories`.`stability` IN ('"${repository_stability_ids__unbuilt}"','"${repository_stability_ids__forbidden}"')' - # remove is-to-be-deleted marker from old binary packages - printf 'UPDATE `binary_packages_in_repositories`' - mysql_join_binary_packages_in_repositories_binary_packages - mysql_join_binary_packages_build_assignments - mysql_join_build_assignments_package_sources - printf ' SET `binary_packages_in_repositories`.`is_to_be_deleted`=0' - printf ' WHERE `package_sources`.`pkgbase`=from_base64("%s");\n' \ - "$( - printf '%s' "${package}" | \ - base64 -w0 - )" - } | \ - mysql_run_query - printf '%s\n' "${package}" >> "${tmp_dir}/modified-packages" - # shellcheck disable=SC2154 - printf '%s ' "${package}" "${git_revision}" "${new_repo_revisions__archlinux32}" "${repository}" >&2 -# TODO: sometimes we schedule the identical package twice (once "normal" -# and once, because we found the deleted package elsewhere) - this could -# be avoided - mysql_generate_package_metadata "${repository_ids__any_to_be_decided}" "${package}" "${git_revision}" "${new_repo_revisions__archlinux32}" "${repository}" - printf '\n' >&2 - continue + printf '%s %s %s %s\n' "${pkgbase}" "${repository}" "${git_revision}" "${mod_git_revision}" + done \ + | if [ -n "${max_upstream_packages}" ]; then + head -n"${max_upstream_packages}" + else + cat + fi + # shellcheck disable=SC2154 + git -C "${repo_paths__archlinux32}" diff "${old_repo_revisions__archlinux32}" "${new_repo_revisions__archlinux32}" --name-status \ + | tr '\t/' ' ' \ + | grep '^[AM]' \ + | cut -d' ' -f2,3 \ + | grep -v '^blacklist ' \ + | while read -r repository pkgbase; do + git_revision=$( + # shellcheck disable=SC2046 + git -C "${repo_paths__state}" archive "${new_repo_revisions__state}" -- $( + printf '%s\n' "${directories}" \ + | grep '^'"${repository}"'-' + ) \ + | tar -Ox \ + | sort -k1,1 \ + > "${tmp_dir}/git-revisions" + echo "${pkgbase}" \ + | join -1 1 -2 1 -o 1.4 "${tmp_dir}/git-revisions" - + ) + if [ -z "${git_revision}" ]; then + git_revision='0000000000000000000000000000000000000000' fi - - >&2 echo "unknown git diff mode '${mode}'" - exit 1 + if [ ${#git_revision} != 40 ] \ + || printf '%s\n' "${git_revision}" \ + | grep -vq '[0-9]'; then + >&2 printf 'invalid git revision "%s"\n' "${git_revision}" + exit 1 + fi + printf '%s %s %s %s\n' "${pkgbase}" "${repository}" "${git_revision}" "${new_repo_revisions__archlinux32}" done +} \ +| sort -u \ +| sort -k1,1 -k2,2 \ +> "${tmp_dir}/modified-packages" + +errors=$( + awk '{print $3 " " $4 " " $1 " " $2}' \ + < "${tmp_dir}/modified-packages" \ + | uniq -Df2 +) +if [ -n "${errors}" ]; then + >&2 printf 'Some packages are scheduled with different versions - this should not happen:\n' + >&2 printf '%s\n' "${errors}" + exit 1 +fi -if [ -s "${tmp_dir}/modified-packages" ] || ! ${pull}; then - echo 'Delete black-listed packages.' - if [ -s "${tmp_dir}/modified-packages" ]; then - sort -u "${tmp_dir}/modified-packages" --output "${tmp_dir}/modified-packages" +echo 'Mark to be deleted packages for removal' + +cut -d' ' -f1,3 "${tmp_dir}/mysql-packages" \ +| sort -u \ +| sponge "${tmp_dir}/mysql-packages" + +{ + cut -d' ' -f1,3 "${tmp_dir}/upstream-packages" + git -C "${repo_paths__archlinux32}" archive "${new_repo_revisions__archlinux32}" \ + | tar -t \ + | grep -v '^blacklist/' \ + | tr '/' ' ' \ + | awk '{print $2 " " $1}' +} \ +| sort -u \ +| sponge "${tmp_dir}/upstream-packages" + +diff "${tmp_dir}/mysql-packages" "${tmp_dir}/upstream-packages" \ +| grep '^<' \ +| cut -d' ' -f2,3 \ +| while read -r pkgbase repository; do + delete_package 'any' "${pkgbase}" "${repository}" +done + +echo 'Insert updated packages' + +while read -r pkgbase repository git_revision mod_git_revision; do + if test "$repository" = "kde-unstable"; then + continue fi - # extract black-listed packages - git -C "${repo_paths__archlinux32}" archive "${new_repo_revisions__archlinux32}" -- 'blacklist' | \ - tar -t 'blacklist' | \ - sed ' - s@^blacklist/\([^/]\+\)/[^/]\+/\([^/]\+\)$@\1\t\2@ - t - d - ' | \ - expand_blacklist_architectures "${tmp_dir}/architecture-compatibilities" | \ - if [ -s "${tmp_dir}/modified-packages" ]; then - sort -k2,2 | \ - join -1 1 -2 2 -o 2.1,2.2 "${tmp_dir}/modified-packages" - - sed ' - /^lib32-/ s/^/any / - t - d - ' "${tmp_dir}/modified-packages" - else - cat - fi | \ - sort -u | \ - while read -r arch pkgbase; do - delete_package "${arch}" "${pkgbase}" - done - rm "${tmp_dir}/architecture-compatibilities" -fi + if test "$repository" = "gnome-unstable"; then + continue + fi + # shellcheck disable=SC2016 + { + # delete old binary packages which are not yet built or on the + # deletion list + mysql_query_delete_packages \ + '`package_sources`.`pkgbase`=from_base64("'"$( + printf '%s' "${pkgbase}" \ + | base64 -w0 + )"'")' \ + '`repositories`.`stability` IN ('"${repository_stability_ids__unbuilt}"','"${repository_stability_ids__forbidden}"')' + # remove is-to-be-deleted marker from old binary packages + printf 'UPDATE `binary_packages_in_repositories`' + mysql_join_binary_packages_in_repositories_binary_packages + mysql_join_binary_packages_build_assignments + mysql_join_build_assignments_package_sources + mysql_join_package_sources_upstream_repositories + printf ' SET `binary_packages_in_repositories`.`is_to_be_deleted`=0' + printf ' WHERE `package_sources`.`pkgbase`=from_base64("%s")' \ + "$( + printf '%s' "${pkgbase}" \ + | base64 -w0 + )" + printf ' AND `upstream_repositories`.`name`=from_base64("%s");\n' \ + "$( + printf '%s' "${repository}" \ + | base64 -w0 + )" + } \ + | mysql_run_query + # shellcheck disable=SC2154 + >&2 printf '%s ' "${pkgbase}" "${git_revision}" "${mod_git_revision}" "${repository}" + mysql_generate_package_metadata "${repository_ids__any_to_be_decided}" "${pkgbase}" "${git_revision}" "${mod_git_revision}" "${repository}" + >&2 printf '\n' +done \ +< "${tmp_dir}/modified-packages" + +echo 'remove blacklisted packages' + +{ + git -C "${repo_paths__archlinux32}" archive "${new_repo_revisions__archlinux32}" -- 'blacklist' \ + | tar -t 'blacklist' \ + | sed ' + s@^blacklist/\([^/]\+\)/[^/]\+/\([^/]\+\)$@\1 \2@ + t + d + ' \ + | sort -k2,2 \ + | join -1 1 -2 2 -o 2.1,2.2 "${tmp_dir}/modified-packages" - + git -C "${repo_paths__archlinux32}" diff --name-status "${old_repo_revisions__archlinux32}" "${new_repo_revisions__archlinux32}" -- 'blacklist' \ + | sed ' + s@^[AM]\sblacklist/\([^/]\+\)/[^/]\+/\([^/]\+\)$@\1 \2@ + t + d + ' +} \ +| sort -u \ +| while read -r arch pkgbase; do + delete_package "${arch}" "${pkgbase}" '%' +done echo 'Done - mark decisions as final.' @@ -539,6 +533,10 @@ echo 'Done - mark decisions as final.' # update hashes of repositories in mysql database for repo in ${repo_names}; do + if [ -n "${max_upstream_packages}" ] \ + && [ "${repo}" = 'state' ]; then + continue + fi printf 'UPDATE `git_repositories`' printf ' SET `git_repositories`.`head`=from_base64("%s")' \ "$(eval 'printf '"'"'%s'"'"' "${new_repo_revisions__'"${repo}"'}"' | base64 -w0)" diff --git a/bin/get-source-info b/bin/get-source-info new file mode 100755 index 0000000..73dc504 --- /dev/null +++ b/bin/get-source-info @@ -0,0 +1,83 @@ +#!/bin/sh + +# shellcheck disable=SC2119,SC2120 + +# get-source-info <package> <repository> <git_revision> <mod_git_revision> +# create .SRCINFO from PKGBUILD within git repositories, output to stdout, +# cache it on https://mirror.archlinux32.org/pkginfo + +# build .SRCINFO if necessary, fetch it from cache when already computed, +# +# this can be used to cache srcinfo (especially for blacklisted packages) +# as it uses quite some time to compute + +# shellcheck source=../lib/load-configuration +. "${0%/*}/../lib/load-configuration" + +# shellcheck disable=SC2016 +usage() { + >&2 echo '' + >&2 echo 'get-source-info <package> <repository> <git_revision> <mod_git_revision> [options]:' + >&2 echo ' get package srcinfo' + >&2 echo '' + >&2 echo 'possible options:' + >&2 echo ' -c|--cache:' + >&2 echo ' Respect the cache when fetching pkginfo' + >&2 echo ' -h|--help:' + >&2 echo ' Show this help and exit.' + [ -z "$1" ] && exit 1 || exit "$1" +} + +eval set -- "$( + getopt -o hc \ + --long help \ + --long cache \ + -n "$(basename "$0")" -- "$@" || \ + echo usage + )" + +respect_cache=0 + +while true +do + case "$1" in + -h|--help) + usage 0 + ;; + -c|--cache) + respect_cache=1 + ;; + --) + shift + break + ;; + *) + >&2 printf 'Whoops, forgot to implement option "%s" internally.\n' \ + "$1" + exit 42 + ;; + esac + shift +done + +if [ $# -ne 4 ]; then + usage 1 +fi + +tmp_dir=$(mktemp -d "${work_dir}/tmp.get-source-info.XXXXXX") +trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT + +PACKAGE="$1" +REPOSITORY="$2" +GIT_REVISION="$3" +MOD_GIT_REVISION="$4" +SRCINFO="${tmp_dir}/SRCINFO" + +if [ "${respect_cache}" = 1 ]; then + curl -LSs "https://buildmaster.archlinux32.org/pkginfo/${PACKAGE}=${REPOSITORY}=${GIT_REVISION}=${MOD_GIT_REVISION}" \ + >"${SRCINFO}" +else + make_source_info "${PACKAGE}" "${REPOSITORY}" "${GIT_REVISION}" "${MOD_GIT_REVISION}" "${SRCINFO}" +fi + +cat "${SRCINFO}" diff --git a/bin/harvest-commit-times b/bin/harvest-commit-times index a978b41..9c6b0eb 100755 --- a/bin/harvest-commit-times +++ b/bin/harvest-commit-times @@ -12,13 +12,15 @@ usage() { >&2 echo ' sources from git and put them into the database' >&2 echo '' >&2 echo 'possible options:' + >&2 echo ' -f|--force: Do not abort on error.' >&2 echo ' -h|--help: Show this help and exit.' >&2 echo ' -w|--wait: If necessary, wait for lock blocking.' [ -z "$1" ] && exit 1 || exit "$1" } eval set -- "$( - getopt -o hw \ + getopt -o fhw \ + --long force \ --long help \ --long wait \ -n "$(basename "$0")" -- "$@" || \ @@ -26,9 +28,13 @@ eval set -- "$( )" block_flag='-n' +force=false; while true; do case "$1" in + -f|--force) + force=true + ;; -h|--help) usage 0 ;; @@ -76,9 +82,9 @@ trap 'rm "${tmp_file}"' EXIT if ! ${i_am_the_master}; then tmp_remote_file=$( - ssh buildmaster "mktemp 'tmp.harvest-commit-times.remotely.XXXXXXXXXX' --tmpdir" + ssh -o PasswordAuthentication=No buildmaster "mktemp 'tmp.harvest-commit-times.remotely.XXXXXXXXXX' --tmpdir" ) - trap 'rm "${tmp_file}"; ssh buildmaster rm "${tmp_remote_file}"' EXIT + trap 'rm "${tmp_file}"; ssh -o PasswordAuthentication=No buildmaster rm "${tmp_remote_file}"' EXIT fi while true; do @@ -91,43 +97,44 @@ while true; do printf '`package_sources`.`git_revision`,' printf '`package_sources`.`mod_git_revision`,' printf '`upstream_repositories`.`name`,' - printf '`git_repositories`.`name`' + printf 'IF(`build_assignments`.`architecture`=%s,"any","x86_64")' "${architecture_ids__any}" printf ' FROM `package_sources`' mysql_join_package_sources_upstream_repositories - mysql_join_upstream_repositories_git_repositories + mysql_join_package_sources_build_assignments printf ' WHERE `package_sources`.`commit_time`="0000-00-00 00:00:00"' printf ' AND `package_sources`.`uses_upstream`' - if ! ${i_am_the_master}; then - printf ' ORDER BY RAND()' - fi + printf ' ORDER BY RAND()' printf ' LIMIT 10' - } | \ - mysql_run_query 'unimportant' | \ - sponge | \ - while read -r id pkgbase git_revision mod_git_revision repository git_repository; do - eval 'git_directory="${repo_paths__'"${git_repository}"'}"' - find_pkgbuilds "${pkgbase}" "${repository}" "${git_repository}" "${git_revision}" "${mod_git_revision}" - commit_time=$( - # shellcheck disable=SC2154 - git -C "${git_directory}" log -n 1 --pretty=format:%ct "${git_revision}" -- "${PKGBUILD}" - ) - if [ -n "${commit_time}" ]; then - printf '%s\t%s\n' \ - "${id}" \ - "${commit_time}" - else - >&2 printf 'Package source %s is not available in git.\n' \ - "${id}" + } \ + | mysql_run_query 'unimportant' \ + | sponge \ + | while read -r id pkgbase git_revision mod_git_revision repository architecture; do + commit_time=$( + # shellcheck disable=SC2154 + git -C "${repo_paths__state}" log -n 1 --pretty=format:%ct HEAD -- "${repository}-${architecture}/${pkgbase}" + ) + if [ -n "${commit_time}" ]; then + printf '%s\t%s\n' \ + "${id}" \ + "${commit_time}" + else + >&2 printf 'Package source %s is not available in git:\n' \ + "${id}" + >&2 printf '%s ' \ + "${pkgbase}" "${git_revision}" "${mod_git_revision}" "${repository}" "${architecture}" + >&2 printf '\n' + if ! ${force}; then exit 2 fi - done > \ - "${tmp_file}" + fi + done > \ + "${tmp_file}" >&2 printf '.' if [ -s "${tmp_file}" ]; then if ! ${i_am_the_master}; then - ssh buildmaster 'cat > "'"${tmp_remote_file}"'"' < \ + ssh -o PasswordAuthentication=No buildmaster 'cat > "'"${tmp_remote_file}"'"' < \ "${tmp_file}" fi # shellcheck disable=SC2016 @@ -149,7 +156,7 @@ while true; do if ${i_am_the_master}; then mysql_run_query 'unimportant' else - ssh buildmaster 'mysql buildmaster -N --raw --batch' + ssh -o PasswordAuthentication=No buildmaster 'mysql buildmaster -N --raw --batch' fi else >&2 printf '\n' diff --git a/bin/ii-watch b/bin/ii-watch index ae008c4..6ae30c0 100755 --- a/bin/ii-watch +++ b/bin/ii-watch @@ -18,7 +18,7 @@ while pgrep -x 'ii' >/dev/null && \ # this avoids missing modifications during our last execution if [ "$(date +%s)" -ge ${next_connection_check} ]; then # request this more often on startup - if [ ${last_seen} -ne 0 ]; then + if [ "${last_seen}" -ne 0 ]; then next_connection_check=$(( $(date +%s) + 60*5 )) diff --git a/bin/interpret-mail b/bin/interpret-mail index 2580c00..06eb4f0 100755 --- a/bin/interpret-mail +++ b/bin/interpret-mail @@ -310,7 +310,7 @@ fi if [ -s "${tmp_dir}/schedule" ]; then # shellcheck disable=SC2046 - "${base_dir}/bin/seed-build-list" --wait $( + "${base_dir}/bin/schedule-for-rebuild" --wait $( tr '[:space:]' '\n' < \ "${tmp_dir}/schedule" | \ grep -vxF '' | \ diff --git a/bin/local-build-package b/bin/local-build-package deleted file mode 100755 index fd4fdab..0000000 --- a/bin/local-build-package +++ /dev/null @@ -1,220 +0,0 @@ -#!/bin/sh - -# build one package to test if modifications are ok (before opening a pull -# request in https://github.com/archlinux32/packages) -# package is built directly on a i486/i686/pentium4 host without any chroots - -# shellcheck source=../lib/load-configuration -. "${0%/*}/../lib/load-configuration" - -# TODO: remove hard-coded package suffixes - -# shellcheck disable=SC2016 -usage() { - >&2 echo '' - >&2 echo 'test-build-package <repository> <package>: build package for testing' - >&2 echo '' - >&2 echo 'possible options:' - >&2 echo ' -h|--help: Show this help and exit.' - >&2 echo ' -a|--arch "i486" | "i686" | "pentium4"' - >&2 echo ' Build locally for this architecture.' - >&2 echo ' -b|--bootstrap' - >&2 echo ' Publishes signed package to the bootstrap directory.' - >&2 echo ' -H|--host <user>@<host>: host and user for bootstrapping' - >&2 echo ' -D|--dir <dir>: bootstrapping directory' - >&2 echo ' $arch and $repo are attached to this path.' - >&2 echo ' -p|--port <SSH port>: the SSH port for bootstrapping.' - >&2 echo ' -n|--nocheck:' - >&2 echo ' Normally execute all checks and do all tests.' - >&2 echo ' This switches off check() and all integrity checks.' - >&2 echo ' -t|--tmpdir <dir>:' - >&2 echo ' Specify tmpdir instead of using a random one, usually with -N' - >&2 echo ' -N|--nobuild:' - >&2 echo ' Assume packages have already been built, just upload them.' - >&2 echo ' -s|--signkey:' - >&2 echo ' Use explicit sign key instead of the one from the configuration.' - [ -z "$1" ] && exit 1 || exit "$1" -} - -eval set -- "$( - getopt -o a:bhnNp:H:D:t:s: \ - --long arch \ - --long bootstrap \ - --long nocheck \ - --long nobuild \ - --long port \ - --long dir \ - --long host \ - --long tmpdir \ - --long signkey \ - --long help \ - -n "$(basename "$0")" -- "$@" || \ - echo usage -)" - -arch=$(uname -m) -bootstrap=false -nocheck=false -nobuild=false -bootstrap_port=22 -bootstrap_host='' -bootstrap_dir='' -tmp_dir=$(mktemp -d "${work_dir}/tmp.XXXXXX") -signkey="${package_key}" -while true -do - case "$1" in - -a|--arch) - shift - arch="$1" - ;; - -b|--bootstrap) - bootstrap=true - ;; - -H|--host) - shift - bootstrap_host="$1" - ;; - -D|--dir) - shift - bootstrap_dir="$1" - ;; - -n|--nocheck) - nocheck=true - ;; - -N|--nobuild) - nobuild=true - ;; - -p|--port) - shift - bootstrap_port="$1" - ;; - -t|--tmpdir) - shift - tmp_dir="$1" - ;; - -s|--signkey) - shift - signkey="$1" - ;; - -h|--help) - usage 0 - ;; - --) - shift - break - ;; - *) - >&2 echo 'Whoops, forgot to implement option "'"$1"'" internally.' - exit 42 - ;; - esac - shift -done - -if [ $# -ne 2 ]; then - >&2 echo 'Too few or too many arguments. Expecting exactly a repository and a package name of the package to test.' - usage -fi - -if [ "$arch" != "any" ] && [ "$arch" != "i486" ] && [ "$arch" != "i686" ] && [ "$arch" != "pentium4" ]; then - >&2 echo "Illegal architecture '$arch', epxecting one of 'any', 'i486', 'i686' or 'pentium4'." - usage -fi - -if ${bootstrap}; then - if [ -z "${bootstrap_host}" ]; then - >&2 echo -- '-b option requires a bootstrapping host to be set with -H' - usage - fi - if [ -z "${bootstrap_dir}" ]; then - >&2 echo -- '-b option requires a bootstrapping directory to be set with -d' - usage - fi -fi - -if ! ${nobuild}; then - # Update git repositories (official packages, community packages and the repository of package customizations). - for repo_name in ${repo_names}; do - eval repo_path='"${repo_paths__'"${repo_name}"'}"' - git -C "${repo_path}" pull - done - - repository=$1 - package=$2 - case $repository in - core) - repo_path='../work/repos/packages' - ;; - extra) - repo_path='../work/repos/packages' - ;; - community) - repo_path='../work/repos/community' - ;; - *) - >&2 echo 'Repository is either "core", "extra" or "community"' - usage - esac - git_revision=$(git -C "${repo_path}" rev-parse HEAD) - - mod_git_revision=$(git -C "${repo_paths__archlinux32}" stash create) - if [ -z "${mod_git_revision}" ]; then - mod_git_revision=$(git -C "${repo_paths__archlinux32}" rev-parse HEAD) - fi - build_command="staging-${arch}-build" - parameters='' - if ${nocheck}; then - parameters='-- -- --nocheck' - fi - - git_repo=$(find_repository_with_commit "${git_revision}") - find_pkgbuilds "${package}" "${repository}" "${git_repo}" "${git_revision}" "${mod_git_revision}" - - extract_source_directory "${git_repo}" "${git_revision}" "${mod_git_revision}" "${tmp_dir}" - - rm -f \ - ./*"-${arch}.pkg.tar.xz" ./*"-${arch}.pkg.tar.xz.sig" \ - ./*"-${arch}.pkg.tar.zst" ./*"-${arch}.pkg.tar.zst.sig" - - cd "${tmp_dir}" || exit 1 - - makepkg_parameters='' - if ${nocheck}; then - makepkg_parameters='--skippgpcheck' - fi - makepkg ${makepkg_parameters} --verifysource - - # shellcheck disable=SC2086 - "${build_command}" ${parameters} -else - cd "${tmp_dir}" || exit 1 -fi - -if ${bootstrap}; then - rm -f \ - ./*"-${arch}.pkg.tar.xz.sig" \ - ./*"-${arch}.pkg.tar.zst.sig" - - find . -maxdepth 1 -type f -name "*${arch}.pkg.tar.zst" \ - -execdir gpg --local-user="${signkey}" --detach-sign '{}' \; - - case "$repository" in - core|extra) - staging_repo="staging" - ;; - community) - staging_repo="community-staging" - ;; - *) - staging_repo="staging" - ;; - esac - - scp -P "${bootstrap_port}" -rC "${tmp_dir}/"*"-${arch}.pkg.tar.zst" "${tmp_dir}/"*"-${arch}.pkg.tar.zst.sig" "${bootstrap_host}:${bootstrap_dir}/${staging_repo}/." - ssh -p "${bootstrap_port}" "${bootstrap_host}" bash -l -c "'cd ${bootstrap_dir}/${staging_repo} && repo-add -n bootstrap-${staging_repo}.db.tar.gz *-${arch}.pkg.tar.zst'" -fi - -# do not delete build reports, why might actually to want to have a look for things -# like checksums, logfiles, etc. -#recursively_umount_and_rm "${tmp_dir}" diff --git a/bin/manage-slaves b/bin/manage-slaves index cddda84..fa1413d 100755 --- a/bin/manage-slaves +++ b/bin/manage-slaves @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # shellcheck source=../lib/load-configuration . "${0%/*}/../lib/load-configuration" @@ -9,7 +9,8 @@ usage() { >&2 echo 'manage-slaves $action [parameters]: manage the list of build slaves' >&2 echo '' >&2 echo 'possible actions:' - >&2 echo ' add $name $owner $ssh-key-fingerprint' + >&2 echo ' list' + >&2 echo ' add $name $owner $ssh-key-type $ssh-key-fingerprint' >&2 echo ' disable $name' >&2 echo ' enable $name' exit 1 @@ -33,10 +34,26 @@ if errors=$( fi case "$1" in + 'list') + # shellcheck disable=SC2016 + { + printf 'SELECT' + printf ' name, CASE WHEN access_allowed = 1 THEN "enabled" ELSE "disabled" END ' + printf ' name, CASE WHEN is_sane = 1 THEN "sane" ELSE "not sane" END ' + printf ' FROM build_slaves' + printf ';\n' + } | \ + mysql_run_query | \ + tr '\t' ' ' + ;; 'add') shift - if [ $# -ne 3 ]; then - >&2 printf '"add" expects 3 parameters, %s were given\n' "$#" + if [ $# -ne 4 ]; then + >&2 printf '"add" expects 4 parameters, %s were given\n' "$#" + usage + fi + if [[ $3 != ssh-* ]]; then + >&2 printf '"$ssh-key-type" must start with "ssh-", "%s" was given\n' "${3}" usage fi person_id=$( @@ -81,10 +98,11 @@ case "$1" in fi # shellcheck disable=SC2016 { - printf 'INSERT INTO `ssh_keys`(`owner`,`fingerprint`)' + printf 'INSERT INTO `ssh_keys`(`owner`,`fingerprint`,`type`)' printf ' VALUES' - printf ' (%s,"%s");\n' \ + printf ' (%s,"%s","%s");\n' \ "${person_id}" \ + "${4}" \ "${3}" printf 'INSERT INTO `build_slaves`(' printf '`name`,' @@ -96,10 +114,11 @@ case "$1" in "${1}" } | \ mysql_run_query - printf 'command="%s/bin/slave-build-connect %s" ssh-rsa %s %s@%s\n' \ + printf 'command="%s/bin/slave-build-connect %s" %s %s %s@%s\n' \ "${base_dir}" \ "${1}" \ "${3}" \ + "${4}" \ "${2}" \ "${1}" >> \ ~/".ssh/authorized_keys" @@ -122,7 +141,9 @@ case "$1" in printf '"command=\\\"%s/bin/slave-build-connect ",' \ "${base_dir}" printf '`build_slaves`.`name`,' - printf '"\\\" ssh-rsa ",' + printf '"\\\" ",' + printf '`ssh_keys`.`type`,' + printf '" ",' printf '`ssh_keys`.`fingerprint`,' printf '" ",' printf '`persons`.`name`,' diff --git a/bin/manual-fix b/bin/manual-fix new file mode 100755 index 0000000..f9cc7b9 --- /dev/null +++ b/bin/manual-fix @@ -0,0 +1,55 @@ +#!/bin/bash + +# shellcheck disable=SC2119,SC2120 + +# shellcheck source=../lib/load-configuration +. "${0%/*}/../lib/load-configuration" + +eval "$( + declare -F \ + | sed ' + s@^declare -f _fix_@unset _fix_@ + t + d + ' +)" + +_fix_package_on_build_and_deletion_list() { + # shellcheck disable=SC2016 + { + printf 'DELETE `bin_del`' + printf ' FROM `binary_packages` AS `bin_del`' + mysql_join_binary_packages_binary_packages_in_repositories 'bin_del' 'bir_del' + mysql_join_binary_packages_in_repositories_repositories 'bir_del' 'r_del' + printf ' AND `r_del`.`name`="deletion-list"' + printf ' JOIN `binary_packages` AS `bin_keep`' + printf ' ON `bin_keep`.`pkgname`=`bin_del`.`pkgname`' + printf ' AND `bin_del`.`architecture`=`bin_keep`.`architecture`' + printf ' AND `bin_del`.`id`!=`bin_keep`.`id`' + printf ' AND `bin_keep`.`sha512sum` IS NULL' + mysql_join_binary_packages_binary_packages_in_repositories 'bin_keep' 'bir_keep' + mysql_join_binary_packages_in_repositories_repositories 'bir_keep' 'r_keep' + printf ' AND `r_keep`.`name`="build-list"' + } \ + | mysql_run_query +} + +usage() { + # shellcheck disable=SC2016 + >&2 printf 'usage: %s $issue\n\n' "${0##*/}" + >&2 printf 'Manually fix an issue.\n\n' + >&2 printf 'fixable issues:\n' + declare -F \ + | sed ' + s@^declare -f _fix_@ @ + t + d + ' >&2 + exit 1 +} + +if [ $# -ne 1 ] || ! declare -f "_fix_$1" >/dev/null; then + usage +fi + +eval "_fix_$1" diff --git a/bin/nit-picker b/bin/nit-picker index 8dd0156..ed5b7da 100755 --- a/bin/nit-picker +++ b/bin/nit-picker @@ -281,9 +281,9 @@ while pgrep -x ii >/dev/null \ case "${action}" in 'commit') # check whether a given commit is present in the git repo git_repo="${parameters%% *}" - git_rev="${parameters#${git_repo} }" + git_rev="${parameters#"${git_repo}" }" git_head="${git_rev%% *}" - git_rev="${git_rev#${git_head} }" + git_rev="${git_rev#"${git_head}" }" # shellcheck disable=SC2016 eval "$( printf 'git_dir="${repo_paths__%s}"\n' \ @@ -881,6 +881,6 @@ done printf ';\n' fi } \ -| ifne ssh buildmaster 'mysql buildmaster +| ifne ssh -o PasswordAuthentication=No buildmaster 'mysql buildmaster rm -f "/tmp/add-those-dependencies" ' diff --git a/bin/opcode b/bin/opcode deleted file mode 100755 index 544c763..0000000 --- a/bin/opcode +++ /dev/null @@ -1,293 +0,0 @@ -#!/bin/bash -# -# Original see post in: -# -# https://superuser.com/questions/726395/how-to-check-if-a-binary-requires-sse4-or-avx-on-linux -# -# Searches disassembled code for specific instructions. -# -# Opcodes obtained from: https://github.com/Shirk/vim-gas/blob/master/syntax/gas.vim -# -# List of opcodes has been obtained using the following commands and making a few modifications: -# echo '#!/bin/bash' > Opcode_list -# wget -q -O- https://raw.githubusercontent.com/Shirk/vim-gas/master/syntax/gas.vim \ -# | grep -B1 -E 'syn keyword gasOpcode_|syn match gasOpcode' | \ -# sed -e '/^--$/d' -e 's/"-- Section:/\n#/g' \ -# -e 's/syn keyword gasOpcode_\([^\t]*\)*\(\t\)*\(.*\)/Opcode_\1="\${Opcode_\1} \3"/g' \ -# -e 's/Opcode_PENT_3DNOW/Opcode_ATHLON_3DNOW/g' -e 's/\\//g' \ -# -e 's/syn match gasOpcode_\([^\t]*\)*.*\/<\(.*\)>\//Opcode_\1="\${Opcode_\1} \2"/g' \ -# >> Opcode_list -# -# Modify file Opcode_list replacing all occurrences of: -# * Opcode_Base within the section "Tejas New Instructions (SSSE3)" with Opcode_SSSE3 -# * Opcode_Base within the section "Willamette MMX instructions (SSE2 SIMD Integer Instructions)" -# with Opcode_WILLAMETTE_Base -# * Remove all line in Opcode_ARM_THUMB -# return values - - -# return values -EXIT_FOUND=0 -EXIT_NOT_FOUND=1 -EXIT_USAGE=2 - -# settings -InstSet_Base="" -Recursive=false -Count_Matching=false -Leading_Separator='\s' -Trailing_Separator='(\s|$)' # $ matches end of line for non-parametric instructions like nop -Case_Insensitive=false -Invert=false -Verbose=false -Stop_After=0 -Line_Numbers=false -Leading_Context=0 -Trailing_Context=0 - -source "${0%/*}/../lib/opcode_list" # include opcodes from a separate file - -# GAS-specific opcodes (unofficial names) belonging to the x64 instruction set. -# They are generated by GNU tools (e.g. GDB, objdump) and specify a variant of ordinal opcodes like NOP and MOV. -# If you do not want these opcodes to be recognized by this script, comment out the following line. -Opcode_X64_GAS="nopw nopl movabs" - - -# instruction sets -InstSet_X86="8086_Base 186_Base 286_Base 386_Base 486_Base PENT_Base P6_Base KATMAI_Base WILLAMETTE_Base PENTM_Base" -InstSet_IA64="IA64_Base" -InstSet_X64="PRESCOTT_Base X64_Base X86_64_Base NEHALEM_Base X64_GAS" -InstSet_MMX="PENT_MMX KATMAI_MMX X64_MMX" -InstSet_MMX2="KATMAI_MMX2" -InstSet_3DNOW="ATHLON_3DNOW" -InstSet_SSE="KATMAI_SSE P6_SSE X64_SSE" -InstSet_SSE2="SSE2 X64_SSE2" -InstSet_SSE3="PRESCOTT_SSE3" -InstSet_SSSE3="SSSE3" -InstSet_VMX="VMX X64_VMX" -InstSet_SSE4_1="SSE41 X64_SSE41" -InstSet_SSE4_2="SSE42 X64_SSE42" -InstSet_SSE4A="AMD_SSE4A" -InstSet_SSE5="AMD_SSE5" -InstSet_FMA="FUTURE_FMA" -InstSet_AVX="SANDYBRIDGE_AVX" - -InstSetDep_X64="X86" -InstSetDep_MMX2="MMX" -InstSetDep_SSE2="SSE" -InstSetDep_SSE3="SSE2" -InstSetDep_SSSE3="SSE3" -InstSetDep_SSE4_1="SSSE3" -InstSetDep_SSE4_2="SSE4_1" -InstSetDep_SSE4A="SSE3" -InstSetDep_SSE5="FMA AVX" # FIXME not reliable - -InstSetList="X86 IA64 X64 MMX MMX2 3DNOW SSE SSE2 SSE3 SSSE3 VMX SSE4_1 SSE4_2 SSE4A SSE5 FMA AVX" - - -# architectures -Arch_8086="8086_Base" -Arch_186="186_Base" -Arch_286="286_Base" -Arch_386="386_Base" -Arch_486="486_Base" -Arch_Pentium="PENT_Base PENT_MMX" # Pentium = P5 architecture -Arch_Athlon="ATHLON_3DNOW" -Arch_Deschutes="P6_Base P6_SSE" # Pentium II -Arch_Katmai="KATMAI_Base KATMAI_MMX KATMAI_MMX2 KATMAI_SSE" # Pentium III -Arch_Willamette="WILLAMETTE_Base SSE2" # original Pentium IV (x86) -Arch_PentiumM="PENTM_Base" -Arch_Prescott="PRESCOTT_Base X64_Base X86_64_Base X64_SSE2 PRESCOTT_SSE3 VMX X64_VMX X64_GAS" # later Pentium IV (x64) with SSE3 (Willamette only implemented SSE2 instructions) and VT (VT-x, aka VMX) -Arch_P6="" -Arch_Barcelona="ATHLON_3DNOW AMD_SSE4A" -Arch_IA64="IA64_Base" # 64-bit Itanium RISC processor; incompatible with x64 architecture -Arch_Penryn="SSSE3 SSE41 X64_SSE41" # later (45nm) Core 2 with SSE4.1 -Arch_Nehalem="NEHALEM_Base SSE42 X64_SSE42" # Core i# -Arch_SandyBridge="SANDYBRIDGE_AVX" -Arch_Haswell="FUTURE_FMA" -Arch_Bulldozer="AMD_SSE5" - -ArchDep_8086="" -ArchDep_186="8086" -ArchDep_286="186" -ArchDep_386="286" -ArchDep_486="386" -ArchDep_Pentium="486" -ArchDep_Athlon="Pentium" # FIXME not reliable -ArchDep_Deschutes="Pentium" -ArchDep_Katmai="Deschutes" -ArchDep_Willamette="Katmai" -ArchDep_PentiumM="Willamette" # FIXME Pentium M is a Pentium III modification (with SSE2). Does it support also WILLAMETTE_Base instructions? -ArchDep_Prescott="Willamette" -ArchDep_P6="Prescott" # P6 started with Pentium Pro; FIXME Pentium Pro did not support MMX instructions (introduced again in Pentium II aka Deschutes) -ArchDep_Barcelona="Prescott" # FIXME not reliable -ArchDep_IA64="" -ArchDep_Penryn="P6" -ArchDep_Nehalem="Penryn" -ArchDep_SandyBridge="Nehalem" -ArchDep_Haswell="SandyBridge" -ArchDep_Bulldozer="Haswell" # FIXME not reliable - -ArchList="8086 186 286 386 486 Pentium Athlon Deschutes Katmai Willamette PentiumM Prescott P6 Barcelona IA64 Penryn Nehalem SandyBridge Haswell Bulldozer" - -usage() { - echo "Usage: $0 OPTIONS" - echo "" - echo " -r set instruction sets recursively according to dependency tree (must precede -a or -s)" - echo " -a set architecture" - echo " -s set instruction set" - echo " -L show list of available architectures" - echo " -l show list of available instruction sets" - echo " -i show base instruction sets of current instruction set (requires -a and/or -s)" - echo " -I show instructions in current instruction set (requires -a and/or -s)" - echo " -c print number of matching instructions instead of normal output" - echo " -f find instruction set of the following instruction (regex allowed)" - echo " -d set leading opcode separator (default '$Leading_Separator')" - echo " -D set trailing opcode separator (default '$Trailing_Separator')" - echo " -C case-insensitive" - echo " -v invert the sense of matching" - echo " -V print all lines, not just the highlighted" - echo " -m stop searching after n matched instructions" - echo " -n print line numbers within the original input" - echo " -B print n instructions of leading context" - echo " -A print n instructions of trailing context" - echo " -h print this help" - echo - echo "Multiple architectures and instruction sets can be used." - echo - echo "Typical usage is:" - echo " objdump -M intel -d FILE | $0 OPTIONS" - echo " objdump -M intel -d FILE | $0 -s SSE2 -s SSE3 -V Highlight SSE2 and SSE3 within FILE." - echo " objdump -M intel -d FILE | tail -n +8 | $0 -r -a Haswell -v -m 1 Find first unknown instruction." - echo " $0 -C -f ADDSD Find which instruction set an opcode belongs to." - echo " $0 -f .*fma.* Find all matching instructions and their instruction sets." - echo - echo "The script uses Intel opcode syntax. When used in conjunction with objdump, \`-M intel' must be set in order to prevent opcode translation using AT&T syntax." - echo - echo "BE AWARE THAT THE LIST OF KNOWN INSTRUCTIONS OR INSTRUCTIONS SUPPORTED BY PARTICULAR ARCHITECTURES (ESPECIALLY AMD'S) IS ONLY TENTATIVE AND MAY CONTAIN MISTAKES!" - kill -TRAP $TOP_PID -} - -list_contains() { # Returns 0 if $2 is in array $1, 1 otherwise. - local e - for e in $1; do - [ "$e" = "$2" ] && return 0 - done - return 1 -} - -build_instruction_set() { # $1 = enum { Arch, InstSet }, $2 = architecture or instruction set as obtained using -L or -l, $3 = "architecture"/"instruction set" to be used in error message - local e - list_contains "`eval echo \\\$${1}List`" "$2" || (echo "$2 is not a valid $3."; usage) # Test if the architecture/instruction set is valid. - if [ -n "`eval echo \\\$${1}_${2}`" ]; then # Add the instruction set(s) if any. - for e in `eval echo \\\$${1}_${2}`; do # Skip duplicates. - list_contains "$InstSet_Base" $e || InstSet_Base="$e $InstSet_Base" - done - fi - if [ $Recursive = true ]; then - for a in `eval echo \\\$${1}Dep_$2`; do - build_instruction_set $1 $a "$3" - done - fi - InstSet_Base="`echo $InstSet_Base | sed 's/$ *//'`" # Remove trailing space. -} - -trap "exit $EXIT_USAGE" TRAP # Allow usage() function to abort script execution. -export TOP_PID=$$ # PID of executing process. - -# Parse command line arguments. -while getopts ":ra:s:LliIcf:Fd:D:CvVm:nB:A:h" o; do - case $o in - r) Recursive=true ;; - a) build_instruction_set Arch "$OPTARG" "architecture" ;; - s) build_instruction_set InstSet "$OPTARG" "instruction set" ;; - L) echo $ArchList; exit $EXIT_USAGE ;; - l) echo $InstSetList; exit $EXIT_USAGE ;; - i) - if [ -n "$InstSet_Base" ]; then - echo $InstSet_Base - exit $EXIT_USAGE - else - echo -e "No instruction set or architecture set.\n" - usage - fi - ;; - I) - if [ -n "$InstSet_Base" ]; then - for s in $InstSet_Base; do - echo -ne "\e[31;1m$s:\e[0m " - eval echo "\$Opcode_$s" - done - exit $EXIT_USAGE - else - echo -e "No instruction set or architecture set.\n" - usage - fi - ;; - c) Count_Matching=true ;; - f) - # Unlike architectures, instruction sets are disjoint. - Found=false - for s in $InstSetList; do - for b in `eval echo \\\$InstSet_$s`; do - Found_In_Base=false - for i in `eval echo \\\$Opcode_$b`; do - if [[ "$i" =~ ^$OPTARG$ ]]; then - $Found_In_Base || echo -ne "Instruction set \e[33;1m$s\e[0m (base instruction set \e[32;1m$b\e[0m):" - echo -ne " \e[31;1m$i\e[0m" - Found_In_Base=true - Found=true - fi - done - $Found_In_Base && echo "" - done - done - if [ $Found = false ]; then - echo -e "Operation code \e[31;1m$OPTARG\e[0m has not been found in the database of known instructions." \ - "Perhaps it is translated using other than Intel syntax. If obtained from objdump, check if the \`-M intel' flag is set." \ - "Be aware that the search is case sensitive by default (you may use the -C flag, otherwise only lower case opcodes are accepted)." - exit $EXIT_NOT_FOUND - else - exit $EXIT_FOUND - fi - ;; - d) Leading_Separator="$OPTARG" ;; - D) Trailing_Separator="$OPTARG" ;; - C) Case_Insensitive=true ;; - v) Invert=true ;; - V) Verbose=true ;; - m) Stop_After=$OPTARG ;; - n) Line_Numbers=true ;; - B) Leading_Context=$OPTARG ;; - A) Trailing_Context=$OPTARG ;; - h) usage ;; - \?) - echo -e "Unknown option: -$OPTARG\n" - usage - ;; - esac -done -shift $((OPTIND-1)) -[ -n "$1" ] && echo -e "Unknown command line parameter: $1\n" && usage -[ -z "$InstSet_Base" ] && usage - -# Create list of grep parameters. -Grep_Params="--color=auto -B $Leading_Context -A $Trailing_Context" -[ $Count_Matching = true ] && Grep_Params="$Grep_Params -c" -[ $Case_Insensitive = true ] && Grep_Params="$Grep_Params -i" -[ $Invert = true ] && Grep_Params="$Grep_Params -v" -[ $Stop_After -gt 0 ] && Grep_Params="$Grep_Params -m $Stop_After" -[ $Line_Numbers = true ] && Grep_Params="$Grep_Params -n" - -# Build regular expression for use in grep. -RegEx="" -for s in $InstSet_Base; do - eval RegEx=\"$RegEx \$Opcode_$s\" -done -# Add leading and trailing opcode separators to prevent false positives. -RegEx="$Leading_Separator`echo $RegEx | sed "s/ /$(echo "$Trailing_Separator"|sed 's/[\/&]/\\\&/g')|$(echo "$Leading_Separator"|sed 's/[\/&]/\\\&/g')/g"`$Trailing_Separator" - -[ $Verbose = true -a $Count_Matching = false ] && RegEx="$RegEx|\$" - -# The actual search. -grep $Grep_Params -E "$RegEx" && exit $EXIT_FOUND || exit $EXIT_NOT_FOUND diff --git a/bin/ping-to-master b/bin/ping-to-master index b1539cc..b7b1eee 100755 --- a/bin/ping-to-master +++ b/bin/ping-to-master @@ -14,8 +14,9 @@ parent_pid="$1" parent_tmp_dir="$2" +lock_file="$3" -exec 9> "${work_dir}/ping-build-master.lock" +exec 9> "${lock_file}" while kill -0 "${parent_pid}" && \ [ -f "${parent_tmp_dir}/.ping-build-master" ]; do @@ -27,7 +28,7 @@ while kill -0 "${parent_pid}" && \ -name '*.build-log' \ -exec wc -l {} \; | \ sed 's, .*/, ,' | \ - ssh \ + ssh -o PasswordAuthentication=No \ -i "${master_build_server_identity}" \ -p "${master_build_server_port}" \ "${master_build_server_user}@${master_build_server}" \ diff --git a/bin/prioritize-build-list b/bin/prioritize-build-list index 04a9d4f..2391c1f 100755 --- a/bin/prioritize-build-list +++ b/bin/prioritize-build-list @@ -109,7 +109,7 @@ updated_rows=$( if ${dependencies}; then new_updated_rows=1 updated_rows=$((updated_rows-1)) - while [ ${new_updated_rows} -ne 0 ]; do + while [ "${new_updated_rows}" -ne 0 ]; do updated_rows=$((updated_rows+new_updated_rows)) new_updated_rows=$( # shellcheck disable=SC2016 diff --git a/bin/return-assignment b/bin/return-assignment index a0cbbbb..47e28f0 100755 --- a/bin/return-assignment +++ b/bin/return-assignment @@ -142,25 +142,25 @@ if [ "$6" = 'ERROR' ]; then exit 2 fi build_assignment_architecture="${infos##* }" - infos="${infos% ${build_assignment_architecture}}" + infos="${infos% "${build_assignment_architecture}"}" pkgrel="${infos##* }" - infos="${infos% ${pkgrel}}" + infos="${infos% "${pkgrel}"}" epoch="${infos##* }" - infos="${infos% ${epoch}}" + infos="${infos% "${epoch}"}" pkgver="${infos##* }" - infos="${infos% ${pkgver}}" + infos="${infos% "${pkgver}"}" pkgver=$( printf '%s' "${pkgver}" \ | base64 -d ) upstream_flag_date="${infos##* }" - infos="${infos% ${upstream_flag_date}}" + infos="${infos% "${upstream_flag_date}"}" upstream_flag_date=$( printf '%s' "${upstream_flag_date}" \ | base64 -d ) was_broken_before="${infos##* }" - build_assignment_id="${infos% ${was_broken_before}}" + build_assignment_id="${infos% "${was_broken_before}"}" # save sent build logs saved_build_logs=$( @@ -498,13 +498,13 @@ if [ "$6" = 'ERROR' ]; then ' ) - # release lock on build-list - otherwise seed-build-list won't run + # release lock on build-list - otherwise schedule-for-rebuild won't run flock -u 9 rescheduled_packages=$( if [ -n "${haskell_rebuild_packages}" ]; then # shellcheck disable=SC2086 - "${base_dir}/bin/seed-build-list" ${haskell_rebuild_packages} | \ + "${base_dir}/bin/schedule-for-rebuild" ${haskell_rebuild_packages} | \ sed 's/ .*$//' fi ) @@ -747,7 +747,8 @@ signatures=$( if [ -z "$( printf '%s\n' "${signatures}" | \ cut -d' ' -f2 | \ - grep -x 'file\|TRUST_FULLY' | \ + grep -x 'file\|TRUST_\(FULLY\|ULTIMATE\)' | \ + sed 's@_ULTIMATE$@_FULLY@' | \ sort | \ uniq -c | \ awk '{print $1}' | \ @@ -759,6 +760,9 @@ if [ -z "$( irc_say "${operator}" printf '%s\n' "${signatures}" | \ irc_say "${operator}" 'copy' >&2 + find . -maxdepth 1 -regextype sed \ + -regex '.*\.pkg\.\('"${package_compression_suffix_regex}"'\)' \ + -exec cp {} {}.sig "${work_dir}/" \; exit 3 fi @@ -956,6 +960,32 @@ if [ -n "${errors}" ]; then exit 1 fi +some_architecture=$( + # shellcheck disable=SC2012 + ls \ + | sed ' + s/^.*-\([^-]\+\)\.pkg\.\('"${package_compression_suffix_regex}"'\)$/\1/ + t + d + ' \ + | sort -u \ + | sed ' + s/^any$/0 \0/ + t + s/^/1 \0/ + ' \ + | sort -k1n,1 \ + | tail -n1 \ + | cut -d' ' -f2 +) + +for build_log in *.build-log.gz; do + [ -f "${build_log}" ] || continue; + mv -n \ + "${build_log}" \ + "${build_log_directory}/success/$1.$2.$3.$4.${some_architecture}.${build_log##*/}" +done + join -1 2 -2 2 -o 1.1,1.2,2.1 "${tmp_dir}/package-ids" "${tmp_dir}/signing-keys" \ | sponge "${tmp_dir}/package-ids" diff --git a/bin/sanity-check b/bin/sanity-check index 60cb958..9682c68 100755 --- a/bin/sanity-check +++ b/bin/sanity-check @@ -46,29 +46,6 @@ eval set -- "$( block_flag='-n' silence=0 -# shellcheck disable=SC2016 -repos=$( - { - printf 'SELECT DISTINCT `repositories`.`name`' - printf ' FROM `repositories`' - printf ' WHERE `repositories`.`is_on_master_mirror`;\n' - } | \ - mysql_run_query -) -# shellcheck disable=SC2016 -archs=$( - { - printf 'SELECT DISTINCT `architectures`.`name`' - printf ' FROM `architectures`' - printf ' WHERE EXISTS (' - printf 'SELECT 1' - printf ' FROM `repositories`' - printf ' WHERE `repositories`.`architecture`=`architectures`.`id`' - printf ' AND `repositories`.`is_on_master_mirror`' - printf ');\n' - } | \ - mysql_run_query -) while true do @@ -104,6 +81,32 @@ if ! verbose_flock ${block_flag} 9; then exit fi +execute_all_intentions + +# shellcheck disable=SC2016 +repos=$( + { + printf 'SELECT DISTINCT `repositories`.`name`' + printf ' FROM `repositories`' + printf ' WHERE `repositories`.`is_on_master_mirror`;\n' + } | \ + mysql_run_query +) +# shellcheck disable=SC2016 +archs=$( + { + printf 'SELECT DISTINCT `architectures`.`name`' + printf ' FROM `architectures`' + printf ' WHERE EXISTS (' + printf 'SELECT 1' + printf ' FROM `repositories`' + printf ' WHERE `repositories`.`architecture`=`architectures`.`id`' + printf ' AND `repositories`.`is_on_master_mirror`' + printf ');\n' + } | \ + mysql_run_query +) + mysql_cleanup finish() { @@ -368,7 +371,8 @@ while [ $# -gt 0 ]; do ) || true if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then - printf '\nThe following packages in %s are missing a signature or vice versa:\n%s\n' \ + printf '\nThe following packages in %s/%s are missing a signature or vice versa:\n%s\n' \ + "${arch}" \ "${repo}" \ "${errors}" | \ tee -a "${tmp_dir}/messages" >&2 @@ -403,7 +407,8 @@ while [ $# -gt 0 ]; do ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then - printf '\nThe following packages in %s are missing from the database or vice versa:\n%s\n' \ + printf '\nThe following packages in %s/%s are missing from the database or vice versa:\n%s\n' \ + "${arch}" \ "${repo}" \ "${errors}" | \ tee -a "${tmp_dir}/messages" >&2 @@ -432,7 +437,8 @@ while [ $# -gt 0 ]; do ) if [ -n "${errors}" ]; then if [ ${silence} -le 1 ]; then - printf '\nThe following packages in %s are missing from the file-database or vice versa:\n%s\n' \ + printf '\nThe following packages in %s/%s are missing from the file-database or vice versa:\n%s\n' \ + "${arch}" \ "${repo}" \ "${errors}" | \ tee -a "${tmp_dir}/messages" >&2 @@ -523,9 +529,9 @@ while [ $# -gt 0 ]; do [ ! -s "${work_dir}/build-master-sanity" ]; then # shellcheck disable=SC2119 { - printf 'girls, my database is dirty again ...\n' - printf 'dirty! girls, my database - so dirty :-(\n' - printf 'girls, please have a look at my dirty database' + printf 'girls, Tasos, my database is dirty again ...\n' + printf 'dirty! girls, Tasos, my database - so dirty :-(\n' + printf 'girls, Tasos, please have a look at my dirty database\n' } | \ shuf -n1 | \ irc_say @@ -584,7 +590,9 @@ while [ $# -gt 0 ]; do printf '"command=\\\"%s/bin/slave-build-connect ",' \ "${base_dir}" printf '`build_slaves`.`name`,' - printf '"\\\" ssh-rsa ",' + printf '"\\\" ",' + printf '`ssh_keys`.`type`,' + printf '" ",' printf '`ssh_keys`.`fingerprint`' printf ')' printf ' FROM' diff --git a/bin/seed-build-list b/bin/schedule-for-rebuild index 3303416..6c9bfbd 100755 --- a/bin/seed-build-list +++ b/bin/schedule-for-rebuild @@ -2,12 +2,11 @@ # shellcheck disable=SC2119,SC2120 -# seed the build list from various sources +# schedule selected packages for a rebuild # # This uses the following schedule: -# - find scheduleworthy packages by pkgname/pkgbase (diff to mirror, -# broken dependencies, explicite regex) and their architecture -# - find pkgbases of those packages (ask upstream, if necessary) +# - find scheduleworthy packages by pkgname/pkgbase (broken +# dependencies, explicite regex) and their architecture # - remove all ignored packages (seed-ignore, explicitely ignored, # blacklist) # - run mysql_generate_package_metadata on each of them once (ignoring @@ -27,12 +26,12 @@ # shellcheck disable=SC2016 usage() { >&2 echo '' - >&2 echo 'seed-build-list [options]:' - >&2 echo ' seed the build list from different sources' + >&2 echo 'schedule-for-rebuild [options]:' + >&2 echo ' schedule selected packages for a rebuild' >&2 echo '' >&2 echo 'possible options:' >&2 echo ' -a|--auto:' - >&2 echo ' Automatically reschedule packages which have run-time' + >&2 echo ' Automatically schedule packages which have run-time' >&2 echo ' dependencies that are not available from any real' >&2 echo ' repository and which cannot be replaced by another,' >&2 echo ' less stable version of the same package.' @@ -41,41 +40,37 @@ usage() { >&2 echo ' -h|--help:' >&2 echo ' Show this help and exit.' >&2 echo ' -i|--ignore $pkgbase|$arch/$pkgbase:' - >&2 echo ' Do not update the given package (for the given $arch).' + >&2 echo ' Never schedule the given package (for the given $arch).' >&2 echo ' -j|--jostle' >&2 echo ' Give new build assignments the highest priority.' - >&2 echo ' -m|--mirror $url:' - >&2 echo ' Schedule all packages, that are newer (this includes' - >&2 echo ' packages currently unavailable on archlinux32) on the' - >&2 echo ' given x86_64 mirror - except packages on the blacklist' - >&2 echo ' or in conf/seed-ignore-packages.' >&2 echo ' -n|--no-action:' - >&2 echo ' Do not actually update build-list, just print it.' + >&2 echo ' Do not actually schedule anything, just print it.' >&2 echo ' -p|--package $pkg_regex:' - >&2 echo ' Reschedule packages with matching pkgname or pkgbase.' - >&2 echo ' Note, that these packages must be known to the database.' + >&2 echo ' Schedule packages with matching pkgname or pkgbase.' >&2 echo ' -s|--skip-arch $arch:' - >&2 echo ' Ignore packages, that are outdated on $arch only (-a|-m).' + >&2 echo ' Ignore packages, that are outdated on $arch only (-a).' + >&2 echo ' -t|--interactive' + >&2 echo ' Ask which of the matching packages to schedule for rebuild.' >&2 echo ' -w|--wait:' >&2 echo ' Wait for lock if necessary.' [ -z "$1" ] && exit 1 || exit "$1" } -tmp_dir=$(mktemp -d 'tmp.seed-build-list.XXXXXXXXXX' --tmpdir) +tmp_dir=$(mktemp -d 'tmp.schedule-for-rebuild.XXXXXXXXXX' --tmpdir) # shellcheck disable=SC2064 trap "rm -rf --one-file-system '${tmp_dir:?}'" EXIT eval set -- "$( - getopt -o afhi:jm:np:s:w \ + getopt -o afhi:jnp:s:tw \ --long auto \ --long force \ --long help \ --long ignore: \ --long jostle \ - --long mirror: \ --long no-action \ --long package: \ --long skip-arch: \ + --long interactive \ --long wait \ -n "$(basename "$0")" -- "$@" || \ echo usage @@ -85,6 +80,7 @@ auto=false ignore_mysql_generate_package_metadata_errors=false jostle=false update=true +interactive=false wait_for_lock='-n' while true @@ -112,11 +108,6 @@ do -j|--jostle) jostle=true ;; - -m|--mirror) - shift - printf '%s\n' "$1" >> \ - "${tmp_dir}/mirrors" - ;; -n|--no-action) update=false ;; @@ -130,6 +121,9 @@ do printf '%s\n' "$1" >> \ "${tmp_dir}/skip-archs" ;; + -t|--interactive) + interactive=true + ;; -w|--wait) wait_for_lock='' ;; @@ -150,8 +144,7 @@ if [ $# -ne 0 ]; then usage 1 fi -if [ ! -s "${tmp_dir}/mirrors" ] && \ - [ ! -s "${tmp_dir}/package-regexes" ] && \ +if [ ! -s "${tmp_dir}/package-regexes" ] && \ ! ${auto}; then # nothing to do >&2 echo 'No options given to do anything.' @@ -160,9 +153,8 @@ if [ ! -s "${tmp_dir}/mirrors" ] && \ fi if [ -s "${tmp_dir}/skip-archs" ] && \ - ! ${auto} && \ - [ ! -s "${tmp_dir}/mirrors" ]; then - >&2 echo 'Invalid combination of options: -s|--skip-archs requires -m|--mirror or -a|--auto.' + ! ${auto}; then + >&2 echo 'Invalid combination of options: -s|--skip-archs requires -a|--auto.' usage 2 exit 2 fi @@ -184,25 +176,12 @@ if ${update}; then fi fi -# shellcheck disable=SC2016 -repos=$( - { - printf 'SELECT DISTINCT `repositories`.`name`' - printf ' FROM `repositories`' - # shellcheck disable=SC2154 - printf ' WHERE `repositories`.`stability`=%s;\n' \ - "${repository_stability_ids__stable}" - } | \ - mysql_run_query - printf '%s\n' 'multilib' -) - -if [ -r "${base_dir}/conf/seed-ignore-packages" ]; then +if [ -r "${conf_dir}/seed-ignore-packages" ]; then sed ' s@/@\t@ t s/^/any\t/ - ' "${base_dir}/conf/seed-ignore-packages" >> \ + ' "${conf_dir}/seed-ignore-packages" >> \ "${tmp_dir}/ignore-packages" fi @@ -223,87 +202,8 @@ for list in 'ignore-packages' 'blacklist'; do | sponge "${tmp_dir}/${list}" done -# TODO: translate lib32-* packages instead of ignoring them for -m - touch "${tmp_dir}/skip-archs" -# harvest pkgnames from mirror delta -if [ -s "${tmp_dir}/mirrors" ]; then - { - # theirs - while read -r mirror; do - if [ -z "${mirror}" ]; then - continue - fi - for repo in ${repos}; do - curl -sS "${mirror}/${repo}/os/x86_64/${repo}.db.tar.gz" | \ - tar -Oxz --wildcards '*/desc' | \ - sed ' - /^%FILENAME%$/!d - N - s/^.*\n// - /^lib32-/d - s/^\(.*-\)x86_64\.pkg\.tar\.\(xz\|zst\)$/'"$( - # shellcheck disable=SC2086,SC2154 - printf '%s\n' ${architectures} \ - | grep -vxF 'any' \ - | grep -vxFf "${tmp_dir}/skip-archs" \ - | sed ' - s/^.*$/\\1\0/ - ' \ - | sed ' - :a - $! N - $! ba - s/\n/\\n/g - ' - )"'/ - s/^\(.*-any\)\.pkg\.tar\.\(xz\|zst\)$/\1/ - ' | \ - sed ' - s/^\(.*\)-\([^-]\+-[^-]\+\)-\([^-]\+\)$/theirs \2 \3 \1/ - ' - done - done < \ - "${tmp_dir}/mirrors" - # ours - # shellcheck disable=SC2016 - { - printf 'SELECT ' - mysql_package_name_query - printf ' FROM `binary_packages`' - mysql_join_binary_packages_architectures - printf ' LEFT' - mysql_join_binary_packages_compressions - mysql_join_binary_packages_binary_packages_in_repositories - mysql_join_binary_packages_in_repositories_repositories - printf ' WHERE `repositories`.`is_on_master_mirror`' - printf ' OR `repositories`.`name`="build-list"' - } | \ - mysql_run_query | \ - sed ' - s/^\(.*\)-\([^-]\+-[^-.]\+\)\(\.[^-.]\+\)\?-\([^-]\+\)\.pkg\.tar\.\(xz\|zst\)$/ours \2 \4 \1/ - s/^\(.* \)any\( \S\+\)$/\0\n\1i486\2\n\1i686\2\n\1pentium4\2/ - ' - } | \ - expand_version 2 | \ - sort -k3,4 -k2Vr,2 -k1,1 | \ - shrink_version 2 | \ - uniq -f2 | \ - sed -n ' - s/^theirs \(\S\+ \)// - T - p - ' | \ - if [ -r "${tmp_dir}/ignore-packages" ]; then - grep -vxFf "${tmp_dir}/ignore-packages" - else - cat - fi | \ - sort -u >> \ - "${tmp_dir}/pkgnames" -fi - # harvest from the package-regexes if [ -s "${tmp_dir}/package-regexes" ]; then # shellcheck disable=SC2016 @@ -312,77 +212,79 @@ if [ -s "${tmp_dir}/package-regexes" ]; then printf 'LOAD DATA LOCAL INFILE "%s" INTO TABLE `names` (`name`);\n' \ "${tmp_dir}/package-regexes" - printf 'SELECT DISTINCT "pkgbase",`package_sources`.`pkgbase`,`upstream_repositories`.`name`' + printf 'SELECT DISTINCT ' + printf '"any",' + printf '`package_sources`.`pkgbase`,' + printf 'IF(' + printf '`package_sources`.`uses_upstream`,' + printf '`package_sources`.`git_revision`,' + printf '"0000000000000000000000000000000000000000"' + printf '),' + printf 'IF(' + printf '`package_sources`.`uses_modification`,' + printf '`package_sources`.`mod_git_revision`,' + printf '"0000000000000000000000000000000000000000"' + printf '),' + printf '`upstream_repositories`.`name`' printf ' FROM `names`' printf ' JOIN `package_sources`' printf ' ON `package_sources`.`pkgbase` REGEXP `names`.`name`' mysql_join_package_sources_upstream_repositories printf ';\n' - printf 'SELECT DISTINCT "pkgname",`binary_packages`.`pkgname`' - printf ' FROM `names`' - printf ' JOIN `binary_packages`' - printf ' ON `binary_packages`.`pkgname` REGEXP `names`.`name`;\n' + printf 'SELECT DISTINCT ' + printf '"any",' + printf '`package_sources`.`pkgbase`,' + printf 'IF(' + printf '`package_sources`.`uses_upstream`,' + printf '`package_sources`.`git_revision`,' + printf '"0000000000000000000000000000000000000000"' + printf '),' + printf 'IF(' + printf '`package_sources`.`uses_modification`,' + printf '`package_sources`.`mod_git_revision`,' + printf '"0000000000000000000000000000000000000000"' + printf '),' + printf '`upstream_repositories`.`name`' + printf ' FROM `binary_packages`' + mysql_join_binary_packages_build_assignments + mysql_join_build_assignments_package_sources + mysql_join_package_sources_upstream_repositories + printf ' JOIN `names`' + printf ' ON `binary_packages`.`pkgname` REGEXP `names`.`name`' + printf ' OR `package_sources`.`pkgbase` REGEXP `names`.`name`' + printf ' LEFT JOIN `versions`' + printf ' ON `versions`.`epoch`=`binary_packages`.`epoch`' + printf ' AND `versions`.`version`=`binary_packages`.`pkgver`' + printf ' WHERE NOT EXISTS (' + printf 'SELECT 1' + printf ' FROM `binary_packages` AS `newer_bp`' + printf ' JOIN `versions` AS `newer_v`' + printf ' ON `newer_v`.`epoch`=`newer_bp`.`epoch`' + printf ' AND `newer_v`.`version`=`newer_bp`.`pkgver`' + printf ' WHERE (`newer_v`.`order`>`versions`.`order`' + printf ' OR (' + printf '`newer_v`.`order`=`versions`.`order`' + printf ' AND `newer_bp`.`pkgrel`>`binary_packages`.`pkgrel`' + # sub_pkgrel does not need to be compared, as it is only + # relevant for binary_packages with the same build_assignment + printf ')' + printf ')' + printf ' AND `binary_packages`.`%s`=`newer_bp`.`%s`' \ + 'pkgname' 'pkgname' \ + 'architecture' 'architecture' + printf ');\n' } | \ mysql_run_query | \ tr '\t' ' ' | \ - sed -n ' - /^pkgbase / { - s/^\S\+ /any / - w /dev/stdout - d - } - /^pkgname / { - s/^\S\+ /any / - w /dev/stderr - d - } - ' \ - >>"${tmp_dir}/pkgbases" \ - 2>>"${tmp_dir}/pkgnames" + tac | awk '!seen[$0]++' | tac \ + >>"${tmp_dir}/pkgbases" fi -# shellcheck disable=SC2016 -{ - # create pkgbases to given pkgnames - if [ -s "${tmp_dir}/pkgnames" ]; then - printf 'CREATE TEMPORARY TABLE `pkgnames` (' - printf '`architecture` VARCHAR(16),' - printf '`pkgname` VARCHAR(64),' - printf 'UNIQUE KEY `content`(`architecture`,`pkgname`)' - printf ');\n' - printf 'LOAD DATA LOCAL INFILE "%s" INTO TABLE `pkgnames` COLUMNS TERMINATED BY " " (`architecture`,`pkgname`);\n' \ - "${tmp_dir}/pkgnames" - - printf 'SELECT DISTINCT' - printf ' "pkgbase",' - printf '`pkgnames`.`architecture`,' - printf '`package_sources`.`pkgbase`,' - printf '`upstream_repositories`.`name`' - printf ' FROM `pkgnames`' - printf ' JOIN `binary_packages`' - printf ' ON `binary_packages`.`pkgname`=`pkgnames`.`pkgname`' - mysql_join_binary_packages_build_assignments - mysql_join_build_assignments_package_sources - mysql_join_package_sources_upstream_repositories - printf ';\n' - - printf 'SELECT DISTINCT' - printf ' "pkgname",' - printf '`pkgnames`.`architecture`,' - printf '`pkgnames`.`pkgname`' - printf ' FROM `package_sources`' - mysql_join_package_sources_upstream_repositories - mysql_join_package_sources_build_assignments - mysql_join_build_assignments_binary_packages - printf ' RIGHT JOIN `pkgnames`' - printf ' ON `pkgnames`.`pkgname`=`binary_packages`.`pkgname`' - printf ' WHERE `package_sources`.`pkgbase` IS NULL;\n' - - printf 'DROP TEMPORARY TABLE `pkgnames`;\n' - fi - # auto-detect pkgbases - if ${auto}; then +# auto-detect pkgbases +if ${auto}; then + # shellcheck disable=SC2016 + { printf 'CREATE TEMPORARY TABLE `relevant_archs`(`id` SMALLINT, PRIMARY KEY `id`(`id`));\n' printf 'INSERT INTO `relevant_archs`(`id`)' printf ' SELECT `architectures`.`id`' @@ -485,7 +387,20 @@ fi "${tmp_dir}/ignore-packages" fi - printf 'SELECT DISTINCT "pkgbase",`ba_a`.`name`,`package_sources`.`pkgbase`,`upstream_repositories`.`name`' + printf 'SELECT DISTINCT ' + printf '`ba_a`.`name`,' + printf '`package_sources`.`pkgbase`,' + printf 'IF(' + printf '`package_sources`.`uses_upstream`,' + printf '`package_sources`.`git_revision`,' + printf '"0000000000000000000000000000000000000000"' + printf '),' + printf 'IF(' + printf '`package_sources`.`uses_modification`,' + printf '`package_sources`.`mod_git_revision`,' + printf '"0000000000000000000000000000000000000000"' + printf '),' + printf '`upstream_repositories`.`name`' printf ' FROM `least_stable_bp`' printf ' JOIN `binary_packages`' printf ' ON `least_stable_bp`.`id`=`binary_packages`.`id`' @@ -547,133 +462,48 @@ fi printf 'DROP TEMPORARY TABLE `least_stable_bp%s`;\n' \ '' '_copy' printf 'DROP TEMPORARY TABLE `ignore_packages`;\n' - fi -} | \ - mysql_run_query | \ - tr '\t' ' ' | \ - sed -n ' - /^pkgbase / { - s/^\S\+ // - w /dev/stderr - d - } - /^pkgname / { - s/^\S\+ // - w /dev/stdout - d - } - ' \ - 2>>"${tmp_dir}/pkgbases" \ - | sponge "${tmp_dir}/pkgnames" - -if [ ! -s "${tmp_dir}/pkgbases" ] && \ - [ ! -s "${tmp_dir}/pkgnames" ]; then + } \ + | mysql_run_query \ + | tr '\t' ' ' \ + | tac | awk '!seen[$0]++' | tac \ + >>"${tmp_dir}/pkgbases" +fi + +if [ ! -s "${tmp_dir}/pkgbases" ]; then >&2 echo 'No packages matched.' exit fi -for s in "${tmp_dir}/pkgbases" "${tmp_dir}/pkgnames"; do - if [ -s "${s}" ]; then - sort -u "${s}" | \ - sponge "${s}" - fi -done +tac "${tmp_dir}/pkgbases" | awk '!seen[$0]++' | tac \ +| sponge "${tmp_dir}/pkgbases" -# pkgnames -> pkgbases (with help from upstream) -if [ -s "${tmp_dir}/pkgnames" ]; then - while read -r architecture pkgname; do - content=$( - curl -Ss 'https://www.archlinux.org/packages/search/json/?name='"${pkgname}" | \ - tr ',' '\n' - ) - repo=$( - printf '%s\n' "${content}" | \ - sed -n ' - s/^\s*"repo"\s*:\s*"// - T - s/".*$// - T - p - ' - ) - pkgbase=$( - printf '%s\n' "${content}" | \ - sed -n ' - s/^\s*"pkgbase"\s*:\s*"// - T - s/".*$// - T - p - ' - ) - if [ -z "${pkgbase}" ] || [ -z "${repo}" ]; then - printf '%s %s\n' "${architecture}" "${pkgname}" - continue - fi - printf '%s %s %s\n' \ - "${architecture}" \ - "${pkgbase}" \ - "${repo}" >> \ - "${tmp_dir}/pkgbases" - done < \ - "${tmp_dir}/pkgnames" | \ - sponge "${tmp_dir}/pkgnames" -fi +if ${interactive}; then + echo "Which packages to rebuild? (Comma separated; Empty means all)" + nl "${tmp_dir}/pkgbases" + read -p "Choice: " pkg_rebuild_choice -if [ -s "${tmp_dir}/pkgnames" ]; then - >&2 echo 'Could not find some packages upstream:' - >&2 cat "${tmp_dir}/pkgnames" - exit 2 + if [ -n "$pkg_rebuild_choice" ]; then + readarray -td, pkg_rebuild_choice_array < <( printf '%s' "$pkg_rebuild_choice" | sed 's/\s//g;s/,\{2,\}/,/g' ) + sed -i -n "$(printf "%sp;" "${pkg_rebuild_choice_array[@]}")" "${tmp_dir}/pkgbases" + fi fi -sort -u "${tmp_dir}/pkgbases" \ -| sort -k3,3 \ -| sponge "${tmp_dir}/pkgbases" - # get the current HEADs - -# shellcheck disable=SC2016 -{ - printf 'SELECT' - printf ' `upstream_repositories`.`name`,' - printf '`git_repositories`.`head`' - printf ' FROM `upstream_repositories`' - mysql_join_upstream_repositories_git_repositories -} \ -| mysql_run_query \ -| tr '\t' ' ' \ -| sort -k1,1 \ -| join -1 3 -2 1 -o 1.1,1.2,1.3,2.2 "${tmp_dir}/pkgbases" - \ -| sponge "${tmp_dir}/pkgbases" - if ${update}; then - cut -d' ' -f 2,3,4 "${tmp_dir}/pkgbases" \ - | sort -u \ - | while read -r pkgbase repo git_rev; do + cut -d' ' -f 2,3,4,5 "${tmp_dir}/pkgbases" \ + | while read -r pkgbase git_rev git_mod_rev repo; do success=false # shellcheck disable=SC2154 - for gr_r in \ - "${git_rev}:${repo}" \ - "${repo_heads__packages}:core" \ - "${repo_heads__packages}:extra" \ - "${repo_heads__community}:community"; do - printf '%s ' "${pkgbase}" "${gr_r%:*}" "${repo_heads__archlinux32}" "${gr_r#*:}" | \ - sed 's/ $/\n/' - if mysql_generate_package_metadata "${repository_ids__any_build_list}" "${pkgbase}" "${gr_r%:*}" "${repo_heads__archlinux32}" "${gr_r#*:}"; then - success=true - break - fi - done - if ! ${success} && \ + printf '%s ' "${pkgbase}" "${git_rev}" "${git_mod_rev}" "${repo_heads__archlinux32}" "${repo}" \ + | sed 's/ $/\n/' + if ! mysql_generate_package_metadata "${repository_ids__any_build_list}" "${pkgbase}" "${git_rev}" "${git_mod_rev}" "${repo}" && \ ! ${ignore_mysql_generate_package_metadata_errors}; then exit 2 fi done - cut -d' ' -f1 < \ - "${tmp_dir}/pkgbases" | \ - sort -u | \ - sponge "${tmp_dir}/pkgbases" + cut -d' ' -f2 "${tmp_dir}/pkgbases" \ + | sponge "${tmp_dir}/pkgbases" # shellcheck disable=SC2016 { @@ -794,8 +624,8 @@ if ${update}; then mysql_join_binary_packages_binary_packages_in_repositories 'j_bp' 'j_bpir' )"' AND `j_bpir`.`repository`='"${repository_ids__any_build_list}" \ '`repositories`.`stability`='"${repository_stability_ids__forbidden}" - } | \ - mysql_run_query + } \ + | mysql_run_query mysql_cleanup @@ -804,8 +634,8 @@ if ${update}; then mysql_find_build_assignment_loops # remove duplicate binary_packages from "build-list" - mysql_query_remove_old_binary_packages_from_build_list | \ - mysql_run_query + mysql_query_remove_old_binary_packages_from_build_list \ + | mysql_run_query else cat "${tmp_dir}/pkgbases" fi diff --git a/bin/strict-bashism-check b/bin/strict-bashism-check index 8e58e05..f1a8de6 100755 --- a/bin/strict-bashism-check +++ b/bin/strict-bashism-check @@ -8,6 +8,11 @@ else against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi +check_files=$( + git diff --cached --name-status "${against}" \ + | cut -f2 +) + # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --bool hooks.allownonascii) @@ -90,10 +95,14 @@ if command -v shellcheck >/dev/null 2>&1; then find bin conf lib \ -type f \ -executable \ - -not -name 'opcode' \ - -not -name 'opcode_list' \ -not -name '.*' \ - -execdir shellcheck -x '{}' \; 2>&1 + | grep -xF "${check_files}" \ + | while read -r file; do + ( + cd "${file%/*}" || exit $? + shellcheck -x "${file##*/}" 2>&1 + ) + done ) if [ -n "${errors}" ]; then diff --git a/bin/watch-build-logs b/bin/watch-build-logs new file mode 100755 index 0000000..064dc85 --- /dev/null +++ b/bin/watch-build-logs @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +trap 'echo ""; kill -- -$$' INT + +# shellcheck source=../lib/load-configuration +. "${0%/*}/../lib/load-configuration" + +runtail() { + # tail will quit with follow=name when the file is deleted + # thus no manual cleanup is needed + tail --follow=name "$1" -n +1 2>/dev/null & +} + +# Check if we're already building something, and if so, tail it before we wait for new files +CURRENTLOG=$(printf '%s\n' "$work_dir/"tmp.build-packages.*/*.build-log | sort | tail -n 1) +if [[ -f $CURRENTLOG ]]; then + runtail "$CURRENTLOG" +fi + +inotifywait -P -r -m "$work_dir" -e create --include '(\.build-log$)|(tmp\.build-packages\.[a-zA-Z0-9]+$)' --format '%w%f' -q | + while read -r FILE; do + if [[ -z $FILE || -d $FILE ]]; then + continue + fi + + runtail "$FILE" + done |