diff options
Diffstat (limited to 'treepkg')
-rwxr-xr-x | treepkg | 217 |
1 files changed, 217 insertions, 0 deletions
@@ -0,0 +1,217 @@ +#!/bin/bash +#set -x +source /etc/libretools.conf +source $XDG_CONFIG_HOME/libretools/libretools.conf >/dev/null 2>&1|| true + +# Get system variables +source /etc/makepkg.conf +source $HOME/makepkg.conf >/dev/null 2>&1|| true + +# End inmediately but print an useful message +trap_exit() { + error "($(basename $0)) $@ (leftovers on ${BUILDDIR})" + exit 1 +} + +# Trap signals from makepkg +set -E +trap 'trap_exit "TERM signal caught. Exiting..."' TERM HUP QUIT +trap 'trap_exit "Aborted by user! Exiting..."' INT +trap 'trap_exit "An unknown error has occurred. Exiting..."' ERR + +# return : full version spec, including epoch (if necessary), pkgver, pkgrel +# usage : get_fullver( ${epoch:-0}, $pkgver, $pkgrel ) +get_fullver() { + if [ $1 -eq 0 ]; then +# zero epoch case, don't include it in version + echo $2-$3 + else + echo $1:$2-$3 + fi + +} + +# Add line to build order cache in CSV format +# *must* be run from the PKGBUILD path +# status;depth;pkgbase;[epoch:]pkgver-pkgrel;path;repo +# $1 status +# $2 pkgname +add_order() { + echo "${1};${DEPTH};${2:-${pkgbase}};${fullver};${PWD};$(guess_repo "$PWD")" >> "${BUILDORDER}" + ${VERBOSE} && msg2 "%${DEPTH}s${2:-${pkgbase}} [${1}]" || true +} + +# Bury a package deeper in the tree +# $1 pkgbase +# $2 nextdepth +bury() { +# Bury only if we are going to build the dep +# Get it's current depth and dir name + local current_depth=$(egrep "build;[0-9]\+;${1};" "${BUILDORDER}" | cut -d ';' -f 2) + local current_name="$(printf "%03d" ${current_depth})_${1}" + +# If there's a depth or the package is not the root of the build tree (which +# can lead to funny chicken-and-egg problems), update the depth to the current +# package next-depth and rename the dir too + if [ -z "${current_depth}" ]; then return; fi + if [ -z "${current_name}" ]; then return; fi + if [ ${current_depth} -eq 0 ]; then return; fi + + ${VERBOSE} && msg "Burying ${1} from ${current_depth} to ${2}" + + { + sed -i "s|^\(build;\)\([0-9]\+\)\(;${1};.*\)$|\1${2}\3|" "${BUILDORDER}" && \ + mv "${BUILDDIR}/${current_name}" "${BUILDDIR}/$(printf "%03d" ${2})_${1}" + } || return 1 +} + +# Finds a PKGBUILD on toru's path cache +# Look in all caches but pick the first one +# TODO move to a toru flag (-p?) +where_is() { + grep -m1 "^${1}:" "${TORUPATH}/paths" 2>/dev/null| \ + cut -d: -f2 2>/dev/null +} + +# Guess the repo from the pkgbase path +# $1 path, pwd or where_is +guess_repo() { + basename "$(dirname "${1}")" +} + +if [ ! -f PKGBUILD ]; then + error "Missing PKGBUILD ($PWD)" + exit 1 +fi + +if ! source PKGBUILD ; then + error "Can't source PKGBUILD" + exit 1 +fi + +# Save resources +unset pkgdesc arch license groups backup install md5sums sha1sums \ + sha256sums source options >/dev/null 2>&1 + +unset build package >/dev/null 2>&1 + +for _pkg in ${pkgname[@]}; do + unset package_${_pkg} >/dev/null 2>&1 || true +done +## + +# Get useful values +pkgbase="${pkgbase:-${pkgname[0]}}" +fullver=$(get_fullver ${epoch:-0} ${pkgver} ${pkgrel}) + +# Get or set the work dir +BUILDDIR="${1:-$(mktemp -d /tmp/${pkgbase}-treepkg-XXXx)}" +BUILDORDER="${BUILDDIR}/BUILDORDER" +DEPTH=${2:-0} +NEXTDEPTH=$((${DEPTH} + 1)) +# This can be set as env vars (ie: $ V=false B=false treepkg) +# TODO Turn into flags? +VERBOSE=${V:-true} +BUILD=${B:-true} +CLEANUP=${C:-true} +# Skip BUILDORDER creation and build anything on BUILDDIR +BUILDNOW=${N:-false} + +if [ ! -z "${1}" -a ${DEPTH} -eq 0 ]; then + BUILDNOW=true +fi + +if ! ${BUILDNOW}; then +# ensure it exists + touch "${BUILDORDER}" + +# If this package is already built quit silently + if is_built "${pkgbase}" "${fullver}"; then + add_order "ignore" + exit 0 + fi + +# Ignore if already in build order + egrep -q ";${pkgbase};" "${BUILDORDER}" && exit 0 + +# Add pkgbase to build order + add_order "build" + +# Copy the directory to the build dir +# TODO run makepkg --source to avoid moving garbage around? + cp -r "${PWD}" "${BUILDDIR}/$(printf "%03d" ${DEPTH})_${pkgbase}" + +# Cleanup dep versioning + deps=($(echo "${depends[@]} ${makedepends[@]}" | \ + sed "s/[=<>]\+[^ ]\+//g" | \ + tr ' ' "\n" | \ + sort -u)) + +# NOTE: getting depends from package() is a PITA + for _dep in ${deps[@]}; do +# Ignore if already in build order +# TODO move deps deeper in the tree if +# pkgbase - dep1 +# \ dep2 - dep1 +# dep1 should be depth + 1 +# probably sed -i buildorder and increase dep's dep depth :D +# remember to change dir name from xxx_pkgbase to xxx+1_pkgbase + egrep -q ";${_dep};" "${BUILDORDER}" && bury "${_dep}" ${NEXTDEPTH} + +# Ask toru where's a PKGBUILD + depdir="$(where_is ${_dep})" + + if [ -z "${depdir}" -o ! -d "${depdir}" ]; then +# We specify the pkgname because we can't source the dep PKGBUILD +# Normally 'any' packages are missing from our work ABS + add_order "missing" "${_dep}" + continue + fi + + pushd "${depdir}" >/dev/null + +# Run itself over dependencies + $0 "${BUILDDIR}" ${NEXTDEPTH} + + done +# End BUILD now +fi + +# Only build at the end +if [ ${DEPTH} -eq 0 ]; then + ${VERBOSE} && msg "Starting build" || true + + if ${BUILD}; then + ${VERBOSE} && msg "Build tree stored in ${BUILDORDER}" || true + +# Build everything sorting the build dir +# The reverse order ensures we start by the deepest packages + for _pkg in $(ls -r "${BUILDDIR}"); do +# Ignore if there's no PKGBUILD + if [ ! -f "${BUILDDIR}/${_pkg}/PKGBUILD" ]; then continue; fi + + ${VERBOSE} && msg "Building ${_pkg/_/ }" || true + +# Run build command + pushd "${BUILDDIR}/${_pkg}" >/dev/null + sudo pacman -Syu --noconfirm + + ${FULLBUILDCMD} +# Run local release hook with $1 = $repo + ${HOOKLOCALRELEASE} $(egrep ";${_pkg#*_};" "${BUILDORDER}" | cut -d';' -f6) + popd >/dev/null + done + + else +# Just print the working dir + ${VERBOSE} || echo "${BUILDORDER}" || true + fi + +if ${CLEANUP} ; then + msg2 "Removing ${BUILDDIR}" + rm -rf "${BUILDDIR}" +fi + +fi + +exit $? |