#!/bin/bash # mp-pool | MatterLinux pool build script # MatterLinux 2023-2024 (https://matterlinux.xyz) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . ############################# ## import common functions ## ############################# location=$(dirname "${0}") location=$(realpath "${location}") commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh" source "${commonsh}" > /dev/null if [ "${?}" != "0" ]; then echo "Failed to import mtsc-common" exit 1 fi #################### ## util functions ## #################### # prints the help info help_cmd() { info "MatterLinux pool build script" info "Usage: ${0} [pool directory] " info "Options:" echo_color " $BOLD--skip-fail$RESET: skip if a package build fails" echo_color " $BOLD--no-depend$RESET: don't check depends" echo_color " $BOLD--no-stdout$RESET: disable stdout for build() function" echo_color " $BOLD--no-cache$RESET: don't use cache" echo_color " $BOLD--no-opts$RESET: don't show/list options" echo_color " $BOLD--no-sign$RESET: don't sign build packages" echo_color " $BOLD--cores$RESET: how many cores to use for the build" echo info "Licensed under GPLv3, see for more information" } # clean the dist directory clean_dist() { rm -f "${distpath}/DATA" rm -f "${distpath}/CHANGES" rm -f "${distpath}/INSTALL" rm -f "${distpath}/HASHES" rm -f "${distpath}/files.tar.gz" } # convert bash array to newline splitted string list_to_str(){ local list=("$@") for el in "${list[@]}"; do if [ -z "${str}" ]; then str="${el}" else printf -v str "${str}\n ${el}" fi done } # run mp-build with options mp_build_opts(){ local opts=("${1}" "--no-opts" "--out='${2}'") if [ $OPT_NO_DEPEND -eq 1 ]; then opts+=("--no-depend") fi if [ $OPT_NO_STDOUT -eq 1 ]; then opts+=("--no-stdout") fi if [ $OPT_NO_CACHE -eq 1 ]; then opts+=("--no-cache") fi mp-build ${opts[@]} return "$?" } ################# ## main script ## ################# OPT_SKIP_FAIL=0 # stop build when a package build fails OPT_NO_DEPEND=0 # checking depends is ENABLED OPT_NO_STDOUT=0 # build() function output is ENABLED OPT_NO_CACHE=0 # cache is ENABLED OPT_NO_OPTS=0 # showing/listing options is ENABLED OPT_NO_SIGN=0 # sign all the built packages OPT_CORES=$(nproc) # use ALL CPU cores OPT_POOLDIR="" # target pool directory (no default) OPT_PACKAGES=() # target packages (all by default) # parses all the options for arg in "$@"; do case $arg in "--help") help_cmd exit 0 ;; "--skip-fail") OPT_SKIP_FAIL=1 ;; "--no-depend") OPT_NO_DEPEND=1 ;; "--no-stdout") OPT_NO_STDOUT=1 ;; "--no-cache") OPT_NO_CACHE=1 ;; "--no-opts") OPT_NO_OPTS=1 ;; "--no-sign") OPT_NO_SIGN=1 ;; "--cores"*) OPT_CORES=$(echo "${arg}" | cut -d "=" -f2) ;; --*) error "Unknown option: ${arg}" exit 1 ;; *) if [ -z "${OPT_POOLDIR}" ]; then OPT_POOLDIR="${arg}" else OPT_PACKAGES+=("${arg}") fi ;; esac done if [ -z "${OPT_POOLDIR}" ]; then error "Pool directory is not specified, run with \"--help\" for more information" exit 1 fi if [ ! -d "${OPT_POOLDIR}" ]; then error "Pool directory \"${OPT_POOLDIR}\" does not exist" exit 1 fi if [ $OPT_NO_DEPEND -eq 0 ] && ! command -v matt &> /dev/null; then error "!!! BUILD ON MATTERLINUX !!!" error "matt is not installed, please build on a MatterLinux system" error "Do NOT create bug reports if build fails on non-MatterLinux systems" info "Auto enabling NO_DEPEND as depend check will fail without mp" OPT_NO_DEPEND=1 fi # print the options if [ $OPT_NO_OPTS -eq 0 ]; then info "Running mp-pool with the options:" print " $BOLD SKIP_FAIL = $(itoyn $OPT_SKIP_FAIL)" print " $BOLD NO_DEPEND = $(itoyn $OPT_NO_DEPEND)" print " $BOLD NO_SDTOUT = $(itoyn $OPT_NO_STDOUT)" print " $BOLD NO_CACHE = $(itoyn $OPT_NO_CACHE)" print " $BOLD NO_OPTS = $(itoyn $OPT_NO_OPTS)" print " $BOLD NO_SIGN = $(itoyn $OPT_NO_SIGN)" print " $BOLD CORES = $OPT_CORES" fi cd "${OPT_POOLDIR}" check_ret "Failed to change directory into \"${OPT_POOLDIR}\"" if [ ! -f "pool.sh" ]; then error "Package directory does not contain a pool script (pool.sh)" exit 1 fi # source and verify the package script source "pool.sh" check_ret "Failed to source the pool script" check_pool_vars check_ret # setup package directories pkgpath="$(realpath .)" distpath="$(realpath 'dist')" srcpath="$(realpath "${SRCDIR}")" mkdir -p "${distpath}" check_ret "Failed to create the dist directory" if [ ! -d "${srcpath}" ]; then error "Source path does not exist" exit 1 fi # obtain every package if no package is specified if [ -z "${OPT_PACKAGES}" ]; then for pkg in "${srcpath}/"*; do pkg_name=$(basename "${pkg}") OPT_PACKAGES+=("${pkg_name}") done fi # build every package pc=${#OPT_PACKAGES[@]} pi=1 for pkg_name in "${OPT_PACKAGES[@]}"; do pkg="${srcpath}/${pkg_name}" if [ ! -d "${pkg}" ]; then error "Package not found: \"${pkg_name}\"" exit 1 fi info "(${pi}/${pc}) Building \"${pkg_name}\"" if [ $OPT_SKIP_FAIL -eq 1 ]; then mp_build_opts "${pkg}" "${distpath}" if [ $? -ne "0" ]; then error "(${pi}/${pc}) Build failed for \"${pkg_name}\", skipping" pi=$((pi+1)) continue fi else mp_build_opts "${pkg}" "${distpath}" check_ret "(${pi}/${pc}) Build failed for \"${pkg_name}\"" fi archive="$(find "${pkg}/dist" -name "*.mpf" | tail -n1)" name="$(echo "${archive}" | cut -d _ -f 1)" if [ ! -z "${archive}" ]; then rm -f "${distpath}/${name}_"* mv "${archive}" "${distpath}" check_ret "(${pi}/${pc}) Moving package archive failed for \"${pkg_name}\"" fi success "(${pi}/${pc}) Build was successful for \"${pkg_name}\"" pi=$((pi+1)) done success "Completed all the package builds" # sign packages if [ "$OPT_NO_SIGN" -eq 0 ]; then gpg --list-secret-keys "${PUBKEY}" &> /dev/null check_ret "Package signing is enabled, however you do not have the required private key" info "Signing package archives" set_indent for pkg in "${distpath}/"*".mpf"; do gpg --default-key "${PUBKEY}" --yes --detach-sign "${pkg}" &> /dev/null check_ret "Failed to sign package archive: \"$(basename "${pkg}")\"" success "Signed archive: $(basename "${pkg}")" done success "Signing process was completed" unset_indent fi info "Creating pool files" set_indent # create INFO file cat > "${distpath}/INFO" << EOF [${NAME}] size = $(du -sb "${distpath}" | awk '{print $1}') maintainer = ${MAINTAINER} pubkey = ${PUBKEY} EOF check_ret "(1/2) Failed to create pool info file (INFO)" success "(1/2) Created pool info file (INFO)" # create LIST archive rm -rf "${distpath}/list" mkdir -p "${distpath}/list" cd "${distpath}/list" check_ret "Failed change directory into temporary list directory" info "Creating package list archive" for pkg in "${distpath}/"*".mpf"; do archive="$(basename "${pkg}")" name="${archive::-4}" mkdir "${name}" check_ret "Failed to create list directory for \"${archive}\", is there two packages with the same name?" tar xf "${pkg}" -C "${name}" DATA check_ret "Failed to extract data file from \"${archive}\"" done pushd "${distpath}/list" > /dev/null tar czf "${distpath}/LIST" * check_ret "(2/2) Failed to create list archive (LIST)" popd > /dev/null rm -r "${distpath}/list" check_ret "(2/2) Failed to remove temporary list directory" success "(2/2) Created package list archive (LIST)" unset_indent success "Pool build was successful"