#!/bin/sh # shellcheck source=conf/default.conf . "${0%/*}/../conf/default.conf" # Create a lock file. if [ $# -eq 0 ]; then broken=$( find "${work_dir}/package-states" -maxdepth 1 -name '*.broken' -printf '%f\n' | \ sed 's|\(\.[^.]\+\)\{4\}$||' | \ sort -u ) new_sum='x' sum='' tmp_dir=$(mktemp -d) trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT find "${work_dir}/package-infos" -maxdepth 1 -name '*.builds' -exec \ grep -HF '' {} \; | \ sed ' s|^.*/|| s|\(\.[^.]\+\)\{4\}:| | ' | \ sort -k2,2 > \ "${tmp_dir}/builds" while ! [ "${new_sum}" = "${sum}" ]; do sum="${new_sum}" # shellcheck disable=SC2086 printf '%s\n' ${broken} | \ sort > \ "${tmp_dir}/broken" broken=$( ( find "${work_dir}/package-infos" -maxdepth 1 -name '*.depends' | \ sed 's|^.*/\(.*\)\(\.[^.]\+\)\{4\}|\1 \0|' | \ sort -k1,1 | \ join -1 1 -2 1 -o 1.2 - "${tmp_dir}/broken" | \ xargs -r cat ) | \ sort -u | \ join -1 1 -2 2 -o 2.1 - "${tmp_dir}/builds" ) broken=$( ( ( # shellcheck disable=SC2086 printf '%s\n' ${broken} cat "${tmp_dir}/broken" ) | \ sort -u awk '{print $1}' "${work_dir}/build-list" | \ sort -u ) | \ sort | \ uniq -d ) new_sum=$( # shellcheck disable=SC2086 printf '%s\n' ${broken} | \ sha512sum ) done rm -rf --one-file-system "${tmp_dir}" trap - EXIT broken=$( ( # shellcheck disable=SC2086 printf '%s\n' ${broken} ( find "${webserver_directory}/graphs" -maxdepth 1 -name '*.png' -printf '%f\n' | \ sed 's|\.png$||' ( awk '{print $1}' < \ "${work_dir}/build-list" cat "${work_dir}/deletion-list" ) | \ sort -u ) | \ sort | \ uniq -d ) | \ sort -u ) # shellcheck disable=SC2086 "$0" 'ALL' ${broken} ( find "${webserver_directory}/graphs" -maxdepth 1 -name '*.png' # shellcheck disable=SC2086 printf "${webserver_directory}"'/graphs/%s.png\n' ${broken} ${broken} 'ALL' 'ALL' ) | \ sort | \ uniq -u | \ xargs -r rm exit fi # shellcheck disable=SC2009 if ps ax | \ grep -v grep | \ grep -v "^\s*$$\s" | \ grep -wF "$0$( printf ' %s' "$@" )"; then >&2 echo $$ >&2 echo 'I was running already.' exit fi exec 9> "${work_dir}/${0##*/}.lock" if ! flock -n 9; then echo 'Cannot get lock.' exit fi tmp_dir=$(mktemp -d) trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT sort -u "${work_dir}/build-order" | \ grep -v '^\(\S\+\) \1$' | \ grep '^\S\+ \S\+$' > \ "${tmp_dir}/original-build-order" sort -k1,1 "${work_dir}/build-list" > \ "${tmp_dir}/build-list.sorted-by-package" ( sort -k1,1 "${tmp_dir}/original-build-order" | \ join -1 1 -2 1 -o 1.1,1.2 - "${tmp_dir}/build-list.sorted-by-package" sort -k2,2 "${tmp_dir}/original-build-order" | \ join -1 2 -2 1 -o 1.1,1.2 - "${tmp_dir}/build-list.sorted-by-package" ) | \ sort -u | \ sponge "${tmp_dir}/original-build-order" find "${work_dir}/package-infos" -maxdepth 1 -printf '%f\n' | \ sed 's|\(\.[^.]\+\)\{4\}$||' | \ sort -u > \ "${tmp_dir}/known-packages" find "${work_dir}/package-infos" -maxdepth 1 -name '*.groups' -printf '%f %p\n' | \ while read -r name pf; do xargs -r printf "${name%.*.*.*.*} %s\n" < \ "${pf}" done > \ "${tmp_dir}/known-groups" find "${work_dir}/package-infos" -maxdepth 1 -name '*.packages' -printf '%f %p\n' | \ while read -r name pf; do grep -vxF "${name%.*.*.*.*}" "${pf}" | \ xargs -r printf "${name%.*.*.*.*} %s\n" done > \ "${tmp_dir}/known-split-packages" for target_package in "$@"; do output="${webserver_directory}/graphs/${target_package}.png" if [ "${target_package}" = 'ALL' ]; then # groups and split packages built by jobs on the build list cat "${tmp_dir}/known-groups" "${tmp_dir}/known-split-packages" | \ grep -v '^\(\S\+\) \1$' | \ sort -k1,1 | \ join -1 1 -2 1 -o 1.2 - "${tmp_dir}/build-list.sorted-by-package" | \ sort -u > \ "${tmp_dir}/relevant-stuff" ( # groups and split packages built by jobs on the build list - which are also dependencies of packages on the build-list sort -k1,1 "${tmp_dir}/original-build-order" | \ join -1 1 -2 1 -o 2.1 - "${tmp_dir}/relevant-stuff" # build list jobs themself awk '{print $1}' "${work_dir}/build-list" ) | \ sort -u | \ sponge "${tmp_dir}/relevant-stuff" sort -k1,1 "${tmp_dir}/original-build-order" | \ join -1 1 -2 1 -o 1.1,1.2 - "${tmp_dir}/relevant-stuff" | \ sort -k2,2 | \ join -1 2 -2 1 -o 1.1,1.2 - "${tmp_dir}/relevant-stuff" > \ "${tmp_dir}/build-order" rm "${tmp_dir}/relevant-stuff" else grep " $(str_to_regex "${target_package}")\$" "${tmp_dir}/original-build-order" | \ sort -u > \ "${tmp_dir}/build-order" printf '0 target-package %s\n' "${target_package}" > \ "${tmp_dir}/knots" last_sum='' current_sum=$(sha512sum "${tmp_dir}/build-order") while ! [ "${last_sum}" = "${current_sum}" ]; do last_sum="${current_sum}" awk '{print $1}' "${tmp_dir}/build-order" | \ sort -u > \ "${tmp_dir}/new" ( cat \ "${tmp_dir}/original-build-order" \ "${tmp_dir}/known-split-packages" grep -v ' base\(-devel\)\?$' "${tmp_dir}/known-groups" || \ true ) | \ sort -k2,2 | \ join -1 2 -2 1 -o 1.1,1.2 - "${tmp_dir}/new" | \ sponge -a "${tmp_dir}/build-order" rm "${tmp_dir}/new" sort -u "${tmp_dir}/build-order" | \ sponge "${tmp_dir}/build-order" current_sum=$(sha512sum "${tmp_dir}/build-order") done fi grep -v '^\(\S\+\) \1$' "${tmp_dir}/build-order" | \ sponge "${tmp_dir}/build-order" # shellcheck disable=SC2129 tr ' ' '\n' < \ "${tmp_dir}/build-order" | \ sort -u | \ join -j 1 - "${tmp_dir}/build-list.sorted-by-package" | \ while read -r pkg rev mod_rev repo; do if [ -f "${work_dir}/package-states/${pkg}.${rev}.${mod_rev}.${repo}.broken" ]; then printf '1 broken-build-list-package %s\n' "${pkg}" else printf '2 build-list-package %s\n' "${pkg}" fi done >> \ "${tmp_dir}/knots" ( sort -u "${work_dir}/deletion-list" tr ' ' '\n' < \ "${tmp_dir}/build-order" | \ sort -u ) | \ sort | \ uniq -d | \ xargs -r printf '3 deletion-list-package %s\n' >> \ "${tmp_dir}/knots" ( awk '{print $2}' "${tmp_dir}/known-split-packages" | \ sort -u tr ' ' '\n' < \ "${tmp_dir}/build-order" | \ sort -u ) | \ sort | \ uniq -d | \ xargs -r printf '4 split-package %s\n' >> \ "${tmp_dir}/knots" ( cat "${tmp_dir}/known-packages" tr ' ' '\n' < \ "${tmp_dir}/build-order" | \ sort -u ) | \ sort | \ uniq -d | \ xargs -r printf '5 package %s\n' >> \ "${tmp_dir}/knots" ( awk '{print $2}' "${tmp_dir}/known-groups" | \ sort -u tr ' ' '\n' < \ "${tmp_dir}/build-order" | \ sort -u ) | \ sort | \ uniq -d | \ xargs -r printf '6 group %s\n' >> \ "${tmp_dir}/knots" tr ' ' '\n' < \ "${tmp_dir}/build-order" | \ sort -u | \ xargs -r printf '100 unknown %s\n' >> \ "${tmp_dir}/knots" sort -k3,3 -k1n,1 "${tmp_dir}/knots" | \ uniq -f2 | \ awk '{print $3 " " $1 " " $2}' | \ sort -k2,3 | \ sponge "${tmp_dir}/knots" if [ "${target_package}" != 'ALL' ]; then mkdir "${tmp_dir}/neighbours" cat "${tmp_dir}/knots" "${tmp_dir}/build-order" | \ awk '{ print $1 " " $2 > "'"${tmp_dir}/neighbours/"'"$1; print $1 " " $2 > "'"${tmp_dir}/neighbours/"'"$2; }' find "${tmp_dir}/neighbours" -maxdepth 1 -type f | \ while read -r file; do sed " s@\(^\| \)$(str_to_regex "${file##*/}")\( \|\$\)@\1\2@ " "${file}" | \ sort -u | \ sponge "${file}" done find "${tmp_dir}/neighbours" -maxdepth 1 -type f -exec \ sha512sum {} \; | \ sed 's|^\(\S\+\) .*/\([^/]\+\)$|\2 \1|' | \ sort -k2,2 | \ uniq -f1 -D | \ awk '{print $2 " " $1}' > \ "${tmp_dir}/sums" rm -rf --one-file-system "${tmp_dir}/neighbours" sed ' :a $!N s|^\(\S\+\) \([^\n]\+\)\n\1 |\1 \2| ta P D ' "${tmp_dir}/sums" | \ join -1 1 -2 1 -o 2.2,1.2 - "${tmp_dir}/sums" | \ while read -r original replacement; do sed -i " s@\( \|^\)$(str_to_regex "${original}")\( \|\$\)@\1${replacement}\2@ " "${tmp_dir}/build-order" "${tmp_dir}/knots" done fi sort -u "${tmp_dir}/build-order" | \ sponge "${tmp_dir}/build-order" sort -u "${tmp_dir}/knots" | \ sponge "${tmp_dir}/knots" { printf '%s\n' \ 'digraph dependencies {' \ ' fontname=dejavu;' cut -d' ' -f1,3 < \ "${tmp_dir}/knots" | \ while read -r who what; do if [ "${what}" = 'broken-build-list-package' ]; then color='#ff0000' elif [ "${what}" = 'build-list-package' ]; then color='#800000' elif [ "${what}" = 'target-package' ]; then color='#00ff00' elif [ "${what}" = 'package' ]; then color='#000000' elif [ "${what}" = 'split-package' ]; then color='#8080ff' elif [ "${what}" = 'group' ]; then color='#0000ff' elif [ "${what}" = 'deletion-list-package' ]; then color='#808080' else color='#ff80ff' fi printf ' "%s" [fontcolor="%s"];\n' "${who}" "${color}" done sed 's|\\|\\\\|g' "${tmp_dir}/build-order" | \ xargs -rn2 printf ' "%s" -> "%s";\n' | \ sort -u printf '%s\n' \ '}' } > \ "${tmp_dir}/input" sed -i ' s||,\\n|g s||, |g ' "${tmp_dir}/input" line_count=$(wc -l < "${tmp_dir}/input") if [ "${line_count}" -gt 500 ] && [ "${target_package}" != 'ALL' ]; then sed -i '/"base\(-devel\)\?"/d' "${tmp_dir}/input" line_count=$(wc -l < "${tmp_dir}/input") if [ "${line_count}" -gt 700 ]; then rm -f "${output}" >&2 printf 'Skipping graph for "%s" - would be too big (%d).\n' \ "${target_package}" \ "${line_count}" continue fi fi printf 'small enough (%s): %d\n' \ "${target_package}" \ "${line_count}" touch "${output}" chmod 644 "${output}" if ! dot -Tpng -o "${output}" "${tmp_dir}/input"; then rm -f "${output}" continue fi done rm "${work_dir}/${0##*/}.lock"