#!/bin/bash source /etc/makepkg.conf source /etc/abs.conf source /etc/libretools.conf source /etc/libretools.d/prtools.conf if [ -z $XDG_CONFIG_HOME ]; then # Avoid /libretools dir doesn't exist errors error "There's no XDG_CONFIG_HOME var set"; exit 1 elif [ -e $XDG_CONFIG_HOME/libretools/libretools.conf ]; then source $XDG_CONFIG_HOME/libretools/libretools.conf fi function usage { echo "cd to a dir containing a PKGBUILD and run:" echo "$0 [options]" printf "This script will check dependencies, build them if possible " printf "and stage the packages on it's repo." echo echo "OPTIONS:" echo " -h : this message." echo " -a absdir : set absdir as ABSROOT." echo " -b build_dir : use a fullpkg build_dir and only build." echo " -c : check deps only, do not build." echo " -d build_dir : use this dir to build. Defaults to mktemp." echo " -n : don't update pacman db." echo " -m max_level : check deps until this level" echo " -r \"command\" : use this instead of \"$FULLBUILDCMD\"" echo exit 1 } function remove_buildorder { # Removes a package from the buildorder # $1 package name # $2 buildorder file grep -Evw "${1}" ${2} > ${2}2 mv -f ${2}2 ${2} } function guess_repo { # Get repo name. Asumes ${ABSROOT}/package/repo/PKGBUILD basename $(pwd) } function get_fullver { # return : full version spec, including epoch (if necessary), pkgver, pkgrel # usage : get_fullver( ${epoch:-0}, $pkgver, $pkgrel ) if [[ $1 -eq 0 ]]; then # zero epoch case, don't include it in version echo $2-$3 else echo $1:$2-$3 fi } function cleanup { # Cleans the build_dir. [ ! -d "${build_dir}" -o "${build_only}" = 'y' ] && return 0 # Do nothing or already cleaned. if [ $level -eq 0 ]; then # Only do cleanup on level 0. msg "Cleaning up ${build_dir}" rm -rf "$build_dir/*" fi } function find_deps { # Checks ABSROOT and look for target pkg deps. Adds them if not built or outdated. source PKGBUILD ## Check this level. local repo=${repo:-$(guess_repo)} local pkgbase=${pkgbase:-${pkgname[0]}} local epoch=${epoch:-0} local fullver=$(get_fullver ${epoch} ${pkgver} ${pkgrel}) if is_built "${pkgbase}" "${fullver}"; then exit 0 # pkg is built and updated fi echo "${level}:${pkgbase}" >> "${build_dir}/BUILDORDER" # greater levels are built first if [ -d "${build_dir}/${pkgbase}" ]; then # PKGBUILD is already there exit 0 else # Copy dir to build_dir mkdir ${build_dir}/${pkgbase} cp -r $(pwd)/* ${build_dir}/${pkgbase} echo "repo=$repo" > "${build_dir}/${pkgbase}/.INFO" # to identify repo later fi msg2 "%${level}s${pkgbase}-${fullver}" # current package plus a space for every level declare -i next_level=$level+1 ## Check next deps level. deps=$(echo "${depends[@]} ${makedepends[@]}" | \ sed "s/[=<>]\+[^ ]\+//g" | \ tr ' ' "\n" | \ sort -u) # All deps in separate line, only once, without version. for _dep in ${deps[@]}; do local found=false if [ -d "${ABSROOT}/${_dep}" ]; then # ABSROOT/package/repo for _repo in ${REPOS[@]}; do # Use PKGBUILD from repo in REPOS array order if [ -e "${ABSROOT}/${_dep}/${_repo}/PKGBUILD" ]; then pushd "${ABSROOT}/${_dep}/${_repo}" > /dev/null $0 -c -d ${build_dir} -l ${next_level} # run this cmd on dep's PKGBUILD dir [ $? -eq 20 ] && return 20 # probable circular deps popd > /dev/null local found=true break 1 # found, go to next dep fi done else # pkgsplit, needs guess for _repo in ${REPOS[@]}; do if _dir=($(find "$ABSROOT/" -type f \ -wholename "*/${_repo}/PKGBUILD" -print0 2>/dev/null | \ "xargs" -0 -e grep -HEw "pkgname=|pkgbase=|provides=" | \ grep -w "$_dep" 2>&1)) ; then _dir=$(dirname $(echo $_dir | cut -d: -f1)) plain "guess for $_dep -> $_dir" pushd "$_dir" > /dev/null $0 -c -d ${build_dir} -l ${next_level} # run this cmd on dep's PKGBUILD dir [ $? -eq 20 ] && return 20 # probable circular dep popd > /dev/null local found=true break 1 # found, go to next dep fi done fi if ( ${found} ); then continue 1 # go to next dep else echo "dep_not_found:$_dep" >> $build_dir/log fi done unset next_level dir # unset PKGBUILD variables unset pkgbase pkgname pkgver pkgrel epoch pkgdesc arch url license groups depends \ makedepens checkdepends optdepends provides conflicts replaces backup \ options install changelog source noextract md5sums build check package } function __build () { pushd ${build_dir} > /dev/null build_packages=($(sort -gr $buildorder | cut -d: -f2)) # greater levels must be built first while [ ${#build_packages[@]} -ge 1 ]; do pushd $build_dir/${build_packages[0]} > /dev/null source PKGBUILD msg2 "${pkgbase:-${pkgname[0]}} $pkgver-$pkgrel" msg2 "Checking for non free deps" pkgbuild-check-nonfree || { if [ $? -eq 15 ]; then # this error means nonfree others means fail. echo "nonfree:$(basename $PWD)" >> $build_dir/log remove_buildorder "$(basename $PWD)" $buildorder # take out package from $buildorder continue # build next package fi } msg2 "Building $(basename $PWD)" $FULLBUILDCMD; r=$? # this buildcmd is on libretools.conf case $r in 0) ## Succesfull build plain "The build was succesful." if source .INFO && [ -n $repo ]; then if [ ! -z $HOOKLOCALRELEASE ]; then # Calls a local release script if it's used find -name "*.pkg.tar.?z" -print0 | xargs -0 $HOOKLOCALRELEASE $repo fi librestage $repo || echo "unstaged:$(basename $PWD)" >> $build_dir/log msg "Updating pacman db and packages" sudo pacman -Sy || true fi echo "built:$(basename $PWD)" >> $build_dir/log ;; *) ## Build failed error "There were errors while trying to build the package." echo "failed:$(basename $PWD)" >> $build_dir/log ;; esac remove_buildorder "${build_packages[0]}" $buildorder || true build_packages=($(sort -gr $buildorder | cut -d: -f2)) # which is next package? popd > /dev/null done pkgs=($(grep "nonfree:" $build_dir/log)) && { error "Those packages contain nonfree deps:" echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2 } pkgs=($(grep "built:" $build_dir/log)) && { msg "Those packages were built and staged:" echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2 } pkgs=($(grep "failed:" $build_dir/log)) && { error "Those packages failed to build:" echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2 } pkgs=($(grep "unstaged:" $build_dir/log)) && { error "Those packages couldn't be staged because of missing reponame:" echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2 } popd > /dev/null } function trap_exit { # End inmediately but print a useful message error "$@" warning "Leftover files left on $build_dir" exit 1 } # Trap signals from makepkg set -E trap 'trap_exit "(prfullpkg:${level}) TERM signal caught. Exiting..."' TERM HUP QUIT trap 'trap_exit "(prfullpkg:${level}) Aborted by user! Exiting..."' INT trap 'trap_exit "(prfullpkg:${level}) An unknown error has occurred. Exiting..."' ERR ban_file=$XDG_CONFIG_HOME/libretools/ban force_build="" level=0 noupdate='n' build_only='n' check_deps_only='n' max_level=21 while getopts 'ha:b:cd:l:nm:r:' arg; do case $arg in h) usage ;; a) ABSROOT="$OPTARG" ;; b) build_only='y' build_dir="$OPTARG" if [ -z ${build_dir} ]; then usage fi if [ ! -r ${build_dir}/BUILDORDER ] ; then error "${build_dir}/BUILDORDER doesn't exist." exit 1 fi;; c) check_deps_only='y' ;; d) build_dir="$OPTARG" ;; l) level=$OPTARG ;; # hidden option to know dep level. n) noupdate='y';; m) max_level=$OPTARG ;; r) FULLBUILDCMD="$OPTARG" ;; esac done if [ ${build_only} == 'n' ]; then [ ! -r PKGBUILD ] && { # Check if we are actually on a build directory. Do this early. error "This isn't a build directory" usage } if [ ! -z "$HOOKPKGBUILDMOD" ]; then "$HOOKPKGBUILDMOD" fi fi if [ $level -eq 0 ]; then if [ ! -d ${build_dir} ]; then # in case of custom -d option mkdir -p ${build_dir} else cleanup # files already there can screw find_deps fi build_dir=${build_dir:-$(mktemp -d /tmp/fullpkg.XXXXXX)} # use -d option or else mktemp touch ${build_dir}/{log,BUILDORDER} ${ban_file} # make files for log and buildorder buildorder=${build_dir}/BUILDORDER if [ ${noupdate} = 'n' ]; then msg "Updating pacman db and packages" sudo pacman -Syu --noconfirm || true fi if [ ${build_only} == 'y' ]; then msg "Build Packages" __build exit 0 fi msg "Checking dependencies" fi [ $level -ge $max_level ] && exit 20 # Probable circular deps find_deps || { if [ $? -eq 20 ]; then # Probable circular deps if [ $level -eq 0 ]; then # Show error only on level 0 error "Check for circular deps on $build_dir/BUILDORDER"; fi fi exit 20 # Pass message 20 } [ $check_deps_only = 'y' -o $level -gt 0 ] && exit 0 # only build on level 0 if [ $level -eq 0 -a -d $build_dir ]; then # Sanity check if [ ! -w $ban_file -o ! -r $ban_file ]; then # Check ban_file permisions chmod a+rw $ban_file || error "Ban file is not readable/writable ($ban_file)" else rsync -e ssh -aq $PARABOLAHOST:mips64el/ban >/dev/null 2>&1 || { warning "Failed to get ban list" && [ -r ${ban_file} ] && { # use local copy if it exist search=$(cat ${ban_file} | tr "\n" "|") egrep -w "$search" ${buildorder} >> ${build_dir}/banned # Keep track of banned files egrep -vw "$search" ${buildorder} > ${buildorder}2 # Take banned packages out of buildorder mv -f ${buildorder}2 ${buildorder} unset search } } fi fi msg "Building packages:" __build # Build the packages echo msg2 "Check if your system works fine and librerelease if it does" exit 0