#!/bin/sh # shellcheck source=../lib/load-configuration . "${0%/*}/../lib/load-configuration" # TODO: remove hard-coded package suffixes # TODO: use the intention-queue # shellcheck disable=SC2016 usage() { >&2 echo 'usage:' >&2 echo ' create-build-support-package [options] --from $pkgname-$epoch:$pkgver-$pkgrel.$sub_pkgrel [--] $file1 $file2 $file3 ...' >&2 echo ' create $pkgname-shim containing' >&2 echo ' $file1, $file2, ... from the original package' >&2 echo ' create-build-support-package [options] --shim $pkgfile' >&2 echo ' insert $pkgfile into $repo_arch/build-support/$pkgname-shim' >&2 echo '' >&2 echo 'possible options:' >&2 echo ' -a|--arch $repo_arch: (required)' >&2 echo ' Operate on repository of given architecture.' >&2 echo ' -h|--help:' >&2 echo ' Show this help and exit.' >&2 echo ' --only-versioned-so-provides:' >&2 echo ' Remove all but versioned *.so provide entries. (only with --from)' >&2 echo ' -w|--wait:' >&2 echo ' Wait for lock if necessary.' [ -z "$1" ] && exit 1 || exit "$1" } eval set -- "$( getopt -o a:hw \ --long arch: \ --long from: \ --long help \ --long only-versioned-so-provides \ --long shim: \ --long wait \ -n "$(basename "$0")" -- "$@" || \ echo usage )" only_versioned_so_provides=false repo_arch='' shim_package='' source_package='' wait_for_lock='-n' while true; do case "$1" in -a|--arch) if [ -n "${repo_arch}" ]; then >&2 prinf -- '-a|--arch given more than once.\n' usage fi shift repo_arch="$1" ;; --from) if [ -n "${source_package}" ]; then >&2 prinf -- '--from given more than once.\n' usage fi shift source_package="$1" ;; -h|--help) usage 0 ;; --only-versioned-so-provides) only_versioned_so_provides=true ;; --shim) if [ -n "${shim_package}" ]; then >&2 prinf -- '--shim given more than once.\n' usage fi shift shim_package="$1" ;; -w|--wait) wait_for_lock='' ;; --) shift break ;; *) >&2 printf 'Whoops, forgot to implement option "%s" internally.\n' \ "$1" exit 42 ;; esac shift done if [ -n "${source_package}" ] \ && [ -n "${shim_package}" ]; then >&2 echo 'Conflicting parameters: --from and --shim' usage fi if ${only_versioned_so_provides} \ && [ -n "${shim_package}" ]; then >&2 echo 'Conflicting parameters: --shim and --only-versioned-so-provides' usage fi exec 9> "${sanity_check_lock_file}" # shellcheck disable=SC2086 verbose_flock -s ${wait_for_lock} 9 tmp_dir=$(mktemp -d 'tmp.create-build-support.XXXXXXXXXX') # shellcheck disable=SC2064 trap "rm -rf --one-file-system '${tmp_dir:?}'" EXIT if [ -n "${source_package}" ]; then # create shim_package from source_package if [ $# -eq 0 ]; then usage 1 fi pkg=$( # shellcheck disable=SC2016 { printf 'SELECT DISTINCT ' mysql_package_name_query printf ' FROM `binary_packages`' mysql_join_binary_packages_binary_packages_in_repositories mysql_join_binary_packages_in_repositories_repositories mysql_join_repositories_architectures '' 'r_a' mysql_join_binary_packages_architectures printf ' LEFT' mysql_join_binary_packages_compressions printf ' WHERE `repositories`.`is_on_master_mirror`' printf ' AND `r_a`.`name`=from_base64("%s")' \ "$( printf '%s' "${repo_arch}" \ | base64 -w0 )" printf ' AND ' mysql_package_name_query '' 'XX' \ | sed ' s/,"-",`XX.*\.`suffix`)// ' printf '=from_base64("%s")' \ "$( printf '%s' "${source_package}" \ | base64 -w0 )" } \ | mysql_run_query \ | tr '\t' ' ' ) if [ -z "${pkg}" ]; then >&2 printf 'Could not find %s/%s in the database.\n' \ "${repo_arch}" "${source_package}" exit 1 fi if printf '%s\n' "${pkg}" \ | wc -l \ | grep -vqxF '1'; then >&2 printf 'Package %s/%s was found multiple times:\n' \ "${repo_arch}" "${source_package}" >&2 printf '%s\n' "${pkg}" exit 1 fi new_pkg="${pkg%-*-*-*}" new_pkg="${new_pkg}-shim${pkg#${new_pkg}}" failsafe_rsync \ "${master_mirror_rsync_directory}/pool/${pkg}" \ "${tmp_dir}/" mkdir "${tmp_dir}/content" bsdtar -C "${tmp_dir}/content" -xf "${tmp_dir}/${pkg}" \ '.BUILDINFO' \ '.PKGINFO' \ "$@" # TODO: mangle customizable meta-infos here (new provides, keep some # depends) sed -i ' /^pkgname = / s/ \S\+$/\0-shim\nprovides =\0/ /^depend = /d ' "${tmp_dir}/content/.PKGINFO" if ${only_versioned_so_provides}; then sed -i ' /^provides = / { / = \S\+\.so=/ ! d } /^replaces = / d /^conflict = / d ' "${tmp_dir}/content/.PKGINFO" fi # from /usr/bin/makepkg list_package_files() { ( cd "${tmp_dir}/content" find . -path './.*' \! -name '.'; find . \! -path './.*' \! -name '.' \ | LC_ALL=C sort ) \ | sed -e 's|^\./||' \ | tr '\n' '\0' } list_package_files \ | LANG=C bsdtar -C "${tmp_dir}/content" -cnf - --format=mtree \ --options='!all,use-set,type,uid,gid,mode,time,size,md5,sha256,link' \ --null --files-from - --exclude .MTREE \ | gzip -c -f -n \ > "${tmp_dir}/content/.MTREE" list_package_files \ | LANG=C bsdtar -C "${tmp_dir}/content" -cnf - --null --files-from - \ | zstd -c -z - \ > "${tmp_dir}/${new_pkg}" rm -rf --one-file-system "${tmp_dir:?}/content" mv "${tmp_dir}/${new_pkg}" "${work_dir}/" >&2 printf 'Please sign %s with a build slave key and run\n' \ "${work_dir}/${new_pkg}" # shellcheck disable=SC2016 >&2 printf 'create-build-support-package --arch %s --shim %s\n' \ "${repo_arch}" \ "${work_dir}/${new_pkg}" elif [ -n "${shim_package}" ]; then # insert shim_package into [build-support] if [ $# -ne 0 ]; then >&2 echo 'Too many arguments' usage fi if [ ! -r "${shim_package}" ]; then >&2 printf 'Cannot open file %s\n' \ "${shim_package}" exit 1 fi if ! gpg --batch --status-fd 1 -q --homedir /etc/pacman.d/gnupg --verify \ "${shim_package}.sig" \ "${shim_package}" \ 2> /dev/null \ | cut -d' ' -f2 \ | grep -qxF TRUST_FULLY; then >&2 printf '%s has invalid signature\n' \ "${shim_package}" exit 1 fi exec 8> "${package_database_lock_file}" # shellcheck disable=SC2086 verbose_flock ${wait_for_lock} 8 # shellcheck disable=SC2086 if intentions_left ${wait_for_lock}; then >&2 echo 'There are still intentions in the queue.' exit 1 fi original_pkg_id=$( # shellcheck disable=SC2016 { printf 'SELECT DISTINCT `binary_packages`.`id`' printf ' FROM `binary_packages`' mysql_join_binary_packages_architectures printf ' LEFT' mysql_join_binary_packages_compressions printf ' WHERE ' mysql_package_name_query \ | sed 's/pkgname`,"/\0-shim/' printf '=from_base64("%s")' \ "$( printf '%s' "${shim_package##*/}" \ | base64 -w0 )" } | \ mysql_run_query ) if [ -z "${original_pkg_id}" ]; then >&2 printf 'could not find the original package to %s.\n' \ "${shim_package##*/}" exit 1 fi cp "${shim_package}" "${shim_package}.sig" "${tmp_dir}/" failsafe_rsync \ "${master_mirror_rsync_directory}/${repo_arch}/build-support/build-support.db."* \ "${master_mirror_rsync_directory}/${repo_arch}/build-support/build-support.files."* \ "${tmp_dir}/" repo-add \ "${tmp_dir}/build-support.db.tar.gz" \ "${tmp_dir}/${shim_package##*/}" # shellcheck disable=SC2016 { printf 'INSERT INTO `binary_packages`(' printf '`build_assignment`,' printf '`epoch`,' printf '`pkgver`,' printf '`pkgrel`,' printf '`sub_pkgrel`,' printf '`architecture`,' printf '`sub_pkgrel_omitted`,' printf '`pkgname`,' printf '`has_issues`,' printf '`is_tested`,' printf '`sha512sum`' printf ')' printf ' SELECT ' printf '`binary_packages`.`%s`,' \ 'build_assignment' \ 'epoch' \ 'pkgver' \ 'pkgrel' \ 'sub_pkgrel' \ 'architecture' \ 'sub_pkgrel_omitted' printf 'CONCAT(`binary_packages`.`pkgname`,"-shim"),' printf '0,0,"%s"' \ "$( sha512sum "${tmp_dir}/${shim_package##*/}" \ | awk '{print $1}' )" printf ' FROM `binary_packages`' printf ' WHERE `binary_packages`.`id`=%s' \ "${original_pkg_id}" printf ' LIMIT 1;\n' printf 'SET @`new_package_id`=LAST_INSERT_ID();\n' printf 'INSERT INTO `binary_packages_in_repositories` (`package`,`repository`,`is_to_be_deleted`)' printf ' SELECT @`new_package_id`,`repositories`.`id`,0' printf ' FROM `repositories`' mysql_join_repositories_architectures printf ' WHERE `repositories`.`name`="build-support"' printf ' AND `architectures`.`name`=from_base64("%s");\n' \ "$( printf '%s' "${repo_arch}" \ | base64 -w0 )" printf 'INSERT INTO `install_target_providers` (`package`,`install_target`,`version`,`install_target_is_group`)' printf ' SELECT @`new_package_id`' printf ',`install_target_providers`.`%s`' \ 'install_target' \ 'version' \ 'install_target_is_group' printf ' FROM `install_target_providers`' printf ' WHERE `install_target_providers`.`package`=%s;\n' \ "${original_pkg_id}" # TODO: maybe add (some?) depends here, too? } | \ mysql_run_query failsafe_rsync \ "${tmp_dir}/${shim_package##*/}" \ "${tmp_dir}/${shim_package##*/}.sig" \ "${master_mirror_rsync_directory}/pool/" rm \ "${tmp_dir}/${shim_package##*/}" \ "${tmp_dir}/${shim_package##*/}.sig" ln -s "../../pool/${shim_package##*/}" "${tmp_dir}/${shim_package##*/}" ln -s "../../pool/${shim_package##*/}.sig" "${tmp_dir}/${shim_package##*/}.sig" failsafe_rsync \ "${tmp_dir}/${shim_package##*/}" \ "${tmp_dir}/${shim_package##*/}.sig" \ "${tmp_dir}/build-support.db."* \ "${tmp_dir}/build-support.files."* \ "${master_mirror_rsync_directory}/${repo_arch}/build-support/" rm\ "${shim_package}" \ "${shim_package}.sig" else >&2 echo 'Need either --from or --shim.' usage fi