2 # aur-build - build packages to a local repository
3 [[ -v AUR_DEBUG
]] && set -o xtrace
9 PS4
='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
12 chroot
=0 no_sync
=0 overwrite
=0 sign_pkg
=0 run_pkgver
=0 truncate
=1
14 # default arguments (empty)
15 chroot_args
=() pacconf_args
=() repo_args
=() repo_add_args
=() pkglist_args
=()
16 makepkg_args
=() makechrootpkg_makepkg_args
=() makepkg_common_args
=()
19 gpg_args
=(--detach-sign --no-armor --batch)
20 makechrootpkg_args
=(-cu) # -c to clean working copy, -u to sync local repository builds
23 # shellcheck disable=SC2155
24 local str
=$
(printf '%s,' "$@")
25 printf '%s' "${str%,}"
28 diag_moved_packages
() {
29 # Print diagnostic on non-moved packages (#794)
32 aur-build encountered an error before moving packages to the local repository.
33 This may happen when signing built packages with gpg (aur build --sign),
34 or with certain makepkg errors.
36 The following files were preserved:
38 #shellcheck disable=SC2030
39 realpath
-z -- "$@" |
while read -rd ''; do
40 printf '%8s%s\n' ' ' "$REPLY"
47 aur-build could not find a pacman.conf(5) file for container usage. Before
48 using --chroot, make sure this file is created and valid. See OPTIONS in
49 aur-build(1) for configuration details.
51 The following file path was checked:
53 printf '%8s%s\n' ' ' "$1"
57 printf >&2 'Running %s\n' "${*:$1}"
62 if [[ ! -v AUR_DEBUG
]]; then
65 # Only remove package directory if all files were moved (#593)
66 if ! rm -df -- "$var_tmp"; then
67 diag_moved_packages
"$var_tmp"/*
70 printf >&2 'AUR_DEBUG: %s: temporary files at %s\n' "$argv0" "$tmp"
71 printf >&2 'AUR_DEBUG: %s: temporary files at %s\n' "$argv0" "$var_tmp"
76 plain
>&2 'usage: %s [-acfNS] [-d repo] [--root path] [--margs makepkg_arg...]' "$argv0"
80 source /usr
/share
/makepkg
/util
/message.sh
81 source /usr
/share
/makepkg
/util
/parseopts.sh
83 if [[ ! -v NO_COLOR
]] && [[ ! -v AUR_DEBUG
]]; then
84 [[ -t 2 ]] && colorize
88 opt_short
='a:d:D:U:AcCfnrsvLNRST'
89 opt_long
=('arg-file:' 'chroot' 'database:' 'force' 'root:' 'sign' 'gpg-sign'
90 'verify' 'directory:' 'no-sync' 'pacman-conf:' 'remove' 'pkgver'
91 'rmdeps' 'no-confirm' 'no-check' 'ignore-arch' 'log' 'new'
92 'makepkg-conf:' 'bind:' 'bind-rw:' 'prevent-downgrade' 'temp'
93 'syncdeps' 'clean' 'namcap' 'checkpkg' 'makepkg-args:' 'user:'
94 'margs:' 'buildscript:')
95 opt_hidden
=('dump-options' 'ignorearch' 'noconfirm' 'nocheck' 'nosync' 'repo:'
96 'results:' 'results-append:')
98 if ! parseopts
"$opt_short" "${opt_long[@]}" "${opt_hidden[@]}" -- "$@"; then
101 set -- "${OPTRET[@]}"
103 unset db_name db_path db_root makepkg_conf pacman_conf results_file queue
113 -d|
--database|
--repo)
115 repo_args
+=(--repo "$1") ;;
117 shift; makepkg_common_args
+=(-p "$1")
118 pkglist_args
+=(-p "$1") ;;
122 shift; makepkg_conf
=$1 ;;
124 shift; pacman_conf
=$1 ;;
126 run_pkgver
=1; makepkg_args
+=(--noextract)
127 makechrootpkg_makepkg_args
+=(--holdver) ;;
130 repo_args
+=(--root "$1") ;;
131 -S|
--sign|
--gpg-sign)
132 sign_pkg
=1; repo_add_args
+=(-s) ;;
135 shift; chroot_args
+=(-D "$1") ;;
137 shift; makechrootpkg_args
+=(-D "$1") ;;
139 shift; makechrootpkg_args
+=(-d"$1") ;;
141 makechrootpkg_args
+=(-n) ;;
143 makechrootpkg_args
+=(-C) ;;
145 makechrootpkg_args
+=(-T) ;;
147 shift; makechrootpkg_args
+=(-U "$1") ;;
148 # makepkg options (common)
149 -A|
--ignorearch|
--ignore-arch)
150 makepkg_common_args
+=(--ignorearch)
151 makechrootpkg_makepkg_args
+=(--ignorearch) ;;
152 -n|
--noconfirm|
--no-confirm)
153 makepkg_common_args
+=(--noconfirm) ;;
155 makepkg_common_args
+=(--rmdeps) ;;
157 makepkg_common_args
+=(--syncdeps) ;;
158 # makepkg options (build)
160 makepkg_args
+=(--clean) ;;
162 makepkg_args
+=(--log) ;;
163 --nocheck|
--no-check)
164 makepkg_args
+=(--nocheck)
165 makechrootpkg_makepkg_args
+=(--nocheck) ;;
166 --makepkg-args|
--margs)
167 shift; IFS
=, read -a arg
-r <<< "$1"
168 makepkg_args
+=("${arg[@]}")
169 makechrootpkg_makepkg_args
+=("${arg[@]}") ;;
172 repo_add_args
+=(-v) ;;
174 repo_add_args
+=(-R) ;;
176 repo_add_args
+=(-n) ;;
178 repo_add_args
+=(-p) ;;
181 shift; results_file
=$1 ;;
183 shift; results_file
=$1; truncate
=0 ;;
185 printf -- '--%s\n' "${opt_long[@]}" ${AUR_DEBUG+"${opt_hidden[@]}"}
186 printf -- '%s' "${opt_short}" | sed 's/.:\?/-&\n/g'
193 # mollyguard for makepkg
194 if [[ $UID == 0 ]] && ! [[ -v AUR_ASROOT ]]; then
195 warning 'aur-%s is not meant to be run as root.' "$argv0"
196 warning 'To proceed anyway, set the %s variable.' 'AUR_ASROOT'
200 # Assign environment variables
201 : "${db_ext=$AUR_DBEXT}" "${db_root=$AUR_DBROOT}" "${db_repo=$AUR_REPO}"
203 # shellcheck disable=SC2174
204 mkdir -pm 0700 "${TMPDIR:-/tmp}/aurutils-
$UID"
205 tmp=$(mktemp -d --tmpdir "aurutils-
$UID/$argv0.XXXXXXXX
")
207 # shellcheck disable=SC2174
208 mkdir -pm 0700 "${TMPDIR:-/var/tmp}/aurutils-
$UID"
209 var_tmp=$(mktemp -d --tmpdir="${TMPDIR:-/var/tmp/}" "aurutils-
$UID/$argv0.XXXXXXXX
")
211 trap 'trap_exit' EXIT
214 if (( chroot )); then
215 # Change the default /usr/share/devtools/pacman-extra.conf in aur-chroot to
216 # /etc/aurutils/pacman-<repo>.conf or /etc/aurutils/pacman-<uname>.conf in
217 # aur-build, and pass it on to aur-chroot (#824, #846)
218 pacman_conf=${pacman_conf-/etc/aurutils/pacman-${db_name:-$machine}.conf}
219 chroot_args+=(--pacman-conf "$pacman_conf")
221 # Early check for availability of pacman.conf (#783)
222 if [[ ! -f $pacman_conf ]]; then
223 diag_pacman_conf "$pacman_conf"
227 # The default path is /usr/share/devtools/makepkg-<uname.conf>, which is
228 # copied to <container path>/etc/makepkg.conf by arch-nspawn.
229 if [[ -v makepkg_conf ]]; then
230 chroot_args+=(--makepkg-conf "$makepkg_conf")
232 # When makechrootpkg calls makepkg inside the container, it uses the above
233 # makepkg.conf for most variables including PKGEXT. (makepkg --packagelist)
234 makepkg_conf=$(aur chroot --path "${chroot_args[@]}")/etc/makepkg.conf
238 # Propagate makepkg/makechrootpkg arguments to aur-chroot
239 if (( ${#makechrootpkg_args[@]} )); then
240 chroot_args+=(--cargs "$
(args_csv
"${makechrootpkg_args[@]}")")
242 if (( ${#makechrootpkg_makepkg_args[@]} )); then
243 chroot_args+=(--margs "$
(args_csv
"${makechrootpkg_makepkg_args[@]}")")
247 # Propagate makepkg and pacman configuration to other tools. This needs to be
248 # done BEFORE retrieving the local repository name/root.
249 if [[ -v pacman_conf ]]; then
250 pacconf_args+=(--config "$pacman_conf")
253 if [[ -v makepkg_conf ]]; then
254 makepkg_common_args+=(--config "$makepkg_conf")
255 pkglist_args+=(--config "$makepkg_conf")
258 # Automatically choose the local repository based on the pacman configuration.
259 if [[ $db_name ]] && [[ $db_root ]]; then
260 db_path=$db_root/$db_name.${db_ext:-db}
261 db_path=$(realpath -- "$db_path")
263 { IFS=: read -r _ db_name
264 IFS=: read -r _ db_root
265 IFS=: read -r _ db_path # canonicalized
266 } < <(aur repo --status "${repo_args[@]}" "${pacconf_args[@]}")
269 db_root=$(realpath -- "$db_root")
271 # File permission checks
272 if [[ ! -f $db_path ]]; then
273 error '%s: %s: not a regular file' "$argv0" "$db_path"
275 elif [[ ! -w $db_path ]]; then
276 error '%s: %s: permission denied' "$argv0" "$db_path"
278 elif [[ -v pacman_conf ]] && [[ ! -r $pacman_conf ]]; then
279 error '%s: %s: permission denied' "$argv0" "$pacman_conf"
281 elif [[ -v makepkg_conf ]] && [[ ! -r $makepkg_conf ]]; then
282 error '%s: %s: permission denied' "$argv0" "$makepkg_conf"
286 # Write successfully built packages to file (#437, #980)
287 if [[ -v results_file ]]; then
288 results_file=$(realpath -- "$results_file")
289 (( truncate )) && true | tee "$results_file"
292 if (( chroot )); then
293 # Update pacman and makepkg configuration for the chroot build
294 # queue. A full system upgrade is run on the /root container to
295 # avoid lenghty upgrades for makechrootpkg -u.
296 run_msg 2 aur chroot --create --update "${chroot_args[@]}"
299 if [[ -v queue ]]; then
302 exec {fd}< <(printf '\n')
305 # Early consistency check for signed database
306 if (( ! sign_pkg )); then
307 db_sigs=("$db_root/$db_name".sig "$db_root/$db_name".files.sig)
309 if [[ -f ${db_sigs[0]} ]]; then
310 error '%s: database signature found, but signing is disabled' "$argv0"
312 printf '%q\n' >&2 "${db_sigs[@]}"
316 elif [[ -v GPGKEY ]]; then
317 gpg --list-keys "$GPGKEY"
318 gpg_args+=(-u "$GPGKEY")
321 while IFS= read -ru "$fd" path; do
322 # Use two cd calls to handle absolute paths in --arg-file
326 # Allow running repo-add(8) on existing packages (#839)
330 # Run pkgver function before --packagelist (#500)
331 if (( run_pkgver )); then
332 #shellcheck disable=SC2086
333 ${AUR_MAKEPKG:-makepkg} -od "${makepkg_common_args[@]}" >&2
336 # Check if the package is already built, but unlike makepkg, do not
337 # exit with an error when so. A warning avoids a queue of builds
338 # aborting because one member already exists.
339 if (( ! overwrite )); then
341 while IFS=':' read -r pkgpath; do
342 [[ -f $pkgpath ]] && exists+=("$pkgpath")
344 PKGDEST="$db_root" aur build--pkglist "${pkglist_args[@]}"
346 # Preserve the exit status from aur-build--pkglist (#671)
349 if (( ${#exists[@]} )); then
350 warning '%s: skipping existing package (use -f to overwrite)' "$argv0"
353 printf '%q\n' >&2 "${exists[@]}"
354 pkglist=("${exists[@]}")
357 if (( ${#exists[@]} )) && [[ -v results_file ]]; then
358 printf "exist
:file://%s
\n" "${exists[@]}" | tee -a "$results_file" >/dev/null
362 if (( create_package )); then
363 if (( chroot )); then
364 PKGDEST="$var_tmp" run_msg 2 aur chroot --build "${chroot_args[@]}"
366 #shellcheck disable=SC2086
367 PKGDEST="$var_tmp" LOGDEST="${LOGDEST:-$PWD}" \
368 run_msg 2 ${AUR_MAKEPKG:-makepkg} "${makepkg_common_args[@]}" "${makepkg_args[@]}"
372 pkglist
=(!(*.sig
)) # discard makepkg --sign from package list (#410)
375 # pkglist has paths to $db_root/<pkg>
378 # Sign any packages without signatures, even if the packages are existing.
381 for p
in "${pkglist[@]}"; do
382 # Package basename (equals $p if create_package=1)
385 # Signature from makepkg --sign
386 if [[ -f $p_base.sig
]]; then
387 siglist
+=("$p_base".sig
)
389 # Skipped package build with signature
390 elif [[ -f $db_root/$p_base.sig
]] && [[ ! -f $p_base ]]; then
391 printf >&2 '%s: existing signature file %q\n' "$argv0" "$db_root/$p_base.sig"
393 # No candidate signature, generate one
394 elif (( sign_pkg
)); then
395 #shellcheck disable=SC2086
396 ${AUR_GPG:-gpg} "${gpg_args[@]}" --output "$p_base".sig
"$p"
398 printf >&2 '%s: created signature file %q\n' "$argv0" "$p_base".sig
399 siglist
+=("$p_base".sig
)
403 if (( ${#siglist[@]} )); then
404 mv -f "${siglist[@]}" "$db_root"
406 if (( create_package
)); then
407 mv -f "${pkglist[@]}" "$db_root"
409 if [[ -v results_file
]]; then
410 printf "build:file://$db_root/%s\n" "${pkglist[@]}" |
tee -a "$results_file" >/dev
/null
416 #shellcheck disable=SC2086
417 LANG
=C
${AUR_REPO_ADD:-repo-add} "${repo_add_args[@]}" "$db_path" "${pkglist[@]}"
419 if (( chroot )) || (( no_sync )); then
422 # Helper which can be used for e.g. sudoers rules (#1012)
423 # Like `makepkg --syncdeps`, this affects the host and so uses
424 # the host pacman configuration. --pacman-conf (which may also
425 # point to a world-writeable file) is not applied.
426 aur build--sync "$db_name"
432 # vim: set et sw=4 sts=4 ft=sh: