#!/bin/sh # usage: why_dont_you $action $package1 $package2 ... # shellcheck disable=SC2119,SC2120 # investigate, why a certain operation is not done with certain packages # shellcheck source=../lib/load-configuration . "${0%/*}/../lib/load-configuration" # TODO: reintrocude "keep", "stubbornly_keep", "stabilize" and "unstage" # using information from the database. action="$1" shift tmp_dir=$(mktemp -d 'tmp.why-dont-you.XXXXXXXXXX' --tmpdir) trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT case "${action}" in 'build') # shellcheck disable=SC2016 { printf 'CREATE TEMPORARY TABLE `searches` (`search` VARCHAR(64));\n' printf 'INSERT INTO `searches` VALUES ' # shellcheck disable=SC2046 printf '(from_base64("%s")),' \ $( printf '%s\n' "$@" | \ base64_encode_each ) | \ sed 's/,$/;\n/' # we select everything which is possibly of any interest: # - id (to see if it actually is on the build-list) # - build_assignments.architecture.name # - to_build.is_broken # - failed_builds_count # - to_build.is_blocked # - deps.pkgbase (any dependency pending?) # - build_slaves.name (is anyone building this?) # - pkgbase printf 'SELECT DISTINCT `to_build`.`ba_id`,' printf '`to_build`.`baa_name`,' printf 'If(`to_build`.`is_broken`,1,0),' printf '(' printf 'SELECT COUNT(1)' printf ' FROM `failed_builds`' printf 'WHERE `failed_builds`.`build_assignment`=`to_build`.`ba_id`' printf ')' printf ',replace(to_base64(`%s`.`%s`),"\\n","")' \ 'to_build' 'is_blocked' \ 'deps' 'pkgbase' \ 'build_slaves' 'name' \ 'to_build' 'pkgbase' # at least one row for each given `search` printf ' FROM `searches`' printf ' LEFT JOIN ' printf '(' # join the tables for the to-be-built packages: # package_source, build_assignment, binary_package, repostory printf 'SELECT DISTINCT ' printf '`tb_ps`.`pkgbase`,' printf '`tb_bin`.`id` AS `bin_id`,' printf '`tb_ba`.`id` AS `ba_id`,' printf '`tb_ba`.`is_blocked`,' printf '`tb_ba`.`is_broken`,' printf '`tb_baa`.`name` AS `baa_name`' printf ' FROM `package_sources` AS `tb_ps`' mysql_join_package_sources_build_assignments 'tb_ps' 'tb_ba' mysql_join_build_assignments_architectures 'tb_ba' 'tb_baa' mysql_join_build_assignments_binary_packages 'tb_ba' 'tb_bin' mysql_join_binary_packages_binary_packages_in_repositories 'tb_bin' 'tb_bir' printf ' WHERE `tb_bir`.`repository`=%s' \ "${repository_ids__any_build_list}" printf ') AS `to_build`' printf ' ON (' printf '`to_build`.`pkgbase`=`searches`.`search`' printf ' OR `searches`.`search`=CONCAT(`to_build`.`baa_name`,"/",`to_build`.`pkgbase`)' printf ') LEFT JOIN ' printf '(' # same join as above, but with different names - for the # potential dependencies printf 'SELECT DISTINCT `dep_ps`.`pkgbase`,`dependencies`.`dependent`' printf ' FROM `package_sources` AS `dep_ps`' mysql_join_package_sources_build_assignments 'dep_ps' 'dep_ba' mysql_join_build_assignments_binary_packages 'dep_ba' 'dep_bin' mysql_join_binary_packages_binary_packages_in_repositories 'dep_bin' 'dep_bir' # now we have some (=3) additional joins, # because we are interested in dependency relations to `to_build` mysql_join_binary_packages_install_target_providers 'dep_bin' mysql_join_install_target_providers_dependencies_with_versions mysql_join_dependencies_dependency_types printf ' WHERE `dep_bir`.`repository`=%s' \ "${repository_ids__any_build_list}" printf ' AND `dependency_types`.`relevant_for_building`' printf ') AS `deps`' printf ' ON `deps`.`dependent`=`to_build`.`bin_id`' # now we join with build slaves to see if someone builds this printf ' LEFT JOIN `build_slaves`' printf ' ON `build_slaves`.`currently_building`=`to_build`.`ba_id`' printf ';\n' } | \ mysql_run_query | \ tr '\t' ' ' | \ sort -k8,8 -k7,7 -k6,6 | \ sed ' / NULL \S\+$/ b multi-dep :multi-slave $!N s/^\(\(\S\+ \)\{6\}\)\(\S\+\)\( \S\+\)\n\(\S\+ \)\{6\}\(\S\+\)\4/\1\3,\6\4/ t multi-slave P D :multi-dep / NULL\( \S\+\)\{3\}$/! b $!N s/^\(\(\S\+ \)\{5\}\)\(\S\+\)\(\( \S\+\)\{2\}\)\n\(\S\+ \)\{5\}\(\S\+\)\4/\1\3,\7\4/ t multi-dep P D ' | \ sed ' s/NULL,//g ' | \ while read -r id ba_arch is_broken trials is_blocked dependency slave pkgbase; do pkgbase=$( printf '%s' "${pkgbase}" | \ base64 -d ) if [ "${id}" = 'NULL' ]; then >&2 printf '"%s" is not on the build list.\n' \ "${pkgbase}" continue fi if [ "${slave}" != 'NULL' ]; then # beware: A slave named "5BË" will look exactly like this! printf '"%s/%s" is locked by %s.\n' \ "${ba_arch}" \ "${pkgbase}" \ "$( printf '%s\n' "${slave}" | \ tr ',' '\n' | \ while read -r line; do printf '%s\n' "${line}" | \ base64 -d printf ',' done | \ sed 's/,$//' )" continue fi if [ "${is_blocked}" != 'NULL' ]; then # beware: A block-reason "5BË" will look exactly like this! printf '"%s/%s" is blocked: "%s".\n' \ "${ba_arch}" \ "${pkgbase}" \ "$( printf '%s' "${is_blocked}" | \ base64 -d )" continue fi if [ "${dependency}" != 'NULL' ]; then printf '"%s/%s" has unmet dependencies:\n' \ "${ba_arch}" \ "${pkgbase}" printf '%s\n' "${dependency}" | \ tr ',' '\n' | \ while read -r line; do printf ' ' printf '%s\n' "${line}" | \ base64 -d printf '\n' done | \ sort -u continue fi if [ "${is_broken}" = '1' ]; then printf '"%s/%s" is broken (%sx built), but would be built.\n' \ "${ba_arch}" \ "${pkgbase}" \ "${trials}" continue fi printf '"%s/%s" would be built.\n' \ "${ba_arch}" \ "${pkgbase}" done ;; 'stabilize'|'unstage') if [ "${action}" = 'stabilize' ]; then # shellcheck disable=SC2154 from_stability=${repository_stability_ids__testing} # shellcheck disable=SC2154 to_stability=${repository_stability_ids__stable} # shellcheck disable=SC2016 test_filter='`binary_packages`.`is_tested`' else # shellcheck disable=SC2154 from_stability=${repository_stability_ids__staging} # shellcheck disable=SC2154 to_stability=${repository_stability_ids__testing} test_filter='1' fi for pkgname in "$@"; do infos=$( # shellcheck disable=SC2016 { printf 'SELECT' printf ' `binary_packages_in_repositories`.`id`,' printf ' IF(%s,1,0),' "${test_filter}" printf ' IF(`binary_packages`.`has_issues`,1,0)' printf ' FROM `binary_packages_in_repositories`' mysql_join_binary_packages_in_repositories_repositories mysql_join_binary_packages_in_repositories_binary_packages printf ' WHERE `repositories`.`stability`=%s' \ "${from_stability}" printf ' AND `binary_packages`.`pkgname`=from_base64("%s")' \ "$( printf '%s' "${pkgname}" | \ base64 -w0 )" } | \ mysql_run_query | \ tr '\t' ' ' ) if [ -z "${infos}" ]; then printf 'Cannot find "%s"\n' \ "${pkgname}" continue fi bpir="${infos%% *}" infos="${infos#* }" if [ "${infos% *}" = '0' ]; then printf '"%s" is not tested.\n' \ "${pkgname}" continue fi infos="${infos#* }" if [ "${infos}" = '1' ]; then printf 'There are unresolved bugs reported against "%s".\n' \ "${pkgname}" continue fi printf '%s %s\n' "${bpir}" "${pkgname}" >> \ "${tmp_dir}/packages" done if [ ! -s "${tmp_dir}/packages" ]; then exit fi # shellcheck disable=SC2016 { printf 'CREATE TEMPORARY TABLE `moveable_bpir` (`id` BIGINT, `to_repository` BIGINT, UNIQUE KEY `id`(`id`));\n' printf 'CREATE TEMPORARY TABLE `replaceable_bpir` (`id` BIGINT, `replaced_by` BIGINT, UNIQUE KEY `id`(`id`));\n' for copy in '' '_copy'; do printf 'CREATE TEMPORARY TABLE `knots%s` (' \ "${copy}" printf '`id` BIGINT NOT NULL AUTO_INCREMENT,' printf ' `and` BIT,' printf ' `content_id` BIGINT,' printf ' `content_type` ENUM("bpir","it"),' printf ' `reason_length` MEDIUMINT,' printf ' `active` BIT,' printf ' `relevant` BIT,' printf ' UNIQUE KEY (`id`),' printf ' UNIQUE KEY `content`(`content_id`,`content_type`));\n' printf 'CREATE TEMPORARY TABLE `edges%s` (' \ "${copy}" printf '`cause` BIGINT,' printf ' `impact` BIGINT,' printf ' `invert` BIT,' printf ' UNIQUE KEY `content` (`cause`,`impact`));\n' done printf 'INSERT IGNORE INTO `moveable_bpir` (`id`,`to_repository`)' printf ' SELECT ' printf '`binary_packages_in_repositories`.`id`,' printf '`repository_moves`.`to_repository`' printf ' FROM `binary_packages_in_repositories`' mysql_join_binary_packages_in_repositories_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 mysql_join_upstream_repositories_repository_moves printf ' AND `repository_moves`.`from_repository`=`repositories`.`id`' printf ' WHERE `repositories`.`stability`=%s' \ "${from_stability}" printf ' AND %s' \ "${test_filter}" printf ' AND NOT `binary_packages`.`has_issues`;\n' printf 'INSERT IGNORE INTO `replaceable_bpir` (`id`,`replaced_by`)' printf ' SELECT `r_bpir`.`id`,`m_bpir`.`id`' printf ' FROM `moveable_bpir`' printf ' JOIN `binary_packages_in_repositories` AS `m_bpir`' printf ' ON `m_bpir`.`id`=`moveable_bpir`.`id`' mysql_join_binary_packages_in_repositories_binary_packages 'm_bpir' 'm_bp' printf ' JOIN `binary_packages` AS `r_bp`' printf ' ON `r_bp`.`pkgname`=`m_bp`.`pkgname`' mysql_join_binary_packages_binary_packages_in_repositories 'r_bp' 'r_bpir' mysql_join_binary_packages_in_repositories_repositories 'r_bpir' 'r_r' printf ' JOIN `repositories` AS `m_r`' printf ' ON `m_r`.`id`=`moveable_bpir`.`to_repository`' printf ' AND `m_r`.`architecture`=`r_r`.`architecture`' printf ' JOIN `repository_stability_relations` AS `rsr`' printf ' ON `rsr`.`more_stable`=`r_r`.`stability`' printf ' AND `rsr`.`less_stable`=`m_r`.`stability`' printf ' WHERE NOT EXISTS (' printf 'SELECT 1' printf ' FROM `binary_packages_in_repositories` AS `subst_bpir`' mysql_join_binary_packages_in_repositories_repositories 'subst_bpir' 'subst_r' mysql_join_binary_packages_in_repositories_binary_packages 'subst_bpir' 'subst_bp' printf ' JOIN `repository_stability_relations` AS `rsr_a`' printf ' ON `rsr_a`.`more_stable`=`subst_r`.`stability`' printf ' JOIN `repository_stability_relations` AS `rsr_b`' printf ' ON `rsr_b`.`less_stable`=`subst_r`.`stability`' printf ' WHERE `subst_bp`.`pkgname`=`r_bp`.`pkgname`' printf ' AND `subst_bp`.`id`=`r_bp`.`id`' printf ' AND `rsr_a`.`less_stable`=`m_r`.`stability`' printf ' AND `rsr_b`.`more_stable`=`r_r`.`stability`' printf ');\n' # we generate a graph with bpir and it as knots printf 'INSERT INTO `knots` (`and`,`content_id`,`content_type`)' printf ' SELECT 1,`moveable_bpir`.`id`,"bpir"' printf ' FROM `moveable_bpir`;\n' printf 'INSERT INTO `knots` (`and`,`content_id`,`content_type`)' printf ' SELECT 1,`binary_packages_in_repositories`.`id`,"bpir"' printf ' FROM `binary_packages_in_repositories`' mysql_join_binary_packages_in_repositories_repositories mysql_join_binary_packages_in_repositories_binary_packages printf ' JOIN `repository_stability_relations`' printf ' ON `repository_stability_relations`.`less_stable`=%s' \ "${to_stability}" printf ' AND `repository_stability_relations`.`more_stable`=`repositories`.`stability`' printf ' WHERE NOT EXISTS(' printf 'SELECT 1' printf ' FROM `binary_packages_in_repositories` AS `subst_bpir`' mysql_join_binary_packages_in_repositories_repositories 'subst_bpir' 'subst_r' printf ' JOIN `repository_stability_relations` AS `rsr_a`' printf ' ON `rsr_a`.`less_stable`=%s' \ "${to_stability}" printf ' AND `rsr_a`.`more_stable`=`subst_r`.`stability`' printf ' JOIN `repository_stability_relations` AS `rsr_b`' printf ' ON `rsr_b`.`less_stable`=`subst_r`.`stability`' mysql_join_binary_packages_in_repositories_binary_packages 'subst_bpir' 'subst_bp' printf ' WHERE `subst_bp`.`pkgname`=`binary_packages`.`pkgname`' printf ' AND `subst_bpir`.`id`!=`binary_packages_in_repositories`.`id`' printf ' AND `rsr_b`.`more_stable`=`repositories`.`stability`' printf ');\n' printf 'INSERT INTO `knots` (`and`,`content_id`,`content_type`)' printf ' SELECT 0,`install_targets`.`id`,"it"' printf ' FROM `install_targets`;\n' # create copy printf 'INSERT INTO `knots_copy`' printf ' SELECT *' printf ' FROM `knots`;\n' # "available" bpir requires available install_target printf 'INSERT INTO `edges` (`cause`,`impact`,`invert`)' printf ' SELECT DISTINCT `c`.`id`,`i`.`id`,0' printf ' FROM `knots` AS `i`' printf ' JOIN `binary_packages_in_repositories`' printf ' ON `binary_packages_in_repositories`.`id`=`i`.`content_id`' printf ' AND `i`.`content_type`="bpir"' mysql_join_binary_packages_in_repositories_dependencies mysql_join_dependencies_dependency_types printf ' AND `dependency_types`.`relevant_for_binary_packages`' printf ' JOIN `knots_copy` AS `c`' printf ' ON `dependencies`.`depending_on`=`c`.`content_id`' printf ' AND `c`.`content_type`="it";\n' # "available" install_target requires available bpir - but we # only care about bpir being moved or being more stable than # target stability for what in 'moveable' 'there'; do printf 'INSERT INTO `edges` (`cause`,`impact`,`invert`)' printf ' SELECT DISTINCT `c`.`id`,`i`.`id`,0' printf ' FROM `knots` AS `c`' printf ' JOIN `binary_packages_in_repositories`' printf ' ON `binary_packages_in_repositories`.`id`=`c`.`content_id`' printf ' AND `c`.`content_type`="bpir"' if [ "${what}" = 'moveable' ]; then printf ' JOIN `moveable_bpir`' printf ' ON `moveable_bpir`.`id`=`binary_packages_in_repositories`.`id`' else mysql_join_binary_packages_in_repositories_repositories printf ' JOIN `repository_stability_relations`' printf ' ON `repository_stability_relations`.`more_stable`=`repositories`.`stability`' printf ' AND `repository_stability_relations`.`less_stable`=%s' \ "${to_stability}" fi mysql_join_binary_packages_in_repositories_install_target_providers printf ' JOIN `knots_copy` AS `i`' printf ' ON `install_target_providers`.`install_target`=`i`.`content_id`' printf ' AND `i`.`content_type`="it";\n' done # additionally, "available" moveable_bpir requires matching # replaceable_bpir unavailable printf 'INSERT INTO `edges` (`cause`,`impact`,`invert`)' printf ' SELECT `c`.`id`,`i`.`id`,1' printf ' FROM `replaceable_bpir`' printf ' JOIN `knots` AS `c`' printf ' ON `c`.`content_id`=`replaceable_bpir`.`id`' printf ' AND `c`.`content_type`="bpir"' printf ' JOIN `knots_copy` AS `i`' printf ' ON `i`.`content_id`=`replaceable_bpir`.`replaced_by`' printf ' AND `i`.`content_type`="bpir";\n' while read -r bpir pkgname; do printf 'CALL `find_the_culprit`(%s);\n' \ "${bpir}" done < \ "${tmp_dir}/packages" } | \ mysql_run_query ;; 'keep'|'stubbornly_keep') printf 'Sry, "why-dont-you %s" is unavailable, until someone recodes it to look into the database.\n' "${action}" ;; *) >&2 printf 'unknown action "%s"\n' "${action}" exit 1 esac