diff options
Diffstat (limited to 'src')
44 files changed, 3904 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..ff8d399 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,3 @@ +libre_execdir=$(bindir) +libre_datadir=$(sysconfdir) +include ../common.mk diff --git a/src/abslibre-tools/Makefile b/src/abslibre-tools/Makefile new file mode 100644 index 0000000..f2cec54 --- /dev/null +++ b/src/abslibre-tools/Makefile @@ -0,0 +1,3 @@ +libre_execdir=$(bindir) +libre_datadir=$(sysconfdir)/libretools.d +include ../../common.mk diff --git a/src/abslibre-tools/createworkdir b/src/abslibre-tools/createworkdir new file mode 100755 index 0000000..b443c08 --- /dev/null +++ b/src/abslibre-tools/createworkdir @@ -0,0 +1,63 @@ +#!/bin/bash +# CreateWorkDir +# Creates a dir structure for working with Parabola packages + +# Copyright 2010 Nicolás Reynolds + +# ---------- GNU General Public License 3 ---------- + +# This file is part of Parabola. + +# Parabola 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. + +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +source /etc/libretools.conf +custom_config=$XDG_CONFIG_HOME/libretools/libretools.conf +[[ -e $custom_config ]] && source $custom_config + +[[ ! -d ${WORKDIR} ]] && { # Create the WORKDIR + + msg "Creating WORKDIR on ${WORKDIR}" + mkdir -p ${WORKDIR} ||{ + error "Could not create ${WORKDIR}"; exit 1 + } + +} + +for _repo in ${REPOS[@]}; do # Create the staging dirs + + [[ ! -d ${WORKDIR}/staging/${_repo} ]] && { + mkdir -p ${WORKDIR}/staging/${_repo} || { + error "Can't create ${WORKDIR}/staging/${_repo}" + exit 1 + } + } + +done + +[[ ! -d ${WORKDIR}/abslibre/.git ]] && { + msg "Cloning into ABSLibre" + CMD="git clone ${ABSLIBREGIT} ${WORKDIR}/abslibre" + ${CMD} || { + error "Could not clone ABSLibre" + plain "Try running this command:" + echo + plain "${CMD}" + exit 1 + } +} + +msg "Finished, your packaging dir tree looks like this now:" +ls --color=always ${WORKDIR}/*/* + +exit 0 diff --git a/src/abslibre-tools/libreaddiff b/src/abslibre-tools/libreaddiff new file mode 100755 index 0000000..98646a2 --- /dev/null +++ b/src/abslibre-tools/libreaddiff @@ -0,0 +1,97 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +# Copyright (C) 2011, 2012 Michał Masłowski <mtjm@mtjm.eu> +# +# 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 Affero 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 <http://www.gnu.org/licenses/>. + + +set -e + +. /etc/libretools.conf +custom_config=$XDG_CONFIG_HOME/libretools/libretools.conf +[ -e $custom_config ] && . $custom_config + +for arg in "$@" ; do + case "$arg" in + -h|--h|--he|--hel|--help|-\?) + echo 'Usage: libreaddiff repo [arch] + +This script outputs a diff of package names and versions in repo +between pacman'\''s sync db and abslibre checkout.' >&2 + exit 0 + ;; + esac +done + +# The repo to find missing packages in. +repo=$1 +# The arch to check in Arch repos, other will have all arches checked. +arch=${2:-mips64el} +# A Python tuple of repos which don't have arch=any packages. +archrepos='("core", "extra", "community")' + +diff -U0 \ + <( ( + cd /var/lib/pacman/sync + for f in $repo.db ; do + tar xOf $f | python -c 'import sys +arch = None +name = None +version = None +it = iter(sys.stdin) +try: + while True: + line = next(it) + if line == "%ARCH%\n": + arch = next(it) + if arch == "'"$arch"'\n" or "'$repo'" not in '"$archrepos"': + print("%s-%s" % (name.strip(), version.strip())) + if line == "%NAME%\n": + name = next(it) + if line == "%VERSION%\n": + version = next(it) +except StopIteration: + pass +' + done + ) | sort ) \ + <( ( + cd "${WORKDIR}/abslibre" + # Needed to not include pkgnames specific to other arches. + CARCH=$arch + for f in $repo/* ; do + unset pkgname + unset epoch + unset pkgver + unset pkgrel + unset arch + . $f/PKGBUILD || continue + is_here=false + for arc in ${arch[@]} ; do + if [ "$arc" = "any" -o "$arc" = "$CARCH" ] ; then + is_here=true + break + fi + done + if [ "$is_here" = "true" ] ; then + for name in ${pkgname[@]} ; do + if [ -z "$epoch" ] ; then + echo $name-$pkgver-$pkgrel + else + echo $name-$epoch:$pkgver-$pkgrel + fi + done + fi + done + ) | sort ) | sed -rn 's/^[+-][^+-].+$/&/p' diff --git a/src/abslibre-tools/librerelease b/src/abslibre-tools/librerelease new file mode 100755 index 0000000..5a98cf8 --- /dev/null +++ b/src/abslibre-tools/librerelease @@ -0,0 +1,157 @@ +#!/bin/bash +# Librerelease +# Uploads packages into [staging] + +# Copyright 2010 Nicolás Reynolds + +# ---------- GNU General Public License 3 ---------- + +# This file is part of Parabola. + +# Parabola 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. + +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +source /etc/libretools.conf +custom_config=$XDG_CONFIG_HOME/libretools/libretools.conf + +function usage { + echo "$(gettext "Usage: $0")" + echo + echo "$(gettext "This script uploads packages on $WORKDIR/stagging")" + echo "$(gettext "to parabola server.")" + echo + echo "$(gettext "OPTIONS:")" + echo "$(gettext " -h this message.")" + echo "$(gettext " -l only list packages but not upload them.")" + echo "$(gettext " -c clean packages on $WORKDIR/staging.")" + echo "$(gettext " -n dry-run")" +} + +function list_packages { + repos=($(find "$WORKDIR/staging/" -mindepth 1 -type d \! -empty -printf '%f ' 2>/dev/null)) + for _repo in ${repos[@]}; do + msg2 "$_repo" + find ${WORKDIR}/staging/${_repo} -type f -printf "%f\n" + done + unset repos +} + +function sign_packages { + if [ -z "${SIGEXT}" ]; then + SIGEXT=.sig + warning "Empty SIGEXT var, using default .sig" + fi + + if [ -z "${GPG_AGENT_INFO}" ]; then + warning "It's better to use gpg-agent to sign packages in batches" + fi + + packages=($(find "${WORKDIR}/staging/" -type f -iname '*.pkg.tar.?z')) + for package in ${packages[@]}; do + if [ -f "${package}${SIGEXT}" ]; then + + warning "Package signature found, verifying..." + +# Verify that the signature is correct, else remove for re-signing + if ! gpg --quiet --verify "${package}${SIGEXT}" >/dev/null 2>&1; then + error "Failed! Resigning..." + rm -f "${package}${SIGEXT}" + fi + fi + + if ! [ -f "${package}${SIGEXT}" ]; then + msg2 "Signing ${package}..." + gpg --default-key "${SIGID}" --output "${package}${SIGEXT}" \ + --detach-sig "${package}" || { + error "Signing failed" + exit 2 + } + fi + + done +} + +# Remove everything that's not a package or a signature +function clean_non_packages { + find $WORKDIR/staging/ -type f \ + \! -iname "*.pkg.tar.?z" -a \! -iname "*.pkg.tar.?z.sig" \ + -delete +} + +# Clean everything if not on dry-run mode +function clean { + [ -z ${dryrun} ] && \ + rm -f $@ +} + +if [ -w / ]; then + error "Run $0 as normal user" + exit 1 +fi + +while getopts 'hlcn' arg; do + case $arg in + h) usage; exit 0 ;; + l) list_packages; exit 0 ;; + c) clean; exit $? ;; + n) dryrun="--dry-run" ;; + esac +done + +[[ -e $custom_config ]] && source $custom_config + +[[ ! -z ${HOOKPRERELEASE} ]] && bash -c "${HOOKPRERELEASE}" + +clean_non_packages +if [ ! -z "${SIGID}" ]; then + sign_packages +else + error "Package signing is *required*, please set SIGID on your libretools.conf" + exit 1 +fi + +# Make the permissions of the packages 644 otherwise the user will get access +# denied error when they try to download (rsync --no-perms doesn't seem to +# work). +find ${WORKDIR}/staging -type f -exec chmod 644 {} \; +find ${WORKDIR}/staging -type d -exec chmod 755 {} \; + +# Get the synced files +SYNCED_FILES=($(find ${WORKDIR}/staging -type f)) + +msg "%s to upload" $(du -h -d 0 ${WORKDIR}/staging | tr "\t" " " | cut -d" " -f1) +msg "Uploading packages..." +rsync --recursive \ + ${dryrun} \ + --no-group \ + --no-perms \ + --copy-links \ + --hard-links \ + --partial \ + --prune-empty-dirs \ + --human-readable \ + --progress \ + -e "ssh " \ + ${WORKDIR}/staging \ + ${PARABOLAHOST}:${LIBREDESTDIR}/ || { + error "Sync failed, try again" + exit 1 + } + +msg "Removing ${#SYNCED_FILES[@]} files from local [staging]" +clean ${SYNCED_FILES[@]} + +msg "Running db-update on repos" +ssh ${PARABOLAHOST} dbscripts/db-update + +exit 0 diff --git a/src/abslibre-tools/librestage b/src/abslibre-tools/librestage new file mode 100755 index 0000000..ae66cce --- /dev/null +++ b/src/abslibre-tools/librestage @@ -0,0 +1,137 @@ +#!/bin/bash +# LibreStage +# Prepares packages for upload into [staging] + +# Copyright 2010 Nicolás Reynolds + +# ---------- GNU General Public License 3 ---------- + +# This file is part of Parabola. + +# Parabola 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. + +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + + +source /etc/libretools.conf +custom_config=$XDG_CONFIG_HOME/libretools/libretools.conf +[[ -e $custom_config ]] && source $custom_config + +if [ -w / ]; then + error "This script should be run as regular user" + exit 1 +fi + + +# End Config + +usage() { + cat <<EOU +LibreStage Copyright (C) 2011 Nicolás Reynolds +This program comes with ABSOLUTELY NO WARRANTY. +This is free software, and you are welcome to redistribute it +under the terms of the GNU General Public License version 3 or later. + + +Usage: $(basename $0) <repo> [<repo2> ... ] + +LibreRelease will stage for upload the package(s) built by the PKGBUILD on +the current directory to the specified repo(s). +EOU +} + +repos=$@ + +while getopts 'h' arg; do + case $arg in + h) usage; exit 0 ;; + esac +done + +if [ ${#repos} -eq 0 ]; then + usage + exit 1; +fi + +[[ ! -e ./PKGBUILD ]] && { + error "PKGBUILD not found" + exit 1 +} + +# Source the needed files +source /etc/makepkg.conf +[[ -e ~/.makepkg.conf ]] && source ~/.makepkg.conf +source ./PKGBUILD +[[ -e ./rePKGBUILD ]] && source ./rePKGBUILD + +# Default package location +PKGDEST=${PKGDEST:-.} +SRCPKGDEST=${SRCPKGDEST:-.} + +PKGEXT=".pkg.tar.?z" + +staged=false +# Copies the packages to the specified repos inside staging +for _arch in ${ARCHES[@]}; do + for pkg in ${pkgname[@]}; do + + pkgpath=$(find ${PKGDEST}/ -type f \ + -name "${pkg}-$(get_full_version "${pkg}")-${_arch}${PKGEXT}") + + [[ -z ${pkgpath} ]] && continue + + pkgfile=$(basename ${pkgpath}) + +# TODO refactor this + if [ -e "${pkgpath}" ]; then + msg "Found ${pkgfile}" + + canonical="" + for _repo in ${repos[@]}; do + + if [ ! -d "${WORKDIR}/staging/${_repo}" ]; then + warning "[${_repo}] didn't exist, creating..." + mkdir -p "${WORKDIR}/staging/${_repo}" + fi + + if [ -z "$canonical" ]; then + canonical="${WORKDIR}/staging/${_repo}/${pkgfile}" + + cp "${pkgpath}" "${WORKDIR}/staging/${_repo}/" || { + error "Can't put ${pkgfile} on [staging]" + exit 1 + } && { + msg2 "${pkg} staged on [${_repo}]" + staged=true + } + + else + ln "${canonical}" "${WORKDIR}/staging/${_repo}/${pkgfile}" || { + error "Can't put ${pkgfile} on [staging]" + exit 1 + } && { + msg2 "${pkg} staged on [${_repo}]" + staged=true + } + + fi + done + fi + done +done + +if ! $staged ; then + error "No package was staged" + exit 1 +fi + +exit 0 @@ -0,0 +1,133 @@ +#!/bin/bash +# Copyright 2010 Nicolás Reynolds, Joshua Ismael + +# ---------- GNU General Public License 3 ---------- + +# This file is part of Parabola. + +# Parabola 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. + +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. /etc/libretools.conf +. /etc/abs.conf + +cmd=${0##*/} + +usage() { + echo "Usage: $cmd pkgname-from-aur1 [pkgname-from-aur2 ...]" + echo + echo "This script will download packages from aur to the current dir" + echo "and check their license for nonfree issues." +} + +main() { + while getopts 'h' arg; do + case $arg in + h) usage; exit 0;; + *) usage; exit 1;; + esac + done + + local missing_deps=() + for _pkg in "$@"; do + + # Remove the version + _pkg="${_pkg%%[<>=]*}" + + if [[ -f "${_pkg}/PKGBUILD" ]]; then + warning "${_pkg} already existed." + + # Check if we want to diff + if [[ -z "${DIFFTOOL}" ]]; then + continue + else + # Store our copy of the PKGBUILD dir + _diff="${PWD}/${_pkg}" + stdnull "pushd $(mktemp --tmpdir -d ${_pkg}.XXXX)" + msg2 "Downloading PKGBUILD into ${PWD} for diff" + fi + fi + + msg "Downloading $_pkg..." + local url=https://aur.archlinux.org/packages/${_pkg:0:2}/${_pkg}/$_pkg.tar.gz + wget -O - -q "$url" | tar xzf - >/dev/null 2>&1 + + if [[ $? -ne 0 ]]; then + error "Couldn't get $_pkg" + continue + fi + + stdnull "pushd $_pkg" + + if [[ ! -z "$_diff" ]]; then + msg2 "Diffing files" + # Diff all files with our difftool + for file in *; do + "${DIFFTOOL}" "${_diff}/${file}" "${file}" + done + + # Go back to our copy to continue working + stdnull "pushd ${_diff}" + fi + + . PKGBUILD + + ################################################################ + + if ! pkgbuild-check-nonfree; then + if [[ $? = 15 ]]; then + warning "This PKGBUILD links to known unfree packages" + fi + fi + + ################################################################ + + msg2 "Checking license..." + local free=0 + for _license in ${license[@]}; do + if [[ ! -d /usr/share/licenses/common/$_license ]]; then + warning "License $_license is not a common license" + free=1 + fi + done + + if [[ $free -eq 1 ]]; then + plain "Please check that the license is included in the package and *specially* that it respects your freedom." + fi + + ################################################################ + + for _dep in "${depends[@]}" "${makedepends[@]}"; do + _dep=${_dep/[<>=]*/} + if ! is_built $_dep; then + if ! find ${ABSROOT} -maxdepth 2 -type d -name "$_dep" | egrep "*" >/dev/null ; then + msg2 "$_dep will be get from AUR" + missing_deps+=($_dep) + fi + else + msg2 "$_dep is on repos" + fi + done + + stdnull popd + done + + [[ ${#missing_deps[*]} -gt 0 ]] && { + msg2 "Retrieving missing deps: ${missing_deps[@]}" + $0 ${missing_deps[@]} + } + + exit 0 +} + +main "$@" diff --git a/src/chroot-tools/Makefile b/src/chroot-tools/Makefile new file mode 100644 index 0000000..3ae95ea --- /dev/null +++ b/src/chroot-tools/Makefile @@ -0,0 +1,3 @@ +libre_execdir=$(sbindir) +libre_datadir=$(sysconfdir)/libretools.d +include ../../common.mk diff --git a/src/chroot-tools/chcleanup b/src/chroot-tools/chcleanup new file mode 100755 index 0000000..f957d3b --- /dev/null +++ b/src/chroot-tools/chcleanup @@ -0,0 +1,76 @@ +#!/bin/bash -eE +# (c) Nicolás Reynolds <fauno@parabola.nu> +# Released under GPLv3 +# +# Performs chroot cleanup smartly, it only removes the unneeded packages or +# leaves you with a cleansystem +# +# See: HOOKPREBUILD + +DRYRUN=${DRYRUN:-false} + +################################################################################ +# Define these here to avoid having dependencies on outside files + +msg() { + local mesg=$1; shift + printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 +} + +msg2() { + local mesg=$1; shift + printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 +} + +error() { + local mesg=$1; shift + printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 +} + +################################################################################ + +if [[ ! -f /.arch-chroot ]] && ! ${DRYRUN}; then + error "(chcleanup): Must be run inside of a chroot" + exit 1 +fi + +source /etc/libretools.d/chroot.conf +# If we're running makepkg +if [ -f PKGBUILD ]; then + source PKGBUILD + CHROOTEXTRAPKG+=("${depends[@]}" + "${makedepends[@]}" + "${checkdepends[@]}") +fi + +msg "Cleaning chroot..." + +TEMPDIR="$(mktemp --tmpdir -d $(basename $0).XXXXX)" +cp -a /var/lib/pacman/sync "${TEMPDIR}/" +cleanup_log="${TEMPDIR}"/libretools-cleanup.log + +# Get the full list of packages needed by dependencies, including the base system +pacman -b "${TEMPDIR}" \ + -Sp --print-format "%n" \ + base-devel "${CHROOTEXTRAPKG[@]}" \ + >"${cleanup_log}" + +# Diff installed packages against a clean chroot then remove leftovers +packages=($(comm -23 <(pacman -Qq | sort -u) \ + <(sort -u "${cleanup_log}"))) + +RET=0 +if [[ ${#packages[@]} != 0 ]]; then + msg2 "Removing %d packages" ${#packages[@]} + + if ${DRYRUN}; then + echo "${packages[@]}" + else + # Only remove leftovers, -Rcs removes too much + pacman --noconfirm -Rn "${packages[@]}" || RET=$? + fi +fi +# Cleanup +rm -rf "${TEMPDIR}" + +exit $RET diff --git a/src/chroot-tools/chroot.conf b/src/chroot-tools/chroot.conf new file mode 100644 index 0000000..a161a61 --- /dev/null +++ b/src/chroot-tools/chroot.conf @@ -0,0 +1,13 @@ +# The full path to the chroot is +# $CHROOTDIR/$CHROOT/$CHROOTCOPY +# where $CHROOTCOPY is set at runtime, either +# - based on the username +# - set with the `-l COPY` flag +# The purpose of having a $CHROOT setting is that multiple clones of the same +# base $CHROOT can quickly and easily be created. +CHROOTDIR=/var/lib/archbuild +CHROOT=default + +# Extra packages to have installed on the chroot. +# This is in addition to CHROOTPKG=(base-devel) +CHROOTEXTRAPKG=(distcc ccache tsocks libretools) diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot new file mode 100755 index 0000000..45aec10 --- /dev/null +++ b/src/chroot-tools/librechroot @@ -0,0 +1,230 @@ +#!/bin/bash -euE +# librechroot + +# Copyright 2010 Nicolás Reynolds +# Copyright 2011 Joshua Haase +# Copyright 2012-2013 Luke Shumaker +# +# This file is part of Parabola. +# +# Parabola 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. +# +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. /usr/share/libretools/conf.sh +load_conf_libretools_chroot + +. libremessages +. /usr/share/devtools/makechrootpkg.sh + +# Because the makechrootpkg.sh library functions don't work with -euE +normshell() ( + set +euE + "$@" +) + +cmd=${0##*/} +usage() { + echo "Usage: $cmd [OPTIONS] COMMAND [ARGS...]" + echo 'Interacts with an archroot (arch chroot).' + echo '' + echo 'There may be multiple chroots; they are stored in $CHROOTDIR.' + echo '' + echo 'Each chroot is named; the default is configured with $CHROOT.' + echo '' + echo "Each named chroot has a master clean copy (named 'root'), and any" + echo 'number of other named copies; the copy used by default is the' + echo "current username (or \$SUDO_USER, or 'copy' if root)." + echo '' + echo 'The full path to the chroot copy is "$CHROOTDIR/$CHROOT/$COPY",' + echo 'Unless the copy name is manually specified as an absolute path,' + echo 'in which case, that path is used.' + echo '' + echo 'The current settings for the above varibles are:' + echo " CHROOTDIR : $CHROOTDIR" + echo " CHROOT : $CHROOT" + echo " COPY : $COPY" + echo " root path : $rootdir" + echo " copy path : $copydir" + echo '' + echo 'If the chroot, or copy does not exist, it will be created' + echo 'automatically.' + echo '' + echo 'This command will make the following configuration changes in' + echo 'the chroot:' + echo " - overwrite \`/etc/libretools.d/chroot.conf'" + echo " - overwrite \`/etc/pacman.d/mirrorlist'" + echo " - set \`CacheDir' in \`/etc/pacman.conf'" + echo '' + echo 'Creating a copy, deleting a copy, or syncing a copy can be fairly' + echo 'slow; but are very fast if $CHROOTDIR is on a btrfs partition.' + echo '' + echo 'Options:' + echo ' -n <CHROOT> Name of the chroot to use' + echo ' -l <COPY> Name of, or absolute path to, the copy to use' + echo ' -N Disable networking in the chroot' + echo ' -C <file> Location of pacman config file' + echo ' -M <file> Location of makepkg config file' + echo '' + echo 'Commands:' + echo ' Create/copy/delete:' + echo ' noop|make Do not do anything, but still creates the' + echo ' chroot copy if it does not exist' + echo " sync Sync the copy with the clean ('root') copy" + echo " delete delete the chroot copy" + echo ' Dealing with packages:' + echo ' install-file FILES... Like `pacman -U FILES...`' + echo ' install-name NAMES... Like `pacman -S NAMES...`' + echo ' update Like `pacman -Syu`' + echo ' clean-pkgs Remove all "exta" packages from the chroot copy' + echo ' Other:' + echo ' run CMD... Run CMD in the chroot copy' + echo ' enter Enter an interactive shell in the chroot copy' + echo ' clean-repo Clean /repo in the chroot copy' + echo ' help Show this message' # usage +} + +# Globals: $CHROOTDIR, $CHROOT, $COPY, $rootdir and $copydir +main() { + COPY=$LIBREUSER + [[ $COPY != root ]] || COPY=copy + + # defaults + rootdir="${CHROOTDIR}/${CHROOT}/root" + copydir="${CHROOTDIR}/${CHROOT}/${COPY}" + + local mode=enter + local archroot_args=() + while getopts 'n:l:NC:M:' arg; do + case $arg in + n) CHROOT=$OPTARG;; + l) COPY=$OPTARG;; + N) + # We do this so that it carries through to + # chroot_* functions + archroot() { + $(which archroot) -N "$@" + } + ;; + C|M) archroot_args+=(-$arg "$OPTARG");; + *) usage; return 1;; + esac + done + shift $(($OPTIND - 1)) + if [[ $# < 1 ]]; then + error "Must specify a command" + usage + return 1 + fi + mode=$1 + shift + + rootdir="${CHROOTDIR}/${CHROOT}/root" + if [[ ${COPY:0:1} = / ]]; then + copydir=$COPY + else + copydir="${CHROOTDIR}/${CHROOT}/${COPY}" + fi + + ######################################################################## + + if [[ $mode == help ]]; then + usage + return 0 + fi + + if (( EUID )); then + error "This program must be run as root." + return 1 + fi + + umask 0022 + + # Keep this lock as long as we are running + # Note that '9' is the same FD number as in (mk)archroot + lock_open_write 9 "$copydir" \ + "Waiting for existing lock on chroot copy to be released: [$COPY]" + + if [[ ! -d $rootdir ]]; then + msg "Creating 'root' copy for chroot [$CHROOT]" + set +u # if archroot_args is empty, it counts as unbound + archroot "${archroot_args[@]}" -m "$rootdir" base-devel + set -u + fi + + if [[ ! -d $copydir ]] || [[ $mode == sync ]]; then + msg "Syncing copy [$COPY] with root copy" + normshell chroot_sync "$CHROOTDIR/$CHROOT" "$COPY" + fi + + mkdir -p "$copydir/etc/libretools.d" + { + if [[ -n ${CHROOTEXTRAPKG[@]:-} ]]; then + printf 'CHROOTEXTRAPKG=(' + printf "'%s' " "${CHROOTEXTRAPKG[@]}" + printf ')\n' + else + printf 'CHROOTEXTRAPKG=()\n' + fi + } > "$copydir"/etc/libretools.d/chroot.conf + + if [[ $mode != delete ]]; then + # "touch" the chroot first + # this will + # - overwrite \`/etc/pacman.d/mirrorlist'" + # - set \`CacheDir' in \`/etc/pacman.conf'" + # - apply -C or -M flags + set +u # if archroot_args is empty, it counts as unbound + archroot "${archroot_args[@]}" -r "$copydir" true + set -u + fi + + ######################################################################## + + case "$mode" in + # Creat/copy/delete + noop|make|sync) :;; + delete) + if [[ -d $copydir ]]; then + normshell chroot_delete "$copydir" + fi + ;; + + # Dealing with packages + install-file) normshell chroot_install_pkgs "$copydir" "$@";; + install-name) archroot -r "$copydir" pacman -Sy "$@";; + clean-pkgs) + trap "rm -f '$copydir'/clean '$copydir'/chrootexec" EXIT + cp -a "$(which chcleanup)" "$copydir/clean" + echo '#!/bin/bash' > "$copydir/chrootexec" + echo 'mkdir /build' >> "$copydir/chrootexec" + echo 'cd /build; /clean' >> "$copydir/chrootexec" + chmod 755 "$copydir/chrootexec" + archroot -r "$copydir" /chrootexec + ;; + + # Other + run) archroot -r "$copydir" "$@";; + enter) archroot -r "$copydir" bash;; + clean-repo) + rm -rf "${copydir}/repo/*" + bsdtar -czf "${copydir}/repo/repo.db.tar.gz" -T /dev/null + ln -s "repo.db.tar.gz" "${copydir}/repo/repo.db" + ;; + *) + error "Unrecognized command: \`$mode'" + return 1 + ;; + esac +} + +main "$@" diff --git a/src/chroot-tools/libremakepkg b/src/chroot-tools/libremakepkg new file mode 100755 index 0000000..b8cdca1 --- /dev/null +++ b/src/chroot-tools/libremakepkg @@ -0,0 +1,311 @@ +#!/bin/bash -euE +# libremakepkg + +# Copyright 2010 - 2011 Nicolás Reynolds +# Copyright 2011 Joshua Ismael Haase Hernández +# Copyright 2012-2013 Luke Shumaker +# +# This file is part of Parabola. +# +# Parabola 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. +# +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. /usr/share/libretools/conf.sh +load_conf_libretools_chroot + +. libremessages + +shopt -s nullglob +umask 0022 + +# Boring/mundane functions ##################################################### + +# End inmediately but print a useful message +trap_exit() { + error "$*" + set +euE + . /usr/share/devtools/makechrootpkg.sh + chroot_copy_out_logs "$@" + exit 1 +} + +# Usage run [-N] $copydir "$cmd" +# Runs cmd properly, whether in a chroot already or not. +# +# Note that $cmd is a quoted string, not a list of arguments. +# $copydir=/ if INCHROOT=true +# +# Environment +# - $INCHROOT is set +run() { + local HASNET=true + [[ $1 == -N ]] && { HASNET=false; shift; } + local copydir=$1; shift + local cmd="$*" + + cat >"$copydir/chrootexec" <<EOF +#!/bin/bash +. /etc/profile +${INCHROOT} || export HOME=/build +${INCHROOT} || cd /build + +${cmd} +EOF + chmod 755 "$copydir/chrootexec" + + local flags='' + if $INCHROOT; then + $HASNET || flags='-n' + unshare $flags -- /chrootexec + else + $HASNET || flags='-N' + librechroot $flags -l "$copydir" run /chrootexec + fi +} + +# Usage: add_to_local_repo $copydir +add_to_local_repo() ( + set +euE + . /usr/share/devtools/makechrootpkg.sh + chroot_add_to_local_repo "$@" +) + +# Usage: chroot_copy_in $copydir +# Environment: +# - In the dirctory of a PKGBUILD +# - $SRCDEST is set +chroot_copy_in() ( + set +euE + . /usr/share/devtools/makechrootpkg.sh + chroot_copy_in "$@" +) + +# Usage: chroot_copy_out $copydir $owner +# Environment: +# - $SRCDEST is set +# - $PKGDEST is set +chroot_copy_out() ( + set +euE + . /usr/share/devtools/makechrootpkg.sh + chroot_copy_out_pkgs "$@" + chroot_copy_out_logs "$@" + chroot_copy_out_srcs "$@" +) + +# Usage: chroot_let_nobody_use_pacman $copydir +chroot_let_nobody_use_pacman() ( + set +euE + . /usr/share/devtools/makechrootpkg.sh + chroot_let_nobody_use_pacman "$@" +) + +# Usage: chroot_init $copydir $repack +# Environment +# - $LIBREHOME is set +chroot_init() { + local copydir=$1 + local repack=$2 + + librechroot -l "$copydir" make # make sure the chroot exists + mkdir -p "$copydir"/{build,pkgdest,srcdest} + + # Remove anything in there UNLESS -R (repack) was passed + $repack || rm -rf "$copydir"/build/* + + if [[ -r "$LIBREHOME/.gnupg/pubring.gpg" ]]; then + install -D "$LIBREHOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" + fi + rm -f "$copydir/build/.makepkg.conf" + + MAKEPKG_CONF="$copydir/etc/makepkg.conf" set_conf_makepkg PKGDEST /pkgdest + MAKEPKG_CONF="$copydir/etc/makepkg.conf" set_conf_makepkg SRCDEST /srcdest + + if grep -q '^\[repo\]' "$copydir/etc/pacman.conf"; then + cat >> "$copydir/etc/makepkg.conf" <<EOF +[repo] +SigLevel = Optional TrustAll +Server = file:///repo +EOF + fi + + chroot_let_nobody_use_pacman "$copydir" +} + +# Core functions ############################################################### + +# Usage: extract +# Extracts the sources (`makepkg -o`) +# Environment: +# - $INCHROOT is set +# - $copydir is set +# - $LIBREUSER is set +extract() { + local user=$LIBREUSER + $INCHROOT || user=nobody + + local clean + if $INCHROOT; then + clean=chcleanup + else + cp -a "$(which chcleanup)" "${copydir}/clean" + clean=/clean + fi + + run "$copydir" "${clean} && sudo -u ${user} makepkg ${makepkg_args} -o" + rm -f "$copydir"/clean +} + +# Usage: build +# Builds the package (`makepkg -e`) +# Environment: +# - $INCHROOT is set +# - $copydir is set +# - $LIBREUSER is set +build() { + local user=$LIBREUSER + $INCHROOT || user=nobody + + run -N "$copydir" "sudo -u ${user} makepkg ${makepkg_args} -e" +} + +# Functions that check for issues with the build ############################### + +check_pkgbuild() { + msg "Checking PKGBUILD for issues" + # TODO + if ! pkgbuild-check-nonfree -f; then + if [[ $? -eq 15 ]]; then + # other errors mean fail, not nonfree + error "PKGBUILD contains non-free issues" + exit 15 + else + warning "PKGBUILD couldn't be check aganist non-free issues" + fi + fi +} + +check_src() { + msg "Checking src directory for issues" + # TODO +} + +check_pkg() { + msg "Checking final package for issues" + # TODO +} + + +# The main program ############################################################# + +cmd=${0##*/} +usage() { + echo "Usage: $cmd [options] [-- makepkg args]" + echo 'This program will build your package.' + echo '' + echo 'If run from outside of a chroot, this will set PKGDEST and' + echo "SRCDEST in the chroot's \`/etc/makepkg.conf', as well as making" + echo "whataver alterations to the chroot \`librechroot' makes." + echo '' + echo "The \`-n' and \`-l' options behave identically to librechroot," + echo 'see the documentation there.' + echo '' + echo 'Options:' + echo ' -n <CHROOT> Name of the chroot to use' + echo ' -l <COPY> Name of, or absolute path to, the copy to use' + echo ' -R Repackage contents of the package without rebuilding' + echo ' -h Show this message' +} + +# Globals: $CHROOTDIR, $CHROOT, $COPY and $copydir +# Globals: $makepkg_args, $INCHROOT +main() { + # Parse command line ################################################### + + COPY=$LIBREUSER + [[ $COPY != root ]] || COPY=copy + + makepkg_args='-s --noconfirm -L ' + local repack=false + + INCHROOT=false + if [[ -f /.arch-chroot ]]; then + INCHROOT=true + fi + + while getopts 'n:l:Rh' arg ; do + case "${arg}" in + n) CHROOT=$OPTARG;; + l) COPY=$OPTARG;; + R) repack=true; makepkg_args+=" -R";; + h) usage; return 0;; + *) usage; return 1;; + esac + done + shift $(($OPTIND - 1)) + # Pass all arguments after -- right to makepkg + makepkg_args+=" $*" + + if $INCHROOT; then + copydir='/' + elif [[ ${COPY:0:1} = / ]]; then + copydir=$COPY + else + copydir="${CHROOTDIR}/${CHROOT}/${COPY}" + fi + + # Init ################################################################# + + if (( EUID )); then + error "This script must be run as root" + exit 1 + fi + + if [[ ! -f PKGBUILD ]]; then + # This is the message used by makepkg + error "PKGBUILD does not exist." + exit 1 + fi + + # Trap signals from makepkg + trap 'trap_exit "(libremakepkg): TERM signal caught. Exiting..."' TERM HUP QUIT + trap 'trap_exit "(libremakepkg): Aborted by user! Exiting..."' INT + trap 'trap_exit "(libremakepkg): An error has occurred. Exiting..."' ERR + + SRCDEST="$(get_conf_makepkg SRCDEST .)" + PKGDEST="$(get_conf_makepkg PKGDEST .)" + + # OK, we're starting now ############################################### + + $INCHROOT || lock_open_write 9 "$copydir" \ + "Waiting for existing lock on chroot copy to be released: [$COPY]" + + # Set target CARCH as it might be used within the PKGBUILD to select + # correct sources + MAKEPKG_CONF=$copydir/etc/makepkg.conf + export CARCH="$(get_conf_makepkg CARCH)" + unset MAKEPKG_CONF + + $INCHROOT || chroot_init "$copydir" "$repack" + + check_pkgbuild + $INCHROOT || chroot_copy_in "$copydir" + $repack || extract + check_src + build + check_pkg + + add_to_local_repo "$copydir" + $INCHROOT || chroot_copy_out "$copydir" "$LIBREUSER" +} + +main "$@" diff --git a/src/devtools/.gitignore b/src/devtools/.gitignore new file mode 100644 index 0000000..06a1942 --- /dev/null +++ b/src/devtools/.gitignore @@ -0,0 +1,4 @@ +* +!*/ +!Makefile +!*.patch diff --git a/src/devtools/Makefile b/src/devtools/Makefile new file mode 100644 index 0000000..e357675 --- /dev/null +++ b/src/devtools/Makefile @@ -0,0 +1,103 @@ +# Configuration +DESTDIR= + +#prefix=/usr/local +prefix=/usr +exec_prefix=$(prefix) +datarootdir=$(prefix)/share + +bindir=$(exec_prefix)/bin +sbindir=$(exec_prefix)/sbin +datadir=$(datarootdir) + +pkgdatadir=$(datadir)/devtools + +devtoolsdir=../../../devtools-par + +default: all +all: build + +###################################################################### + +copy: \ + archroot.in \ + checkpkg.in \ + find-libdeps.in \ + finddeps.in \ + lddd.in \ + lib/common.sh.in \ + lib/makechrootpkg.sh.in + +archroot.in: $(devtoolsdir)/mkarchroot.in ; cp $< $@ +checkpkg.in: $(devtoolsdir)/checkpkg.in ; cp $< $@ +find-libdeps.in: $(devtoolsdir)/find-libdeps.in ; cp $< $@ +finddeps.in: $(devtoolsdir)/finddeps.in ; cp $< $@ +lddd.in: $(devtoolsdir)/lddd.in ; cp $< $@ +lib/common.sh.in: $(devtoolsdir)/lib/common.sh ; cp $< $@ +lib/makechrootpkg.sh.in: $(devtoolsdir)/makechrootpkg.in ; cp $< $@ + +###################################################################### + +build: \ + archroot \ + checkpkg \ + find-libdeps \ + finddeps \ + lddd \ + lib/common.sh \ + lib/makechrootpkg.sh + +edit = sed -e 's|m4_include(lib/\(.*\))|. @pkgdatadir@/\1|' -e "s|@pkgdatadir[@]|$(pkgdatadir)|g" + +indent = emacs --batch $1 \ + --eval '(setq sh-basic-offset 8)' \ + --eval '(indent-region (point-min) (point-max) nil)' \ + -f save-buffer &>/dev/null + +%: %.in Makefile + @echo "GEN $@" + @$(edit) <"$<" >"$@" + @chmod 755 "$@" + +lib/common.sh: %: %.in Makefile + @echo "GEN $@" + @{ \ + echo 'if [[ -z $${_INCLUDE_COMMON_SH:-} ]]; then' && \ + echo '_INCLUDE_COMMON_SH=true' && \ + cat "$<" && \ + echo 'fi'; } > "$@" + +lib/makechrootpkg.sh.ugly: %.ugly: %.in %.patch Makefile + @echo "GEN $@" + @cp $*.in $@ + @patch $@ $*.patch + +lib/makechrootpkg.sh: %: %.ugly Makefile + @echo "GEN $@" + @$(edit) <"$<" >"$@" + $(call indent,$@) + +###################################################################### + +install: \ + $(DESTDIR)$(sbindir)/archroot \ + $(DESTDIR)$(bindir)/checkpkg \ + $(DESTDIR)$(bindir)/find-libdeps \ + $(DESTDIR)$(bindir)/find-libprovides \ + $(DESTDIR)$(bindir)/finddeps \ + $(DESTDIR)$(bindir)/lddd \ + $(DESTDIR)$(pkgdatadir)/common.sh \ + $(DESTDIR)$(pkgdatadir)/makechrootpkg.sh + +$(DESTDIR)$(sbindir)/%: % + install -Dm755 $< $@ + +$(DESTDIR)$(bindir)/%: % + install -Dm755 $< $@ + +$(DESTDIR)$(pkgdatadir)/%: lib/% + install -Dm644 $< $@ + +$(DESTDIR)$(bindir)/find-libprovides: + install -d $(@D) + ln -sf find-libdeps $@ diff --git a/src/devtools/lib/makechrootpkg.sh.patch b/src/devtools/lib/makechrootpkg.sh.patch new file mode 100644 index 0000000..6016ba4 --- /dev/null +++ b/src/devtools/lib/makechrootpkg.sh.patch @@ -0,0 +1,254 @@ +--- makechrootpkg.sh.in ++++ makechrootpkg.sh.ugly +@@ -12,12 +12,7 @@ + + shopt -s nullglob + +-# So that usage conflicts between upstream and -par mkarchroot don't get hidden +-# silently in a merge. +-archroot() { +- mkarchroot "$@" +-} +- ++init_variables() { + makepkg_args='-s --noconfirm -L' + repack=false + update_first=false +@@ -28,13 +23,14 @@ + temp_chroot=false + chrootdir= + passeddir= +-declare -a install_pkgs +-declare -i ret=0 ++declare -ag install_pkgs ++declare -ig ret=0 + + copy=$USER + [[ -n $SUDO_USER ]] && copy=$SUDO_USER + [[ -z "$copy" || $copy = root ]] && copy=copy + src_owner=${SUDO_USER:-$USER} ++} + + usage() { + echo "Usage: ${0##*/} [options] -r <chrootdir> [--] [makepkg args]" +@@ -69,6 +65,7 @@ + exit 1 + } + ++parse_options_init() { + while getopts 'hcudr:I:l:nT' arg; do + case "$arg" in + h) usage ;; +@@ -129,8 +126,20 @@ + # Note this is the same FD number as in mkarchroot + lock_open_write 9 "$copydir" \ + "Waiting for existing lock on chroot copy to be released: [$copy]" ++} ++ ++# Usage: chroot_sync $CHROOTDIR/$CHROOT [$CHROOTCOPY|$copydir] ++chroot_sync() { ++ local chrootdir=$1 ++ local copy=$2 ++ local copydir='' ++ if [[ ${copy:0:1} = / ]]; then ++ copydir=$copy ++ else ++ copydir="$chrootdir/$copy" ++ fi ++ local chroottype=$(stat -f -c %T "$chrootdir") + +-if [[ ! -d $copydir ]] || $clean_first; then + # Get a read lock on the root chroot to make + # sure we don't clone a half-updated chroot + lock_open_read 8 "$chrootdir/root" \ +@@ -152,9 +161,16 @@ + + # Drop the read lock again + lock_close 8 +-fi ++} ++ ++# Usage: chroot_install_pkgs $copydir $pkgs... ++chroot_install_pkgs() { ++ local copydir=$1 ++ shift ++ declare -i ret=0 ++ declare -a install_pkgs=("$@") ++ local pkgname + +-if [[ -n "${install_pkgs[*]}" ]]; then + for install_pkg in "${install_pkgs[@]}"; do + pkgname="${install_pkg##*/}" + cp "$install_pkg" "$copydir/$pkgname" +@@ -165,10 +181,10 @@ + rm "$copydir/$pkgname" + done + +- # If there is no PKGBUILD we have done +- [[ -f PKGBUILD ]] || exit $ret +-fi ++ return $ret ++} + ++func1() { + $update_first && archroot -u "$copydir" + + mkdir -p "$copydir/build" +@@ -230,7 +246,14 @@ + # Set target CARCH as it might be used within the PKGBUILD to select correct sources + eval $(grep '^CARCH=' "$copydir/etc/makepkg.conf") + export CARCH ++} + ++# Usage: chroot_copy_in $copydir ++# Environment: ++# - In the dirctory of a PKGBUILD ++# - $SRCDEST is set ++chroot_copy_in() { ++local copydir=$1 + # Copy PKGBUILD and sources + cp PKGBUILD "$copydir/build/" + ( +@@ -256,13 +279,23 @@ + ) + + chown -R nobody "$copydir"/{build,pkgdest,srcdest} ++} + ++# Usage: chroot_let_nobody_use_pacman $copydir ++chroot_let_nobody_use_pacman() { ++local copydir=$1 + cat > "$copydir/etc/sudoers.d/nobody-pacman" <<EOF + Defaults env_keep += "HOME" + nobody ALL = NOPASSWD: /usr/bin/pacman + EOF + chmod 440 "$copydir/etc/sudoers.d/nobody-pacman" ++} + ++# Usage: chroot_build $copydir $makepkg_args $run_namcap ++chroot_build() { ++local copydir=$1 ++local makepkg_args=$2 ++local run_namcap=$3 + # This is a little gross, but this way the script is recreated every time in the + # working copy + cat >"$copydir/chrootbuild" <<EOF +@@ -284,37 +317,62 @@ + exit 0 + EOF + chmod +x "$copydir/chrootbuild" ++archroot -r "$copydir" "/chrootbuild" ++} + +-if archroot -r "$copydir" "/chrootbuild"; then +- for pkgfile in "$copydir"/pkgdest/*.pkg.tar.?z; do +- if $add_to_db; then ++# Usage: chroot_add_to_local_repo $copydir ++chroot_add_to_local_repo() { ++ local copydir=$1 ++ for pkgfile in "$copydir"/pkgdest/*.pkg.tar*; do + mkdir -p "$copydir/repo" + pushd "$copydir/repo" >/dev/null + cp "$pkgfile" . + repo-add repo.db.tar.gz "${pkgfile##*/}" + popd >/dev/null +- fi ++ done ++} + ++# Usage: chroot_copy_out_pkgs $copydir $user ++# Environment: ++# - $PKGDEST is set ++chroot_copy_out_pkgs() { ++ local copydir=$1 ++ local src_owner=$2 ++ for pkgfile in "$copydir"/pkgdest/*.pkg.tar*; do + chown "$src_owner" "$pkgfile" + mv "$pkgfile" "$PKGDEST" ++ if [[ $PKGDEST != . ]]; then ++ ln -sf "$PKGDEST/${pkgfile##*/}" . ++ fi + done ++} + +- for l in "$copydir"/build/*-{build,check,namcap,package,package_*}.log; do ++# Usage: chroot_copy_out_pkgs $copydir $user ++chroot_copy_out_logs() { ++ local copydir=$1 ++ local src_owner=$2 ++ for l in "$copydir"/build/*.log; do + chown "$src_owner" "$l" + [[ -f $l ]] && mv "$l" . + done +-else +- # Just in case. We returned 1, make sure we fail +- ret=1 +-fi ++} + ++# Usage: chroot_copy_out_srcs $copydir $user ++# Environment: ++# - $SRCDEST is set ++chroot_copy_out_srcs() { ++local copydir=$1 ++local src_owner=$2 + for f in "$copydir"/srcdest/*; do + chown "$src_owner" "$f" + mv "$f" "$SRCDEST" + done ++} + +-if $temp_chroot; then +- stat_busy "Removing temporary directoy [$copy]" ++# Usage: chroot_delete $copydir ++chroot_delete() { ++ local chroottype=$(stat -f -c %T "$copydir") ++ stat_busy "Removing chroot copy [$copy]" + if [[ "$chroottype" == btrfs ]]; then + btrfs subvolume delete "$copydir" >/dev/null || + die "Unable to delete subvolume $copydir" +@@ -326,8 +384,39 @@ + # remove lock file + rm --force "$copydir.lock" + stat_done +-elif (( ret != 0 )); then +- die "Build failed, check $copydir/build" +-else +- true +-fi ++} ++ ++main() { ++ init_variables ++ parse_options_init "$@" ++ if [[ ! -d $copydir ]] || $clean_first; then ++ chroot_sync "$chrootdir" "$copy" ++ fi ++ if [[ -n "${install_pkgs[*]}" ]]; then ++ chroot_install_pkgs "$copydir" "${install_pkgs[@]}" ++ ret=$? ++ # If there is no PKGBUILD we have done ++ [[ -f PKGBUILD ]] || exit $ret ++ fi ++ func1 ++ chroot_copy_in "$copydir" ++ chroot_let_nobody_use_pacman "$copydir" ++ chroot_build "$copydir" "$makepkg_args" "$run_namcap" ++ func2 ++ if chroot_build; then ++ chroot_add_to_local_repo "$copydir" ++ chroot_copy_out_pkgs "$copydir" "$src_owner" ++ chroot_copy_out_logs "$copydir" "$src_owner" ++ else ++ # Just in case. We returned 1, make sure we fail ++ ret=1 ++ fi ++ chroot_copy_out_srcs "$copydir" "$src_owner" ++ if $temp_chroot; then ++ chroot_delete "$copydir" ++ elif (( ret != 0 )); then ++ die "Build failed, check $copydir/build" ++ else ++ true ++ fi ++} diff --git a/src/diff-unfree b/src/diff-unfree new file mode 100755 index 0000000..24ada67 --- /dev/null +++ b/src/diff-unfree @@ -0,0 +1,86 @@ +#!/bin/bash +# This script will help you diff a *-libre PKGBUILD against the unfree one +# to check for updates. +# Copyright 2010 Nicolás Reynolds + +# ---------- GNU General Public License 3 ---------- + +# This file is part of Parabola. + +# Parabola 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. + +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. /etc/libretools.conf + +cmd=${0##*/} + +usage() { + echo "Usage: $cmd [community|packages] [unfree-package] [repo]" + echo "Usage: $cmd --help" + echo "Helps you diff build scripts from ABSLibre against (Unfree) ABS." + echo "" + echo "Package name and repo will we guessed if you don't specify them." +} + +main() { + if [[ "$1" == "--help" ]]; then + usage + exit 0 + fi + + local package_guess=${PWD##*/} + local repo=${1:-$(basename ${PWD%/*})} + local package=${2:-${package_guess%-libre}} + local trunk=${3:-trunk} + + svnrepo="packages" + case $repo in + community*) svnrepo="community";; + multilib*) svnrepo="community";; + *) :;; + esac + + if [[ ! -r PKGBUILD ]]; then + error "This is not a build dir." + exit 1 + fi + + + tmp_dir="$(mktemp --tmpdir -d ${package}.XXXXXX)" + if [[ ! -d "${tmp_dir}" ]]; then + error "Can't create temp dir" + exit 1 + fi + unfree_dir="${tmp_dir}/${svnrepo}/${package}/${trunk}" + + stdnull 'pushd "${tmp_dir}"' + + msg "Getting diff from $repo/$package..." + + stdnull 'svn checkout --depth=empty svn://svn.archlinux.org/$svnrepo' + + cd ${svnrepo} + svn update ${package} + + # Back to start dir + stdnull popd + + msg "Diffing files" + + for _file in ${unfree_dir}/*; do + msg2 "$(basename "${_file}")" + ${DIFFTOOL} "$PWD/$(basename "${_file}")" "${_file}" + done +} + +main "$@" diff --git a/src/fullpkg/Makefile b/src/fullpkg/Makefile new file mode 100644 index 0000000..f2cec54 --- /dev/null +++ b/src/fullpkg/Makefile @@ -0,0 +1,3 @@ +libre_execdir=$(bindir) +libre_datadir=$(sysconfdir)/libretools.d +include ../../common.mk diff --git a/src/fullpkg/fullpkg b/src/fullpkg/fullpkg new file mode 100755 index 0000000..6d6153a --- /dev/null +++ b/src/fullpkg/fullpkg @@ -0,0 +1,34 @@ +#!/bin/bash +# set -x # uncomment for debug +# Builds packages from ABS recursively. It tries to find dependencies that +# aren't built or need update and then makepkg them in order. + +usage() { + + echo "cd to a dir containing a PKGBUILD and run:" + echo "$0 [build_dir]" + echo "" + echo "This script will check dependencies, build them if possible " + echo "and stage the packages on it's repo." + echo "" + echo "OPTIONS:" + echo " -h : this message." + echo "" + echo "Wrapper for \`fullpkg-find' and \`fullpkg-build'" + echo "" + exit 1 + +} + +while getopts 'h' arg; do + case "$arg" in + h) usage ;; + esac +done + +shift $(( OPTIND - 1 )) + +build_dir="${1:-$(mktemp -d /tmp/fullpkg.XXXXXX)}" +fullpkg-find "$build_dir" && fullpkg-build -N "$build_dir" + +exit 0 diff --git a/src/fullpkg/fullpkg-build b/src/fullpkg/fullpkg-build new file mode 100755 index 0000000..b497db5 --- /dev/null +++ b/src/fullpkg/fullpkg-build @@ -0,0 +1,211 @@ +#!/bin/bash +# set -x # uncomment for debug +# Builds packages from ABS recursively. It tries to find dependencies that +# aren't built or need update and then makepkg them in order. + +# TODO move __build to chroot + +source /etc/makepkg.conf +source /etc/libretools.conf + +if [ -e $XDG_CONFIG_HOME/libretools/libretools.conf ]; then + source $XDG_CONFIG_HOME/libretools/libretools.conf +fi + + +## List packages on log that are on status +## usage: list_pkgs <status> <message> +# +## status: nonfree, built, failed, unstaged +list_pkgs() { + msg="$2" + local pkgs=($(grep "$1:" $build_dir/log)) && { + msg "$2" + echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2 + } +} + +# 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 + +} + +## Check all build_dir, fails if one PKGBUILD is nonfree +check_nonfree() { + find "$build_dir" -name PKGBUILD \ + -exec pkgbuild-check-nonfree {} + + if [ "$?" -eq 15 ]; then + error "Some PKGBUILD have nonfree problems" + exit 15 + fi + +} + +# Removes a package from the buildorder +# $1 package name +# $2 buildorder file +remove_buildorder() { + grep -Evw "${1}" ${2} > ${2}2 + mv -f ${2}2 ${2} + + return $? +} + +succesfull_build() { + + if [ "$RUN" != "$FULLBUILDCMD" ]; then + return 0 # Custom command or download sources + fi + + if source .INFO && [ -n "$repo" ]; then + + if [ ! -z "$HOOKLOCALRELEASE" ]; then + 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_description() { + list_pkgs "nonfree" "Those packages contain nonfree deps:" + list_pkgs "built" "Those packages were built and staged:" + list_pkgs "failed" "Those packages failed to build:" + list_pkgs "unstaged" "Those packages couldn't be staged (missing reponame):" +} + +__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 + + if [ -n "${HOOKPKGBUILDMOD}" ]; then + ${HOOKPKGBUILDMOD} || true + fi + + eval "$RUN"; r=$? + + case $r in + + 0) succesfull_build ;; + + *) 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 + +# which is next package? + build_packages=($(sort -gr $buildorder | cut -d: -f2)) + popd > /dev/null + done + + popd >/dev/null +} + +# End inmediately but print a useful message +trap_exit() { + error "$@" + warning "Leftover files left on $build_dir" + mv .BUILDORDER BUILDORDER + exit 1 +} + +# Trap signals from makepkg +set -E +trap 'trap_exit "(fullpkg-build) TERM signal caught. Exiting..."' TERM HUP QUIT +trap 'trap_exit "(fullpkg-build) Aborted by user! Exiting..."' INT +trap 'trap_exit "(fullpkg-build) An unknown error has occurred. Exiting..."' ERR + +CLEANUP="false" +CHECKNONFREE="true" +RUN="$FULLBUILDCMD" +MESSAGE="Building packages" + +usage() { + + echo "" + echo "$(basename $0) [options] <build_dir>" + echo "" + echo "Builds packages from build_dir, create a build_dir using:" + echo "'fullpkg-find <build_dir>'" + echo "" + echo "If no <build_dir> is specified, it uses the current directory." + echo "" + echo "OPTIONS:" + echo " -h : this message." + echo " -c : clean <build_dir> on succesfull build" + echo " -N : don't check for freedom issues." #Also made by fullpkg-find + echo " -r \"command\" : use this instead of \"$FULLBUILDCMD\"." + echo " -g : get sources for building packages on build_dir." + echo "" + exit 1 + +} + +while getopts 'hNr:g' arg; do + case $arg in + h) usage ;; + c) CLEAN ;; + N) CHECKNONFREE="false" ;; + r) RUN="$OPTARG" + MESSAGE="Executing custom action";; + g) RUN='makepkg -g > /dev/null' + MESSAGE="Downloading packages";; + esac +done + +shift $(( OPTIND - 1 )) +build_dir="${1:-`pwd`}" +buildorder="${build_dir}/BUILDORDER" + +if [ ! -e "$buildorder" ]; then + error "This is not a build_dir. Make one using fullpkg." + usage +else +# backup BUILDORDER + cp "$buildorder" "$build_dir/.BUILDORDER" +fi + +if "$CHECKNONFREE"; then + check_nonfree +fi + +if [ -z "$FULLBUILDCMD" ]; then + error "Set your FULLBUILDCMD on libretools.conf" +fi + +msg "$MESSAGE" +__build + +if [ "$RUN" != "$FULLBUILDCMD" ]; then + # Used for downloading or custom command + mv "$build_dir/.BUILDORDER" "$buildorder" + exit 0 +elif "$CLEANUP"; then + find "$build_dir" -mindepth 1 -delete +fi + +build_description + +plain "Test packages on and if they work fine librerelease." + +exit 0 diff --git a/src/fullpkg/fullpkg-find b/src/fullpkg/fullpkg-find new file mode 100755 index 0000000..b09edf9 --- /dev/null +++ b/src/fullpkg/fullpkg-find @@ -0,0 +1,211 @@ +#!/bin/bash +# set -x # uncomment for debug +# Builds packages from ABS recursively. It tries to find dependencies that +# aren't built or need update and then makepkg them in order. + +# TODO: fullpkg-find should find packages wich depend on the +# package to be build, so we can avoid "missing $name.so errors" + +# Get repo name. Asumes ${ABSROOT}/repo/package/PKGBUILD +guess_repo() { + basename $(dirname $(pwd)) +} + +# 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 + +} + +copy_files() { + + local copydir="$build_dir/${pkgbase:-${pkgname[0]}}" + mkdir -p "$copydir" + + # Copy PKGBUILD and sources + cp PKGBUILD "$copydir" + ( + source PKGBUILD + for file in "${source[@]}"; do + file="${file%%::*}" + file="${file##*://*/}" + if [[ -f $file ]]; then + cp "$file" "$copydir/" + elif [[ -f $SRCDEST/$file ]]; then + cp "$SRCDEST/$file" "$copydir/" + fi + done + + # Find all changelog and install files, even inside functions + for i in 'changelog' 'install'; do + while read -r file; do + # evaluate any bash variables used + eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\" + [[ -f $file ]] && cp "$file" "$copydir" + done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD) + done + ) +} + +# Checks ABSROOT and look for target pkg deps. Adds them if not built or outdated. +find_deps() { +# Check this level + source PKGBUILD + + local repo="${repo:-$(guess_repo)}" + local pkgbase="${pkgbase:-${pkgname[0]}}" + local fullver="$(get_fullver ${epoch:-0} ${pkgver} ${pkgrel})" + + if ! pkgbuild-check-nonfree > /dev/null 2> /dev/null; then + if [ "$?" -eq 15 ]; then + error "pkgbase" has nonfree issues + return 15 + fi + fi + + # Checking any package built, since otherwise e.g. kdebase would + # be always considered outdated: there is no package built named kdebase. + # TODO: maybe check for the package requested in case of recursive calls, + # instead of the first one listed? + if is_built "${pkgname[0]}" "${fullver}"; then + exit 0 # pkg is built and updated + fi + +# greater levels are built first + echo "${LEVEL}:${pkgbase}" >>"$build_dir/BUILDORDER" +# PKGBUILD is already there + if [ -d "${build_dir}/${pkgbase}" ]; then + exit 0 +# Copy dir to build_dir + else + copy_files + +# to identify repo later + echo "repo=$repo" > "${build_dir}/${pkgbase}/.INFO" + fi + +# current package plus a space for every level + msg2 "%${LEVEL}s${pkgbase}-${fullver}" + +## Check next levels + declare -i next_level=$LEVEL+1 + +# All deps in separate line, only once, without version. + deps=($(echo "${depends[@]} ${makedepends[@]}" | \ + sed "s/[=<>]\+[^ ]\+//g" | \ + tr ' ' "\n" | \ + sort -u)) + + for _dep in ${deps[@]}; do + + local found=false + # May fail, e.g. since abslibre-mips64el doesn't include + # arch=any packages. + local pkgdir=$(toru -p ${_dep}) || true + + if [ -n "$pkgdir" -a -d "${pkgdir}" ]; then + found=true + + pushd "${pkgdir}" > /dev/null +# runs itself on dep's PKGBUILD dir + $0 -l ${next_level} ${build_dir} || return $? + popd > /dev/null + fi + + if ! (( found )); then + echo "dep_not_found:$_dep" >>$build_dir/log + fi + + done + +## End variable block + + unset next_level dir +} + +source /etc/libretools.conf +source /etc/makepkg.conf + +if [ -e $XDG_CONFIG_HOME/libretools/libretools.conf ]; then + source $XDG_CONFIG_HOME/libretools/libretools.conf +fi + +LEVEL=0 +MAXLEVEL=20 +CLEANFIRST='false' +UPDATEDB='true' + +usage() { + + echo "" + echo "cd to a dir containing a PKGBUILD and run:" + echo "$(basename $0) [options] <build_dir>" + echo "" + echo "This script will create a build_dir for recursive building" + echo "it tries to find dependencies that aren't built or need update." + echo "" + echo "If no <build_dir> is specified, the script works on a tempdir" + echo "" + echo "OPTIONS:" + echo " -h : this message." + echo " -A <absroot> : use this ABSROOT." + echo " -c : clean <build_dir> before working." + echo " -m <max_level> : check deps until this level" + echo " -n : don't update pacman db." + echo "" + exit 1 + +} + +while getopts 'hA:l:cmn' arg; do + case "$arg" in + h) usage ;; + A) ABSROOT="$OPTARG" ;; + l) LEVEL="$OPTARG" ;; # hidden option to know dep level. + c) CLEANFIRST='true' ;; + m) MAXLEVEL="$OPTARG" ;; + n) UPDATEDB='false' ;; + esac +done + +if [ ! -r PKGBUILD ]; then + error "This directory doesnt contain a PKGBUILD" + usage +fi + +shift $(( OPTIND - 1 )) +build_dir="${1}" + +if [ "$LEVEL" -eq 0 ]; then + + build_dir="${1:-$(mktemp -d /tmp/fullpkg.XXXXXX)}" + + if [ ! -d "$build_dir" ]; then + mkdir -p "$build_dir" + elif "$CLEANFIRST"; then + # Erase files already in dir + msg "Cleaning up files in dir" + find "$build_dir" -mindepth 1 -delete + fi + + if "$UPDATEDB"; then + msg "Updating pacman db" + sudo pacman -Sy --noconfirm || true + fi + +# make files for log and buildorder + touch "${build_dir}"/{log,BUILDORDER} + buildorder="${build_dir}/BUILDORDER" + + msg "Checking dependencies" +fi + +find_deps + +exit 0 diff --git a/src/is_built b/src/is_built new file mode 100755 index 0000000..1fa79d2 --- /dev/null +++ b/src/is_built @@ -0,0 +1,36 @@ +#!/bin/bash +usage() { + echo "$0 " + echo + echo "Detect if a given package version is already in repos" + echo "Assuming you want greater or equal" + echo + echo "Example usage: is_built 'pcre' '20'" +} + +while getopts 'h' arg; do + case $arg in + h) usage; exit 0 ;; + *) usage; exit 1 ;; + esac +done + +ver=${2} +pkg=${1} +pver=$(LC_ALL=C pacman -Sddp --print-format "%v" "${pkg}" 2>/dev/null) + +# if pacman fails or returns nothing +r=$? +[ "${pver}" = " there is nothing to do" ] && r=1 + +result=$(vercmp "${pver}" "${ver}") + +# if vercmp > 1 means our version is bigger +if [ ${result} -ge 0 -a ${r} -eq 0 ]; then + exit 0 +else + exit 1 +fi + +# just in case +exit 1 diff --git a/src/is_unfree b/src/is_unfree new file mode 100755 index 0000000..c2a37c9 --- /dev/null +++ b/src/is_unfree @@ -0,0 +1,8 @@ +#!/bin/bash +# Checks if a package is on blacklist + +. /etc/libretools.conf + +blacklist="$XDG_CONFIG_HOME/libretools/blacklist.txt" +egrep -q "^${1}:" "${blacklist}" +exit $? diff --git a/src/lib/Makefile b/src/lib/Makefile new file mode 100644 index 0000000..0c69ba3 --- /dev/null +++ b/src/lib/Makefile @@ -0,0 +1,2 @@ +libre_datadir=$(datadir)/libretools +include ../../common.mk diff --git a/src/lib/conf.sh b/src/lib/conf.sh new file mode 100644 index 0000000..43a30af --- /dev/null +++ b/src/lib/conf.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +INCLUDE_CONF_SH=conf.sh + +LIBREUSER="${SUDO_USER:-$USER}" +LIBREHOME="$(eval echo ~$LIBREUSER)" +if [[ -z ${XDG_CONFIG_HOME:-} ]]; then + export XDG_CONFIG_HOME="${LIBREHOME}/.config" +fi + +# Generic functions ############################################################ + +get_files() { + local slug=$1 + case $slug in + makepkg.conf) + if [[ $MAKEPKG_CONF != /etc/$slug && -r $MAKEPKG_CONF ]]; then + echo "$MAKEPKG_CONF" + else + echo /etc/$slug + echo "$LIBREHOME/.$slug" + fi + ;; + libretools.conf) + echo /etc/$slug + echo "$XDG_CONFIG_HOME/libretools/$slug" + ;; + *.conf) + echo /etc/libretools.d/$slug + echo "$XDG_CONFIG_HOME/libretools/$slug" + ;; + esac +} + +load_files() { + for file in $(get_files $1.conf); do + if [[ -r $file ]]; then + . "$file" + fi + done +} + +check_vars() { + local slug=$1 + shift + local ret=0 + for VAR in "$@"; do + if [[ -z ${!VAR} ]]; then + if [[ $(get_files $slug|wc -l) > 1 ]]; then + echo "Configure '$VAR' in one of:" + get_files $slug | sed 's/./ -> &/' + else + echo "Configure '$VAR' in $(get_files $slug)" + fi + ret=1 + fi >>/dev/stderr + done + if [[ $ret != 0 ]]; then + return 1 + fi +} + +# makepkg configuration ######################################################## + +[[ -n ${MAKEPKG_CONF:-} ]] || MAKEPKG_CONF=/etc/makepkg.conf + +load_conf_makepkg() { + load_files makepkg +} + +get_conf_makepkg() ( + set +euE + local setting=$1 + local default=$2 + load_conf_makepkg + printf '%s\n' "${!setting:-${default}}" +) + +set_conf_makepkg() { + local key=$1 + local val=$2 + for file in `get_files makepkg.conf|tac`; do + if [[ -w $file ]]; then + sed -i "/^\s*$key=/d" "$file" + echo "$key='$val'" >> "$file" + return 0 + fi + done + return 1 +} + + +# libretools configuration ##################################################### + +check_conf_libretools() { + check_vars libretools.conf \ + PARABOLAHOST LIBREDESTDIR BLACKLIST WORKDIR REPOS ARCHES \ + ABSLIBREGIT DIFFTOOL FULLBUILDCMD SIGEXT SIGID +} + +load_conf_libretools() { + load_files libretools + check_conf_libretools +} + +load_conf_libretools_chroot() { + load_files chroot + # Exclude CHROOTEXTRAPKG from the checks because an empty value is valid + if [[ -f /.arch-chroot ]]; then + # inside of a chroot, only CHROOTEXTRAPKG needs to be set, but + # as stated above, we don't check for it. + : + else + check_vars chroot.conf CHROOTDIR CHROOT + fi +} + +load_conf_libretools_librefetch() { + load_files librefetch + check_vars librefetch.conf MIRROR DOWNLOADER +} diff --git a/src/librediff b/src/librediff new file mode 100755 index 0000000..6dbe41b --- /dev/null +++ b/src/librediff @@ -0,0 +1,57 @@ +#!/bin/bash +# Generates a patch for a nonfree PKGBUILD +# +# Copyright 2010 Nicolás Reynolds + +# ---------- GNU General Public License 3 ---------- + +# This file is part of Parabola. + +# Parabola 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. + +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. /etc/libretools.conf + +cmd=${0##*/} + +usage() { + echo "Usage: $cmd <pkgname> [<pkgname2> ...]" + echo "Requirements:" + echo " * Have a <pkgname>/ directory with nonfree build scripts inside" + echo " * Have a <pkgname>-libre/ directory with libre build scripts inside" +} + +main() { + local packages=("$@") + if [[ ${packages[#]} = 0 ]]; then + usage + exit 1 + fi + + for package in "${packages[@]}"; do + if [[ ! -f ./${package}/PKGBUILD || ! -f ./${package}-libre/PKGBUILD ]] + then + error "Build scripts not found for ${package}(-libre)" + else + + . ./${package}-libre/PKGBUILD + [[ -z ${pkgbase} ]] && pkgbase=${pkgname} + + # Generate a diff file, no -r since we don't want to patch src/ nor pkg/ + diff -auN ${package} ${package}-libre > $PATCHDIR/${pkgbase}-${pkgver}-${pkgrel}.patch + done + + exit 0 +} + +main "$@" diff --git a/src/librefetch/Makefile b/src/librefetch/Makefile new file mode 100644 index 0000000..f2cec54 --- /dev/null +++ b/src/librefetch/Makefile @@ -0,0 +1,3 @@ +libre_execdir=$(bindir) +libre_datadir=$(sysconfdir)/libretools.d +include ../../common.mk diff --git a/src/librefetch/librefetch b/src/librefetch/librefetch new file mode 100755 index 0000000..6a05cb9 --- /dev/null +++ b/src/librefetch/librefetch @@ -0,0 +1,301 @@ +#!/bin/bash +# librefetch +# +# Copyright 2013 Luke Shumaker <lukeshu@sbcglobal.net> +# +# This file is part of Parabola. +# +# Parabola 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. +# +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. /usr/share/libretools/conf.sh +. libremessages + +declare -r tempdir="$(mktemp -d --tmpdir ${0##*/}.XXXXXXXXXXX)" +cleanup() { rm -rf -- "$tempdir"; } +trap cleanup EXIT + +cmd=${0##*/} +usage() { + print "Usage: %s [options] <source-url> <output-file>" "$cmd" + print "Usage: %s -[g|V|h]" "$cmd" + print "Downloads or creates a liberated source tarball." + echo + print "The default build script is 'PKGBUILD', or 'SRCBUILD' if it exists." + echo + print "Unrecognized options are passed straight to makepkg." + echo + print "Example usage:" + print ' $ %s libre://mypackage-1.0.tar.gz $SRCDEST/mypackage-1.0.tar.gz.part' "$cmd" + echo + print "Options:" + print " Settings:" + print " -C Force create mode (don't download)" + print " -D Force download mode (don't create)" + print " -p <file> Use an alternate build script (instead of 'PKGBUILD')" + print " If an SRCBUILD exists in the same directory, it is used" + print " instead" + print " Alternate modes:" + print " -g, --geninteg Generage integrity checks for source files" + print " -V, --version Show version information" + print " -h, --help Show this message" +} + +version() { + print "librefetch (libretools) beta 4" + echo + print "Copyright (C) 2013 Luke Shumaksr <lukeshu@sbcglobal.net>" + print "This is free software; see the source for copying conditions." + print "There is NO WARRANTY, to the extent permitted by law." +} + +main() { + BUILDFILE="$(readlink -m PKGBUILD)" + makepkg_opts=() + extra_opts=() + mode=download-create + parse_options "$@" + + local startdir=$PWD + export BUILDDIR="${BUILDFILE%/*}" + if [[ -f "${BUILDDIR}/SRCBUILD" ]]; then + BUILDFILE="${BUILDDIR}/SRCBUILD" + srcbuild="$(modified_srcbuild "$BUILDFILE")" + else + srcbuild="$(modified_pkgbuild "$BUILDFILE")" + fi + makepkg="$(modified_makepkg "$(which "${MAKEPKG:-makepkg}")")" + + # Mode: version, help ################################################## + + if [[ $mode =~ version ]]; then + version + return 0 + fi + if [[ $mode =~ help ]]; then + usage + return 0 + fi + + # Mode: checksums ###################################################### + + if [[ $mode =~ checksums ]]; then + if [[ ${#extra_opts[@]} != 0 ]]; then + print "%s: found extra non-flag arguments: %s" "$cmd" "${extra_opts[*]}" + usage >> /dev/stderr + return 1 + fi + "$makepkg" "${makepkg_opts[@]}" -g -p "$srcbuild" | + case ${BUILDFILE##*/} in + PKGBUILD) sed -e 's/^[a-z]/mk&/' -e 's/^\s/ &/';; + SRCBUILD) cat;; + esac + return 0 + fi + + ######################################################################## + + if [[ ${#extra_opts[@]} != 2 ]]; then + print "%s: %d non-flag arguments found, expected 2: %s" "$cmd" ${#extra_opts[@]} + usage >> /dev/stderr + return 1 + fi + local src="${extra_opts[0]#*://}" + local dst="$(readlink -m "${extra_opts[1]}")" + + # Mode: download ####################################################### + + if [[ $mode =~ download ]]; then + load_conf_libretools_librefetch || return 1 + + local url="${MIRROR}/${src}" + + local dlcmd="${DOWNLOADER}" + dlcmd="${dlcmd//\%o/\"$dst\"}" + dlcmd="${dlcmd//\%u/\"$url\"}" + { eval "$dlcmd"; } && return 0 + fi + + # Mode: create ######################################################### + + if [[ $mode =~ create ]]; then + PKGEXT=${dst##*/} + export PKGEXT=${PKGEXT%.part} + export PKGDEST=$startdir + export pkg_file=$dst + "$makepkg" "${makepkg_opts[@]}" -p "$srcbuild" + fi +} + +# sets the variables BUILDFILE, makepkg_opts, extra_opts, mode +parse_options() { + # Detect makepkg options that take a second argument + local makepkg_orig="$(which "${MAKEPKG:-makepkg}")" + local makepkg_opt2long=($("${makepkg_orig}" -h | sed -rn 's/\s*(--\S*) <.*/\1/p')) + local makepkg_opt2short=($("${makepkg_orig}" -h | sed -rn 's/\s*(-.) <.*/\1/p')) + + local opt + local have_opt + while [[ $# > 0 ]]; do + arg=$1 + have_opt=false + if in_array "${arg%%=*}" "${makepkg_opt2long[@]}"; then + opt="${arg#*=}" + arg="${arg%%=*}" + have_opt=true + fi + if in_array "${arg}" "${makepkg_opt2short[@]}"; then + shift + opt=$1 + have_opt=true + fi + case "$arg" in + -C) mode=create;; + -D) mode=download;; + -g|--geninteg) mode=checksums;; + -p) BUILDFILE="$(readlink -m "$opt")";; + -V|--version) mode=version;; + -h|--help) mode=help;; + -*) + makepkg_opts+=("$arg") + $have_opt && makepkg_opts+=("$opt") + ;; + --) shift; break;; + *) extra_opts+=("$arg");; + esac + shift + done + extra_opts+=("$@") +} + +# Modify makepkg ############################################################### + +# an ERE +makepkg_modify=' +/create_package\(\) \{/,/^\}$/ { + /pkg_file=/d # allow us to set pkg_file + /check_package/d # do not run check_package + s/"?\$\{comp_files\[@\]\}"?// # do not include .{PKGINFO,INSTALL,CHANGELOG} +} + +/tidy_install\(\) \{/,/^\}$/ { + /for .*PURGE_TARGETS/itidy_install_purge + /for .*PURGE_TARGETS/,/done/d + /^\}$/ifind . -exec touch --date="1990-01-01 0:0:0 +0" {} + +} + +s|srcdir=.*|srcdir="$BUILDDIR/src-libre"| +s|pkgdir=.*|pkgdir="$BUILDDIR/pkg-libre"| +s|check_build_status$|:| +' + +tidy_install_purge() { + local pt + for pt in "${PURGE_TARGETS[@]}"; do + if [[ ${pt} = "${pt%/}" ]]; then + if [[ ${pt} = "${pt//\/}" ]]; then + find . ! -type d -name "${pt}" -exec rm -f -- '{}' + + else + rm -f "${pt}" + fi + else + if [[ ${pt%/} = "${pt//\/}" ]]; then + find . -type d -name "${pt%/}" -exec rm -rf -- '{}' + + else + rm -rf "${pt}" + fi + fi + done +} + +modified_makepkg() { + local makepkg_orig=$1 + local makepkg_mine="$tempdir/makepkg" + { + echo '#!/bin/bash' + declare -f tidy_install_purge + sed -r "$makepkg_modify" < "$makepkg_orig" + } > "$makepkg_mine" + chmod 755 "$makepkg_mine" + printf "%s\n" "$makepkg_mine" +} + +# Modify PKGBUILD ############################################################## + +# a string to be appended +pkgbuild_append=' +# do not do split packages +if [[ -n $pkgbase ]]; then + pkgname=$pkgbase +else + pkgname=$pkgname +fi + +# copy source variables +source=("${mksource[@]}") +noextract=("${mknoextract[@]}") +md5sums=("${mkmd5sums[@]}") +sha1sums=("${mksha1sums[@]}") +sha256sums=("${mksha256sums[@]}") +sha384sums=("${mksha384sums[@]}") +sha512sums=("${mksha512sums[@]}") + +depends=() +checkdepends=() +makedepends=("${mkdepends[@]}") + +#### +options+=(!strip docs libtool emptydirs !zipman purge !upx) +PURGE_TARGETS+=(.bzr/ .cvs/ .git/ .hg/ .svn/) + +#### +if ! declare -f mksource >/dev/null; then + mksource() { :; } +fi +build() { mksource; } +package() { + if [[ $(ls "$pkgdir" | wc -l) == 0 ]]; then + # pkgdir is empty; provide good default behavior + cp -a "${srcdir}"/*/ "$pkgdir/" + fi +} +' + +modified_pkgbuild() { + local pkgbuild=$1 + local srcbuild="$tempdir/SRCBUILD" + printf '%s' "$pkgbuild_append" | cat "$pkgbuild" - > "$srcbuild" + printf '%s\n' "$srcbuild" +} + + +# Modify SRCBUILD ############################################################## + +modified_srcbuild() { + local orig=$1 + local new="$tempdir/SRCBUILD" + sed -e '/PKGDEST=/d' -e 's/PKGEXT=/d' < "$orig" > "$new" + printf '%s\n' "$new" +} + +# "Library" crap ############################################################### + +print() { + local fmt=$1 + shift + printf -- "$(gettext "$fmt")\n" "$@" +} + +################################################################################ + +main "$@" diff --git a/src/librefetch/librefetch.conf b/src/librefetch/librefetch.conf new file mode 100644 index 0000000..40d2078 --- /dev/null +++ b/src/librefetch/librefetch.conf @@ -0,0 +1,2 @@ +MIRROR='https://repo.parabolagnulinux.org/sources/' +DOWNLOADER='/usr/bin/curl -fLC - --retry 3 --retry-delay 3 -o %o %u' diff --git a/src/libremessages b/src/libremessages new file mode 100755 index 0000000..5c5a02a --- /dev/null +++ b/src/libremessages @@ -0,0 +1,65 @@ +#!/bin/bash +# Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> +# Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> +# Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> +# Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> +# Copyright (c) 2006 by Alex Smith <alex@alex-smith.me.uk> +# Copyright (c) 2006 by Andras Voroskoi <voroskoi@frugalware.org> +# Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> +# Copyright (c) 2011 by Joshua Haase <hahj87@gmail.com> +# +# 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 <http://www.gnu.org/licenses/>. + +################################################################################ +# Inherit most functions from devtools # +################################################################################ + +# This is only installed in Parabola's distribution of devtools, not Arch's +. /usr/share/devtools/common.sh + +################################################################################ +# gettext initialization # +################################################################################ + +export TEXTDOMAIN='libretools' +export TEXTDOMAINDIR='/usr/share/locale' + +################################################################################ +# Own functions # +################################################################################ + +stdnull() { + eval "$@ >/dev/null 2>&1" +} + +# Set the terminal title +term_title() { + local fmt='' + case "$TERM" in + screen|tmux) fmt='\ek%s\e\\';; + xterm*|rxvt*) fmt='\e]0;%s\a';; + esac + printf "$fmt" "$*" +} + +################################################################################ +# Run one of the defined functions if invoked directly # +################################################################################ + +if [[ "${0##*/}" = libremessages ]]; then + _libremessages_cmd=$1 + shift + "$_libremessages_cmd" "$@" + unset _libremessages_cmd +fi diff --git a/src/libretools.conf b/src/libretools.conf new file mode 100644 index 0000000..da5abc0 --- /dev/null +++ b/src/libretools.conf @@ -0,0 +1,98 @@ +#!/bin/bash + +################################################################################ +# misc # +################################################################################ + +## Blacklist URL +## Used by `pkgbuild-check-nonfree` +BLACKLIST=http://repo.parabolagnulinux.org/docs/blacklist.txt + +## Diff tool (vimdiff, gvimdiff, meld, etc) +## Used by `aur`, `diff-unfree` +DIFFTOOL=`which vimdiff gvimdiff meld colordiff diff 2>/dev/null|sed 's/\s.*//;1q'` + +## The repos you'll be packaging for +## Used by `toru`, `createworkdir`, `prfullpkg` +# Tip: As early repos take precedence on $REPOS loops, you can use this as +# inverted order of precedence. Put testing repos first so fullpkg find new +# PKGBUILDs first, for instance. Toru-path uses reverse order to enforce repo +# precedence on the path cache (the last path added replaces the rest) +REPOS=('core' 'libre' 'extra' 'community' 'libre-testing' 'social' 'sugar' 'pcr' 'java') + +## The architectures +## Used by `librestage` +ARCHES=('i686' 'x86_64' 'mips64el' 'any') + +################################################################################ +# abslibre # +################################################################################ + +# The dir where you work on +WORKDIR=/home/$USER/packages + +## Package signing +SIGEXT=".sig" +#SIGID="0xYOURID" + +## Parabola hostname +PARABOLAHOST=parabola +## Assumes something similar in your .ssh/config: + +## Repo server +# Host parabola +# Port 1863 +# HostName repo.parabolagnulinux.org +# User repo + +## Server destination of libre packages +# Don't change unless you know what you're doing and you won't screw +# anything ;) +LIBREDESTDIR=/srv/http/repo/public + +## ABSLibre +ABSLIBREGIT=http://projects.parabolagnulinux.org/abslibre.git + +################################################################################ +# fullpkg # +################################################################################ + +## Uncomment one of those or make one of your choice +# Normal fullpkg +FULLBUILDCMD="sudo libremakepkg" +# Cross compiling fullkpg +# FULLBUILDCMD="sudo libremakepkg -n cross-compile-chroot" +# Build from within the chroot (or host system) +# FULLBUILDCMD="makepkg -sL --noconfirm" + +# Run a command before releasing a package (ie. SSH connection, SSH tunnel, etc.) +HOOKPRERELEASE="ssh -fN parabola" + +# Run a command before running FULLBUILDCMD, usually to cleanup uneeded packages +# Note! chcleanup *is not* chroot aware, if you run it as it is it will cleanup +# your system +# HOOKPREBUILD="chcleanup" + +# Locally release the package or any other action after running FULLBUILDCMD +# succesfully +# HOOKLOCALRELEASE="" + +################################################################################ +# toru # +################################################################################ + +TORUPATH=/var/lib/libretools/toru + +################################################################################ +# Stub for old programs; wouldn't normally be in a .conf file # +################################################################################ + +if [[ -z ${INCLUDE_CONF_SH:-} ]]; then + . /usr/share/libretools/conf.sh + if [[ -e "$XDG_CONFIG_HOME/libretools/libretools.conf" ]]; then + . "$XDG_CONFIG_HOME/libretools/libretools.conf" + fi + check_conf_libretools || exit $? + + . /usr/bin/libremessages +fi diff --git a/src/mips64el-tools/Makefile b/src/mips64el-tools/Makefile new file mode 100644 index 0000000..f2cec54 --- /dev/null +++ b/src/mips64el-tools/Makefile @@ -0,0 +1,3 @@ +libre_execdir=$(bindir) +libre_datadir=$(sysconfdir)/libretools.d +include ../../common.mk diff --git a/src/mips64el-tools/add-mips64el b/src/mips64el-tools/add-mips64el new file mode 100755 index 0000000..e06d857 --- /dev/null +++ b/src/mips64el-tools/add-mips64el @@ -0,0 +1,6 @@ +#!/bin/bash +# Change all arch array that aren't any or mips64el already + +find -name 'PKGBUILD' -exec sed -i "s/^\(arch=([^)anym]\+\))/\1 'mips64el')/" '{}' \; + +exit $? diff --git a/src/mips64el-tools/librebasebuilder b/src/mips64el-tools/librebasebuilder new file mode 100755 index 0000000..604f1c7 --- /dev/null +++ b/src/mips64el-tools/librebasebuilder @@ -0,0 +1,84 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +# Copyright (C) 2012 Michał Masłowski <mtjm@mtjm.eu> +# +# 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 Affero 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 <http://www.gnu.org/licenses/>. + + +set -e + +# TODO: + +# - make it more configurable + +# - compare the result with previous base images + +for arg in "$@" ; do + case "$arg" in + -h|--h|--he|--hel|--help|-\?) + echo 'Usage: librebasebuilder + +Make a base tarball named parabola-mips64el-DATE.tar.bz2. + +This script must be run as root.' >&2 + exit 0 + ;; + esac +done + +[[ "$UID" != "0" ]] && { + echo "This script must be run as root." >&2 + exit 1 +} + +tempdir=/home/chroot/base +outdir=$(pwd) + +archroot -n $tempdir mkinitcpio base sudo parted nano zile vi ed openssh + +cd $tempdir + +# Don't list mtjm's DNS servers. +cat > etc/resolv.conf <<EOF +# +# /etc/resolv.conf +# + +#search <yourdomain.tld> +#nameserver <ip> + +# End of file +EOF + +# From pacman-mirrorlist-libre-20120307-1. Remember to escape dollars. +cat > etc/pacman.d/mirrorlist <<EOF +# Parabola GNU/Linux - Last Updated: Wed Mar 7 17:33:36 GMT 2012 + +# Atlanta, GA, USA +# Responsible: belos +Server = http://parabola.techno-geeks.org/\$repo/os/\$arch + +# Nuremberg, Germany +# Responsible: johkra +Server = http://parabolaweb.eu/\$repo/os/\$arch + +# UK +# Responsible: Parabola Project +Server = http://repo.parabolagnulinux.org/\$repo/os/\$arch + +EOF + +rm .arch-chroot + +tar cjf $outdir/parabola-mips64el-$(LC_ALL=C date -u +%Y%m%d).tar.bz2 . diff --git a/src/mips64el-tools/mips-add b/src/mips64el-tools/mips-add new file mode 100755 index 0000000..da9b431 --- /dev/null +++ b/src/mips64el-tools/mips-add @@ -0,0 +1,7 @@ +#!/bin/bash +source /etc/libretools.conf +if ! grep mips64el PKGBUILD >/dev/null; then # Add mips64el in ${arch} array if it isn't 'any' + warning "Adding mips64el arch" + sed -i "s/^\(arch=([^)anym]\+\))/\1 'mips64el')/" "PKGBUILD" + librecommit PKGBUILD +fi diff --git a/src/mips64el-tools/mips64el.conf b/src/mips64el-tools/mips64el.conf new file mode 100644 index 0000000..836b407 --- /dev/null +++ b/src/mips64el-tools/mips64el.conf @@ -0,0 +1,12 @@ +## Arquitecture specific commands + +## Run a command for PKGBUILD modifications before building +## Like adding 'mips64el' to arch if it's not there +# HOOKPKGBUILDMOD="mips-add" + +## Run a command for local releasing of packages +# Useful for mass packaging (ie. mips port) +# Must accept the following parameters even if the command won't use them: +# $1 repo name +# $2+ packages +# HOOKLOCALRELEASE="mipsrelease" diff --git a/src/mips64el-tools/mipsrelease b/src/mips64el-tools/mipsrelease new file mode 100755 index 0000000..4d7a7de --- /dev/null +++ b/src/mips64el-tools/mipsrelease @@ -0,0 +1,65 @@ +#!/bin/bash +# Lic: GPLv3+ +# Author: Nicolas Reynolds <fauno@kiwwwi.com.ar> +# Local release of mips64el packages + clean ABS sync +# Called by HOOKLOCALRELEASE + +# $1 repo +# $2+ packages + +source /etc/makepkg.conf +source /etc/libretools.conf + +libretoolsdir="$(dirname $0)/../" + +usage() { + echo "$0 repo package1 [ package2 ... packageN ]" + echo + echo " release packages locally on ${PKGDEST}/stage3." + echo " and make a clean ABS sync " +} + +## +# usage : get_full_version( $epoch, $pkgver, $pkgrel ) +# return : full version spec, including epoch (if necessary), pkgver, pkgrel +## +get_full_version() { + if [[ $1 -eq 0 ]]; then + # zero epoch case, don't include it in version + echo $2-$3 + else + echo $1:$2-$3 + fi +} + +repo=$1; shift + +if [ -z "${repo}" ]; then + error "Empty repo" + exit 1 +fi + +# Get all needed sources +source PKGBUILD +fullver=$(get_full_version ${epoch:-0} ${pkgver} ${pkgrel}) +pkgs=() +makepkg --source -f --skippgpcheck + +msg "Adding packages to [stage3]..." +for name in ${pkgname[@]}; do + msg2 "${name} ${fullver}" + pkgs+=("${PKGDEST}/${name}-${fullver}-*.pkg.tar.*") +done + +repo-add ${PKGDEST}/stage3.db.tar.gz ${pkgs[@]} + +librestage ${repo} + + +mkdir -p ${WORKDIR}/abs/${CARCH}/${repo} >/dev/null + +pushd ${WORKDIR}/abs/${CARCH}/${repo} >/dev/null + tar xvf $SRCPKGDEST/${pkgbase:-${pkgname[0]}}-${fullver}${SRCEXT} +popd >/dev/null + +exit $? diff --git a/src/pkgbuild-check-nonfree b/src/pkgbuild-check-nonfree new file mode 100755 index 0000000..0fd480c --- /dev/null +++ b/src/pkgbuild-check-nonfree @@ -0,0 +1,187 @@ +#!/bin/bash +# pkgbuild-check-nonfree +# Copyright 2010 Joshua Ismael Haase Hernández, Joseph Graham +# Copyright 2012 Luke Shumaker + +# ---------- GNU General Public License 3 ---------- + +# This file is part of Parabola. + +# Parabola 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. + +# Parabola 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 Parabola. If not, see <http://www.gnu.org/licenses/>. + +. /etc/libretools.conf + +cmd=${0##*/} +ev=0 + +# log_end() { +# kill "$teepid" +# rm "$logpipe" +# } + +# log() { +# local LOG="pkgbuild-check-nonfree-$(date -u +%Y%m%d).log" +# # ensure overridden package variables survive tee with split packages +# logpipe="$(mktemp)" +# mkfifo "$logpipe" +# tee "$LOG" < "$logpipe" & +# teepid=$! +# trap log_end ERR EXIT +# } + + +unset_pkgbuild() { + unset 'pkgbase' 'pkgname' 'pkgver' 'pkgrel' 'epoch' 'pkgdesc' \ + 'arch' 'url' 'license' 'groups' 'optdepends' 'provides' \ + 'conflicts' 'replaces' 'backup' 'options' 'install' \ + 'changelog' 'source' 'noextract' 'md5sums' 'build' \ + 'check' 'package' 'depends' 'makedepends' 'checkdepends' +} + +assert_pkgbuild() { + if [ -e "$1" ]; then + + source "$1" + if [ -n "${pkgname[0]}" ]; then + return 0 # valid PKGBUILD + fi + + fi + + error "$1 is not a valid PKGBUILD" + return 1 +} + +check_replacement() { + [ $2 ] || return 0 # Free (not found) + local needle=$1; shift + local item + local rep + for line in $@; do + + local item="$(echo "$line" | cut -d':' -f1)" + local rep="$(echo "$line" | cut -s -d':' -f2)" + + if [ "$item" == "$needle" ]; then + if [ -z "$rep" ]; then + return 15 # Nonfree (found) + else + echo "$rep" + return 0 # Free (has replacement) + fi + fi + + done + return 0 # Free (not found) +} + +## +# Download the blacklist. +## +get_blacklist() { + mkdir -p "$XDG_CONFIG_HOME/libretools" + pushd "$XDG_CONFIG_HOME/libretools" >/dev/null + + msg "Downloading the blacklist of proprietary software packages." + + if ! wget -N -q -O blacklist.txt "${BLACKLIST}" 2>/dev/null; then + + if [ -e "$XDG_CONFIG_HOME/libretools/blacklist.txt" ]; then + warning "Using local copy of blacklist" + else + error "Download failed, exiting" + fi + + fi + + popd > /dev/null +} + +## +# Check wheter a package depends on non-free +## +check_deps() { + unset_pkgbuild + if ! assert_pkgbuild "$1"; then + exit 1 # not PKGBUILD + fi + + msg2 "${pkgbase:-${pkgname[0]}} $pkgver $pkgrel ${epoch:-""}" # > "$logpipe" + + for pkg in "${pkgname[@]}" "${depends[@]}" "${makedepends[@]}" "${checkdepends[@]}"; do + + local lines=($(grep "$pkg" "$XDG_CONFIG_HOME/libretools/blacklist.txt" | tr " " "_")) + + local rep="$(check_replacement $pkg ${lines[@]})" + local freedom=$? + + if [[ $freedom = 15 ]]; then + warning "found $pkg" # > "$logpipe" + ev=15 + elif [ -n "$rep" ]; then + if [ "$rep" = "$pkg" ]; then + plain "$pkg is repackaged with the same name." # > "$logpipe" + else + plain "$pkg -> $rep" # > "$logpipe" + fi + fi + done +} + +usage() { + # TODO: implement PKGBUILD arguments + echo "Usage: $cmd [OPTIONS] [PKGBUILD1 PKGBUILD2 ...]" + echo "" + echo "If no PKGBUILD is specified, \`./PKGBUILD' is implied" + echo "" + echo "Options:" + echo " -f Allow running as root user" + echo " -h Show this message" +} + +main() { + local asroot=false + while getopts 'fh' arg; do + case "$arg" in + f) asroot=true;; + h) usage; exit 0;; + *) usage; exit 1;; + esac + done + shift $(($OPTIND - 1)) + pkgbuilds=("$@") + if [[ $# < 1 ]]; then + pkgbuilds=("`pwd`/PKGBUILD") + fi + + if [[ -w / ]] && ! $asroot; then + error "Run as normal user" + exit 1 + fi + + get_blacklist + # log + + msg "Looking for unfree dependencies" + + for p in "${pkgbuilds[@]}"; do + if [[ -n "$p" ]]; then + check_deps "$p" + fi + done + + return $ev +} + +main "$@" diff --git a/src/toru/Makefile b/src/toru/Makefile new file mode 100644 index 0000000..f2cec54 --- /dev/null +++ b/src/toru/Makefile @@ -0,0 +1,3 @@ +libre_execdir=$(bindir) +libre_datadir=$(sysconfdir)/libretools.d +include ../../common.mk diff --git a/src/toru/toru b/src/toru/toru new file mode 100755 index 0000000..28f0b8a --- /dev/null +++ b/src/toru/toru @@ -0,0 +1,314 @@ +#!/bin/bash +# Queries the ABS +# License: GPL3 + +## TODO +# * Add license text +# * Create symlinks from pkgbase to pkgname[@] for easy package finding + +## GOALS +# * Have a searchable database of PKGBUILD metadata +# * Have an interface for source-only builds +# * Possibility to hook up ABS dirs besides ABSROOT (low priority) +# * Tell updates and non available binary packages (working on this) + +source $(dirname $(command -v $0))/toru-utils + +# Saves contents on a named cache +# $1 cache name (repo) +# $2+ contents +function store_cache { + cache=$1; shift + + [ -z "$cache" ] && return 1 + + cat $@ > ${TORUPATH}/${cache}.cache + + return $? +} + +# Return cache contents +# $1 cache name +read_cache() { + cat ${TORUPATH}/${1}.cache 2>/dev/null + + return $? +} + +## +# usage : get_full_version( $epoch, $pkgver, $pkgrel ) +# return : full version spec, including epoch (if necessary), pkgver, pkgrel +## +get_full_version() { + if [[ $1 -eq 0 ]]; then + # zero epoch case, don't include it in version + echo $2-$3 + else + echo $1:$2-$3 + fi +} + +# Outputs an ordered package-fullpkgver array +print_package_array() { + echo "$@" | tr " " "\n" | sort -u +} + + +# Gets repo.db contents (unordered) +# $1 repo +get_db_contents() { + [ ! -r /var/lib/pacman/sync/$1.db ] && return 0 + + bsdtar -tf /var/lib/pacman/sync/$1.db | cut -d'/' -f1 | sort -u +} + +# Get the pkgname +# pkgname from pkgver separator can be either '-' or ' ' +extract_pkgname() { + echo "$@" | tr " " "\n" | sed "s/^\(.\+\)[- ][^-]\+-[^-]\+$/\1/" +} + +# Get all the pkgnames from a file +# pkgname from pkgver separator can be either '-' or ' ' +extract_pkgname_from_file() { + sed "s/^\(.\+\)[- ][^-]\+-[^-]\+$/\1/" $1 +} + +# Split pkgnames from pkgvers +split_pkgname_from_pkgver() { + sed "s/^\(.\+\)-\([^-]\+-[^-]\+\)$/\1 \2/" $1 +} + +# Get the fullpkgver +# pkgname from pkgver separator can be either '-' or ' ' +extract_fullpkgver() { + echo "$@" | tr " " "\n" | sed "s/^.\+[ -]\([^-]\+-[^-]\+\)$/\1/" +} + +# Checks if $1 is a valid repo +is_repo() { + if ! in_array ${1} ${REPOS[@]}; then + $quiet || warning "${1} is not a valid repo (check REPOS array at libretools.conf)" + return 1 + fi +} + +# Updates the database by finding all PKGBUILDS +# Workflow: +# * Find all PKGBUILDs on the ABS repo specified +# * Get all packages already on package repos +# * Compare them +# Args: +update() { + local update_sync_file=false +# The PKGBUILDs found + local -a pkgbuilds=() +# The list of pkgname-fullpkgver + local -a packages_in_abs=() + local -a pkg_updates=() + local -a package_paths=() + +# Traverse all specified repos + for __repo in $@; do +# Check if the repo is set as such, otherwise skip + is_repo ${__repo} || continue + +# Fullpath of the repo + _repopath=$(readlink -f ${__repo}) + +# This is the syncfile, stores the last date as content and mtime + local lastsyncfile=${TORUPATH}/${__repo}.lastsync + +# Find all the PKGBUILDs newer than the last update +# Update newer, otherwise everything + if [[ $force = true || ! -e ${lastsyncfile} ]]; then + + $quiet || warning "Forcing upgrade" +# Get all PKGBUILDs + pkgbuilds=($(find ${_repopath} -maxdepth 2 -type f -name 'PKGBUILD')) + + else + +# Only find newer than lastsyncfile and read everything else from cache + pkgbuilds=($(find ${_repopath} -maxdepth 2 -type f -name 'PKGBUILD' -newer ${lastsyncfile})) + packages_in_abs=($(read_cache ${__repo})) + + $quiet || msg2 "Getting ${#packages_in_abs[@]} packages from cache" + + fi + + package_paths=($(read_cache ${__repo}.paths || true)) + +# Inform how many PKGBUILDS were found and quit immediately if none + $quiet || msg "Found $((${#pkgbuilds[*]}-1)) PKGBUILDs to update" + +# Traverse all found PKGBUILDs + for _pkgbuild in ${pkgbuilds[@]}; do +# Update the sync file because there are pkgbuilds to update + update_sync_file=true + +# Load PKGBUILD's metadata + source ${_pkgbuild} || continue + +# Guess pkgbase from PKGBUILD's basedir + _pkgpath=$(dirname "${_pkgbuild}") + _pkgbase=${pkgbase:-${pkgname[0]}} + +# We won't need this (all unsets are for memory efficiency) + unset build package url md5sums install pkgdesc backup options +# TODO fill a license list + unset license +# TODO create source tarballs? + unset mksource +# TODO solve dependency tree? + unset depends makedepends + + for _pkg in ${pkgname[@]}; do +# Keep removing unneeded stuff + unset package_${_pkg} >/dev/null 2>&1 || true +# Fill the list of packages to find + packages_in_abs+=($_pkg-$(get_full_version ${epoch:-0} $pkgver $pkgrel)) + package_paths+=($_pkg:$_pkgpath) + done # end pkgnames + + unset pkgbase pkgname pkgver pkgrel source epoch + done # end pkgbuilds + +# Sync! (Only if there was an actual sync) + ${update_sync_file} && lastsync ${lastsyncfile} + + if [ "${lastsyncfile}" -nt "${TORUPATH}/${__repo}.paths.cache" ]; then + print_package_array "${package_paths[@]}" > $TMPDIR/paths + store_cache ${__repo}.paths $TMPDIR/paths + fi + +# If there isn't an update cache or it's older than the last update, we check + if [ "${lastsyncfile}" -nt "${TORUPATH}/${__repo}.updates.cache" ]; then + +# Get repo database contents + packages_in_sync=($(get_db_contents ${__repo})) +# Drops arrays into files + print_package_array "${packages_in_abs[@]}" > ${TMPDIR}/packages_in_abs + print_package_array "${packages_in_sync[@]}" > ${TMPDIR}/packages_in_sync + +# Work with files + unset packages_in_abs package_in_sync + +# Use a different separator for pkgnames and pkgvers +# so we can join them by pkgname (first field) + split_pkgname_from_pkgver ${TMPDIR}/packages_in_abs | sort -k1b,1 > ${TMPDIR}/in_abs + split_pkgname_from_pkgver ${TMPDIR}/packages_in_sync | sort -k1b,1 > ${TMPDIR}/in_sync + + $quiet || msg "These packages are available to update" +# Join both files by pkgname, the end result is: +# pkgname syncver absver + join ${TMPDIR}/in_sync ${TMPDIR}/in_abs | \ + while read need_line; do + _pkg=$(echo "${need_line}" | cut -d' ' -f1) + _syncver=$(echo "${need_line}" | cut -d' ' -f2) + _absver=$(echo "${need_line}" | cut -d' ' -f3) + +# If the versions differ we need an update +# TODO move this to update query + if [ "${_syncver}" != "${_absver}" ]; then + $quiet || msg2 "$_pkg update from $_syncver to $_absver" + $quiet && echo "$_pkg" + +# FIXME this works all right but it's unset once the while ends + #pkg_updates+=("$_pkg") + +# Fix for the above problem, but it access the file every time instead of +# puting all packages together once + echo $_pkg >> ${TMPDIR}/updates + + fi + done # end need_line + + unset _pkg _syncver _absver need_line + +# Save the cache + store_cache ${__repo} ${TMPDIR}/packages_in_abs + +# See above FIXME + # print_package_array "${updates[@]}" > ${TMPDIR}/updates + if [ -r ${TMPDIR}/updates ]; then + store_cache ${__repo}.updates ${TMPDIR}/updates + fi + + else + $quiet || msg "Reading updates from cache..." + read_cache ${__repo}.updates + fi + + done # end repos +} + +# Find all the packages that are missing from the repo dbs (aka not built) +missing() { + true +} + +## Finds a PKGBUILD on toru's path cache +## usage: where_is <pkgname> +# Look in all caches but pick the first one +where_is() { + local __repo + local _path + for __repo in ${REPOS[@]}; do + _path=$(grep "^${1}:" "${TORUPATH}/${__repo}.paths.cache" 2>/dev/null | + cut -d: -f2) + + [ -n "${_path}" ] && break + done + + [ -z "$_path" ] && return 1 + + echo ${_path} +} + +# TODO: clean usage instructions +function usage { + echo "" + echo "$0 [options] repo1 ... repon" + echo "" + echo "Make a db containing PKGBUILD metadata." + echo "" + echo "-h : this message" +# echo "-a : update all repos at once" + echo "-u : update repo information" + echo "-q : quiet" + echo "-f : rebuild the db even if it is updated" + echo "-p <pkgname>: return the path for pkgname" + echo "" + exit 1 +} + +## MAIN +commands=() +repos=() +quiet=false +force=false +while getopts 'haqfpum' arg; do + case $arg in + h) usage; exit 0 ;; +# TODO: Update all repos on $REPOS array +# a) update_all_repos ;; + q) quiet=true ;; + f) force=true ;; + u) commands+=(update);; + p) shift $(( OPTIND - 1 )) + where_is "$1" || exit 1;; + m) commands+=(missing);; + esac + + shift $(( OPTIND - 1 )) +done + + +TMPDIR=$(mktemp -d) + +[[ -z ${TMPDIR} ]] && exit 1 + +${commands[0]} ${@} + +exit $? diff --git a/src/toru/toru-info b/src/toru/toru-info new file mode 100755 index 0000000..523f682 --- /dev/null +++ b/src/toru/toru-info @@ -0,0 +1,28 @@ +#!/bin/bash +# Prints info about a given pkgname +source /etc/libretools.conf + +for _pkg in $@; do + _pkgbuild="$(toru-where $_pkg)" + + if [ -f "$_pkgbuild/PKGBUILD" ]; then + source "$_pkgbuild/PKGBUILD" 2>/dev/null || { + warning "Errors on %s" $_pkg + continue + } + + deps="${depends[@]} ${makedepends[@]} ${checkdepends[@]}" + repo="$(basename $(dirname "$_pkgbuild"))" + + unset build package depends makedepends checkdepends optdepends source md5sums + + msg "%s/%s %s-%s" $repo $_pkg $pkgver $pkgrel + msg2 "$pkgdesc" + msg2 "$url" + msg2 "Depends: ${deps}" + else + warning "%s doesn't exist" $_pkg + fi + + unset pkgname pkgver pkgrel pkgdesc url +done diff --git a/src/toru/toru-path b/src/toru/toru-path new file mode 100755 index 0000000..baeaeb5 --- /dev/null +++ b/src/toru/toru-path @@ -0,0 +1,50 @@ +#!/bin/bash + +source $(dirname $(command -v $0))/toru-utils + +TORUPATH=${T:-${TORUPATH}} +VERBOSE=${V:-false} + +if [ ! -w "$TORUPATH" ]; then + error "Toru's path isn't writable. Please check $TORUPATH" + exit 1 +fi + +LASTSYNCFILE=${TORUPATH}/lastsync.paths +PATHFILE=${TORUPATH}/paths.tch + +if [ ! -e "${PATHFILE}" ]; then + tcamgr create "${PATHFILE}" +fi + +# TODO pass other paths via flags +# ABSROOT has trailing slash +fullrepos=() +for (( i = ${#REPOS[@]}-1 ; i >= 0 ; i-- )); do + ${VERBOSE} && msg "Processing [%s]" ${REPOS[$i]} + + [ -d "${ABSROOT}${REPOS[$i]}" ] && \ + fullrepos+=("${ABSROOT}${REPOS[$i]}") +done +pkgbuilds=($(get_pkgbuilds ${fullrepos[@]})) + +msg "Updating path cache" +msg2 "${#pkgbuilds[@]} PKGBUILDs to update" +for _pkgbuild in ${pkgbuilds[@]}; do +# plain "$_pkgbuild" + source ${_pkgbuild} >/dev/null 2>&1 || { + error "${_pkgbuild} contains errors, skipping" + continue + } + + fullpath=$(dirname ${_pkgbuild}) + + for _pkg in ${pkgbase} ${pkgname[@]} ${provides[@]}; do + $VERBOSE && msg2 "${_pkg} -> ${fullpath}" + tcamgr put ${PATHFILE} ${_pkg/[<>=]*} ${fullpath} + done + + unset pkgbase pkgname provides +done + +lastsync ${LASTSYNCFILE} diff --git a/src/toru/toru-utils b/src/toru/toru-utils new file mode 100755 index 0000000..316e6b8 --- /dev/null +++ b/src/toru/toru-utils @@ -0,0 +1,76 @@ +#!/bin/bash + +source /etc/abs.conf +source /etc/libretools.conf + +LASTSYNCFILE=${TORUPATH}/lastsync +FORCE=false +QUIET=false +DEBUG=false + +# usage : in_array( $needle, $haystack ) +function in_array { + [[ $2 ]] || return 1 # Not found + + local needle=$1; shift + local item + + for item in "$@"; do + [[ ${item#@} = $needle ]] && return 0 # Found + done + + return 1 # Not Found +} + +# Stores the lastsync date +lastsync() { + local lastsyncfile + + lastsyncfile=$1 + + [ -e ${lastsyncfile} -a ! -w ${lastsyncfile} ] && { + error "The sync date can't be saved. ${lastsyncfile} isn't writable." + return 1 + } + + date +%s > ${lastsyncfile} + touch ${lastsyncfile} +} + +get_dbs() { + local _db + for _db in /var/lib/pacman/sync/*.db; do + bsdtar tf ${_db} | cut -d'/' -f1 | sort -u + done +} + +# repo paths +get_pkgbuilds() { + pkgbuilds=() + + if [[ $FORCE = true || ! -e ${LASTSYNCFILE} ]]; then + + $QUIET || warning "Forcing upgrade" +# Get all PKGBUILDs + extra="" + else +# Only find newer than lastsyncfile and read everything else from cache + extra=" -newer ${LASTSYNCFILE}" + fi + +# Return all PKGBUILDs found + find $@ -mindepth 2 -maxdepth 3 -type f -name 'PKGBUILD' ${extra} +} + +# End inmediately but print a useful message +trap_exit() { + error "$@" + + 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 diff --git a/src/toru/toru-where b/src/toru/toru-where new file mode 100755 index 0000000..e9ab29d --- /dev/null +++ b/src/toru/toru-where @@ -0,0 +1,7 @@ +#!/bin/bash +# Locates a PKGBUILD dir on toru's path cache +source /etc/libretools.conf + +PATHFILE=${TORUPATH}/paths.tch + +tcamgr get ${PATHFILE} $1 2>/dev/null || echo "" diff --git a/src/treepkg b/src/treepkg new file mode 100755 index 0000000..1453f41 --- /dev/null +++ b/src/treepkg @@ -0,0 +1,237 @@ +#!/bin/bash +#set -x +# (c) 2012 Nicolás Reynolds <fauno@parabola.nu> +# +# 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 Affero 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 <http://www.gnu.org/licenses/>. + +source /etc/libretools.conf +source $XDG_CONFIG_HOME/libretools/libretools.conf >/dev/null 2>&1|| true + +term_title "$(basename $0)" + +# 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() { + term_title "error!" + 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=$(grep "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 + if [ ${current_depth} -ge $2 ]; 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 +} + +# Guess the repo from the pkgbase path +# $1 path, pwd or toru-where +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 + for _pkg in ${pkgname[@]}; do + if is_built "${_pkg}" "${fullver}"; then + add_order "ignore" + exit 0 + fi + done + + # 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 + # Move deps deeper in the tree if + # pkgbase - dep1 + # \ dep2 - dep1 + # dep1 should be depth + 1 + egrep -q ";${_dep};" "${BUILDORDER}" && bury "${_dep}" ${NEXTDEPTH} + + # Ask toru where's a PKGBUILD + depdir="$(toru-where ${_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 + # Skip if already built (faster than calling is_build again) + if [ -f "${BUILDDIR}/${_pkg}/built_ok" ]; then continue; fi + + ${VERBOSE} && msg "Building ${_pkg/_/ }" || true + + # Remove leading zeros and space if any + term_title "$(echo ${_pkg/_/ } | sed "s/^0\+ \?//")" + + # Run build command + pushd "${BUILDDIR}/${_pkg}" >/dev/null + sudo -E pacman -Syu --noconfirm + + ${HOOKPREBUILD} + + ${FULLBUILDCMD} + # Run local release hook with $1 = $repo + ${HOOKLOCALRELEASE} $(egrep ";${_pkg#*_};" "${BUILDORDER}" | cut -d';' -f6) + + touch built_ok + 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 + +term_title "done" +exit $? |