diff --git a/Makefile b/Makefile index 75859f9..2db2109 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -V=0.9.1 +V=0.9.2 PREFIX = /usr/local @@ -15,7 +15,8 @@ BINPROGS = \ bin/basestrap \ bin/manjaro-chroot \ bin/fstabgen \ - bin/make-set + bin/make-set \ + bin/chroot-run SYSCONFIGFILES = \ conf/manjaro-tools.conf @@ -64,10 +65,10 @@ install: install -m0644 ${CONFIGFILES} $(DESTDIR)$(PREFIX)/share/manjaro-tools ln -sf find-libdeps $(DESTDIR)$(PREFIX)/bin/find-libprovides install -m0644 ${LIBS} $(DESTDIR)$(PREFIX)/lib/manjaro-tools - # compat symlinks + # compat symlink for manjaroiso ln -sf basestrap $(DESTDIR)$(PREFIX)/bin/pacstrap - ln -sf fstabgen $(DESTDIR)$(PREFIX)/bin/genfstab - ln -sf manjaro-chroot $(DESTDIR)$(PREFIX)/bin/arch-chroot + #ln -sf fstabgen $(DESTDIR)$(PREFIX)/bin/genfstab + #ln -sf manjaro-chroot $(DESTDIR)$(PREFIX)/bin/arch-chroot uninstall: for f in ${SYSCONFIGFILES}; do rm -f $(DESTDIR)$(SYSCONFDIR)/manjaro-tools/$$f; done @@ -76,10 +77,10 @@ uninstall: for f in ${CONFIGFILES}; do rm -f $(DESTDIR)$(PREFIX)/share/manjaro-tools/$$f; done rm -f $(DESTDIR)$(PREFIX)/bin/find-libprovides for f in ${LIBS}; do rm -f $(DESTDIR)$(PREFIX)/lib/manjaro-tools/$$f; done - # compat symlinks + # compat symlink for manjaroiso rm -f $(DESTDIR)$(PREFIX)/bin/pacstrap - rm -f $(DESTDIR)$(PREFIX)/bin/genfstab - rm -f $(DESTDIR)$(PREFIX)/bin/arch-chroot + #rm -f $(DESTDIR)$(PREFIX)/bin/genfstab + #rm -f $(DESTDIR)$(PREFIX)/bin/arch-chroot dist: git archive --format=tar --prefix=manjaro-tools-$(V)/ $(V) | gzip -9 > manjaro-tools-$(V).tar.gz diff --git a/bin/build-set.in b/bin/build-set.in index 1c6e8d4..109d580 100644 --- a/bin/build-set.in +++ b/bin/build-set.in @@ -19,6 +19,44 @@ if [[ -r @libdir@/build-api.sh ]];then source @libdir@/build-api.sh fi +display_settings(){ + msg "manjaro-tools version: ${version}" + + msg "OPTARGS:" + msg2 "arch: ${arch}" + msg2 "branch: ${branch}" + msg2 "chroots: ${chroots}" + + msg "PATHS:" + msg2 "chrootdir: ${chrootdir}" + msg2 "profiledir: ${profiledir}" + msg2 "pkgdir: ${pkgdir}" + msg2 "pacman_conf: ${pacman_conf}" + msg2 "makepkg_conf: ${makepkg_conf}" + msg2 "pm_conf: ${pm_conf}" + + if ${clean_first};then + msg "PKG:" + msg2 "base_packages: ${base_packages[*]}" + fi + + msg "SETS:" + msg2 "profiles: $(get_profiles)" + msg2 "profile: ${profile}" + msg2 "is_profile: ${is_profile}" + + if ${is_profile};then + msg "These packages will be built:" + local list=$(cat ${profiledir}/${profile}.set) + for item in ${list[@]}; do + msg2 "$item" + done + else + msg "This package will be built:" + msg2 "${profile}" + fi +} + run(){ eval_profile if ${pretend}; then @@ -34,10 +72,10 @@ run(){ clean_dir "${pkgdir}" fi display_settings - chroot_init + #chroot_init prepare_dir "${pkgdir}" - chroot_build - ch_owner "$(dirname ${pkgdir})" + #chroot_build + #ch_owner "$(dirname ${pkgdir})" if ${sign}; then sign_pkgs @@ -81,7 +119,7 @@ fi pacman_conf_arch='default' -clean_first=false +# clean_first=false wipe_clean=false namcap=false pretend=false @@ -100,7 +138,7 @@ usage() { echo " -a Set arch [default: ${arch}]" echo " -b Set branch [default: ${branch}]" echo " -r Chroots directory [default: ${chroots}]" - echo ' -c Clean chroot' +# echo ' -c Clean chroot' echo ' -w Wipe clean pkgbuild and pkg directory' echo ' -n Run namcap check' echo ' -s Sign packages' @@ -119,7 +157,7 @@ while getopts "${opts}" arg; do a) arch="$OPTARG" ;; b) branch="$OPTARG" ;; r) chroots="$OPTARG" ;; - c) clean_first=true ;; +# c) clean_first=true ;; w) wipe_clean=true ;; n) namcap=true; mkchrootpkg_args+=(-n) ;; s) sign=true ;; @@ -139,6 +177,7 @@ fi pacman_conf="@pkgdatadir@/pacman-${pacman_conf_arch}.conf" makepkg_conf="@pkgdatadir@/makepkg-${arch}.conf" +pm_conf="@pkgdatadir@/pacman-mirrors-${branch}.conf" if [[ -n ${pkgdir} ]];then pkgdir="${pkgdir}/${branch}/${arch}" @@ -146,7 +185,7 @@ else pkgdir="/var/cache/manjaro-tools/pkg/${branch}/${arch}" fi -mkchroot_args+=(-C ${pacman_conf} -M ${makepkg_conf} -b ${branch}) +mkchroot_args+=(-C ${pacman_conf} -M ${makepkg_conf} -S ${pm_conf}) mkchrootpkg_args+=(-b ${branch} -r ${chrootdir}) diff --git a/bin/chroot-run.in b/bin/chroot-run.in new file mode 100644 index 0000000..c06a3ab --- /dev/null +++ b/bin/chroot-run.in @@ -0,0 +1,134 @@ +#!/bin/bash +# 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; version 2 of the License. +# +# 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. + +version=@version@ + +if [[ -r @libdir@/messages.sh ]];then + source @libdir@/messages.sh +fi + +if [[ -r @libdir@/mount-api.sh ]];then + source @libdir@/mount-api.sh +fi + +working_dir='' + +usage() { + echo "Usage: ${0##*/} [options] working-dir [systemd-nspawn arguments]" + echo "A wrapper around systemd-nspawn. Provides support for pacman." + echo + echo ' options:' + echo ' -C Location of a pacman config file' + echo ' -M Location of a makepkg config file' + echo ' -S Location of a pacman-mirrors config file' + echo ' -c Set pacman cache' + echo ' -p Set PKGDEST mountpoint' + echo ' -s Set PKGSRC mountpoint' + echo ' -h This message' + exit 1 +} + +orig_argv=("$@") + +while getopts 'hC:M:S:c:' arg; do + case "$arg" in + C) pac_conf="$OPTARG" ;; + M) makepkg_conf="$OPTARG" ;; + S) mirrors_conf="$OPTARG" ;; + c) cache_dir="$OPTARG" ;; + p) pkgdest="$OPTARG" ;; + s) pkgsrc="$OPTARG" ;; + h|?) usage ;; + *) error "invalid argument '$arg'"; usage ;; + esac +done +shift $(($OPTIND - 1)) + +(( $# < 1 )) && die 'You must specify a directory.' +check_root "$0" "${orig_argv[@]}" + +working_dir=$(readlink -f "$1") +shift 1 + +[[ -z $working_dir ]] && die 'Please specify a working directory.' + +if [[ -z $cache_dir ]]; then + cache_dirs=($(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) +else + cache_dirs=("$cache_dir") +fi + +host_mirror=$(pacman -Sddp extra/devtools 2>/dev/null | sed -E "s#(.*/)(.*/)extra/.*#\1branch/\$repo/\$arch#") +[[ $host_mirror == *file://* ]] && host_mirror_path=$(echo "$host_mirror" | sed -r 's#file://(/.*)/\$repo/os/\$arch#\1#g') + +# {{{ functions +build_mount_args() { + declare -g mount_args=() + + if [[ -n $host_mirror_path ]]; then + mount_args+=(--bind-ro="$host_mirror_path") + fi + + mount_args+=(--bind="${cache_dirs[0]}") + + for cache_dir in ${cache_dirs[@]:1}; do + mount_args+=(--bind-ro="$cache_dir") + done +} + +copy_hostconf () { + cp -a /etc/pacman.d/gnupg "$working_dir/etc/pacman.d" + + [[ -n $pac_conf ]] && cp $pac_conf "$working_dir/etc/pacman.conf" + [[ -n $makepkg_conf ]] && cp $makepkg_conf "$working_dir/etc/makepkg.conf" + [[ -n $mirrors_conf ]] && cp ${mirrors_conf} "${working_dir}/etc/pacman-mirrors.conf" + + branch=$(cat "${working_dir}/etc/pacman-mirrors.conf" | grep '^Branch=' | sed 's/Branch=\s*//g') + host_mirror=$(echo "$host_mirror" | sed -E "s#/branch/#/${branch}/#") + echo "Server = $host_mirror" >"$working_dir/etc/pacman.d/mirrorlist" + + sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n ${cache_dirs[@]})|g" -i "$working_dir/etc/pacman.conf" +} +# }}} + +umask 0022 + +# Sanity check +if [[ ! -f "$working_dir/.manjaro-chroot" ]]; then + die "'%s' does not appear to be a Manjaro chroot." "$working_dir" +elif [[ $(cat "$working_dir/.manjaro-chroot") != $version ]]; then + die "chroot '%s' is not at version %s. Please rebuild." "$working_dir" "$version" +fi + +api_fs_mount "${working_dir}" +track_mount /etc/resolv.conf "${working_dir}/etc/resolv.conf" -Br +track_mount ${cache_dirs[0]} "${working_dir}/${cache_dirs[0]}" -Br + +if [[ -n $pkgdest ]]; then + track_mount $pkgdest "${working_dir}/$pkgdest" -Br +fi + +if [[ -n $pkgsrc ]]; then + track_mount $pkgsrc "${working_dir}/$pkgsrc" -Br +fi + +copy_hostconf + +eval $(grep '^CARCH=' "$working_dir/etc/makepkg.conf") + + + +exec ${CARCH:+setarch "$CARCH"} chroot "${working_dir}" "$@" + +# exec ${CARCH:+setarch "$CARCH"} systemd-nspawn 2>/dev/null \ +# -D "$working_dir" \ +# --register=no \ +# "${mount_args[@]}" \ +# "$@" diff --git a/bin/mkchroot.in b/bin/mkchroot.in index 685dfae..e4ae307 100644 --- a/bin/mkchroot.in +++ b/bin/mkchroot.in @@ -14,149 +14,152 @@ if [[ -r @libdir@/messages.sh ]];then source @libdir@/messages.sh fi -if [[ -r @libdir@/mount-api.sh ]];then - source @libdir@/mount-api.sh +if [[ -r @libdir@/util.sh ]];then + source @libdir@/util.sh fi -# if [[ -r @libdir@/build-api.sh ]];then -# source @libdir@/build-api.sh -# fi +working_dir='' -# CMD='' -# NOCOPY='n' - -chrootdir='' -branch='stable' - -APPNAME=$(basename "${0}") - -# usage: usage usage() { - echo "Usage: ${APPNAME} [options] working-dir [package-list | app]" - echo ' options:' - echo ' -r Run "app" within the context of the chroot' -# echo ' -u Update the chroot via pacman' - echo ' -C Location of a pacman config file' - echo ' -M Location of a makepkg config file' - echo ' -S Location of a pacman-mirrors config file' -# echo ' -n Do not copy config files into the chroot' - echo ' -c Set pacman cache' - echo ' -b Set repository branch' - echo ' -h This message' - exit 1 + echo "Usage: ${0##*/} [options] working-dir package-list..." + echo ' options:' + echo ' -C Location of a pacman config file' + echo ' -M Location of a makepkg config file' + echo ' -S Location of a pacman-mirrors config file' + echo ' -c Set pacman cache' + echo ' -h This message' + exit 1 } -# orig_argv=("$@") +orig_argv=("$@") -while getopts 'hC:M:S:c:b:' arg; do - case "${arg}" in -# r) CMD="$OPTARG" ;; -# u) CMD='pacman -Syu --noconfirm' ;; - C) pac_conf="$OPTARG" ;; - M) makepkg_conf="$OPTARG" ;; -# n) NOCOPY='y' ;; - c) cache_dir="$OPTARG" ;; - b) branch="$OPTARG" ;; - S) mirrors_conf="$OPTARG" ;; - h|?) usage ;; - *) error "invalid argument '${arg}'"; usage ;; - esac +while getopts 'hC:M:S:c:' arg; do + case "$arg" in + C) pac_conf="$OPTARG" ;; + M) makepkg_conf="$OPTARG" ;; + S) mirrors_conf="$OPTARG" ;; + c) cache_dir="$OPTARG" ;; + h|?) usage ;; + *) error "invalid argument '$arg'"; usage ;; + esac done shift $(($OPTIND - 1)) -# check_root "$0" "${orig_argv[@]}" - -if (( $EUID != 0 )); then - die 'This script must be run as root.' -fi - - (( $# < 2 )) && die 'You must specify a directory and one or more packages.' -# if [[ -z $CMD ]] && (( $# < 2 )); then -# die 'You must specify a directory and one or more packages.' -# elif (( $# < 1 )); then -# die 'You must specify a directory.' -# fi +check_root "$0" "${orig_argv[@]}" -chrootdir="$(readlink -f ${1})" +working_dir="$(readlink -f $1)" shift 1 -[[ -z $chrootdir ]] && die 'Please specify a working directory.' +[[ -z $working_dir ]] && die 'Please specify a working directory.' -get_cache_dirs(){ - local cache_dirs - if [[ -z ${cache_dir} ]]; then - cache_dirs=($(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) - else - cache_dirs=("${cache_dir}") - fi - echo ${cache_dirs[@]} -} - -copy_hostconf () { - - cp -a /etc/pacman.d/gnupg "${chrootdir}/etc/pacman.d" - - [[ -n $pac_conf ]] && cp $pac_conf "${chrootdir}/etc/pacman.conf" - [[ -n $makepkg_conf ]] && cp $makepkg_conf "${chrootdir}/etc/makepkg.conf" - [[ -n $mirrors_conf ]] && cp ${mirrors_conf} "${chrootdir}/etc/pacman-mirrors.conf" - - host_mirror=$(echo "$host_mirror" | sed -E "s#/branch/#/${branch}/#") - echo "Server = $host_mirror" >"${chrootdir}/etc/pacman.d/mirrorlist" - sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n $(get_cache_dirs))|g" -i "${chrootdir}/etc/pacman.conf" - -} - -chroot_lock () { - # Only reopen the FD if it wasn't handed to us - if [[ $(readlink -f /dev/fd/9) != "${chrootdir}.lock" ]]; then - exec 9>"${chrootdir}.lock" - fi - - # Lock the chroot. Take note of the FD number. - if ! flock -n 9; then - stat_busy "Locking chroot" - flock 9 - stat_done - fi -} - -mk_chroot(){ - if [[ -e ${chrootdir} ]]; then - die "Working directory '${chrootdir}' already exists" - fi - - mkdir -p "${chrootdir}" - - if [[ "$(stat -f -c %T "${chrootdir}")" == btrfs ]]; then - rmdir "${chrootdir}" - if ! btrfs subvolume create "${chrootdir}"; then - die "Couldn't create subvolume for '${chrootdir}'" - fi - chmod 0755 "${chrootdir}" - fi - - chroot_lock - - pacargs=("${cache_dirs[@]/#/--cachedir=}") - if [[ -n $pac_conf ]]; then - pacargs+=("--config=${pac_conf}") - fi - - if ! basestrap -GMcd "${chrootdir}" "${pacargs[@]}" "$@"; then - die 'Failed to install all packages' - fi - - printf '%s.UTF-8 UTF-8\n' en_US de_DE > "${chrootdir}/etc/locale.gen" - chroot "${chrootdir}" locale-gen - echo 'LANG=C' > "${chrootdir}/etc/locale.conf" - - copy_hostconf - - echo "${version}" > "${chrootdir}/.manjaro-chroot" -} +if [[ -z $cache_dir ]]; then + cache_dirs=($(pacman -v $cache_conf 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) +else + cache_dirs=(${cache_dir}) +fi umask 0022 -mk_chroot +[[ -e $working_dir ]] && die "Working directory '%s' already exists" "$working_dir" + +mkdir -p "$working_dir" + +lock 9 "${working_dir}.lock" "Locking chroot" + +if [[ $(stat -f -c %T "$working_dir") == btrfs ]]; then + rmdir "$working_dir" + if ! btrfs subvolume create "$working_dir"; then + die "Couldn't create subvolume for '%s'" "$working_dir" + fi + chmod 0755 "$working_dir" +fi + +basestrap -GMcd ${pac_conf:+-C "$pac_conf"} "$working_dir" \ + "${cache_dirs[@]/#/--cachedir=}" "$@" || die 'Failed to install all packages' + +printf '%s.UTF-8 UTF-8\n' en_US de_DE > "$working_dir/etc/locale.gen" +echo 'LANG=C' > "$working_dir/etc/locale.conf" +echo "$CHROOT_VERSION" > "$working_dir/.manjaro-chroot" + +exec chroot-run \ + ${pac_conf:+-C "$pac_conf"} \ + ${makepkg_conf:+-M "$makepkg_conf"} \ + ${mirrors_conf:+-S "$mirrors_conf"} \ + ${cache_dir:+-c "$cache_dir"} \ + "$working_dir" locale-gen + + +# chrootdir='' +# branch='stable' +# +# APPNAME=$(basename "${0}") +# +# # usage: usage +# usage() { +# echo "Usage: ${APPNAME} [options] working-dir [package-list | app]" +# echo ' options:' +# echo ' -r Run "app" within the context of the chroot' +# echo ' -C Location of a pacman config file' +# echo ' -M Location of a makepkg config file' +# echo ' -S Location of a pacman-mirrors config file' +# echo ' -c Set pacman cache' +# echo ' -b Set repository branch' +# echo ' -h This message' +# exit 1 +# } +# +# orig_argv=("$@") +# +# while getopts 'hC:M:S:c:b:' arg; do +# case "${arg}" in +# C) pac_conf="$OPTARG" ;; +# M) makepkg_conf="$OPTARG" ;; +# c) cache_dir="$OPTARG" ;; +# b) branch="$OPTARG" ;; +# S) mirrors_conf="$OPTARG" ;; +# h|?) usage ;; +# *) error "invalid argument '${arg}'"; usage ;; +# esac +# done +# shift $(($OPTIND - 1)) +# +# check_root "$0" "${orig_argv[@]}" +# +# (( $# < 2 )) && die 'You must specify a directory and one or more packages.' +# +# chrootdir="$(readlink -f ${1})" +# shift 1 +# +# [[ -z $chrootdir ]] && die 'Please specify a working directory.' +# +# umask 0022 +# +# [[ -e ${chrootdir} ]] && die "Working directory '%s' already exists" "${chrootdir}" +# +# mkdir -p "${chrootdir}" +# +# lock 9 "${chrootdir}.lock" "Locking chroot" +# +# if [[ $(stat -f -c %T "${chrootdir}") == btrfs ]]; then +# rmdir "${chrootdir}" +# if ! btrfs subvolume create "${chrootdir}"; then +# die "Couldn't create subvolume for '%s'" "${chrootdir}" +# fi +# chmod 0755 "${chrootdir}" +# fi +# +# cache=$(get_cache_dirs) +# +# basestrap -GMcd ${pac_conf:+-C "$pac_conf"} "${chrootdir}" "${cache[@]/#/--cachedir=}" "$@" || die 'Failed to install all packages' +# +# printf '%s.UTF-8 UTF-8\n' en_US de_DE > "${chrootdir}/etc/locale.gen" +# +# chroot "${chrootdir}" locale-gen +# +# echo 'LANG=C' > "${chrootdir}/etc/locale.conf" +# +# copy_hostconf "${chrootdir}" +# +# echo "${version}" > "${chrootdir}/.manjaro-chroot" \ No newline at end of file diff --git a/bin/mkchrootpkg.in b/bin/mkchrootpkg.in index 7d4b7ea..7d5aa4d 100644 --- a/bin/mkchrootpkg.in +++ b/bin/mkchrootpkg.in @@ -16,20 +16,21 @@ fi shopt -s nullglob -makepkg_args='-s --noconfirm -L' +makepkg_args=(-s --noconfirm -L --holdver) repack=false update_first=false clean_first=false install_pkg= -add_to_db=false run_namcap=false temp_chroot=false chrootdir= passeddir= -branch='stable' declare -a install_pkgs declare -i ret=0 +bindmounts_ro=() +bindmounts_rw=() + copy=$USER [[ -n $SUDO_USER ]] && copy=$SUDO_USER [[ -z "$copy" || $copy = root ]] && copy=copy @@ -38,8 +39,8 @@ src_owner=${SUDO_USER:-$USER} usage() { echo "Usage: ${0##*/} [options] -r [--] [makepkg args]" echo ' Run this script in a PKGBUILD dir to build a package inside a' - echo ' clean chroot. All unrecognized arguments passed to this script' - echo ' will be passed to makepkg.' + echo ' clean chroot. Arguments passed to this script after the' + echo ' end-of-options marker (--) will be passed to makepkg.' echo '' echo ' The chroot dir consists of the following directories:' echo ' /{root, copy} but only "root" is required' @@ -49,44 +50,54 @@ usage() { echo 'command:' echo ' mkmanjaroroot /root base-devel' echo '' - echo "Default makepkg args: $makepkg_args" + echo "Default makepkg args: ${makepkg_args[*]}" echo '' echo 'Flags:' - echo '-h This help' - echo '-c Clean the chroot before building' - echo '-u Update the working copy of the chroot before building' - echo ' This is useful for rebuilds without dirtying the pristine' - echo ' chroot' - echo '-d Add the package to a local db at /repo after building' - echo '-r The chroot dir to use' - echo '-I Install a package into the working copy of the chroot' - echo '-l The directory to use as the working copy of the chroot' - echo ' Useful for maintaining multiple copies' - echo " Default: $copy" - echo '-n Run namcap on the package' - echo '-T Build in a temporary directory' - echo '-b Set repository branch' + echo '-h This help' + echo '-c Clean the chroot before building' + echo '-d Bind directory into build chroot as read-write' + echo '-D Bind directory into build chroot as read-only' + echo '-u Update the working copy of the chroot before building' + echo ' This is useful for rebuilds without dirtying the pristine' + echo ' chroot' + echo '-r The chroot dir to use' + echo '-I Install a package into the working copy of the chroot' + echo '-l The directory to use as the working copy of the chroot' + echo ' Useful for maintaining multiple copies' + echo " Default: $copy" + echo '-n Run namcap on the package' + echo '-T Build in a temporary directory' exit 1 } -while getopts 'hcudr:I:l:nTb:' arg; do +orig_argv=("$@") + +while getopts 'hcur:I:l:nTD:d:' arg; do case "$arg" in - h) usage ;; c) clean_first=true ;; + D) bindmounts_ro+=(--bind-ro="$OPTARG") ;; + d) bindmounts_rw+=(--bind="$OPTARG") ;; u) update_first=true ;; - d) add_to_db=true ;; r) passeddir="$OPTARG" ;; I) install_pkgs+=("$OPTARG") ;; l) copy="$OPTARG" ;; - n) run_namcap=true; makepkg_args="$makepkg_args -i" ;; - T) temp_chroot=true; copy+="-$RANDOM" ;; - b) branch="$OPTARG" ;; - *) makepkg_args="$makepkg_args -$arg $OPTARG" ;; + n) run_namcap=true; makepkg_args+=(-i) ;; + T) temp_chroot=true; copy+="-$$" ;; + h|*) usage ;; esac done +[[ ! -f PKGBUILD && -z "${install_pkgs[*]}" ]] && die 'This must be run in a directory containing a PKGBUILD.' + +check_root "$0" "${orig_argv[@]}" + # Canonicalize chrootdir, getting rid of trailing / chrootdir=$(readlink -e "$passeddir") +[[ ! -d $chrootdir ]] && die "No chroot dir defined, or invalid path '%s'" "$passeddir" +[[ ! -d $chrootdir/root ]] && die "Missing chroot dir root directory. Try using: mkchroot %s/root base-devel" "$chrootdir" + +# Detect chrootdir filesystem type +chroottype=$(stat -f -c %T "$chrootdir") if [[ ${copy:0:1} = / ]]; then copydir=$copy @@ -95,249 +106,645 @@ else fi # Pass all arguments after -- right to makepkg -makepkg_args="$makepkg_args ${*:$OPTIND}" +makepkg_args+=("${@:$OPTIND}") # See if -R was passed to makepkg -for arg in ${*:$OPTIND}; do - if [[ $arg = -R ]]; then - repack=true - break - fi +for arg in "${@:OPTIND}"; do + case ${arg%%=*} in + -*R*|--repackage) + repack=true + break 2 + ;; + esac done -if (( EUID )); then - die 'This script must be run as root.' +if [[ -n $SUDO_USER ]]; then + eval "USER_HOME=~$SUDO_USER" +else + USER_HOME=$HOME fi -if [[ ! -f PKGBUILD && -z "${install_pkgs[*]}" ]]; then - die 'This must be run in a directory containing a PKGBUILD.' -fi +# {{{ functions +load_vars() { + local makepkg_conf="$1" var -if [[ ! -d $chrootdir ]]; then - die "No chroot dir defined, or invalid path '$passeddir'" -fi + [[ -f $makepkg_conf ]] || return 1 -if [[ ! -d $chrootdir/root ]]; then - die "Missing chroot dir root directory. Try using: mkmanjaroroot $chrootdir/root base-devel" -fi + for var in {SRC,SRCPKG,PKG,LOG}DEST MAKEFLAGS PACKAGER; do + [[ -z ${!var} ]] && eval $(grep "^${var}=" "$makepkg_conf") + done -umask 0022 + return 0 +} -# Detect chrootdir filesystem type -chroottype=$(stat -f -c %T "$chrootdir") +create_chroot() { + # Lock the chroot we want to use. We'll keep this lock until we exit. + lock 9 "$copydir.lock" "Locking chroot copy [$copy]" -# Lock the chroot we want to use. We'll keep this lock until we exit. -# Note this is the same FD number as in mkmanjaroroot -exec 9>"$copydir.lock" -if ! flock -n 9; then - stat_busy "Locking chroot copy [$copy]" - flock 9 - stat_done -fi + 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 + slock 8 "$chrootdir/root.lock" "Locking clean chroot" -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 - exec 8>"$chrootdir/root.lock" - - if ! flock -sn 8; then - stat_busy "Locking clean chroot" - flock -s 8 - stat_done - fi - - stat_busy "Creating clean working copy [$copy]" - if [[ "$chroottype" == btrfs ]]; then - if [[ -d $copydir ]]; then - btrfs subvolume delete "$copydir" >/dev/null || - die "Unable to delete subvolume $copydir" + stat_busy "Creating clean working copy [$copy]" + if [[ "$chroottype" == btrfs ]] && ! mountpoint -q "$copydir"; then + if [[ -d $copydir ]]; then + btrfs subvolume delete "$copydir" >/dev/null || + die "Unable to delete subvolume %s" "$copydir" + fi + btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || + die "Unable to create subvolume %s" "$copydir" + else + mkdir -p "$copydir" + rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir" fi - btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || - die "Unable to create subvolume $copydir" - else - mkdir -p "$copydir" - rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir" + stat_done + + # Drop the read lock again + exec 8>&- fi + + # Update mtime + touch "$copydir" +} + +clean_temporary() { + stat_busy "Removing temporary copy [$copy]" + if [[ "$chroottype" == btrfs ]] && ! mountpoint -q "$copydir"; then + btrfs subvolume delete "$copydir" >/dev/null || + die "Unable to delete subvolume %s" "$copydir" + else + # avoid change of filesystem in case of an umount failure + rm --recursive --force --one-file-system "$copydir" || + die "Unable to delete %s" "$copydir" + fi + + # remove lock file + rm -f "$copydir.lock" stat_done +} - # Drop the read lock again - exec 8>&- -fi +install_packages() { + local pkgname -if [[ -n "${install_pkgs[*]}" ]]; then for install_pkg in "${install_pkgs[@]}"; do pkgname="${install_pkg##*/}" cp "$install_pkg" "$copydir/$pkgname" - mkchroot -b "${branch}" -r "pacman -U /$pkgname --noconfirm" "$copydir" + arch-nspawn "$copydir" \ + "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \ + pacman -U /$pkgname --noconfirm (( ret += !! $? )) rm "$copydir/$pkgname" done - # If there is no PKGBUILD we have done + # If there is no PKGBUILD we are done [[ -f PKGBUILD ]] || exit $ret -fi +} -$update_first && mkchroot -b "${branch}" -u "$copydir" +prepare_chroot() { + $repack || rm -rf "$copydir/build" -mkdir -p "$copydir/build" - -# Remove anything in there UNLESS -R (repack) was passed to makepkg -$repack || rm -rf "$copydir"/build/* - -# Read .makepkg.conf and .gnupg/pubring.gpg even if called via sudo -if [[ -n $SUDO_USER ]]; then - SUDO_HOME="$(eval echo ~$SUDO_USER)" - makepkg_conf="$SUDO_HOME/.makepkg.conf" - if [[ -r "$SUDO_HOME/.gnupg/pubring.gpg" ]]; then - install -D "$SUDO_HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" + mkdir -p "$copydir/build" + if ! grep -q 'BUILDDIR="/build"' "$copydir/etc/makepkg.conf"; then + echo 'BUILDDIR="/build"' >> "$copydir/etc/makepkg.conf" fi -else - makepkg_conf="$HOME/.makepkg.conf" - if [[ -r "$HOME/.gnupg/pubring.gpg" ]]; then - install -D "$HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" + + # Read .makepkg.conf and .gnupg/pubring.gpg even if called via sudo + if [[ -r "$USER_HOME/.gnupg/pubring.gpg" ]]; then + install -D "$USER_HOME/.gnupg/pubring.gpg" \ + "$copydir/build/.gnupg/pubring.gpg" fi -fi -# Get SRC/PKGDEST from makepkg.conf -if [[ -f $makepkg_conf ]]; then - eval $(grep '^SRCDEST=' "$makepkg_conf") - eval $(grep '^PKGDEST=' "$makepkg_conf") - eval $(grep '^MAKEFLAGS=' "$makepkg_conf") - eval $(grep '^PACKAGER=' "$makepkg_conf") -fi + mkdir -p "$copydir/pkgdest" + if ! grep -q 'PKGDEST="/pkgdest"' "$copydir/etc/makepkg.conf"; then + echo 'PKGDEST="/pkgdest"' >> "$copydir/etc/makepkg.conf" + fi -[[ -z $SRCDEST ]] && eval $(grep '^SRCDEST=' /etc/makepkg.conf) -[[ -z $PKGDEST ]] && eval $(grep '^PKGDEST=' /etc/makepkg.conf) -[[ -z $MAKEFLAGS ]] && eval $(grep '^MAKEFLAGS=' /etc/makepkg.conf) -[[ -z $PACKAGER ]] && eval $(grep '^PACKAGER=' /etc/makepkg.conf) + mkdir -p "$copydir/srcpkgdest" + if ! grep -q 'SRCPKGDEST="/srcpkgdest"' "$copydir/etc/makepkg.conf"; then + echo 'SRCPKGDEST="/srcpkgdest"' >> "$copydir/etc/makepkg.conf" + fi -# Use PKGBUILD directory if PKGDEST or SRCDEST don't exist -[[ -d $PKGDEST ]] || PKGDEST=. -[[ -d $SRCDEST ]] || SRCDEST=. + mkdir -p "$copydir/logdest" + if ! grep -q 'LOGDEST="/logdest"' "$copydir/etc/makepkg.conf"; then + echo 'LOGDEST="/logdest"' >> "$copydir/etc/makepkg.conf" + fi -mkdir -p "$copydir/pkgdest" -if ! grep -q 'PKGDEST="/pkgdest"' "$copydir/etc/makepkg.conf"; then - echo 'PKGDEST="/pkgdest"' >> "$copydir/etc/makepkg.conf" -fi + # These two get bind-mounted read-only + # XXX: makepkg dislikes having these dirs read-only, so separate them + mkdir -p "$copydir/startdir" "$copydir/startdir_host" + mkdir -p "$copydir/srcdest" "$copydir/srcdest_host" + if ! grep -q 'SRCDEST="/srcdest"' "$copydir/etc/makepkg.conf"; then + echo 'SRCDEST="/srcdest"' >> "$copydir/etc/makepkg.conf" + fi -mkdir -p "$copydir/srcdest" -if ! grep -q 'SRCDEST="/srcdest"' "$copydir/etc/makepkg.conf"; then - echo 'SRCDEST="/srcdest"' >> "$copydir/etc/makepkg.conf" -fi + builduser_uid=${SUDO_UID:-$UID} -if [[ -n $MAKEFLAGS ]]; then - sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf" - echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf" -fi + # We can't use useradd without chrooting, otherwise it invokes PAM modules + # which we might not be able to load (i.e. when building i686 packages on + # an x86_64 host). + printf 'builduser:x:%d:100:builduser:/:/usr/bin/nologin\n' "$builduser_uid" >>"$copydir/etc/passwd" + chown -R "$builduser_uid" "$copydir"/{build,pkgdest,srcpkgdest,logdest,srcdest,startdir} -if [[ -n $PACKAGER ]]; then - sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf" - echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf" -fi + if [[ -n $MAKEFLAGS ]]; then + sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf" + echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf" + fi -# Set target CARCH as it might be used within the PKGBUILD to select correct sources -eval $(grep '^CARCH=' "$copydir/etc/makepkg.conf") -export CARCH + if [[ -n $PACKAGER ]]; then + sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf" + echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf" + fi -# Copy PKGBUILD and sources -cp PKGBUILD "$copydir/build/" -( - source PKGBUILD - for file in "${source[@]}"; do - file="${file%%::*}" - file="${file##*://*/}" - if [[ -f $file ]]; then - cp "$file" "$copydir/srcdest/" - elif [[ -f $SRCDEST/$file ]]; then - cp "$SRCDEST/$file" "$copydir/srcdest/" - 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/build/" - done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD) - done -) - -chown -R nobody "$copydir"/{build,pkgdest,srcdest} - -cat > "$copydir/etc/sudoers.d/nobody-pacman" < "$copydir/etc/sudoers.d/builduser-pacman" <"$copydir/chrootbuild" <&1 | tee "/build/\${pkgfile##*/}-namcap.log" - done -fi - -exit 0 + if $run_namcap; then + cat <<'EOF' +pacman -S --needed --noconfirm namcap +for pkgfile in /startdir/PKGBUILD /pkgdest/*; do + echo "Checking ${pkgfile##*/}" + sudo -u builduser namcap "$pkgfile" 2>&1 | tee "/logdest/${pkgfile##*/}-namcap.log" +done EOF -chmod +x "$copydir/chrootbuild" - -if mkchroot -b "${branch}" -r "/chrootbuild" "$copydir"; then - for pkgfile in "$copydir"/pkgdest/*.pkg.tar.?z; do - if $add_to_db; then - mkdir -p "$copydir/repo" - pushd "$copydir/repo" >/dev/null - cp "$pkgfile" . - repo-add repo.db.tar.gz "${pkgfile##*/}" - popd >/dev/null fi + } >"$copydir/chrootbuild" + chmod +x "$copydir/chrootbuild" +} +download_sources() { + local builddir="$(mktemp -d)" + chmod 1777 "$builddir" + + # Ensure sources are downloaded + if [[ -n $SUDO_USER ]]; then + sudo -u $SUDO_USER env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \ + makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o + else + ( export SRCDEST BUILDDIR="$builddir" + makepkg --asroot --config="$copydir/etc/makepkg.conf" --verifysource -o + ) + fi + (( $? != 0 )) && die "Could not download sources." + + # Clean up garbage from verifysource + rm -rf $builddir +} + +_chrootbuild() { + # This function isn't run in makechrootpkg, + # so no global variables + + . /etc/profile + export HOME=/build + shopt -s nullglob + + # XXX: Workaround makepkg disliking read-only dirs + ln -sft /srcdest /srcdest_host/* + ln -sft /startdir /startdir_host/* + + # XXX: Keep bzr and svn sources writable + # Since makepkg 4.1.1 they get checked out via cp -a, copying the symlink + for dir in /srcdest /startdir; do + for vcs in bzr svn; do + cd "$dir" + for vcsdir in */.$vcs; do + rm "${vcsdir%/.$vcs}" + cp -a "${dir}_host/${vcsdir%/.$vcs}" . + chown -R builduser "${vcsdir%/.$vcs}" + done + done + done + + cd /startdir + + # XXX: Keep PKGBUILD writable for pkgver() + rm PKGBUILD* + cp /startdir_host/PKGBUILD* . + chown builduser PKGBUILD* + + # Safety check + if [[ ! -w PKGBUILD ]]; then + echo "Can't write to PKGBUILD!" + exit 1 + fi + + sudo -u builduser makepkg "$@" +} + +move_products() { + for pkgfile in "$copydir"/pkgdest/*; do chown "$src_owner" "$pkgfile" mv "$pkgfile" "$PKGDEST" done - for l in "$copydir"/build/*-{build,check,namcap,package,package_*}.log; do + for l in "$copydir"/logdest/*; do + [[ $l == */logpipe.* ]] && continue chown "$src_owner" "$l" - [[ -f $l ]] && mv "$l" . + mv "$l" "$LOGDEST" done + + for s in "$copydir"/srcpkgdest/*; do + chown "$src_owner" "$s" + mv "$s" "$SRCPKGDEST" + done +} +# }}} + +umask 0022 + +load_vars "$USER_HOME/.makepkg.conf" +load_vars /etc/makepkg.conf + +# Use PKGBUILD directory if these don't exist +[[ -d $PKGDEST ]] || PKGDEST=$PWD +[[ -d $SRCDEST ]] || SRCDEST=$PWD +[[ -d $SRCPKGDEST ]] || SRCPKGDEST=$PWD +[[ -d $LOGDEST ]] || LOGDEST=$PWD + +create_chroot + +$update_first && chroot-run "$copydir" \ + pacman -Syu --noconfirm + +[[ -n ${install_pkgs[*]} ]] && install_packages + +prepare_chroot + +download_sources + +# if arch-nspawn "$copydir" \ +# --bind-ro="$PWD:/startdir_host" \ +# --bind-ro="$SRCDEST:/srcdest_host" \ +# "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \ +# /chrootbuild; then +# move_products +# else +# (( ret += 1 )) +# fi + +if chroot-run -p "$PWD:/startdir_host" \ + -s "$SRCDEST:/srcdest_host" \ + "$copydir" \ + /chrootbuild; then + move_products else - # Just in case. We returned 1, make sure we fail - ret=1 + (( ret += 1 )) fi -for f in "$copydir"/srcdest/*; do - chown "$src_owner" "$f" - mv "$f" "$SRCDEST" -done +$temp_chroot && clean_temporary -if $temp_chroot; then - stat_busy "Removing temporary directoy [$copy]" - if [[ "$chroottype" == btrfs ]]; then - btrfs subvolume delete "$copydir" >/dev/null || - die "Unable to delete subvolume $copydir" +if (( ret != 0 )); then + if $temp_chroot; then + die "Build failed" else - # avoid change of filesystem in case of an umount failure - rm --recursive --force --one-file-system "$copydir" || - die "Unable to delete $copydir" + die "Build failed, check %s/build" "$copydir" fi - # remove lock file - rm --force "$copydir.lock" - stat_done -elif (( ret != 0 )); then - die "Build failed, check $copydir/build" else true fi + + +# shopt -s nullglob +# +# makepkg_args='-s --noconfirm -L' +# repack=false +# update_first=false +# clean_first=false +# install_pkg= +# add_to_db=false +# run_namcap=false +# temp_chroot=false +# chrootdir= +# passeddir= +# branch='stable' +# declare -a install_pkgs +# declare -i 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 [--] [makepkg args]" +# echo ' Run this script in a PKGBUILD dir to build a package inside a' +# echo ' clean chroot. All unrecognized arguments passed to this script' +# echo ' will be passed to makepkg.' +# echo '' +# echo ' The chroot dir consists of the following directories:' +# echo ' /{root, copy} but only "root" is required' +# echo ' by default. The working copy will be created as needed' +# echo '' +# echo 'The chroot "root" directory must be created via the following' +# echo 'command:' +# echo ' mkmanjaroroot /root base-devel' +# echo '' +# echo "Default makepkg args: $makepkg_args" +# echo '' +# echo 'Flags:' +# echo '-h This help' +# echo '-c Clean the chroot before building' +# echo '-u Update the working copy of the chroot before building' +# echo ' This is useful for rebuilds without dirtying the pristine' +# echo ' chroot' +# echo '-d Add the package to a local db at /repo after building' +# echo '-r The chroot dir to use' +# echo '-I Install a package into the working copy of the chroot' +# echo '-l The directory to use as the working copy of the chroot' +# echo ' Useful for maintaining multiple copies' +# echo " Default: $copy" +# echo '-n Run namcap on the package' +# echo '-T Build in a temporary directory' +# echo '-b Set repository branch' +# exit 1 +# } +# +# while getopts 'hcudr:I:l:nTb:' arg; do +# case "$arg" in +# h) usage ;; +# c) clean_first=true ;; +# u) update_first=true ;; +# d) add_to_db=true ;; +# r) passeddir="$OPTARG" ;; +# I) install_pkgs+=("$OPTARG") ;; +# l) copy="$OPTARG" ;; +# n) run_namcap=true; makepkg_args="$makepkg_args -i" ;; +# T) temp_chroot=true; copy+="-$RANDOM" ;; +# b) branch="$OPTARG" ;; +# *) makepkg_args="$makepkg_args -$arg $OPTARG" ;; +# esac +# done +# +# # Canonicalize chrootdir, getting rid of trailing / +# chrootdir=$(readlink -e "$passeddir") +# +# if [[ ${copy:0:1} = / ]]; then +# copydir=$copy +# else +# copydir="$chrootdir/$copy" +# fi +# +# # Pass all arguments after -- right to makepkg +# makepkg_args="$makepkg_args ${*:$OPTIND}" +# +# # See if -R was passed to makepkg +# for arg in ${*:$OPTIND}; do +# if [[ $arg = -R ]]; then +# repack=true +# break +# fi +# done +# +# if (( EUID )); then +# die 'This script must be run as root.' +# fi +# +# if [[ ! -f PKGBUILD && -z "${install_pkgs[*]}" ]]; then +# die 'This must be run in a directory containing a PKGBUILD.' +# fi +# +# if [[ ! -d $chrootdir ]]; then +# die "No chroot dir defined, or invalid path '$passeddir'" +# fi +# +# if [[ ! -d $chrootdir/root ]]; then +# die "Missing chroot dir root directory. Try using: mkmanjaroroot $chrootdir/root base-devel" +# fi +# +# umask 0022 +# +# # Detect chrootdir filesystem type +# chroottype=$(stat -f -c %T "$chrootdir") +# +# # Lock the chroot we want to use. We'll keep this lock until we exit. +# # Note this is the same FD number as in mkmanjaroroot +# exec 9>"$copydir.lock" +# if ! flock -n 9; then +# stat_busy "Locking chroot copy [$copy]" +# flock 9 +# stat_done +# fi +# +# 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 +# exec 8>"$chrootdir/root.lock" +# +# if ! flock -sn 8; then +# stat_busy "Locking clean chroot" +# flock -s 8 +# stat_done +# fi +# +# stat_busy "Creating clean working copy [$copy]" +# if [[ "$chroottype" == btrfs ]]; then +# if [[ -d $copydir ]]; then +# btrfs subvolume delete "$copydir" >/dev/null || +# die "Unable to delete subvolume $copydir" +# fi +# btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || +# die "Unable to create subvolume $copydir" +# else +# mkdir -p "$copydir" +# rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir" +# fi +# stat_done +# +# # Drop the read lock again +# exec 8>&- +# fi +# +# if [[ -n "${install_pkgs[*]}" ]]; then +# for install_pkg in "${install_pkgs[@]}"; do +# pkgname="${install_pkg##*/}" +# cp "$install_pkg" "$copydir/$pkgname" +# +# mkchroot -b "${branch}" -r "pacman -U /$pkgname --noconfirm" "$copydir" +# (( ret += !! $? )) +# +# rm "$copydir/$pkgname" +# done +# +# # If there is no PKGBUILD we have done +# [[ -f PKGBUILD ]] || exit $ret +# fi +# +# $update_first && mkchroot -b "${branch}" -u "$copydir" +# +# mkdir -p "$copydir/build" +# +# # Remove anything in there UNLESS -R (repack) was passed to makepkg +# $repack || rm -rf "$copydir"/build/* +# +# # Read .makepkg.conf and .gnupg/pubring.gpg even if called via sudo +# if [[ -n $SUDO_USER ]]; then +# SUDO_HOME="$(eval echo ~$SUDO_USER)" +# makepkg_conf="$SUDO_HOME/.makepkg.conf" +# if [[ -r "$SUDO_HOME/.gnupg/pubring.gpg" ]]; then +# install -D "$SUDO_HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" +# fi +# else +# makepkg_conf="$HOME/.makepkg.conf" +# if [[ -r "$HOME/.gnupg/pubring.gpg" ]]; then +# install -D "$HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" +# fi +# fi +# +# # Get SRC/PKGDEST from makepkg.conf +# if [[ -f $makepkg_conf ]]; then +# eval $(grep '^SRCDEST=' "$makepkg_conf") +# eval $(grep '^PKGDEST=' "$makepkg_conf") +# eval $(grep '^MAKEFLAGS=' "$makepkg_conf") +# eval $(grep '^PACKAGER=' "$makepkg_conf") +# fi +# +# [[ -z $SRCDEST ]] && eval $(grep '^SRCDEST=' /etc/makepkg.conf) +# [[ -z $PKGDEST ]] && eval $(grep '^PKGDEST=' /etc/makepkg.conf) +# [[ -z $MAKEFLAGS ]] && eval $(grep '^MAKEFLAGS=' /etc/makepkg.conf) +# [[ -z $PACKAGER ]] && eval $(grep '^PACKAGER=' /etc/makepkg.conf) +# +# # Use PKGBUILD directory if PKGDEST or SRCDEST don't exist +# [[ -d $PKGDEST ]] || PKGDEST=. +# [[ -d $SRCDEST ]] || SRCDEST=. +# +# mkdir -p "$copydir/pkgdest" +# if ! grep -q 'PKGDEST="/pkgdest"' "$copydir/etc/makepkg.conf"; then +# echo 'PKGDEST="/pkgdest"' >> "$copydir/etc/makepkg.conf" +# fi +# +# mkdir -p "$copydir/srcdest" +# if ! grep -q 'SRCDEST="/srcdest"' "$copydir/etc/makepkg.conf"; then +# echo 'SRCDEST="/srcdest"' >> "$copydir/etc/makepkg.conf" +# fi +# +# if [[ -n $MAKEFLAGS ]]; then +# sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf" +# echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf" +# fi +# +# if [[ -n $PACKAGER ]]; then +# sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf" +# echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf" +# fi +# +# # Set target CARCH as it might be used within the PKGBUILD to select correct sources +# eval $(grep '^CARCH=' "$copydir/etc/makepkg.conf") +# export CARCH +# +# # Copy PKGBUILD and sources +# cp PKGBUILD "$copydir/build/" +# ( +# source PKGBUILD +# for file in "${source[@]}"; do +# file="${file%%::*}" +# file="${file##*://*/}" +# if [[ -f $file ]]; then +# cp "$file" "$copydir/srcdest/" +# elif [[ -f $SRCDEST/$file ]]; then +# cp "$SRCDEST/$file" "$copydir/srcdest/" +# 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/build/" +# done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD) +# done +# ) +# +# chown -R nobody "$copydir"/{build,pkgdest,srcdest} +# +# cat > "$copydir/etc/sudoers.d/nobody-pacman" <"$copydir/chrootbuild" <&1 | tee "/build/\${pkgfile##*/}-namcap.log" +# done +# fi +# +# exit 0 +# EOF +# chmod +x "$copydir/chrootbuild" +# +# if mkchroot -b "${branch}" -r "/chrootbuild" "$copydir"; then +# for pkgfile in "$copydir"/pkgdest/*.pkg.tar.?z; do +# if $add_to_db; then +# mkdir -p "$copydir/repo" +# pushd "$copydir/repo" >/dev/null +# cp "$pkgfile" . +# repo-add repo.db.tar.gz "${pkgfile##*/}" +# popd >/dev/null +# fi +# +# chown "$src_owner" "$pkgfile" +# mv "$pkgfile" "$PKGDEST" +# done +# +# for l in "$copydir"/build/*-{build,check,namcap,package,package_*}.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 +# +# for f in "$copydir"/srcdest/*; do +# chown "$src_owner" "$f" +# mv "$f" "$SRCDEST" +# done +# +# if $temp_chroot; then +# stat_busy "Removing temporary directoy [$copy]" +# if [[ "$chroottype" == btrfs ]]; then +# btrfs subvolume delete "$copydir" >/dev/null || +# die "Unable to delete subvolume $copydir" +# else +# # avoid change of filesystem in case of an umount failure +# rm --recursive --force --one-file-system "$copydir" || +# die "Unable to delete $copydir" +# fi +# # remove lock file +# rm --force "$copydir.lock" +# stat_done +# elif (( ret != 0 )); then +# die "Build failed, check $copydir/build" +# else +# true +# fi diff --git a/lib/build-api.sh b/lib/build-api.sh index 8e510eb..6f82ec7 100644 --- a/lib/build-api.sh +++ b/lib/build-api.sh @@ -54,53 +54,44 @@ git_clean(){ ####chroot controller###### -chroot_clean(){ - for copy in "${chrootdir}"/*; do - [[ -d "${copy}" ]] || continue - msg2 "Deleting chroot copy '$(basename "${copy}")'..." - - exec 9>"${copy}.lock" - if ! flock -n 9; then - stat_busy "Locking chroot copy '${copy}'" - flock 9 - stat_done - fi - - if [[ "$(stat -f -c %T "${copy}")" == btrfs ]]; then - { type -P btrfs && btrfs subvolume delete "${copy}"; } &>/dev/null - fi - rm -rf --one-file-system "${copy}" - done - exec 9>&- - - rm -rf --one-file-system "${chrootdir}" -} - -chroot_create(){ - mkdir -p "${chrootdir}" - setarch "${arch}" \ - mkchroot ${mkchroot_args[*]} ${chrootdir}/root ${base_packages[*]} || abort -} - - -# chroot_update(){ -# setarch "${arch}" \ -# mkchroot ${mkchroot_args[*]} -u ${chrootdir}/$(get_user) || abort +# chroot_clean(){ +# for copy in "${chrootdir}"/*; do +# [[ -d "${copy}" ]] || continue +# msg2 "Deleting chroot copy '$(basename "${copy}")'..." +# +# exec 9>"${copy}.lock" +# if ! flock -n 9; then +# stat_busy "Locking chroot copy '${copy}'" +# flock 9 +# stat_done +# fi +# +# if [[ "$(stat -f -c %T "${copy}")" == btrfs ]]; then +# { type -P btrfs && btrfs subvolume delete "${copy}"; } &>/dev/null +# fi +# rm -rf --one-file-system "${copy}" +# done +# exec 9>&- +# +# rm -rf --one-file-system "${chrootdir}" # } - -chroot_init(){ - if [[ ! -d "${chrootdir}" ]]; then - msg "Creating chroot for [${branch}] (${arch})..." - chroot_create - else ${clean_first};then - msg "Creating chroot for [${branch}] (${arch})..." - chroot_clean - chroot_create +# +# chroot_create(){ +# mkdir -p "${chrootdir}" +# setarch "${arch}" \ +# mkchroot ${mkchroot_args[*]} ${chrootdir}/root ${base_packages[*]} || abort +# } +# +# chroot_init(){ +# if [[ -e ${chrootdir} ]]; then +# msg "Creating chroot for [${branch}] (${arch})..." +# chroot_clean +# chroot_create # else -# msg "Updating chroot for [${branch}] (${arch})..." -# chroot_update - fi -} +# msg "Creating chroot for [${branch}] (${arch})..." +# chroot_create +# fi +# } chroot_build(){ if ${is_profile};then @@ -130,7 +121,6 @@ chroot_build(){ ####end chroot controller###### - eval_profile(){ eval "case ${profile} in $(get_profiles)) is_profile=true ;; @@ -142,56 +132,19 @@ blacklist_pkg(){ local blacklist=('libsystemd') cmd=$(pacman -Q ${blacklist[@]} -r ${chrootdir}/root 2> /dev/null) if [[ -n $cmd ]] ; then msg2 "Removing blacklisted [${blacklist[@]}] ..." - pacman -Rdd "${blacklist[@]}" -r ${chrootdir}/root --noconfirm + setarch "${arch}" pacman -Rdd "${blacklist[@]}" -r ${chrootdir}/root --noconfirm else msg2 "Blacklisted [${blacklist[@]}] not present." fi } -install_pkg(){ - msg2 "Installing built package ..." - setarch "${arch}" pacman -U *pkg*z -r ${chrootdir}/$(get_user) --noconfirm -} +# install_pkg(){ +# msg2 "Installing built package ..." +# setarch "${arch}" pacman -U *pkg*z -r ${chrootdir}/$(get_user) --noconfirm +# } move_pkg(){ msg2 "Moving [$1] to [${pkgdir}]" local ext='pkg.tar.xz' mv *.${ext} ${pkgdir}/ } - -display_settings(){ - msg "manjaro-tools version: ${version}" - - msg "OPTARGS:" - msg2 "arch: ${arch}" - msg2 "branch: ${branch}" - msg2 "chroots: ${chroots}" - - msg "PATHS:" - msg2 "chrootdir: ${chrootdir}" - msg2 "profiledir: ${profiledir}" - msg2 "pkgdir: ${pkgdir}" - msg2 "pacman_conf: ${pacman_conf}" - msg2 "makepkg_conf: ${makepkg_conf}" - - if ${clean_first};then - msg "PKG:" - msg2 "base_packages: ${base_packages[*]}" - fi - - msg "SETS:" - msg2 "profiles: $(get_profiles)" - msg2 "profile: ${profile}" - msg2 "is_profile: ${is_profile}" - - if ${is_profile};then - msg "These packages will be built:" - local list=$(cat ${profiledir}/${profile}.set) - for item in ${list[@]}; do - msg2 "$item" - done - else - msg "This package will be built:" - msg2 "${profile}" - fi -} diff --git a/lib/messages.sh b/lib/messages.sh index c0041d6..84a036c 100644 --- a/lib/messages.sh +++ b/lib/messages.sh @@ -96,5 +96,23 @@ die() { cleanup 255 } +lock() { + eval "exec $1>"'"$2"' + if ! flock -n $1; then + stat_busy "$3" + flock $1 + stat_done + fi +} + +slock() { + eval "exec $1>"'"$2"' + if ! flock -sn $1; then + stat_busy "$3" + flock -s $1 + stat_done + fi +} + trap 'trap_abort' INT QUIT TERM HUP trap 'trap_exit' EXIT diff --git a/lib/mount-api.sh b/lib/mount-api.sh index da9426c..d5bf71a 100644 --- a/lib/mount-api.sh +++ b/lib/mount-api.sh @@ -159,12 +159,3 @@ dm_name_for_devnode() { error 'Failed to resolve device mapper name for: %s' "$1" fi } - -# check_root() { -# (( EUID == 0 )) && return -# if type -P sudo >/dev/null; then -# exec sudo -- "$@" -# else -# exec su root -c "$(printf ' %q' "$@")" -# fi -# } diff --git a/lib/util.sh b/lib/util.sh index bfa0e2e..44026d3 100644 --- a/lib/util.sh +++ b/lib/util.sh @@ -139,3 +139,35 @@ pkgver_equal() { [[ ${1%%-*} = "${2%%-*}" ]] fi } + +check_root() { + (( EUID == 0 )) && return + if type -P sudo >/dev/null; then + exec sudo -- "$@" + else + exec su root -c "$(printf ' %q' "$@")" + fi +} + +get_cache_dirs(){ + local cache_dirs + if [[ -z ${cache_dir} ]]; then + cache_dirs=($(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) + else + cache_dirs=("${cache_dir}") + fi + echo ${cache_dirs[@]} +} + +copy_hostconf () { + + cp -a /etc/pacman.d/gnupg "$1/etc/pacman.d" + + [[ -n $pac_conf ]] && cp $pac_conf "$1/etc/pacman.conf" + [[ -n $makepkg_conf ]] && cp $makepkg_conf "$1/etc/makepkg.conf" + [[ -n $mirrors_conf ]] && cp ${mirrors_conf} "$1/etc/pacman-mirrors.conf" + + local host_mirror=$(echo "$host_mirror" | sed -E "s#/branch/#/${branch}/#") + echo "Server = $host_mirror" >"$1/etc/pacman.d/mirrorlist" + sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n $(get_cache_dirs))|g" -i "$1/etc/pacman.conf" +}