summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--PKGBUILD.proto48
-rw-r--r--arch-nspawn.in29
-rw-r--r--archbuild.in9
-rw-r--r--archco.in2
-rw-r--r--archrelease.in6
-rw-r--r--archrm.in2
-rw-r--r--bash_completion.in7
-rw-r--r--checkpkg.in19
-rw-r--r--commitpkg.in47
-rw-r--r--crossrepomove.in16
-rw-r--r--find-libdeps.in14
-rw-r--r--finddeps.in11
-rw-r--r--lddd.in24
-rw-r--r--lib/archroot.sh67
-rw-r--r--lib/common.sh129
-rw-r--r--lib/valid-tags.sh4
-rw-r--r--makechrootpkg.in234
-rw-r--r--makepkg-i686.conf3
-rw-r--r--makepkg-x86_64.conf3
-rw-r--r--mkarchroot.in17
-rw-r--r--rebuildpkgs.in23
22 files changed, 433 insertions, 290 deletions
diff --git a/Makefile b/Makefile
index d93fefd..9549569 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-V=20160528
+V=20170320
PREFIX = /usr/local
@@ -74,7 +74,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 "$@"
@@ -114,5 +114,8 @@ dist:
upload:
scp devtools-$(V).tar.gz devtools-$(V).tar.gz.sig repos.archlinux.org:/srv/ftp/other/devtools/
-.PHONY: all clean install uninstall dist upload
+check: $(BINPROGS) bash_completion makepkg-x86_64.conf PKGBUILD.proto
+ shellcheck $^
+.PHONY: all clean install uninstall dist upload check
+.DELETE_ON_ERROR:
diff --git a/PKGBUILD.proto b/PKGBUILD.proto
new file mode 100644
index 0000000..e8690e4
--- /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 adee72e..0b0dc68 100644
--- a/arch-nspawn.in
+++ b/arch-nspawn.in
@@ -11,8 +11,7 @@
# GNU General Public License for more details.
m4_include(lib/common.sh)
-
-CHROOT_VERSION='v3'
+m4_include(lib/archroot.sh)
working_dir=''
@@ -32,8 +31,6 @@ usage() {
exit 1
}
-orig_argv=("$@")
-
while getopts 'hC:M:c:f:s' arg; do
case "$arg" in
C) pac_conf="$OPTARG" ;;
@@ -45,10 +42,10 @@ while getopts 'hC:M: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 "$0" "${orig_argv[@]}"
+check_root
working_dir=$(readlink -f "$1")
shift 1
@@ -61,7 +58,9 @@ else
cache_dirs=("$cache_dir")
fi
+# shellcheck disable=2016
host_mirror=$(pacman --cachedir /doesnt/exist -Sddp extra/devtools 2>/dev/null | sed -r 's#(.*/)extra/os/.*#\1$repo/os/$arch#')
+# shellcheck disable=2016
[[ $host_mirror == *file://* ]] && host_mirror_path=$(echo "$host_mirror" | sed -r 's#file://(/.*)/\$repo/os/\$arch#\1#g')
# {{{ functions
@@ -69,13 +68,13 @@ 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
}
@@ -83,8 +82,8 @@ copy_hostconf () {
cp -a /etc/pacman.d/gnupg "$working_dir/etc/pacman.d"
echo "Server = $host_mirror" >"$working_dir/etc/pacman.d/mirrorlist"
- [[ -n $pac_conf ]] && cp $pac_conf "$working_dir/etc/pacman.conf"
- [[ -n $makepkg_conf ]] && cp $makepkg_conf "$working_dir/etc/makepkg.conf"
+ [[ -n $pac_conf ]] && cp "$pac_conf" "$working_dir/etc/pacman.conf"
+ [[ -n $makepkg_conf ]] && cp "$makepkg_conf" "$working_dir/etc/makepkg.conf"
local file
for file in "${files[@]}"; do
@@ -92,7 +91,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"
}
# }}}
@@ -101,7 +100,7 @@ umask 0022
# Sanity check
if [[ ! -f "$working_dir/.arch-chroot" ]]; then
die "'%s' does not appear to be an Arch chroot." "$working_dir"
-elif [[ $(cat "$working_dir/.arch-chroot") != $CHROOT_VERSION ]]; then
+elif [[ $(cat "$working_dir/.arch-chroot") != "$CHROOT_VERSION" ]]; then
die "chroot '%s' is not at version %s. Please rebuild." "$working_dir" "$CHROOT_VERSION"
fi
@@ -109,7 +108,7 @@ build_mount_args
cache_dirs+=('/repo/')
copy_hostconf
-eval $(grep '^CARCH=' "$working_dir/etc/makepkg.conf")
+eval "$(grep '^CARCH=' "$working_dir/etc/makepkg.conf")"
case "$CARCH" in
armv7h) CARCH=armv7l;;
esac
diff --git a/archbuild.in b/archbuild.in
index 60e7cec..8339aef 100644
--- a/archbuild.in
+++ b/archbuild.in
@@ -2,6 +2,7 @@
# License: Unspecified
m4_include(lib/common.sh)
+m4_include(lib/archroot.sh)
base_packages=(base-devel)
makechrootpkg_args=(-c -n)
@@ -30,8 +31,6 @@ usage() {
exit 1
}
-orig_argv=("$@")
-
while getopts 'hcr:' arg; do
case "${arg}" in
c) clean_first=true ;;
@@ -40,7 +39,7 @@ while getopts 'hcr:' arg; do
esac
done
-check_root "$0" "${orig_argv[@]}"
+check_root
# Pass all arguments after -- right to makepkg
makechrootpkg_args+=("${@:$OPTIND}")
@@ -54,9 +53,7 @@ if ${clean_first} || [[ ! -d "${chroots}/${repo}-${arch}" ]]; then
lock 9 "$copy.lock" "Locking chroot copy '%s'" "$copy"
- if [[ "$(stat -f -c %T "${copy}")" == btrfs ]]; then
- { type -P btrfs && btrfs subvolume delete "${copy}"; } &>/dev/null
- fi
+ subvolume_delete_recursive "${copy}"
rm -rf --one-file-system "${copy}"
done
lock_close 9
diff --git a/archco.in b/archco.in
index 6088b8e..77cc8c4 100644
--- a/archco.in
+++ b/archco.in
@@ -6,7 +6,7 @@ m4_include(lib/common.sh)
scriptname=${0##*/}
if [[ -z $1 ]]; then
- echo 'Usage: '$scriptname' <package name>...'
+ printf 'Usage: %s <package name>...\n' "$scriptname"
exit 1
fi
diff --git a/archrelease.in b/archrelease.in
index 3b11652..6b4f1be 100644
--- a/archrelease.in
+++ b/archrelease.in
@@ -38,7 +38,7 @@ trunk=${PWD##*/}
# Normally this should be trunk, but it may be something
# such as 'gnome-unstable'
IFS='/' read -r -d '' -a parts <<< "$PWD"
-if [[ "${parts[@]:(-2):1}" == "repos" ]]; then
+if [[ "${parts[*]:(-2):1}" == "repos" ]]; then
die 'archrelease: Should not be in repos dir (try from trunk/)'
fi
unset parts
@@ -67,14 +67,14 @@ for tag in "$@"; do
while read -r file; do
trash+=("repos/$tag/$file")
done < <(svn ls "repos/$tag")
- [[ $trash ]] && svn rm -q "${trash[@]/%/@}"
+ [[ ${#trash[@]} == 0 ]] || svn rm -q "${trash[@]/%/@}"
else
mkdir -p "repos/$tag"
svn add --parents -q "repos/$tag"
fi
# copy all files at once from trunk to the subdirectory in repos/
- svn copy -q -r HEAD ${known_files[@]/#/$trunk/} "repos/$tag/"
+ svn copy -q -r HEAD "${known_files[@]/#/$trunk/}" "repos/$tag/"
stat_done
done
diff --git a/archrm.in b/archrm.in
index 3173131..6f4dfc3 100644
--- a/archrm.in
+++ b/archrm.in
@@ -13,4 +13,4 @@ fi
#
#popd
-rm -rf $1
+rm -rf "$1"
diff --git a/bash_completion.in b/bash_completion.in
index b9ed69c..9feef74 100644
--- a/bash_completion.in
+++ b/bash_completion.in
@@ -1,11 +1,12 @@
+#!/hint/bash
# License: Unspecified
_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
@@ -14,7 +15,7 @@ _devtools_compgen() {
_archco_pkg() {
_devtools_compgen "$(
- \pacman -$1
+ command pacman "-$1"
)"
}
diff --git a/checkpkg.in b/checkpkg.in
index 6904e32..cfec71e 100644
--- a/checkpkg.in
+++ b/checkpkg.in
@@ -28,14 +28,19 @@ fi
# 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!'
fi
# Source user-specific makepkg.conf overrides
-if [[ -r ~/.makepkg.conf ]]; then
- source ~/.makepkg.conf
+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
if [[ ! -f PKGBUILD ]]; then
@@ -44,8 +49,9 @@ if [[ ! -f PKGBUILD ]]; then
exit 1
fi
+# shellcheck source=PKGBUILD.proto
. ./PKGBUILD
-if [[ $arch == 'any' ]]; then
+if [[ ${arch[0]} == 'any' ]]; then
CARCH='any'
fi
@@ -60,15 +66,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/commitpkg.in b/commitpkg.in
index d31f6ba..53b6612 100644
--- a/commitpkg.in
+++ b/commitpkg.in
@@ -5,14 +5,19 @@ 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!'
fi
# Source user-specific makepkg.conf overrides
-if [[ -r ~/.makepkg.conf ]]; then
- . ~/.makepkg.conf
+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
cmd=${0##*/}
@@ -21,6 +26,8 @@ if [[ ! -f PKGBUILD ]]; then
die 'No PKGBUILD file'
fi
+source=()
+# shellcheck source=PKGBUILD.proto
. ./PKGBUILD
pkgbase=${pkgbase:-$pkgname}
@@ -48,7 +55,7 @@ done
for i in 'changelog' 'install'; do
while read -r file; do
# evaluate any bash variables used
- eval file=\"$(sed "s/^\(['\"]\)\(.*\)\1\$/\2/" <<< "$file")\"
+ eval "file=\"$(sed "s/^\(['\"]\)\(.*\)\1\$/\2/" <<< "$file")\""
needsversioning+=("$file")
done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD)
done
@@ -62,7 +69,7 @@ if (( ${#needsversioning[*]} )); then
(( ${#unversioned[*]} )) && die "%s is not under version control" "${unversioned[@]}"
fi
-rsyncopts=(-e ssh -p --chmod=ug=rw,o=r -c -h -L --progress --partial -y)
+rsyncopts=(-e ssh -p '--chmod=ug=rw,o=r' -c -h -L --progress --partial -y)
archreleaseopts=()
while getopts ':l:a:s:f' flag; do
case $flag in
@@ -77,12 +84,12 @@ done
shift $(( OPTIND - 1 ))
# check packages have the packager field set
-for _arch in ${arch[@]}; do
+for _arch in "${arch[@]}"; do
if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then
continue
fi
- for _pkgname in ${pkgname[@]}; do
- fullver=$(get_full_version $_pkgname)
+ for _pkgname in "${pkgname[@]}"; do
+ fullver=$(get_full_version "$_pkgname")
if pkgfile=$(find_cached_package "$_pkgname" "$_arch" "$fullver"); then
if grep -q "packager = Unknown Packager" <(bsdtar -xOqf "$pkgfile" .PKGINFO); then
@@ -126,18 +133,18 @@ declare -a uploads
declare -a commit_arches
declare -a skip_arches
-for _arch in ${arch[@]}; do
+for _arch in "${arch[@]}"; do
if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then
- skip_arches+=($_arch)
+ skip_arches+=("$_arch")
continue
fi
- for _pkgname in ${pkgname[@]}; do
- fullver=$(get_full_version $_pkgname)
+ for _pkgname in "${pkgname[@]}"; do
+ fullver=$(get_full_version "$_pkgname")
if ! pkgfile=$(find_cached_package "$_pkgname" "$fullver" "${_arch}"); then
warning "Skipping %s: failed to locate package file" "$_pkgname-$fullver-$_arch"
- skip_arches+=($_arch)
+ skip_arches+=("$_arch")
continue 2
fi
uploads+=("$pkgfile")
@@ -146,9 +153,9 @@ for _arch in ${arch[@]}; do
if [[ ! -f $sigfile ]]; then
msg "Signing package %s..." "${pkgfile}"
if [[ -n $GPGKEY ]]; then
- SIGNWITHKEY="-u ${GPGKEY}"
+ SIGNWITHKEY=(-u "${GPGKEY}")
fi
- gpg --detach-sign --use-agent --no-armor ${SIGNWITHKEY} "${pkgfile}" || die
+ gpg --detach-sign --use-agent --no-armor "${SIGNWITHKEY[@]}" "${pkgfile}" || die
fi
if ! gpg --verify "$sigfile" >/dev/null 2>&1; then
die "Signature %s.sig is incorrect!" "$pkgfile"
@@ -157,9 +164,9 @@ for _arch in ${arch[@]}; do
done
done
-for _arch in ${arch[@]}; do
- if ! in_array $_arch ${skip_arches[@]}; then
- commit_arches+=($_arch)
+for _arch in "${arch[@]}"; do
+ if ! in_array "$_arch" "${skip_arches[@]}"; then
+ commit_arches+=("$_arch")
fi
done
@@ -185,8 +192,8 @@ if [[ "${arch[*]}" == 'any' ]]; then
if [[ -d ../repos/$repo-i686 && -d ../repos/$repo-x86_64 ]]; then
pushd ../repos/ >/dev/null
stat_busy "Removing %s and %s" "$repo-i686" "$repo-x86_64"
- svn rm -q $repo-i686
- svn rm -q $repo-x86_64
+ svn rm -q "$repo-i686"
+ svn rm -q "$repo-x86_64"
svn commit -q -m "Removed $repo-i686 and $repo-x86_64 for $pkgname"
stat_done
popd >/dev/null
@@ -195,7 +202,7 @@ else
if [[ -d ../repos/$repo-any ]]; then
pushd ../repos/ >/dev/null
stat_busy "Removing %s" "$repo-any"
- svn rm -q $repo-any
+ svn rm -q "$repo-any"
svn commit -q -m "Removed $repo-any for $pkgname"
stat_done
popd >/dev/null
diff --git a/crossrepomove.in b/crossrepomove.in
index 1be2dc3..b45b8ae 100644
--- a/crossrepomove.in
+++ b/crossrepomove.in
@@ -6,7 +6,7 @@ m4_include(lib/common.sh)
scriptname=${0##*/}
if [[ -z $1 ]]; then
- echo 'Usage: '$scriptname' [pkgbase]'
+ printf 'Usage: %s [pkgbase]\n' "$scriptname"
exit 1
fi
@@ -38,24 +38,26 @@ target_dbscripts="/srv/repos/svn-${target_name}/dbscripts"
setup_workdir
-pushd $WORKDIR >/dev/null
+pushd "$WORKDIR" >/dev/null
msg "Downloading sources for %s" "${pkgbase}"
svn -q checkout -N "${target_svn}" target_checkout
mkdir -p "target_checkout/${pkgbase}/repos"
svn -q export "${source_svn}/${pkgbase}/trunk" "target_checkout/${pkgbase}/trunk" || die
+# shellcheck source=PKGBUILD.proto
. "target_checkout/${pkgbase}/trunk/PKGBUILD"
msg "Downloading packages for %s" "${pkgbase}"
-for _arch in ${arch[@]}; do
+for _arch in "${arch[@]}"; do
if [[ "${_arch[*]}" == 'any' ]]; then
repo_arch='x86_64'
else
repo_arch=${_arch}
fi
- for _pkgname in ${pkgname[@]}; do
- fullver=$(get_full_version $_pkgname)
+ for _pkgname in "${pkgname[@]}"; do
+ fullver=$(get_full_version "$_pkgname")
pkgpath="/srv/ftp/$source_repo/os/$repo_arch/$_pkgname-$fullver-${_arch}.pkg.tar.*"
+ # shellcheck disable=2029
ssh "$server" "cp $pkgpath staging/$target_repo" || die
done
done
@@ -68,10 +70,12 @@ pushd "target_checkout/${pkgbase}/trunk" >/dev/null
archrelease "${arch[@]/#/$target_repo-}" || die
popd >/dev/null
+# shellcheck disable=2029
ssh "${server}" "${target_dbscripts}/db-update" || die
msg "Removing %s from %s" "${pkgbase}" "${source_repo}"
-for _arch in ${arch[@]}; do
+for _arch in "${arch[@]}"; do
+ # shellcheck disable=2029
ssh "${server}" "${source_dbscripts}/db-remove ${source_repo} ${_arch} ${pkgbase}"
done
svn -q checkout -N "${source_svn}" source_checkout
diff --git a/find-libdeps.in b/find-libdeps.in
index 794a2cd..cb68237 100644
--- a/find-libdeps.in
+++ b/find-libdeps.in
@@ -28,10 +28,10 @@ usage() {
echo
print ' <soname>=<soversion>-<soarch>'
echo
- prose 'Where <soversion> is the shared library version, or
+ prose "Where <soversion> is the shared library version, or
<soname> repeated if there is no version attached; and
- <soarch> is the architecture of the library (either `32`
- or `64`, based on the ELF Class).'
+ <soarch> is the architecture of the library (either \`32\`
+ or \`64\`, based on the ELF Class)."
echo
print "Options:"
flag "--ignore-internal" "Ignore internal libraries; libraries
@@ -48,7 +48,7 @@ if [[ $1 = '-h' ]]; then
fi
if [[ -d $1 ]]; then
- pushd $1 >/dev/null
+ pushd "$1" >/dev/null
else
setup_workdir
@@ -65,10 +65,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}")
@@ -80,7 +80,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 cc1ffab..5f89b55 100644
--- a/finddeps.in
+++ b/finddeps.in
@@ -23,24 +23,25 @@ if [[ $match = '-h' ]]; then
exit 0
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 09e0d07..4c6871c 100644
--- a/lddd.in
+++ b/lddd.in
@@ -10,8 +10,8 @@ usage() {
print "Usage: %s [-h]" "${0##*/}"
print "Find broken library links on your machine."
echo
- prose 'Scans $PATH and library directories for ELF files with
- references to missing shared libraries.'
+ prose "Scans \$PATH and library directories for ELF files with
+ references to missing shared libraries."
}
if [[ $1 = '-h' ]]; then
@@ -36,7 +36,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' \
@@ -44,22 +44,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
new file mode 100644
index 0000000..98fd2cf
--- /dev/null
+++ b/lib/archroot.sh
@@ -0,0 +1,67 @@
+#!/hint/bash
+# License: Unspecified
+:
+
+# shellcheck disable=2034
+CHROOT_VERSION='v4'
+
+##
+# usage : check_root
+##
+orig_argv=("$0" "$@")
+check_root() {
+ (( EUID == 0 )) && return
+ if type -P sudo >/dev/null; then
+ exec sudo -- "${orig_argv[@]}"
+ else
+ exec su root -c "$(printf ' %q' "${orig_argv[@]}")"
+ fi
+}
+
+##
+# usage : is_btrfs( $path )
+# return : whether $path is on a btrfs
+##
+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 )
+#
+# Find all btrfs subvolumes under and including $path and delete them.
+##
+subvolume_delete_recursive() {
+ local subvol
+
+ is_subvolume "$1" || return 0
+
+ while IFS= read -d $'\0' -r subvol; do
+ if ! subvolume_delete_recursive "$subvol"; then
+ return 1
+ fi
+ 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 68b001d..118a06c 100644
--- a/lib/common.sh
+++ b/lib/common.sh
@@ -25,7 +25,7 @@ _l() {
shopt -s extglob
# check if messages are to be printed using color
-declare ALL_OFF= BOLD= BLUE= GREEN= RED= YELLOW=
+declare ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW=''
if [[ -t 2 ]]; then
# prefer terminal safe colored and bold text when tput is supported
if tput setaf 0 &>/dev/null; then
@@ -47,36 +47,43 @@ fi
readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
plain() {
- local mesg="$(_ "$1")"; shift
+ local mesg; mesg="$(_ "$1")"; shift
+ # shellcheck disable=2059
printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
msg() {
- local mesg="$(_ "$1")"; shift
+ local mesg; mesg="$(_ "$1")"; shift
+ # shellcheck disable=2059
printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
msg2() {
- local mesg="$(_ "$1")"; shift
+ local mesg; mesg="$(_ "$1")"; shift
+ # shellcheck disable=2059
printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
warning() {
- local mesg="$(_ "$1")"; shift
- printf "${YELLOW}==> $(_l _ "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+ local mesg; mesg="$(_ "$1")"; shift
+ # shellcheck disable=2059
+ printf "${YELLOW}==> WARNING:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
error() {
- local mesg="$(_ "$1")"; shift
- printf "${RED}==> $(_l _ "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+ local mesg; mesg="$(_ "$1")"; shift
+ # shellcheck disable=2059
+ printf "${RED}==> ERROR:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
stat_busy() {
- local mesg="$(_ "$1")"; shift
+ local mesg; mesg="$(_ "$1")"; shift
+ # shellcheck disable=2059
printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}...${ALL_OFF}" "$@" >&2
}
stat_done() {
+ # shellcheck disable=2059
printf "${BOLD}$(_l _ "done")${ALL_OFF}\n" >&2
}
@@ -92,7 +99,7 @@ cleanup() {
if [[ -n ${WORKDIR:-} ]] && $_setup_workdir; then
rm -rf "$WORKDIR"
fi
- exit ${1:-0}
+ exit "${1:-0}"
}
abort() {
@@ -125,7 +132,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
}
@@ -136,24 +143,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
}
@@ -164,13 +174,13 @@ get_full_version() {
lock() {
# Only reopen the FD if it wasn't handed to us
if ! [[ "/dev/fd/$1" -ef "$2" ]]; then
- mkdir -p "${2%/*}"
+ mkdir -p -- "$(dirname -- "$2")"
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
}
@@ -181,13 +191,13 @@ lock() {
slock() {
# Only reopen the FD if it wasn't handed to us
if ! [[ "/dev/fd/$1" -ef "$2" ]]; then
- mkdir -p "${2%/*}"
+ mkdir -p -- "$(dirname -- "$2")"
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
}
@@ -197,6 +207,8 @@ slock() {
##
lock_close() {
local fd=$1
+ # https://github.com/koalaman/shellcheck/issues/862
+ # shellcheck disable=2034
exec {fd}>&-
}
@@ -204,8 +216,6 @@ lock_close() {
# usage: pkgver_equal( $pkgver1, $pkgver2 )
##
pkgver_equal() {
- local left right
-
if [[ $1 = *-* && $2 = *-* ]]; then
# if both versions have a pkgrel, then they must be an exact match
[[ $1 = "$2" ]]
@@ -224,7 +234,7 @@ pkgver_equal() {
find_cached_package() {
local searchdirs=("$PWD" "$PKGDEST") results=()
local targetname=$1 targetver=$2 targetarch=$3
- local dir pkg pkgbasename pkgparts name ver rel arch size r results
+ local dir pkg pkgbasename name ver rel arch r results
for dir in "${searchdirs[@]}"; do
[[ -d $dir ]] || continue
@@ -262,7 +272,7 @@ find_cached_package() {
return 1
;;
1)
- printf '%s\n' "$results"
+ printf '%s\n' "${results[0]}"
return 0
;;
*)
@@ -273,13 +283,58 @@ find_cached_package() {
}
##
-# usage : check_root ("$0" "$@")
+# usage: find_cached_srcpackage( $pkgname, $pkgver, $arch )
+#
+# $pkgver can be supplied with or without a pkgrel appended.
+# If not supplied, any pkgrel will be matched.
##
-check_root() {
- (( EUID == 0 )) && return
- if type -P sudo >/dev/null; then
- exec sudo -- "$@"
- else
- exec su root -c "$(printf ' %q' "$@")"
- fi
+find_cached_srcpackage() {
+ local searchdirs=("$PWD" "$SRCPKGDEST") results=()
+ local targetname=$1 targetver=$2 targetarch=$3
+ local dir pkg pkgbasename name ver rel arch r results
+
+ for dir in "${searchdirs[@]}"; do
+ [[ -d $dir ]] || continue
+
+ for pkg in "$dir"/*.src.tar?(.?z); do
+ [[ -f $pkg ]] || continue
+
+ # avoid adding duplicates of the same inode
+ for r in "${results[@]}"; do
+ [[ $r -ef $pkg ]] && continue 2
+ done
+
+ # split apart package filename into parts
+ pkgbasename=${pkg##*/}
+ pkgbasename=${pkgbasename%.src.tar?(.?z)}
+
+ arch=${pkgbasename##*-}
+ pkgbasename=${pkgbasename%-"$arch"}
+
+ rel=${pkgbasename##*-}
+ pkgbasename=${pkgbasename%-"$rel"}
+
+ ver=${pkgbasename##*-}
+ name=${pkgbasename%-"$ver"}
+
+ if [[ $targetname = "$name" && $targetarch = "$arch" ]] &&
+ pkgver_equal "$targetver" "$ver-$rel"; then
+ results+=("$pkg")
+ fi
+ done
+ done
+
+ case ${#results[*]} in
+ 0)
+ return 1
+ ;;
+ 1)
+ printf '%s\n' "${results[0]}"
+ return 0
+ ;;
+ *)
+ _l error 'Multiple packages found:'
+ printf '\t%s\n' "${results[@]}" >&2
+ return 1
+ esac
}
diff --git a/lib/valid-tags.sh b/lib/valid-tags.sh
index 0543ab2..2916dc7 100644
--- a/lib/valid-tags.sh
+++ b/lib/valid-tags.sh
@@ -1,11 +1,15 @@
+#!/hint/bash
# License: Unspecified
+:
+# shellcheck disable=2034
_arch=(
i686
x86_64
any
)
+# shellcheck disable=2034
_tags=(
core-i686 core-x86_64 core-any
extra-i686 extra-x86_64 extra-any
diff --git a/makechrootpkg.in b/makechrootpkg.in
index c6ef240..7589737 100644
--- a/makechrootpkg.in
+++ b/makechrootpkg.in
@@ -11,6 +11,7 @@
# GNU General Public License for more details.
m4_include(lib/common.sh)
+m4_include(lib/archroot.sh)
shopt -s nullglob
@@ -20,13 +21,13 @@ init_variables() {
repack=false
update_first=false
clean_first=false
- install_pkg=
run_namcap=false
temp_chroot=false
chrootdir=
passeddir=
- declare -a install_pkgs
- declare -i ret=0
+ makepkg_user=
+ declare -ga install_pkgs
+ declare -gi ret=0
bindmounts_ro=()
bindmounts_rw=()
@@ -51,6 +52,10 @@ usage() {
echo 'command:'
echo ' mkarchroot <chrootdir>/root base-devel'
echo ''
+ echo 'This script reads {SRC,SRCPKG,PKG,LOG}DEST, MAKEFLAGS and PACKAGER'
+ echo 'from makepkg.conf(5), if those variables are not part of the'
+ echo 'environment.'
+ echo ''
echo "Default makepkg args: ${default_makepkg_args[*]}"
echo ''
echo 'Flags:'
@@ -68,6 +73,7 @@ usage() {
echo " Default: $copy"
echo '-n Run namcap on the package'
echo '-T Build in a temporary directory'
+ echo '-U Run makepkg as a specified user'
exit 1
}
@@ -86,136 +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: btrfs_subvolume_id $SUBVOLUME
-btrfs_subvolume_id() (
- set -o pipefail
- LC_ALL=C btrfs subvolume show "$1" | sed -n 's/^\tSubvolume ID:\s*//p'
-)
-
-# Usage: btrfs_subvolume_list_all $FILEPATH
-#
-# Given $FILEPATH somewhere on a mounted btrfs filesystem, print the
-# ID and full path of every subvolume on the filesystem, one per line
-# in the format "$ID $PATH", where $PATH is relative to the top-level
-# subvolume (which might not be what is mounted).
-#
-# BUG: Due to limitations in the `btrfs` tool, this will not correctly
-# list subvolumes whose path contains a space.
-btrfs_subvolume_list_all() (
- set -o pipefail
-
- local mountpoint all
- mountpoint="$(df --output=target "$1" | sed 1d)" || return
- # The output of `btrfs subvolume list -a` is a space-separated
- # sequence of "key value key value...". Unfortunately both
- # keys and values can contain space, and there's no escaping
- # or indication of when this happens. So we assume
- # 1. ID is the first column
- # 2. That no key or value will contain " path"
- # 3. That the "path" value does not contain a space.
- all="$(LC_ALL=C btrfs subvolume list -a "$mountpoint" | sed -r 's|^ID ([0-9]+) .* path (<FS_TREE>/)?(\S*).*|\1 \3|')" || return
-
- # Sanity check the output
- local id path
- while read -r id path; do
- # ID should be numeric
- [[ "$id" =~ ^-?[0-9]+$ ]] || return
- # While a path could countain a space, the above code
- # doesn't support it; if there is space, then it means
- # we got a line not matching the expected format.
- [[ "$path" != *' '* ]] || return
- done <<<"$all"
-
- printf '%s\n' "$all"
-)
-
-# Usage: btrfs_subvolume_list $SUBVOLUME
-#
-# Assuming that $SUBVOLUME is a btrfs subvolume, list all child
-# subvolumes; from most deeply nested to most shallowly nested.
-#
-# This is intended to be a sane version of `btrfs subvolume list`.
-btrfs_subvolume_list() {
- local subvolume=$1
-
- local id all path subpath
- id="$(btrfs_subvolume_id "$subvolume")" || return
- all="$(btrfs_subvolume_list_all "$subvolume")" || return
- path=$(awk -v id="$id" '$1 == id { sub($1 FS, ""); print }' <<<"$all")
- while read -r id subpath; do
- if [[ "$subpath" = "$path"/* ]]; then
- printf '%s\n' "${subpath#"${path}/"}"
- fi
- done <<<"$all" | LC_ALL=C sort --reverse
-}
-
-# Usage: btrfs_subvolume_delete $SUBVOLUME
-#
-# Assuming that $SUBVOLUME is a btrfs subvolume, delete it and all
-# subvolumes below it.
-#
-# This is intended to be a recursive version of
-# `btrfs subvolume delete`.
-btrfs_subvolume_delete() {
- local dir="$1"
-
- # We store the result as a variable because we want to see if
- # btrfs_subvolume_list fails or succeeds before we start
- # deleting things. (Then we have to work around the subshell
- # trimming the trailing newlines.)
- local subvolumes
- subvolumes="$(btrfs_subvolume_list "$dir")" || return
- [[ -z "$subvolumes" ]] || subvolumes+=$'\n'
-
- local subvolume
- while read -r subvolume; do
- btrfs subvolume delete "$dir/$subvolume" || return
- done < <(printf '%s' "$subvolumes")
-
- btrfs subvolume delete "$dir"
-}
-
-# 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
- # Detect chrootdir filesystem type
- local chroottype=$(stat -f -c %T "$chrootdir")
-
# 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"
+ slock 8 "$rootdir.lock" \
+ "Locking clean chroot [%s]" "$rootdir"
- stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$chrootdir/root" "$copydir"
- if [[ "$chroottype" == btrfs ]] && ! mountpoint -q "$copydir"; then
- if [[ -d $copydir ]]; then
- btrfs_subvolume_delete "$copydir" >/dev/null ||
+ 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 "$chrootdir/root" "$copydir" >/dev/null ||
+ 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
@@ -226,15 +139,14 @@ sync_chroot() {
touch "$copydir"
}
-# Usage: delete_chroot $copydir
+# Usage: delete_chroot $copydir [$copy]
delete_chroot() {
local copydir=$1
- # Detect chrootdir filesystem type
- local chroottype=$(stat -f -c %T "$copydir")
+ local copy=${1:-$2}
- stat_busy "Removing chroot copy [%s]" "$copydir"
- if [[ "$chroottype" == btrfs ]] && ! mountpoint -q "$copydir"; then
- btrfs_subvolume_delete "$copydir" >/dev/null ||
+ stat_busy "Removing chroot copy [%s]" "$copy"
+ if is_subvolume "$copydir" && ! mountpoint -q "$copydir"; then
+ subvolume_delete_recursive "$copydir" ||
die "Unable to delete subvolume %s" "$copydir"
else
# avoid change of filesystem in case of an umount failure
@@ -278,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
@@ -287,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}
@@ -306,13 +219,13 @@ prepare_chroot() {
done
cat > "$copydir/etc/sudoers.d/builduser-pacman" <<EOF
-Defaults env_keep += "HOME"
builduser ALL = NOPASSWD: /usr/bin/pacman
EOF
chmod 440 "$copydir/etc/sudoers.d/builduser-pacman"
if ! grep -q '^\[repo\]' "$copydir/etc/pacman.conf"; then
- local line=$(grep -n '^\[' "$copydir/etc/pacman.conf" |grep -Fv ':[options]'|sed 's/:.*//;1q')
+ local line
+ line=$(grep -n '^\[' "$copydir/etc/pacman.conf" |grep -Fv ':[options]'|sed 's/:.*//;1q')
local ins='[repo]
SigLevel = Optional TrustAll
Server = file:///repo
@@ -347,12 +260,36 @@ Server = file:///repo
# These functions aren't run in makechrootpkg,
# so no global variables
_chrootprepare() {
+ # 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 "$@" --nobuild' -bash "$@"
}
_chrootbuild() {
+ # shellcheck source=/dev/null
. /etc/profile
+ local srcext
+ srcext="$(
+ # shellcheck source=makepkg-x86_64.conf
+ . /etc/makepkg.conf || exit
+ # shellcheck source=PKGBUILD.proto
+ . /startdir/PKGBUILD || exit
+ if [ "$arch" = any ]; then
+ pkgarch=any
+ else
+ pkgarch=$CARCH
+ fi
+ printf '%s\n' "-$pkgarch$SRCEXT"
+ )" || return
+ # 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; SRCEXT="${1}" makepkg "${@:2}" --allsource' -bash "$srcext" "$@" || return
sudo -iu builduser bash -c 'cd /startdir; makepkg "$@" --noextract --noprepare' -bash "$@"
}
@@ -364,27 +301,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
- if [[ $USER != $src_owner ]]; then
- sudo -u $src_owner env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \
- makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o
+ if [[ "$(id -u "$makepkg_user")" != 0 ]]; then
+ sudo -u "$makepkg_user" env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \
+ makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o ||
+ die "Could not download sources."
else
- ( export SRCDEST BUILDDIR="$builddir"
- makepkg --asroot --config="$copydir/etc/makepkg.conf" --verifysource -o
- )
+ 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"
@@ -402,8 +339,10 @@ move_products() {
for pkgfile in "$copydir"/pkgdest/*; do
chown "$src_owner" "$pkgfile"
mv "$pkgfile" "$PKGDEST"
- if [[ $PKGDEST != $PWD ]]; then
- ln -sf "$PKGDEST/${pkgfile##*/}" .
+
+ # Fix broken symlink because of temporary chroot PKGDEST /pkgdest
+ if [[ "$PWD" != "$PKGDEST" && -L "$PWD/${pkgfile##*/}" ]]; then
+ ln -sf "$PKGDEST/${pkgfile##*/}"
fi
done
@@ -424,26 +363,27 @@ move_products() {
main() {
init_variables
- orig_argv=("$@")
-
- while getopts 'hcur:I:l:nTD:d:' arg; do
+ 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") ;;
l) copy="$OPTARG" ;;
n) run_namcap=true; makepkg_args+=(-i) ;;
T) temp_chroot=true; copy+="-$$" ;;
+ U) makepkg_user="$OPTARG" ;;
h|*) usage ;;
esac
done
[[ ! -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 "$0" "${orig_argv[@]}"
+ check_root
# Canonicalize chrootdir, getting rid of trailing /
chrootdir=$(readlink -e "$passeddir")
@@ -490,7 +430,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" \
@@ -504,7 +444,7 @@ main() {
[[ -f PKGBUILD ]] || return $ret
fi
- download_sources "$copydir" "$src_owner"
+ download_sources "$copydir" "$makepkg_user"
prepare_chroot "$copydir" "$USER_HOME" "$repack"
@@ -524,7 +464,7 @@ main() {
(( ret += 1 ))
fi
- $temp_chroot && delete_chroot "$copydir"
+ $temp_chroot && delete_chroot "$copydir" "$copy"
if (( ret != 0 )); then
if $temp_chroot; then
diff --git a/makepkg-i686.conf b/makepkg-i686.conf
index c565795..4cbc28b 100644
--- a/makepkg-i686.conf
+++ b/makepkg-i686.conf
@@ -1,3 +1,6 @@
+#!/hint/bash
+# shellcheck disable=2034
+
#
# /etc/makepkg.conf
#
diff --git a/makepkg-x86_64.conf b/makepkg-x86_64.conf
index 058da9b..79858a7 100644
--- a/makepkg-x86_64.conf
+++ b/makepkg-x86_64.conf
@@ -1,3 +1,6 @@
+#!/hint/bash
+# shellcheck disable=2034
+
#
# /etc/makepkg.conf
#
diff --git a/mkarchroot.in b/mkarchroot.in
index f86ae35..5165960 100644
--- a/mkarchroot.in
+++ b/mkarchroot.in
@@ -11,8 +11,7 @@
# GNU General Public License for more details.
m4_include(lib/common.sh)
-
-CHROOT_VERSION='v3'
+m4_include(lib/archroot.sh)
working_dir=''
@@ -30,8 +29,6 @@ usage() {
exit 1
}
-orig_argv=("$@")
-
while getopts 'hC:M:c:f:s' arg; do
case "$arg" in
C) pac_conf="$OPTARG" ;;
@@ -43,19 +40,19 @@ while getopts 'hC:M: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 "$0" "${orig_argv[@]}"
+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
@@ -68,7 +65,7 @@ mkdir -p "$working_dir"
lock 9 "${working_dir}.lock" "Locking chroot"
-if [[ $(stat -f -c %T "$working_dir") == btrfs ]]; then
+if is_btrfs "$working_dir"; then
rmdir "$working_dir"
if ! btrfs subvolume create "$working_dir"; then
die "Couldn't create subvolume for '%s'" "$working_dir"
@@ -90,7 +87,7 @@ pacstrap -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 'LANG=en_US.UTF-8' > "$working_dir/etc/locale.conf"
echo "$CHROOT_VERSION" > "$working_dir/.arch-chroot"
systemd-machine-id-setup --root="$working_dir"
diff --git a/rebuildpkgs.in b/rebuildpkgs.in
index 215439f..4f4f98b 100644
--- a/rebuildpkgs.in
+++ b/rebuildpkgs.in
@@ -14,18 +14,28 @@
m4_include(lib/common.sh)
if (( $# < 1 )); then
- echo "Usage: $(basename $0) <chrootdir> <packages to rebuild>"
- echo " example: $(basename $0) ~/chroot readline bash foo bar baz"
+ printf 'Usage: %s <chrootdir> <packages to rebuild>\n' "$(basename "$0")"
+ printf ' example: %s ~/chroot readline bash foo bar baz\n' "$(basename "$0")"
exit 1
fi
# 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!'
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
+
bump_pkgrel() {
# Get the current pkgrel from SVN and update the working copy with it
# This prevents us from incrementing out of control :)
@@ -33,9 +43,9 @@ bump_pkgrel() {
oldrel=$(grep 'pkgrel=' $pbuild | cut -d= -f2)
#remove decimals
- rel=$(echo $oldrel | cut -d. -f1)
+ rel=${oldrel%%.*}
- newrel=$(($rel + 1))
+ newrel=$((rel + 1))
sed -i "s/pkgrel=$oldrel/pkgrel=$newrel/" PKGBUILD
}
@@ -43,11 +53,12 @@ bump_pkgrel() {
pkg_from_pkgbuild() {
# we want the sourcing to be done in a subshell so we don't pollute our current namespace
export CARCH PKGEXT
+ # shellcheck source=PKGBUILD.proto
(source PKGBUILD; echo "$pkgname-$pkgver-$pkgrel-$CARCH$PKGEXT")
}
chrootdir="$1"; shift
-pkgs="$@"
+pkgs=("$@")
SVNPATH='svn+ssh://repos.archlinux.org/srv/repos/svn-packages/svn'
@@ -60,7 +71,7 @@ cd "$REBUILD_ROOT"
/usr/bin/svn co -N $SVNPATH
FAILED=""
-for pkg in $pkgs; do
+for pkg in "${pkgs[@]}"; do
cd "$REBUILD_ROOT/svn-packages"
msg2 "Building '%s'" "$pkg"