diff --git a/Makefile b/Makefile index e2d531214e26f4dc8c70d882247e8aa7f50217f1..ba43f56d99ac2681e641772c21a2980c1486a2b9 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ edit = sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g" %: %.in Makefile lib/common.sh @echo "GEN $@" @$(RM) "$@" - @m4 -P $@.in | $(edit) >$@ + @{ echo -n 'm4_changequote([[[,]]])'; cat $@.in; } | m4 -P | $(edit) >$@ @chmod a-w "$@" @chmod +x "$@" @bash -O extglob -n "$@" @@ -78,4 +78,8 @@ dist: git archive --format=tar --prefix=devtools-$(V)/ $(V) | gzip -9 > devtools-$(V).tar.gz gpg --detach-sign --use-agent devtools-$(V).tar.gz +check: $(BINPROGS) bash_completion makepkg-x86_64.conf PKGBUILD.proto + shellcheck $^ + .PHONY: all clean install uninstall dist +.DELETE_ON_ERROR: diff --git a/PKGBUILD.proto b/PKGBUILD.proto new file mode 100644 index 0000000000000000000000000000000000000000..e8690e4e3f860a5250b2e05a0c0721748f4e9d4e --- /dev/null +++ b/PKGBUILD.proto @@ -0,0 +1,48 @@ +#!/hint/bash +# shellcheck disable=2034 + +# This is an example PKGBUILD file, so that shellcheck can know what +# variables to expect be set after including a PKGBUILD. + +# Maintainer: Your Name <youremail@domain.com> +pkgname=NAME +pkgver=VERSION +pkgrel=1 +epoch= +pkgdesc="" +arch=() +url="" +license=('GPL') +groups=() +depends=() +makedepends=() +checkdepends=() +optdepends=() +provides=() +conflicts=() +replaces=() +backup=() +options=() +install= +changelog= +source=("$pkgname-$pkgver.tar.gz" + "$pkgname-$pkgver.patch") +noextract=() +md5sums=() +validpgpkeys=() + +prepare() { + : +} + +build() { + : +} + +check() { + : +} + +package() { + : +} diff --git a/arch-nspawn.in b/arch-nspawn.in index b9b16ed338b760b3afc313fb086d518f30a96aa2..9ffc9d8df2285fe2b0847bb4d1bee2b07490a0a8 100644 --- a/arch-nspawn.in +++ b/arch-nspawn.in @@ -44,7 +44,7 @@ while getopts 'hC:M:S:c:f:s' arg; do *) error "invalid argument '%s'" "$arg"; usage ;; esac done -shift $(($OPTIND - 1)) +shift $((OPTIND - 1)) (( $# < 1 )) && die 'You must specify a directory.' check_root @@ -60,7 +60,9 @@ else cache_dirs=("$cache_dir") fi +# shellcheck disable=2016 host_mirror=$(pacman --cachedir /doesnt/exist -Sddp extra/devtools 2>/dev/null | sed -E "s#(.*/)(.*/)extra/.*#\1branch/\$repo/\$arch#") +# shellcheck disable=2016 [[ $host_mirror == *file://* ]] && host_mirror_path=$(echo "$host_mirror" | sed -r 's#file://(/.*)/\$repo/os/\$arch#\1#g') # {{{ functions @@ -68,22 +70,22 @@ build_mount_args() { declare -g mount_args=() if [[ -n $host_mirror_path ]]; then - mount_args+=(--bind-ro="$host_mirror_path") + mount_args+=("--bind-ro=$host_mirror_path") fi - mount_args+=(--bind="${cache_dirs[0]}") + mount_args+=("--bind=${cache_dirs[0]}") - for cache_dir in ${cache_dirs[@]:1}; do - mount_args+=(--bind-ro="$cache_dir") + 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" + [[ -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}/#") @@ -95,7 +97,7 @@ copy_hostconf () { cp -T "$file" "$working_dir$file" done - sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n ${cache_dirs[@]})|g" -i "$working_dir/etc/pacman.conf" + sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n "${cache_dirs[@]}")|g" -i "$working_dir/etc/pacman.conf" } # }}} @@ -104,14 +106,14 @@ 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") != $CHROOT_VERSION ]]; then +elif [[ $(cat "$working_dir/.manjaro-chroot") != "$CHROOT_VERSION" ]]; then die "chroot '%s' is not at version %s. Please rebuild." "$working_dir" "$CHROOT_VERSION" fi build_mount_args copy_hostconf -eval $(grep '^CARCH=' "$working_dir/etc/makepkg.conf") +eval "$(grep '^CARCH=' "$working_dir/etc/makepkg.conf")" [[ -z $nosetarch ]] || unset CARCH diff --git a/bash_completion.in b/bash_completion.in index 5329af756f4c1ef89ad12f5ffca8987cc6c44e49..6cccf232c33343d014c55ccf0f857eaa9e4d8731 100644 --- a/bash_completion.in +++ b/bash_completion.in @@ -5,8 +5,8 @@ _devtools_compgen() { local i r COMPREPLY=($(compgen -W '$*' -- "$cur")) for ((i=1; i < ${#COMP_WORDS[@]}-1; i++)); do - for r in ${!COMPREPLY[@]}; do - if [[ ${COMP_WORDS[i]} = ${COMPREPLY[r]} ]]; then + for r in "${!COMPREPLY[@]}"; do + if [[ ${COMP_WORDS[i]} = "${COMPREPLY[r]}" ]]; then unset 'COMPREPLY[r]'; break fi done diff --git a/checkpkg.in b/checkpkg.in index ec58ff69cc6a9e712b817465814bc6f259fdbb29..e0e1f83b0d053e2f3ee570dfdb4c5b816055153f 100644 --- a/checkpkg.in +++ b/checkpkg.in @@ -7,6 +7,7 @@ m4_include(lib/common.sh) # Source makepkg.conf; fail if it is not found if [[ -r '/etc/makepkg.conf' ]]; then + # shellcheck source=makepkg-x86_64.conf source '/etc/makepkg.conf' else die '/etc/makepkg.conf not found!' @@ -14,8 +15,10 @@ fi # Source user-specific makepkg.conf overrides if [[ -r "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" ]]; then + # shellcheck source=/dev/null source "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" elif [[ -r "$HOME/.makepkg.conf" ]]; then + # shellcheck source=/dev/null source "$HOME/.makepkg.conf" fi @@ -23,8 +26,9 @@ if [[ ! -f PKGBUILD ]]; then die 'This must be run in the directory of a built package.' fi +# shellcheck source=PKGBUILD.proto . ./PKGBUILD -if [[ $arch == 'any' ]]; then +if [[ ${arch[0]} == 'any' ]]; then CARCH='any' fi @@ -39,15 +43,12 @@ for _pkgname in "${pkgname[@]}"; do ln -s "$pkgfile" "$TEMPDIR" - pkgurl=$(pacman -Spdd --print-format '%l' --noconfirm "$_pkgname") - - if [[ $? -ne 0 ]]; then + pkgurl=$(pacman -Spdd --print-format '%l' --noconfirm "$_pkgname") || die "Couldn't download previous package for %s." "$_pkgname" - fi oldpkg=${pkgurl##*://*/} - if [[ ${oldpkg##*/} = ${pkgfile##*/} ]]; then + if [[ ${oldpkg##*/} = "${pkgfile##*/}" ]]; then die "The built package (%s) is the one in the repo right now!" "$_pkgname" fi diff --git a/find-libdeps.in b/find-libdeps.in index 5c350a986dd4a63573e8f641eb2fbca9ba4386f7..1fb1fdfcbc00e22332254b8640c9f188a29dcc4e 100644 --- a/find-libdeps.in +++ b/find-libdeps.in @@ -28,7 +28,7 @@ if [[ -z $1 ]]; then fi if [[ -d $1 ]]; then - pushd $1 >/dev/null + pushd "$1" >/dev/null else setup_workdir @@ -45,10 +45,10 @@ process_sofile() { soname="${sofile%.so?(+(.+([0-9])))}".so # extract the major version: 1 soversion="${sofile##*\.so\.}" - if [[ "$soversion" = "$sofile" ]] && (($IGNORE_INTERNAL)); then + if [[ "$soversion" = "$sofile" ]] && ((IGNORE_INTERNAL)); then continue fi - if ! in_array "${soname}=${soversion}-${soarch}" ${soobjects[@]}; then + if ! in_array "${soname}=${soversion}-${soarch}" "${soobjects[@]}"; then # libfoo.so=1-64 echo "${soname}=${soversion}-${soarch}" soobjects+=("${soname}=${soversion}-${soarch}") @@ -60,7 +60,7 @@ case $script_mode in provides) find_args=(-name '*.so*');; esac -find . -type f "${find_args[@]}" | while read filename; do +find . -type f "${find_args[@]}" | while read -r filename; do if [[ $script_mode = "provides" ]]; then # ignore if we don't have a shared object if ! LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then diff --git a/finddeps.in b/finddeps.in index 89ccc41d3647fc6acad40552d692a3bf81360f2f..2a085e56745719ca7dad69267d1b3d2e3ce882e9 100644 --- a/finddeps.in +++ b/finddeps.in @@ -17,24 +17,25 @@ if [[ -z $match ]]; then exit 1 fi -find . -type d | while read d; do +find . -type d | while read -r d; do if [[ -f "$d/PKGBUILD" ]]; then - unset pkgname depends makedepends optdepends + pkgname=() depends=() makedepends=() optdepends=() + # shellcheck source=PKGBUILD.proto . "$d/PKGBUILD" for dep in "${depends[@]}"; do # lose the version comparator, if any depname=${dep%%[<>=]*} - [[ $depname = $match ]] && echo "$d (depends)" + [[ $depname = "$match" ]] && echo "$d (depends)" done for dep in "${makedepends[@]}"; do # lose the version comparator, if any depname=${dep%%[<>=]*} - [[ $depname = $match ]] && echo "$d (makedepends)" + [[ $depname = "$match" ]] && echo "$d (makedepends)" done for dep in "${optdepends[@]/:*}"; do # lose the version comaparator, if any depname=${dep%%[<>=]*} - [[ $depname = $match ]] && echo "$d (optdepends)" + [[ $depname = "$match" ]] && echo "$d (optdepends)" done fi done diff --git a/lddd.in b/lddd.in index f01ebf9b65aa1b83402292dd6fa6d5fdba725e08..908923b038123073076ba4cdec8269e9a163063d 100644 --- a/lddd.in +++ b/lddd.in @@ -20,7 +20,7 @@ for tree in $PATH $libdirs $extras; do msg2 "DIR %s" "$tree" # Get list of files in tree. - files=$(find $tree -type f ! -name '*.a' ! -name '*.la' ! -name '*.py*' ! -name '*.txt' ! -name '*.h' ! -name '*.ttf' ! \ + files=$(find "$tree" -type f ! -name '*.a' ! -name '*.la' ! -name '*.py*' ! -name '*.txt' ! -name '*.h' ! -name '*.ttf' ! \ -name '*.rb' ! -name '*.ko' ! -name '*.pc' ! -name '*.enc' ! -name '*.cf' ! -name '*.def' ! -name '*.rules' ! -name \ '*.cmi' ! -name '*.mli' ! -name '*.ml' ! -name '*.cma' ! -name '*.cmx' ! -name '*.cmxa' ! -name '*.pod' ! -name '*.pm' \ ! -name '*.pl' ! -name '*.al' ! -name '*.tcl' ! -name '*.bs' ! -name '*.o' ! -name '*.png' ! -name '*.gif' ! -name '*.cmo' \ @@ -28,22 +28,22 @@ for tree in $PATH $libdirs $extras; do -name '*.mcopclass' ! -name '*.mcoptype') IFS=$ifs for i in $files; do - if (( $(file $i | grep -c 'ELF') != 0 )); then + if (( $(file "$i" | grep -c 'ELF') != 0 )); then # Is an ELF binary. - if (( $(ldd $i 2>/dev/null | grep -c 'not found') != 0 )); then + if (( $(ldd "$i" 2>/dev/null | grep -c 'not found') != 0 )); then # Missing lib. - echo "$i:" >> $TEMPDIR/raw.txt - ldd $i 2>/dev/null | grep 'not found' >> $TEMPDIR/raw.txt + echo "$i:" >> "$TEMPDIR/raw.txt" + ldd "$i" 2>/dev/null | grep 'not found' >> "$TEMPDIR/raw.txt" fi fi done done -grep '^/' $TEMPDIR/raw.txt | sed -e 's/://g' >> $TEMPDIR/affected-files.txt +grep '^/' "$TEMPDIR/raw.txt" | sed -e 's/://g' >> "$TEMPDIR/affected-files.txt" # invoke pacman -for i in $(cat $TEMPDIR/affected-files.txt); do - pacman -Qo $i | awk '{print $4,$5}' >> $TEMPDIR/pacman.txt -done +while read -r i; do + pacman -Qo "$i" | awk '{print $4,$5}' >> "$TEMPDIR/pacman.txt" +done < "$TEMPDIR/affected-files.txt" # clean list -sort -u $TEMPDIR/pacman.txt >> $TEMPDIR/possible-rebuilds.txt +sort -u "$TEMPDIR/pacman.txt" >> "$TEMPDIR/possible-rebuilds.txt" msg "Files saved to %s" "$TEMPDIR" diff --git a/lib/archroot.sh b/lib/archroot.sh index 46d49639e1084b1313dc073ad41c23e24159c08d..98fd2cfb594316007abcf0cd0953dea367a8948e 100644 --- a/lib/archroot.sh +++ b/lib/archroot.sh @@ -1,6 +1,8 @@ #!/hint/bash # License: Unspecified +: +# shellcheck disable=2034 CHROOT_VERSION='v4' ## @@ -24,6 +26,23 @@ is_btrfs() { [[ -e "$1" && "$(stat -f -c %T "$1")" == btrfs ]] } +## +# usage : is_subvolume( $path ) +# return : whether $path is a the root of a btrfs subvolume (including +# the top-level subvolume). +## +is_subvolume() { + [[ -e "$1" && "$(stat -f -c %T "$1")" == btrfs && "$(stat -c %i "$1")" == 256 ]] +} + +## +# usage : is_same_fs( $path_a, $path_b ) +# return : whether $path_a and $path_b are on the same filesystem +## +is_same_fs() { + [[ "$(stat -c %d "$1")" == "$(stat -c %d "$1")" ]] +} + ## # usage : subvolume_delete_recursive( $path ) # @@ -32,14 +51,17 @@ is_btrfs() { subvolume_delete_recursive() { local subvol - is_btrfs "$1" || return 0 + is_subvolume "$1" || return 0 while IFS= read -d $'\0' -r subvol; do - if ! btrfs subvolume delete "$subvol" &>/dev/null; then - error "Unable to delete subvolume %s" "$subvol" + if ! subvolume_delete_recursive "$subvol"; then return 1 fi - done < <(find "$1" -xdev -depth -inum 256 -print0) + done < <(find "$1" -mindepth 1 -xdev -depth -inum 256 -print0) + if ! btrfs subvolume delete "$1" &>/dev/null; then + error "Unable to delete subvolume %s" "$subvol" + return 1 + fi return 0 } diff --git a/lib/common.sh b/lib/common.sh index c9afc363463eb57338b42eb6caa2cb7ae3636a95..0fb93d9deb671cda8d460f82733ac257c989ba0a 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -35,35 +35,42 @@ readonly ALL_OFF BOLD BLUE GREEN RED YELLOW plain() { local mesg=$1; shift + # shellcheck disable=2059 printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg() { local mesg=$1; shift + # shellcheck disable=2059 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg2() { local mesg=$1; shift + # shellcheck disable=2059 printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } warning() { local mesg=$1; shift + # shellcheck disable=2059 printf "${YELLOW}==> WARNING:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } error() { local mesg=$1; shift + # shellcheck disable=2059 printf "${RED}==> ERROR:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } stat_busy() { local mesg=$1; shift + # shellcheck disable=2059 printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}...${ALL_OFF}" "$@" >&2 } stat_done() { + # shellcheck disable=2059 printf "${BOLD}done${ALL_OFF}\n" >&2 } @@ -79,7 +86,7 @@ cleanup() { if [[ -n ${WORKDIR:-} ]] && $_setup_workdir; then rm -rf "$WORKDIR" fi - exit ${1:-0} + exit "${1:-0}" } abort() { @@ -112,7 +119,7 @@ in_array() { local needle=$1; shift local item for item in "$@"; do - [[ $item = $needle ]] && return 0 # Found + [[ $item = "$needle" ]] && return 0 # Found done return 1 # Not Found } @@ -123,24 +130,27 @@ in_array() { ## get_full_version() { # set defaults if they weren't specified in buildfile - pkgbase=${pkgbase:-${pkgname[0]}} - epoch=${epoch:-0} + local pkgbase=${pkgbase:-${pkgname[0]}} + local epoch=${epoch:-0} + local pkgver=${pkgver} + local pkgrel=${pkgrel} if [[ -z $1 ]]; then if (( ! epoch )); then - echo $pkgver-$pkgrel + printf '%s\n' "$pkgver-$pkgrel" else - echo $epoch:$pkgver-$pkgrel + printf '%s\n' "$epoch:$pkgver-$pkgrel" fi else + local pkgver_override='' pkgrel_override='' epoch_override='' for i in pkgver pkgrel epoch; do local indirect="${i}_override" - eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p") + eval "$(declare -f "package_$1" | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")" [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\" done - if (( ! $epoch_override )); then - echo $pkgver_override-$pkgrel_override + if (( ! epoch_override )); then + printf '%s\n' "$pkgver_override-$pkgrel_override" else - echo $epoch_override:$pkgver_override-$pkgrel_override + printf '%s\n' "$epoch_override:$pkgver_override-$pkgrel_override" fi fi } @@ -155,9 +165,9 @@ lock() { eval "exec $1>"'"$2"' fi - if ! flock -n $1; then + if ! flock -n "$1"; then stat_busy "${@:3}" - flock $1 + flock "$1" stat_done fi } @@ -172,9 +182,9 @@ slock() { eval "exec $1>"'"$2"' fi - if ! flock -sn $1; then + if ! flock -sn "$1"; then stat_busy "${@:3}" - flock -s $1 + flock -s "$1" stat_done fi } @@ -184,6 +194,8 @@ slock() { ## lock_close() { local fd=$1 + # https://github.com/koalaman/shellcheck/issues/862 + # shellcheck disable=2034 exec {fd}>&- } @@ -247,7 +259,7 @@ find_cached_package() { return 1 ;; 1) - printf '%s\n' "$results" + printf '%s\n' "${results[0]}" return 0 ;; *) diff --git a/lib/valid-tags.sh b/lib/valid-tags.sh index 97ff005dbdc7f1e2ae947a050cb75e4aadb70733..27d30fc9b82e3b7ed88ff7fa689ae7d74ae8fb09 100644 --- a/lib/valid-tags.sh +++ b/lib/valid-tags.sh @@ -1,6 +1,8 @@ #!/hint/bash # License: Unspecified +: +# shellcheck disable=2034 _arch=( i686 x86_64 diff --git a/makechrootpkg.in b/makechrootpkg.in index 63673e8a58660d6e7da3b28e8315884f0c27295c..77dce826156f69d9fdbe8410c7b202e9a7f00ce5 100644 --- a/makechrootpkg.in +++ b/makechrootpkg.in @@ -92,42 +92,43 @@ load_vars() { [[ -f $makepkg_conf ]] || return 1 for var in {SRC,SRCPKG,PKG,LOG}DEST MAKEFLAGS PACKAGER; do - [[ -z ${!var:-} ]] && eval $(grep "^${var}=" "$makepkg_conf") + [[ -z ${!var:-} ]] && eval "$(grep "^${var}=" "$makepkg_conf")" done return 0 } -# Usage: sync_chroot $CHROOTDIR/$CHROOT <$CHROOTCOPY|$copydir> +# Usage: sync_chroot $rootdir $copydir [$copy] sync_chroot() { - local chrootdir=$1 - local copy=$2 - local copydir='' - if [[ ${copy:0:1} = / ]]; then - copydir=$copy - else - copydir="$chrootdir/$copy" - fi + local rootdir=$1 + local copydir=$2 + local copy=${3:-$2} - if [[ "$chrootdir/root" -ef "$copydir" ]]; then + if [[ "$rootdir" -ef "$copydir" ]]; then error 'Cannot sync copy with itself: %s' "$copydir" return 1 fi # 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 [%s]" "$chrootdir/root" - - stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$chrootdir/root" "$copydir" - if is_btrfs "$chrootdir" && ! mountpoint -q "$copydir"; then - subvolume_delete_recursive "$copydir" || - die "Unable to delete subvolume %s" "$copydir" - btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || + slock 8 "$rootdir.lock" \ + "Locking clean chroot [%s]" "$rootdir" + + stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$rootdir" "$copy" + if is_subvolume "$rootdir" && is_same_fs "$rootdir" "$(dirname -- "$copydir")" && ! mountpoint -q "$copydir"; then + if is_subvolume "$copydir"; then + subvolume_delete_recursive "$copydir" || + 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 + btrfs subvolume snapshot "$rootdir" "$copydir" >/dev/null || die "Unable to create subvolume %s" "$copydir" else mkdir -p "$copydir" - rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir" + rsync -a --delete -q -W -x "$rootdir/" "$copydir" fi stat_done @@ -144,7 +145,7 @@ delete_chroot() { local copy=${1:-$2} stat_busy "Removing chroot copy [%s]" "$copy" - if is_btrfs "$chrootdir" && ! mountpoint -q "$copydir"; then + if is_subvolume "$copydir" && ! mountpoint -q "$copydir"; then subvolume_delete_recursive "$copydir" || die "Unable to delete subvolume %s" "$copydir" else @@ -189,8 +190,9 @@ prepare_chroot() { $repack || rm -rf "$copydir/build" - local builduser_uid="${SUDO_UID:-$UID}" - local builduser_gid="$(id -g "$builduser_uid")" + local builduser_uid builduser_gid + builduser_uid="${SUDO_UID:-$UID}" + builduser_gid="$(id -g "$builduser_uid")" local install="install -o $builduser_uid -g $builduser_gid" local x @@ -198,8 +200,8 @@ prepare_chroot() { # which we might not be able to load (i.e. when building i686 packages on # an x86_64 host). sed -e '/^builduser:/d' -i "$copydir"/etc/{passwd,group} - printf >>"$copydir/etc/group" 'builduser:x:%d:\n' $builduser_gid - printf >>"$copydir/etc/passwd" 'builduser:x:%d:%d:builduser:/build:/bin/bash\n' $builduser_uid $builduser_gid + printf >>"$copydir/etc/group" 'builduser:x:%d:\n' "$builduser_gid" + printf >>"$copydir/etc/passwd" 'builduser:x:%d:%d:builduser:/build:/bin/bash\n' "$builduser_uid" "$builduser_gid" $install -d "$copydir"/{build,build/.gnupg,startdir,{pkg,srcpkg,src,log}dest} @@ -239,7 +241,12 @@ EOF # These functions aren't run in makechrootpkg, # so no global variables _chrootbuild() { + # shellcheck source=/dev/null . /etc/profile + # Beware, there are some stupid arbitrary rules on how you can + # use "$" in arguments to commands with "sudo -i". ${foo} or + # ${1} is OK, but $foo or $1 isn't. + # https://bugzilla.sudo.ws/show_bug.cgi?id=765 sudo -iu builduser bash -c 'cd /startdir; makepkg "$@"' -bash "$@" } @@ -251,27 +258,27 @@ _chrootnamcap() { done } -# Usage: download_sources $copydir $src_owner +# Usage: download_sources $copydir $makepkg_user # Globals: # - SRCDEST # - USER download_sources() { local copydir=$1 - local src_owner=$2 + local makepkg_user=$2 - local builddir="$(mktemp -d)" + local builddir + builddir="$(mktemp -d)" chmod 1777 "$builddir" # Ensure sources are downloaded - makepkg_user=${makepkg_user:-$SUDO_USER} - if [[ -n $makepkg_user ]]; then + if [[ "$(id -u "$makepkg_user")" != 0 ]]; then sudo -u "$makepkg_user" env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \ - makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o + makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o || + die "Could not download sources." else error "Running makepkg as root is not allowed." exit 1 fi - (( $? != 0 )) && die "Could not download sources." # Clean up garbage from verifysource rm -rf "$builddir" @@ -306,6 +313,11 @@ move_products() { for s in "$copydir"/srcpkgdest/*; do chown "$src_owner" "$s" mv "$s" "$SRCPKGDEST" + + # Fix broken symlink because of temporary chroot SRCPKGDEST /srcpkgdest + if [[ "$PWD" != "$SRCPKGDEST" && -L "$PWD/${s##*/}" ]]; then + ln -sf "$SRCPKGDEST/${s##*/}" + fi done } # }}} @@ -316,8 +328,8 @@ main() { while getopts 'hcur:I:l:nTD:d:U:' arg; do case "$arg" in c) clean_first=true ;; - D) bindmounts_ro+=(--bind-ro="$OPTARG") ;; - d) bindmounts_rw+=(--bind="$OPTARG") ;; + D) bindmounts_ro+=("--bind-ro=$OPTARG") ;; + d) bindmounts_rw+=("--bind=$OPTARG") ;; u) update_first=true ;; r) passeddir="$OPTARG" ;; I) install_pkgs+=("$OPTARG") ;; @@ -331,6 +343,7 @@ main() { [[ ! -f PKGBUILD && -z "${install_pkgs[*]}" ]] && die 'This must be run in a directory containing a PKGBUILD.' [[ -n $makepkg_user && -z $(id -u "$makepkg_user") ]] && die 'Invalid makepkg user.' + makepkg_user=${makepkg_user:-${SUDO_USER:-$USER}} check_root @@ -379,7 +392,7 @@ main() { lock 9 "$copydir.lock" "Locking chroot copy [%s]" "$copy" if [[ ! -d $copydir ]] || $clean_first; then - sync_chroot "$chrootdir" "$copy" + sync_chroot "$chrootdir/root" "$copydir" "$copy" fi $update_first && arch-nspawn "$copydir" \ @@ -393,7 +406,7 @@ main() { [[ -f PKGBUILD ]] || return $ret fi - download_sources "$copydir" "$src_owner" + download_sources "$copydir" "$makepkg_user" prepare_chroot "$copydir" "$USER_HOME" "$repack" diff --git a/makepkg-i686.conf b/makepkg-i686.conf index c5657959a755461d6f45688ff87c63bbfa31ded2..f7ea2c262cd3fe373063256039a84fa6a905c375 100644 --- a/makepkg-i686.conf +++ b/makepkg-i686.conf @@ -1,3 +1,6 @@ +#!/hint/bash +# shellcheck disable=2034 + # # /etc/makepkg.conf # @@ -37,9 +40,9 @@ CHOST="i686-pc-linux-gnu" # -march (or -mcpu) builds exclusively for an architecture # -mtune optimizes for an architecture, but builds for whole processor family CPPFLAGS="-D_FORTIFY_SOURCE=2" -CFLAGS="-march=i686 -mtune=generic -O2 -pipe -fstack-protector-strong" -CXXFLAGS="-march=i686 -mtune=generic -O2 -pipe -fstack-protector-strong" -LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro" +CFLAGS="-march=i686 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt" +CXXFLAGS="-march=i686 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt" +LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now" #-- Make Flags: change this for DistCC/SMP systems #MAKEFLAGS="-j2" #-- Debugging flags diff --git a/makepkg-x86_64.conf b/makepkg-x86_64.conf index 058da9baa73c50759ee4a0db2c05ffee610f4b7f..67cb2008035b3913f5ea12e9c2a641d02b468945 100644 --- a/makepkg-x86_64.conf +++ b/makepkg-x86_64.conf @@ -1,3 +1,6 @@ +#!/hint/bash +# shellcheck disable=2034 + # # /etc/makepkg.conf # @@ -37,9 +40,9 @@ CHOST="x86_64-pc-linux-gnu" # -march (or -mcpu) builds exclusively for an architecture # -mtune optimizes for an architecture, but builds for whole processor family CPPFLAGS="-D_FORTIFY_SOURCE=2" -CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong" -CXXFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong" -LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro" +CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt" +CXXFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt" +LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now" #-- Make Flags: change this for DistCC/SMP systems #MAKEFLAGS="-j2" #-- Debugging flags diff --git a/mkarchroot.in b/mkarchroot.in index 98ec04de9ba470f52e8ac2c130785413865fc743..31201f8403b4f0cfe91a897b2970dd817e567a1a 100644 --- a/mkarchroot.in +++ b/mkarchroot.in @@ -42,19 +42,19 @@ while getopts 'hC:M:S:c:f:s' arg; do *) error "invalid argument '%s'" "$arg"; usage ;; esac done -shift $(($OPTIND - 1)) +shift $((OPTIND - 1)) (( $# < 2 )) && die 'You must specify a directory and one or more packages.' check_root -working_dir="$(readlink -f $1)" +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 $cache_conf 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) + cache_dirs=($(pacman -v "$cache_conf" 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) else cache_dirs=(${cache_dir}) fi