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]}(): }'
11 # Avoid CDPATH screwing with cd (#1047)
15 chroot
=0 no_sync
=0 overwrite
=0 sign_pkg
=0 run_pkgver
=0 truncate
=1
17 # default arguments (empty)
18 chroot_args
=() pacconf_args
=() repo_args
=() repo_add_args
=() pkglist_args
=()
19 makepkg_args
=() makechrootpkg_makepkg_args
=() makepkg_common_args
=() read_args
=()
22 gpg_args
=(--detach-sign --no-armor --batch)
23 makechrootpkg_args
=(-cu) # -c to clean working copy, -u to sync local repository builds
26 # shellcheck disable=SC2155
27 local str
=$
(printf '%s,' "$@")
28 printf '%s' "${str%,}"
31 diag_moved_packages
() {
32 # Print diagnostic on non-moved packages (#794)
35 aur-build encountered an error before moving packages to the local repository.
36 This may happen when signing built packages with gpg (aur build --sign),
37 or with certain makepkg errors.
39 The following files were preserved:
41 #shellcheck disable=SC2030
42 realpath
-z -- "$@" |
while read -rd ''; do
43 printf '%8s%s\n' ' ' "$REPLY"
50 aur-build could not find a pacman.conf(5) file for container usage. Before
51 using --chroot, make sure this file is created and valid. See OPTIONS in
52 aur-build(1) for configuration details.
54 The following file paths were checked:
56 #shellcheck disable=SC2030
57 realpath
-z -- "$@" |
while read -rd ''; do
58 printf '%8s%s\n' ' ' "$REPLY"
62 get_local_upgrades
() {
65 LANG
=C pacman
-Sup --print-format '%r/%n' |
while IFS
=/ read -ra line
; do
68 printf '%s\n' "$repo/${line[1]}" ;;
69 ::\
*) # XXX: pacman prints diagnostics to standard output
70 printf >&2 '%s\n' "${line[*]}" ;;
73 return "${PIPESTATUS[0]}"
77 if [[ ! -v AUR_DEBUG
]]; then
80 # Only remove package directory if all files were moved (#593)
81 if ! rm -df -- "$var_tmp"; then
82 diag_moved_packages
"$var_tmp"/*
85 printf >&2 'AUR_DEBUG: %s: temporary files at %s\n' "$argv0" "$tmp"
86 printf >&2 'AUR_DEBUG: %s: temporary files at %s\n' "$argv0" "$var_tmp"
91 printf >&2 'usage: %s [-acfNS] [-d repo] [--root path] [--margs makepkg_arg...]\n' "$argv0"
95 # mollyguard for makepkg
96 if (( UID
== 0 )) && ! [[ -v AUR_ASROOT
]]; then
97 warning
'aur-%s is not meant to be run as root.' "$argv0"
98 warning
'To proceed anyway, set the %s variable.' 'AUR_ASROOT'
103 opt_short
='a:d:D:U:AcCfnrsvzLNRST'
104 opt_long
=('arg-file:' 'chroot' 'database:' 'force' 'root:' 'sign' 'gpg-sign'
105 'verify' 'directory:' 'no-sync' 'pacman-conf:' 'remove' 'pkgver'
106 'rmdeps' 'no-confirm' 'no-check' 'ignore-arch' 'log' 'new'
107 'makepkg-conf:' 'bind:' 'bind-rw:' 'prevent-downgrade' 'temp'
108 'syncdeps' 'clean' 'namcap' 'checkpkg' 'makepkg-args:' 'user:'
109 'margs:' 'buildscript:' 'null')
110 opt_hidden
=('dump-options' 'ignorearch' 'noconfirm' 'nocheck' 'nosync' 'repo:'
111 'results:' 'results-append:')
113 if opts
=$
(getopt
-o "$opt_short" -l "$(args_csv "${opt_long[@]}" "${opt_hidden[@]}")" -n "$argv0" -- "$@"); then
119 unset db_name db_path db_root makepkg_conf pacman_conf results_file pkgrel_incr queue
129 -d|
--database|
--repo)
131 repo_args
+=(--repo "$1") ;;
133 shift; makepkg_common_args
+=(-p "$1")
134 pkglist_args
+=(-p "$1") ;;
138 shift; makepkg_conf
=$1 ;;
140 shift; pacman_conf
=$1 ;;
142 run_pkgver
=1; makepkg_args
+=(--noextract)
143 makechrootpkg_makepkg_args
+=(--holdver) ;;
146 repo_args
+=(--root "$1") ;;
147 -S|
--sign|
--gpg-sign)
148 sign_pkg
=1; repo_add_args
+=(-s) ;;
151 shift; chroot_args
+=(-D "$1") ;;
153 shift; makechrootpkg_args
+=(-D "$1") ;;
155 shift; makechrootpkg_args
+=(-d"$1") ;;
157 makechrootpkg_args
+=(-n) ;;
159 makechrootpkg_args
+=(-C) ;;
161 makechrootpkg_args
+=(-T) ;;
163 shift; makechrootpkg_args
+=(-U "$1") ;;
164 # makepkg options (common)
165 -A|
--ignorearch|
--ignore-arch)
166 makepkg_common_args
+=(--ignorearch)
167 makechrootpkg_makepkg_args
+=(--ignorearch) ;;
168 -n|
--noconfirm|
--no-confirm)
169 makepkg_common_args
+=(--noconfirm) ;;
171 makepkg_common_args
+=(--rmdeps) ;;
173 makepkg_common_args
+=(--syncdeps) ;;
174 # makepkg options (build)
176 makepkg_args
+=(--clean) ;;
178 makepkg_args
+=(--log) ;;
179 --nocheck|
--no-check)
180 makepkg_args
+=(--nocheck)
181 makechrootpkg_makepkg_args
+=(--nocheck) ;;
182 --makepkg-args|
--margs)
183 shift; IFS
=, read -a arg
-r <<< "$1"
184 makepkg_args
+=("${arg[@]}")
185 makechrootpkg_makepkg_args
+=("${arg[@]}") ;;
188 repo_add_args
+=(-v) ;;
190 repo_add_args
+=(-R) ;;
192 repo_add_args
+=(-n) ;;
194 repo_add_args
+=(-p) ;;
197 shift; results_file
=$1 ;;
199 shift; results_file
=$1; truncate
=0 ;;
201 read_args
+=(-d $
'\0') ;;
203 printf -- '--%s\n' "${opt_long[@]}" ${AUR_DEBUG+"${opt_hidden[@]}"}
204 printf -- '%s' "${opt_short}" | sed 's/.:\?/-&\n/g'
211 # Assign environment variables
212 : "${db_ext=$AUR_DBEXT}" "${db_root=$AUR_DBROOT}" "${db_repo=$AUR_REPO}"
214 # shellcheck disable=SC2174
215 mkdir -pm 0700 -- "${TMPDIR:-/tmp}/aurutils-
$UID"
216 tmp=$(mktemp -d --tmpdir "aurutils-
$UID/$argv0.XXXXXXXX
")
218 # shellcheck disable=SC2174
219 mkdir -pm 0700 -- "${TMPDIR:-/var/tmp}/aurutils-
$UID"
220 var_tmp=$(mktemp -d --tmpdir="${TMPDIR:-/var/tmp/}" "aurutils-
$UID/$argv0.XXXXXXXX
")
222 trap 'trap_exit' EXIT
225 # XXX: default paths can be set through the Makefile
226 if (( chroot )); then
227 # The pacman configuration in the chroot may contain a local repository that
228 # is not configured on the host. Therefore, $db_name is only used for the
229 # default paths below when specified on the command-line or through `AUR_REPO`.
230 if [[ $db_name ]]; then
231 default_paths=("/etc
/aurutils
/pacman-
$db_name.conf
" "/etc
/aurutils
/pacman-
$machine.conf
")
233 default_paths=("/etc
/aurutils
/pacman-
$machine.conf
")
236 # Change the default /usr/share/devtools/pacman-extra.conf in aur-chroot to
237 # /etc/aurutils/pacman-<repo>.conf or /etc/aurutils/pacman-<uname>.conf in
238 # aur-build, and pass it on to aur-chroot (#824, #846)
239 for def in "${default_paths[@]}"; do
240 if [[ -f $def ]] && [[ ! -v pacman_conf ]]; then
246 # No pacman configuration is available for the container, or it points to a
247 # non-existing file. Print a matching diagnostic and exit.
248 if [[ ! -v pacman_conf ]]; then
249 diag_pacman_conf "${default_paths[@]}"
252 elif [[ ! -f $pacman_conf ]]; then
253 diag_pacman_conf "$pacman_conf"
256 chroot_args+=(--pacman-conf "$pacman_conf")
258 # The default path is /usr/share/devtools/makepkg-<uname.conf>, which is
259 # copied to <container path>/etc/makepkg.conf by arch-nspawn.
260 if [[ -v makepkg_conf ]]; then
261 chroot_args+=(--makepkg-conf "$makepkg_conf")
263 # When makechrootpkg calls makepkg inside the container, it uses the above
264 # makepkg.conf for most variables including PKGEXT. (makepkg --packagelist)
265 makepkg_conf=$(aur chroot --path "${chroot_args[@]}")/etc/makepkg.conf
269 # Propagate makepkg/makechrootpkg arguments to aur-chroot
270 if (( ${#makechrootpkg_args[@]} )); then
271 chroot_args+=(--cargs "$
(args_csv
"${makechrootpkg_args[@]}")")
273 if (( ${#makechrootpkg_makepkg_args[@]} )); then
274 chroot_args+=(--margs "$
(args_csv
"${makechrootpkg_makepkg_args[@]}")")
278 # Propagate makepkg and pacman configuration to other tools. This must be done
279 # BEFORE retrieving the local repository name/root. It should be done AFTER
280 # retrieving the container configuration, as it may contain (local) repositories
281 # not enabled on the host.
282 if [[ -v pacman_conf ]]; then
283 pacconf_args+=(--config "$pacman_conf")
286 if [[ -v makepkg_conf ]]; then
287 makepkg_common_args+=(--config "$makepkg_conf")
288 pkglist_args+=(--config "$makepkg_conf")
291 # Automatically choose the local repository based on the pacman configuration.
292 if [[ $db_name ]] && [[ $db_root ]]; then
293 db_path=$db_root/$db_name.${db_ext:-db}
294 db_path=$(realpath -- "$db_path")
296 { IFS=: read -r _ db_name
297 IFS=: read -r _ db_root
298 IFS=: read -r _ db_path # canonicalized
299 } < <(aur repo --status "${repo_args[@]}" "${pacconf_args[@]}")
302 db_root=$(realpath -- "$db_root")
304 # Check that a valid database extension was retrieved (#700, #1038)
305 if [[ -z $AUR_DBEXT ]] && [[ $db_path =~ \.db$ ]]; then
306 printf >&2 '%s: %s does not have a valid database archive extension\n' "$argv0" "$db_path"
307 # TODO: this usually happens on file systems not supporting symbolic links
308 # (SMB/CIFS). Add a diagnostic to point towards AUR_DBEXT in this case
312 # File permission checks
313 if [[ ! -f $db_path ]]; then
314 printf >&2 '%s: %s: not a regular file\n' "$argv0" "$db_path"
316 elif [[ ! -w $db_path ]]; then
317 printf >&2 '%s: %s: permission denied\n' "$argv0" "$db_path"
319 elif [[ -v pacman_conf ]] && [[ ! -r $pacman_conf ]]; then
320 printf >&2 '%s: %s: permission denied\n' "$argv0" "$pacman_conf"
322 elif [[ -v makepkg_conf ]] && [[ ! -r $makepkg_conf ]]; then
323 printf >&2 '%s: %s: permission denied\n' "$argv0" "$makepkg_conf"
327 # Write successfully built packages to file (#437, #980)
328 if [[ -v results_file ]]; then
329 results_file=$(realpath -- "$results_file")
330 (( truncate )) && true | tee "$results_file"
333 if (( chroot )); then
334 # Update pacman and makepkg configuration for the chroot build
335 # queue. A full system upgrade is run on the /root container to
336 # avoid lenghty upgrades for makechrootpkg -u.
337 aur chroot --create --update "${chroot_args[@]}"
340 if [[ -v queue ]]; then
343 exec {fd}< <(echo "$startdir")
346 # Early consistency check for signed database
347 if (( ! sign_pkg )); then
348 db_sigs=("$db_root/$db_name".sig "$db_root/$db_name".files.sig)
350 if [[ -f ${db_sigs[0]} ]]; then
351 printf >&2 '%s: database signature found, but signing is disabled\n' "$argv0"
353 printf '%q\n' >&2 "${db_sigs[@]}"
357 elif [[ -v GPGKEY ]]; then
358 #shellcheck disable=SC2086
359 ${AUR_GPG:-gpg} --list-keys "$GPGKEY"
360 gpg_args+=(-u "$GPGKEY")
363 while IFS= read "${read_args[@]}" -ru "$fd" path; do
365 [[ $path ]] && cd -- "$path"
367 # Allow running repo-add(8) on existing packages (#839)
371 # Run pkgver function before --packagelist (#500)
372 if (( run_pkgver )); then
373 #shellcheck disable=SC2086
374 ${AUR_MAKEPKG:-makepkg} -od "${makepkg_common_args[@]}" >&2
377 # Retrieve list of potential package paths. This is used to (optionally)
378 # check if package paths are already available in the local repository
379 # before builds. If so, the build is skipped and the path is passed to
380 # repo-add (create_package=0). If no paths are available, the package is
381 # assumed to not exist and the build proceeds as usual (create_package=1).
382 if (( ! overwrite )); then
384 #shellcheck disable=SC2086
385 while read -r pkgpath; do
386 [[ -f $pkgpath ]] && exists+=("$pkgpath")
387 done < <(PKGDEST="$db_root" ${AUR_BUILD_PKGLIST:-aur build--pkglist} "${pkglist_args[@]}")
390 printf >&2 '%s: warning: failed to retrieve package list\n' "$argv0"
393 if (( ${#exists[@]} )); then
394 printf >&2 '%s: warning: skipping existing package (use -f to overwrite)\n' "$argv0"
397 printf '%q\n' >&2 "${exists[@]}"
398 pkglist=("${exists[@]}")
401 if (( ${#exists[@]} )) && [[ -v results_file ]]; then
402 printf "exist
:file://%s
\n" "${exists[@]}" | tee -a "$results_file" >/dev/null
406 if (( create_package )); then
407 if (( chroot )); then
408 PKGDEST="$var_tmp" aur chroot --build "${chroot_args[@]}"
410 #shellcheck disable=SC2086
411 PKGDEST="$var_tmp" LOGDEST="${LOGDEST:-$PWD}" \
412 ${AUR_MAKEPKG:-makepkg} "${makepkg_common_args[@]}" "${makepkg_args[@]}"
416 pkglist
=(!(*.sig
)) # discard makepkg --sign from package list (#410)
419 # pkglist has paths to $db_root/<pkg>
422 # Sign any packages without signatures, even if the packages are existing.
425 for p
in "${pkglist[@]}"; do
426 # Package basename (equals $p if create_package=1)
429 # Signature from makepkg --sign
430 if [[ -f $p_base.sig
]]; then
431 siglist
+=("$p_base".sig
)
433 # Skipped package build with signature
434 elif [[ -f $db_root/$p_base.sig
]] && [[ ! -f $p_base ]]; then
435 printf >&2 '%s: existing signature file %q\n' "$argv0" "$db_root/$p_base.sig"
437 # No candidate signature, generate one
438 elif (( sign_pkg
)); then
439 #shellcheck disable=SC2086
440 ${AUR_GPG:-gpg} "${gpg_args[@]}" --output "$p_base".sig
"$p"
442 printf >&2 '%s: created signature file %q\n' "$argv0" "$p_base".sig
443 siglist
+=("$p_base".sig
)
447 if (( create_package
)); then
448 mv -f "${siglist[@]}" "${pkglist[@]}" "$db_root"
450 if [[ -v results_file
]]; then
451 printf "build:file://$db_root/%s\n" "${pkglist[@]}" |
tee -a "$results_file" >/dev
/null
454 elif (( ${#siglist[@]} )); then
455 mv -f "${siglist[@]}" "$db_root"
459 #shellcheck disable=SC2086
460 env
-C "$db_root" LANG
=C
${AUR_REPO_ADD:-repo-add} "${repo_add_args[@]}" "$db_path" "${pkglist[@]}"
462 if (( chroot )) || (( no_sync )); then
465 #shellcheck disable=SC2086
466 ${AUR_PACMAN_AUTH:-sudo} pacsync "$db_name"
467 #shellcheck disable=SC2086
468 ${AUR_PACMAN_AUTH:-sudo} pacsync "$db_name" --dbext=.files
470 # Retrieve upgrade targets in local repository. May error in case of
471 # conflicts or dependency errors.
472 mapfile -t targets < <(get_local_upgrades "$db_name")
475 if (( ${#targets[@]} )); then
476 printf >&2 "%s
: upgrading packages
in repository
'%s'\n" "$argv0" "$db_name"
477 #shellcheck disable=SC2086
478 printf '%s\n' "${targets[@]}" | ${AUR_PACMAN_AUTH:-sudo} pacman -S --noconfirm -
485 # vim: set et sw=4 sts=4 ft=sh: