From e7b82f36ef586127453e8c68660e0ef7826d0127 Mon Sep 17 00:00:00 2001
From: Christian Heusel <christian@heusel.eu>
Date: Tue, 25 Jul 2023 11:19:11 +0200
Subject: feat(build): add --updpkgsums option

This is useful so people who update patches etc. can update their checksums on building.
The functionality itself was already implemented for --pkgver, but was not available separately.

Fixes #168
Component: pkgctl build
Signed-off-by: Christian Heusel <christian@heusel.eu>
---
 doc/man/pkgctl-build.1.asciidoc | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'doc/man/pkgctl-build.1.asciidoc')

diff --git a/doc/man/pkgctl-build.1.asciidoc b/doc/man/pkgctl-build.1.asciidoc
index f68e7cf..2637ebc 100644
--- a/doc/man/pkgctl-build.1.asciidoc
+++ b/doc/man/pkgctl-build.1.asciidoc
@@ -59,6 +59,9 @@ PKGBUILD Options
 *--rebuild*::
 	Increment the current pkgrel variable
 
+*--updpkgsums*::
+	Regenerate the checksums
+
 *-e, --edit*::
 	Edit the PKGBUILD before building
 
-- 
cgit v1.2.3-70-g09d2


From cc369e86d2e060d8b65c7dbbb0c933d18f8aa6b0 Mon Sep 17 00:00:00 2001
From: Levente Polyak <anthraxx@archlinux.org>
Date: Thu, 23 Mar 2023 23:38:29 +0100
Subject: feat(makechrootpkg): add option to interactively inspect the chroot

Implement the -x option for makechrootpkg which allows to get an
interactive shell in the chroot after building the package. Useful to
ease the debugging of a package build.

Depending on the argument, the interactive shell is either always
spawned or only when an error occurred during build.

This option is also forwarded from `pkgctl build` via the `--inspect`
flag.

Component: pkgctl build
Component: makechrootpkg
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
---
 contrib/completion/bash/devtools.in |  9 +++++++++
 contrib/completion/zsh/_devtools.in |  4 ++++
 doc/man/makechrootpkg.1.asciidoc    |  4 ++++
 doc/man/pkgctl-build.1.asciidoc     |  4 ++++
 src/lib/build/build.sh              | 11 +++++++++++
 src/lib/valid-inspect.sh            | 10 ++++++++++
 src/makechrootpkg.in                | 38 ++++++++++++++++++++++++++++++++-----
 7 files changed, 75 insertions(+), 5 deletions(-)
 create mode 100644 src/lib/valid-inspect.sh

(limited to 'doc/man/pkgctl-build.1.asciidoc')

diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in
index e0fca51..b347b31 100644
--- a/contrib/completion/bash/devtools.in
+++ b/contrib/completion/bash/devtools.in
@@ -7,6 +7,8 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
 # shellcheck source=src/lib/valid-repos.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
+# shellcheck source=src/lib/valid-inspect.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
 
 _binary_arch=${DEVTOOLS_VALID_ARCHES[*]:0:-1}
 _colors=(never always auto)
@@ -24,6 +26,7 @@ _makechrootpkg_args=(
 	-n
 	-T
 	-U
+	-x
 )
 _makechrootpkg_args_d_opts() { _filedir -d; }
 _makechrootpkg_args_D_opts() { _filedir -d; }
@@ -31,6 +34,7 @@ _makechrootpkg_args_r_opts() { _filedir -d; }
 _makechrootpkg_args_I_opts() { _filedir '*.pkg.tar.*'; }
 _makechrootpkg_args_l_opts() { _filedir -d; }
 _makechrootpkg_args_U_opts() { :; }
+_makechrootpkg_args_x_opts() { _devtools_completions_inspect; }
 _makechrootpkg() { __devtools_complete _makechrootpkg; }
 complete -F _makechrootpkg makechrootpkg
 
@@ -169,6 +173,7 @@ _pkgctl_build_args=(
 	-o --offload
 	-c --clean
 	-w --worker
+	--inspect
 
 	--pkgver
 	--pkgrel
@@ -186,6 +191,7 @@ _pkgctl_build_args__arch_opts() { _devtools_completions_arch; }
 _pkgctl_build_args__repo_opts() { _devtools_completions_repo; }
 _pkgctl_build_args__worker_opts() { :; }
 _pkgctl_build_args_w_opts() { _pkgctl_build_args__worker_opts; }
+_pkgctl_build_args__inspect_opts() { _devtools_completions_inspect; }
 _pkgctl_build_args__pkgver_opts() { :; }
 _pkgctl_build_args__pkgrel_opts() { :; }
 _pkgctl_build_args__message_opts() { :; }
@@ -371,6 +377,9 @@ _devtools_completions_all_packages() {
 _devtools_completions_protocol() {
 	mapfile -t COMPREPLY < <(compgen -W "https" -- "$cur")
 }
+_devtools_completions_inspect() {
+	mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_INSPECT_MODES[*]}" -- "$cur")
+}
 
 __devtools_complete() {
 	local service=$1
diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in
index d3d6df0..feeb2c2 100644
--- a/contrib/completion/zsh/_devtools.in
+++ b/contrib/completion/zsh/_devtools.in
@@ -7,6 +7,8 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
 # shellcheck source=src/lib/valid-repos.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
+# shellcheck source=src/lib/valid-inspect.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
 
 _binary_arch=${DEVTOOLS_VALID_ARCHES[*]:0:-1}
 _colors=(never always auto)
@@ -42,6 +44,7 @@ _pkgctl_build_args=(
 	'(-o --offload)'{-o,--offload}'[Build on a remote server and transfer artifacts afterwards]'
 	'(-c --clean)'{-c,--clean}'[Recreate the chroot before building]'
 	'(-I --install)'{-I,--install}'[Install a package into the working copy of the chroot]:target:_files -g "*.pkg.tar.*(.)"'
+	"--inspect[Spawn an interactive shell to inspect the chroot (never, always, failure)]:inspect:($DEVTOOLS_VALID_INSPECT_MODES[*])"
 	'(-w --worker)'{-w,--worker}'[Name of the worker slot, useful for concurrent builds (disables auto-detection)]:slot:'
 	'--nocheck[Do not run the check() function in the PKGBUILD]'
 	'--pkgver=[Set pkgver, reset pkgrel and update checksums]:pkgver:'
@@ -190,6 +193,7 @@ _makechrootpkg_args=(
 	'-n[Run namcap on the package]'
 	'-T[Build in a temporary directory]'
 	'-U[Run makepkg as a specified user]:makepkg_user'
+	"-x[Spawn an interactive shell to inspect the chroot (never, always, failure)]:inspect:($DEVTOOLS_VALID_INSPECT_MODES[*])"
 )
 
 _mkarchroot_args=(
diff --git a/doc/man/makechrootpkg.1.asciidoc b/doc/man/makechrootpkg.1.asciidoc
index 12d32f1..3aa1be5 100644
--- a/doc/man/makechrootpkg.1.asciidoc
+++ b/doc/man/makechrootpkg.1.asciidoc
@@ -73,4 +73,8 @@ Options
 *-U*::
 	Run makepkg as a specified user
 
+*-x* <when>::
+	Inspect chroot after build, possible modes are 'never' (default), 'always' or 'failure'
+
+
 include::include/footer.asciidoc[]
diff --git a/doc/man/pkgctl-build.1.asciidoc b/doc/man/pkgctl-build.1.asciidoc
index 2637ebc..3f2d44e 100644
--- a/doc/man/pkgctl-build.1.asciidoc
+++ b/doc/man/pkgctl-build.1.asciidoc
@@ -38,6 +38,10 @@ Build Options
 *-I, --install* 'FILE'::
 	Install a package into the working copy of the chroot
 
+*--inspect* 'WHEN'::
+	Spawn an interactive shell to inspect the chroot after building. Useful to ease the debugging of a package build. +
+	Possible values for 'WHEN' are `'never'`, `'always'` or `'failure'`
+
 *-w, --worker* 'SLOT'::
 	Name of the worker slot, useful for concurrent builds. By default the slot
 	is automatically assigned to the current tty pts number. In case the caller
diff --git a/src/lib/build/build.sh b/src/lib/build/build.sh
index 8d58b63..2b9d4cf 100644
--- a/src/lib/build/build.sh
+++ b/src/lib/build/build.sh
@@ -20,6 +20,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
 # shellcheck source=src/lib/valid-tags.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
+# shellcheck source=src/lib/valid-inspect.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
 
 source /usr/share/makepkg/util/config.sh
 source /usr/share/makepkg/util/message.sh
@@ -48,6 +50,7 @@ pkgctl_build_usage() {
 		    -o, --offload        Build on a remote server and transfer artifacts afterwards
 		    -c, --clean          Recreate the chroot before building
 		    -I, --install FILE   Install a package into the working copy of the chroot
+		    --inspect WHEN       Spawn an interactive shell to inspect the chroot (never, always, failure)
 		    -w, --worker SLOT    Name of the worker slot, useful for concurrent builds (disables automatic names)
 		    --nocheck            Do not run the check() function in the PKGBUILD
 
@@ -218,6 +221,14 @@ pkgctl_build() {
 				warning 'not running checks is disallowed for official packages, except for bootstrapping. Please rebuild after bootstrapping is completed!'
 				shift
 				;;
+			--inspect)
+				(( $# <= 1 )) && die "missing argument for %s" "$1"
+				if ! in_array "${2}" "${DEVTOOLS_VALID_INSPECT_MODES[@]}"; then
+					die "Invalid inspect mode: %s" "${2}"
+				fi
+				MAKECHROOT_OPTIONS+=("-x" "${2}")
+				shift 2
+				;;
 			-r|--release)
 				# shellcheck source=src/lib/release.sh
 				source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
diff --git a/src/lib/valid-inspect.sh b/src/lib/valid-inspect.sh
new file mode 100644
index 0000000..3b5dcad
--- /dev/null
+++ b/src/lib/valid-inspect.sh
@@ -0,0 +1,10 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+# shellcheck disable=2034
+DEVTOOLS_VALID_INSPECT_MODES=(
+	never
+	always
+	failure
+)
diff --git a/src/makechrootpkg.in b/src/makechrootpkg.in
index 2cfd849..14b8f11 100644
--- a/src/makechrootpkg.in
+++ b/src/makechrootpkg.in
@@ -8,9 +8,12 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
 # shellcheck source=src/lib/archroot.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/archroot.sh
+# shellcheck source=src/lib/valid-inspect.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-inspect.sh
 
 
 source /usr/share/makepkg/util/config.sh
+source /usr/share/makepkg/util/util.sh
 
 shopt -s nullglob
 
@@ -31,6 +34,8 @@ run_checkpkg=0
 temp_chroot=0
 tmp_opts="nosuid,nodev,size=50%,nr_inodes=2m"
 
+inspect=never
+
 bindmounts_ro=()
 bindmounts_rw=()
 
@@ -76,6 +81,7 @@ usage() {
 	echo '-C         Run checkpkg on the package'
 	echo '-T         Build in a temporary directory'
 	echo '-U         Run makepkg as a specified user'
+	echo '-x <when>  Inspect chroot after build (never, always, failure)'
 	exit 1
 }
 
@@ -280,7 +286,7 @@ move_products() {
 }
 # }}}
 
-while getopts 'hcur:I:l:nCTD:d:U:' arg; do
+while getopts 'hcur:I:l:nCTD:d:U:x:' arg; do
 	case "$arg" in
 		c) clean_first=1 ;;
 		D) bindmounts_ro+=("--bind-ro=$OPTARG") ;;
@@ -293,6 +299,7 @@ while getopts 'hcur:I:l:nCTD:d:U:' arg; do
 		C) run_checkpkg=1 ;;
 		T) temp_chroot=1; copy+="-$$" ;;
 		U) makepkg_user="$OPTARG" ;;
+		x) inspect="$OPTARG" ;;
 		h|*) usage ;;
 	esac
 done
@@ -314,6 +321,10 @@ else
 	copydir="$chrootdir/$copy"
 fi
 
+if ! in_array "${inspect}" "${DEVTOOLS_VALID_INSPECT_MODES[@]}"; then
+	die "Invalid inspect mode: %s" "${inspect}"
+fi
+
 # Pass all arguments after -- right to makepkg
 makepkg_args+=("${@:$OPTIND}")
 
@@ -368,11 +379,16 @@ download_sources
 
 prepare_chroot
 
+nspawn_build_args=(
+	--bind="${PWD//:/\\:}:/startdir"
+	--bind="${SRCDEST//:/\\:}:/srcdest"
+	--tmpfs="/tmp:${tmp_opts}"
+	"${bindmounts_ro[@]}"
+	"${bindmounts_rw[@]}"
+)
+
 if arch-nspawn "$copydir" \
-	--bind="${PWD//:/\\:}:/startdir" \
-	--bind="${SRCDEST//:/\\:}:/srcdest" \
-	--tmpfs="/tmp:${tmp_opts}" \
-	"${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
+	"${nspawn_build_args[@]}" \
 	/chrootbuild "${makepkg_args[@]}"
 then
 	mapfile -t pkgnames < <(sudo -u "$makepkg_user" bash -c 'source PKGBUILD; printf "%s\n" "${pkgname[@]}"')
@@ -382,6 +398,18 @@ else
 	move_logfiles
 fi
 
+if [[ $inspect == always ]] || ( [[ $inspect == failure ]] && (( ret != 0 )) ); then
+	if (( ret == 0 )); then
+		msg "Build succeeded, inspecting %s" "$copydir"
+	else
+		error "Build failed, inspecting %s" "$copydir"
+	fi
+	arch-nspawn "$copydir" \
+		"${nspawn_build_args[@]}" \
+		--user=builduser \
+		--chdir=/build
+fi
+
 (( temp_chroot )) && delete_chroot "$copydir" "$copy"
 
 if (( ret != 0 )); then
-- 
cgit v1.2.3-70-g09d2


From 4425913e4f3bfd3cb346c38e13a10f0002615a55 Mon Sep 17 00:00:00 2001
From: Levente Polyak <anthraxx@archlinux.org>
Date: Thu, 21 Dec 2023 21:40:57 +0100
Subject: chore(build): use more intuitive update-checksums option for humans

The philosophy of our CLI is to provide options that better match human
expectations in an intuitive way rather than mimic wording of previous
tools with abbreviation.

Component: pkgctl build
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
---
 contrib/completion/bash/devtools.in |  2 +-
 contrib/completion/zsh/_devtools.in |  2 +-
 doc/man/pkgctl-build.1.asciidoc     |  8 ++++++--
 src/lib/build/build.sh              | 12 ++++++------
 4 files changed, 14 insertions(+), 10 deletions(-)

(limited to 'doc/man/pkgctl-build.1.asciidoc')

diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in
index 83264ce..b974257 100644
--- a/contrib/completion/bash/devtools.in
+++ b/contrib/completion/bash/devtools.in
@@ -179,7 +179,7 @@ _pkgctl_build_args=(
 	--pkgver
 	--pkgrel
 	--rebuild
-	--updpkgsums
+	--update-checksums
 	-e --edit
 
 	-r --release
diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in
index b82ece4..35ab2dc 100644
--- a/contrib/completion/zsh/_devtools.in
+++ b/contrib/completion/zsh/_devtools.in
@@ -50,7 +50,7 @@ _pkgctl_build_args=(
 	'--pkgver=[Set pkgver, reset pkgrel and update checksums]:pkgver:'
 	'--pkgrel=[Set pkgrel to a given value]:pkgrel:'
 	'--rebuild[Increment the pkgrel variable]'
-	'--updpkgsums[Regenerate the checksums]'
+	'--update-checksums[Force computation and update of the checksums (disables auto-detection)]'
 	'(-e --edit)'{-e,--edit}'[Edit the PKGBUILD before building]'
 	'(-r --release)'{-r,--release}'[Automatically commit, tag and release after building]'
 	'(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
diff --git a/doc/man/pkgctl-build.1.asciidoc b/doc/man/pkgctl-build.1.asciidoc
index 3f2d44e..12deaaa 100644
--- a/doc/man/pkgctl-build.1.asciidoc
+++ b/doc/man/pkgctl-build.1.asciidoc
@@ -63,8 +63,12 @@ PKGBUILD Options
 *--rebuild*::
 	Increment the current pkgrel variable
 
-*--updpkgsums*::
-	Regenerate the checksums
+*--update-checksums*::
+	Force computation and update of the checksums by disabling auto-detection. +
+	Should only be used in special circumstances, like when adding new patch
+	files to the source array. During regular packaging operations, checksums
+	are either automatically updated when upgrading a package using `--pkgver`
+	or should remain immutable during rebuilds.
 
 *-e, --edit*::
 	Edit the PKGBUILD before building
diff --git a/src/lib/build/build.sh b/src/lib/build/build.sh
index 2b9d4cf..e0982e4 100644
--- a/src/lib/build/build.sh
+++ b/src/lib/build/build.sh
@@ -58,7 +58,7 @@ pkgctl_build_usage() {
 		    --pkgver=PKGVER      Set pkgver, reset pkgrel and update checksums
 		    --pkgrel=PKGREL      Set pkgrel to a given value
 		    --rebuild            Increment the current pkgrel variable
-		    --updpkgsums         Regenerate the checksums
+		    --update-checksums   Force computation and update of the checksums (disables auto-detection)
 		    -e, --edit           Edit the PKGBUILD before building
 
 		RELEASE OPTIONS
@@ -108,7 +108,7 @@ pkgctl_build() {
 		exit 1
 	fi
 
-	local UPDPKGSUMS=0
+	local UPDATE_CHECKSUMS=0
 	local EDIT=0
 	local REBUILD=0
 	local OFFLOAD=0
@@ -165,7 +165,7 @@ pkgctl_build() {
 				pkgctl_build_check_option_group_ver '--pkgver' "${PKGVER}" "${PKGREL}" "${REBUILD}"
 				PKGVER="${1#*=}"
 				PKGREL=1
-				UPDPKGSUMS=1
+				UPDATE_CHECKSUMS=1
 				shift
 				;;
 			--pkgrel=*)
@@ -173,8 +173,8 @@ pkgctl_build() {
 				PKGREL="${1#*=}"
 				shift
 				;;
-			--updpkgsums)
-				UPDPKGSUMS=1
+			--update-checksums)
+				UPDATE_CHECKSUMS=1
 				shift
 				;;
 			--rebuild)
@@ -407,7 +407,7 @@ pkgctl_build() {
 
 
 		# update checksums if any sources are declared
-		if (( UPDPKGSUMS )) && (( ${#source[@]} >= 1 )); then
+		if (( UPDATE_CHECKSUMS )) && (( ${#source[@]} >= 1 )); then
 			updpkgsums
 		fi
 
-- 
cgit v1.2.3-70-g09d2


From 5042dcaeb4916e199b30ecf21048a4234da43499 Mon Sep 17 00:00:00 2001
From: Christian Heusel <christian@heusel.eu>
Date: Thu, 15 Jun 2023 16:30:41 +0200
Subject: feat(build): allow to test-install the built packages

This change introduces the new --install-to-host flag to pkgctl build,
which can be used with one of the modes 'all' or 'auto'. Depending on
the mode either all or just already installed packages are installed to
the host system.

BREAKING CHANGE: the --install flag is renamed to --install-to-chroot
to avoid confusion with the newly introduced flag.

Component: pkgctl build
Signed-off-by: Christian Heusel <christian@heusel.eu>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
---
 contrib/completion/bash/devtools.in | 11 +++++++
 contrib/completion/zsh/_devtools.in |  5 ++-
 doc/man/pkgctl-build.1.asciidoc     | 14 +++++++--
 src/lib/build/build.sh              | 61 ++++++++++++++++++++++++++++++++++---
 src/lib/valid-build-install.sh      | 11 +++++++
 5 files changed, 93 insertions(+), 9 deletions(-)
 create mode 100644 src/lib/valid-build-install.sh

(limited to 'doc/man/pkgctl-build.1.asciidoc')

diff --git a/contrib/completion/bash/devtools.in b/contrib/completion/bash/devtools.in
index f8b1c9f..11fa234 100644
--- a/contrib/completion/bash/devtools.in
+++ b/contrib/completion/bash/devtools.in
@@ -3,6 +3,8 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/valid-build-install.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-build-install.sh
 # shellcheck source=src/lib/valid-tags.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
 # shellcheck source=src/lib/valid-repos.sh
@@ -179,6 +181,8 @@ _pkgctl_build_args=(
 	-c --clean
 	-w --worker
 	--inspect
+	-I --install-to-chroot
+	-i --install-to-host
 
 	--pkgver
 	--pkgrel
@@ -199,9 +203,16 @@ _pkgctl_build_args_w_opts() { _pkgctl_build_args__worker_opts; }
 _pkgctl_build_args__inspect_opts() { _devtools_completions_inspect; }
 _pkgctl_build_args__pkgver_opts() { :; }
 _pkgctl_build_args__pkgrel_opts() { :; }
+_pkgctl_build_args__install_to_host_opts() { _pkgctl_build_completions_install_mode; }
+_pkgctl_build_args_i_opts() { _pkgctl_build_args__install_to_host_opts; }
+_pkgctl_build_args__install_to_chroot_opts() { _makechrootpkg_args_I_opts; }
+_pkgctl_build_args_I_opts() { _pkgctl_build_args__install_to_chroot_opts; }
 _pkgctl_build_args__message_opts() { :; }
 _pkgctl_build_args_m_opts() { _pkgctl_build_args__message_opts; }
 _pkgctl_build_opts() { _filedir -d; }
+_pkgctl_build_completions_install_mode() {
+	mapfile -t COMPREPLY < <(compgen -W "${DEVTOOLS_VALID_BUILD_INSTALL[*]}" -- "$cur")
+}
 
 
 _pkgctl_db_cmds=(
diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in
index 34f90c6..24e57bf 100644
--- a/contrib/completion/zsh/_devtools.in
+++ b/contrib/completion/zsh/_devtools.in
@@ -3,6 +3,8 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/valid-build-install.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-build-install.sh
 # shellcheck source=src/lib/valid-tags.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-tags.sh
 # shellcheck source=src/lib/valid-repos.sh
@@ -45,8 +47,9 @@ _pkgctl_build_args=(
 	'(-t --testing)'{-t,--testing}'[Build against the testing counterpart of the auto-detected repo]'
 	'(-o --offload)'{-o,--offload}'[Build on a remote server and transfer artifacts afterwards]'
 	'(-c --clean)'{-c,--clean}'[Recreate the chroot before building]'
-	'(-I --install)'{-I,--install}'[Install a package into the working copy of the chroot]:target:_files -g "*.pkg.tar.*(.)"'
 	"--inspect[Spawn an interactive shell to inspect the chroot (never, always, failure)]:inspect:($DEVTOOLS_VALID_INSPECT_MODES[*])"
+	'(-I --install-to-chroot)'{-I,--install-to-chroot}'[Install a package to the working copy of the chroot]:target:_files -g "*.pkg.tar.*(.)"'
+	'(-i --install-to-host)'{-i,--install-to-host}"[Install the built packages to the host system]:mode:($DEVTOOLS_VALID_BUILD_INSTALL[*])"
 	'(-w --worker)'{-w,--worker}'[Name of the worker slot, useful for concurrent builds (disables auto-detection)]:slot:'
 	'--nocheck[Do not run the check() function in the PKGBUILD]'
 	'--pkgver=[Set pkgver, reset pkgrel and update checksums]:pkgver:'
diff --git a/doc/man/pkgctl-build.1.asciidoc b/doc/man/pkgctl-build.1.asciidoc
index 12deaaa..e7ec714 100644
--- a/doc/man/pkgctl-build.1.asciidoc
+++ b/doc/man/pkgctl-build.1.asciidoc
@@ -35,9 +35,6 @@ Build Options
 *-c, --clean*::
 	Recreate the chroot before building
 
-*-I, --install* 'FILE'::
-	Install a package into the working copy of the chroot
-
 *--inspect* 'WHEN'::
 	Spawn an interactive shell to inspect the chroot after building. Useful to ease the debugging of a package build. +
 	Possible values for 'WHEN' are `'never'`, `'always'` or `'failure'`
@@ -51,6 +48,17 @@ Build Options
 *--nocheck*::
 	Do not run the check() function in the PKGBUILD
 
+Install Options
+---------------
+
+*-I, --install-to-chroot* 'FILE'::
+	Install a package to the working copy of the chroot
+
+*-i, --install-to-host* 'MODE'::
+	Install the built packages to the host system. Useful when one wants to verify that the package works as intended.
+	* When 'MODE' is 'all', this installs all built packages
+	* When 'MODE' is 'auto', this installs all built packages which are currently installed
+
 PKGBUILD Options
 ----------------
 
diff --git a/src/lib/build/build.sh b/src/lib/build/build.sh
index 712be22..64a6ce3 100644
--- a/src/lib/build/build.sh
+++ b/src/lib/build/build.sh
@@ -20,6 +20,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
 # shellcheck source=src/lib/util/pkgbuild.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pkgbuild.sh
+# shellcheck source=src/lib/valid-build-install.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-build-install.sh
 # shellcheck source=src/lib/valid-repos.sh
 source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh
 # shellcheck source=src/lib/valid-tags.sh
@@ -52,11 +54,14 @@ pkgctl_build_usage() {
 		    -t, --testing        Build against the testing counterpart of the auto-detected repo
 		    -o, --offload        Build on a remote server and transfer artifacts afterwards
 		    -c, --clean          Recreate the chroot before building
-		    -I, --install FILE   Install a package into the working copy of the chroot
 		    --inspect WHEN       Spawn an interactive shell to inspect the chroot (never, always, failure)
 		    -w, --worker SLOT    Name of the worker slot, useful for concurrent builds (disables automatic names)
 		    --nocheck            Do not run the check() function in the PKGBUILD
 
+		INSTALL OPTIONS
+		    -I, --install-to-chroot FILE   Install a package to the working copy of the chroot
+		    -i, --install-to-host MODE     Install the built package to the host system, possible modes are 'all' and 'auto'
+
 		PKGBUILD OPTIONS
 		    --pkgver=PKGVER      Set pkgver, reset pkgrel and update checksums
 		    --pkgrel=PKGREL      Set pkgrel to a given value
@@ -119,6 +124,7 @@ pkgctl_build() {
 	local TESTING=0
 	local RELEASE=0
 	local DB_UPDATE=0
+	local INSTALL_TO_HOST=none
 
 	local REPO=
 	local PKGVER=
@@ -131,12 +137,13 @@ pkgctl_build() {
 	local MAKECHROOT_OPTIONS=()
 	local RELEASE_OPTIONS=()
 	local MAKEPKG_OPTIONS=()
+	local INSTALL_HOST_PACKAGES=()
 
 	local WORKER=
 	local WORKER_SLOT=
 
 	# variables
-	local _arch path pkgbase pkgrepo source pkgbuild_checksum
+	local _arch path pkgbase pkgrepo source pkgbuild_checksum current_checksum
 
 	while (( $# )); do
 		case $1 in
@@ -209,14 +216,22 @@ pkgctl_build() {
 				BUILD_OPTIONS+=("-c")
 				shift
 				;;
-			-I|--install)
+			-I|--install-to-chroot)
 				(( $# <= 1 )) && die "missing argument for %s" "$1"
 				if (( OFFLOAD )); then
 					MAKECHROOT_OPTIONS+=("-I" "$2")
 				else
 					MAKECHROOT_OPTIONS+=("-I" "$(realpath "$2")")
 				fi
-				warning 'installing packages into the chroot may break reproducible builds, use with caution!'
+				warning 'installing packages to the chroot may break reproducible builds, use with caution!'
+				shift 2
+				;;
+			-i|--install-to-host)
+				(( $# <= 1 )) && die "missing argument for %s" "$1"
+				if ! in_array "$2" "${DEVTOOLS_VALID_BUILD_INSTALL[@]}"; then
+					die 'invalid install mode: %s' "${2}"
+				fi
+				INSTALL_TO_HOST=$2
 				shift 2
 				;;
 			--nocheck)
@@ -410,7 +425,9 @@ pkgctl_build() {
 		fi
 
 		# re-source the PKGBUILD if it changed
-		if [[ ${pkgbuild_checksum} != "$(b2sum PKGBUILD | awk '{print $1}')" ]]; then
+		current_checksum="$(b2sum PKGBUILD | awk '{print $1}')"
+		if [[ ${pkgbuild_checksum} != "${current_checksum}" ]]; then
+			pkgbuild_checksum=${current_checksum}
 			# shellcheck source=contrib/makepkg/PKGBUILD.proto
 			. ./PKGBUILD
 		fi
@@ -432,10 +449,38 @@ pkgctl_build() {
 			fi
 		done
 
+		# re-source the PKGBUILD if it changed
+		current_checksum="$(b2sum PKGBUILD | awk '{print $1}')"
+		if [[ ${pkgbuild_checksum} != "${current_checksum}" ]]; then
+			pkgbuild_checksum=${current_checksum}
+			# shellcheck source=contrib/makepkg/PKGBUILD.proto
+			. ./PKGBUILD
+		fi
+
 		# auto generate .SRCINFO
 		# shellcheck disable=SC2119
 		write_srcinfo_file
 
+		# test-install (some of) the produced packages
+		if [[ ${INSTALL_TO_HOST} == auto ]] || [[ ${INSTALL_TO_HOST} == all ]]; then
+			# shellcheck disable=2119
+			load_makepkg_config
+
+			# this is inspired by print_all_package_names from libmakepkg
+			local version pkg_architecture pkg pkgfile
+			version=$(get_full_version)
+
+			for pkg in "${pkgname[@]}"; do
+				pkg_architecture=$(get_pkg_arch "$pkg")
+				pkgfile=$(realpath "$(printf "%s/%s-%s-%s%s\n" "${PKGDEST:-.}" "$pkg" "$version" "$pkg_architecture" "$PKGEXT")")
+
+				# check if we install all packages or if the (split-)package is already installed
+				if [[ ${INSTALL_TO_HOST} == all ]] || ( [[ ${INSTALL_TO_HOST} == auto ]] && pacman -Qq -- "$pkg" &>/dev/null ); then
+					INSTALL_HOST_PACKAGES+=("$pkgfile")
+				fi
+			done
+		fi
+
 		# release the build
 		if (( RELEASE )); then
 			pkgctl_release --repo "${pkgrepo}" "${RELEASE_OPTIONS[@]}"
@@ -446,6 +491,12 @@ pkgctl_build() {
 		popd >/dev/null
 	done
 
+	# install all collected packages to the host system
+	if (( ${#INSTALL_HOST_PACKAGES[@]} )); then
+		msg "Installing built packages to the host system"
+		sudo pacman -U -- "${INSTALL_HOST_PACKAGES[@]}"
+	fi
+
 	# update the binary package repo db as last action
 	if (( RELEASE )) && (( DB_UPDATE )); then
 		# shellcheck disable=2119
diff --git a/src/lib/valid-build-install.sh b/src/lib/valid-build-install.sh
new file mode 100644
index 0000000..9e98be2
--- /dev/null
+++ b/src/lib/valid-build-install.sh
@@ -0,0 +1,11 @@
+#!/hint/bash
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+:
+
+# shellcheck disable=2034
+DEVTOOLS_VALID_BUILD_INSTALL=(
+	none
+	auto
+	all
+)
-- 
cgit v1.2.3-70-g09d2


From 3ecba314fc3a7508d80c5450aaae4b5fc507d62b Mon Sep 17 00:00:00 2001
From: Levente Polyak <anthraxx@archlinux.org>
Date: Tue, 6 Feb 2024 21:59:11 +0100
Subject: feat(build): consolidate repo flags in build and release subcommand

Previously the behavior was inconsistent and not fully fulfilling its
purpose of only using --repo once when initially pushing a new and
unknown package to the official repositories.

Consolidate the behavior by only allowing to use --repo during the
initial packaging and disallow any subsequent usage. The expected user
experience is to subsequently use --testing or --staging to influence
the auto-detection of the build target. This avoids any kind of human
error which leads to releasing core packages to extra-testing by
accident.

Furthermore, allow the build subcommand to automatically fallback to
extra as the default stable repository target which greatly improves the
usability for AUR or local override builds.

Fixes #193
Fixes #191

Component: pkgctl build
Component: pkgctl release
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
---
 contrib/completion/zsh/_devtools.in |  2 +-
 doc/man/pkgctl-build.1.asciidoc     |  5 ++++-
 doc/man/pkgctl-release.1.asciidoc   |  4 +++-
 src/lib/build/build.sh              | 35 +++++++++++++++++++++--------------
 src/lib/release.sh                  | 29 ++++++++++++++++++-----------
 src/lib/util/pacman.sh              |  7 ++++++-
 6 files changed, 53 insertions(+), 29 deletions(-)

(limited to 'doc/man/pkgctl-build.1.asciidoc')

diff --git a/contrib/completion/zsh/_devtools.in b/contrib/completion/zsh/_devtools.in
index 24e57bf..3aa0f96 100644
--- a/contrib/completion/zsh/_devtools.in
+++ b/contrib/completion/zsh/_devtools.in
@@ -91,7 +91,7 @@ _pkgctl_db_update_args=(
 
 _pkgctl_release_args=(
 	'(-m --message=)'{-m,--message=}"[Use the given <msg> as the commit message]:message:"
-	'(-r --repo=)'{-r,--repo=}"[Specify a target repository (disables auto-detection)]:repo:($DEVTOOLS_VALID_REPOS[*])"
+	'(-r --repo=)'{-r,--repo=}"[Specify a target repository for new packages]:repo:($DEVTOOLS_VALID_REPOS[*])"
 	'(-s --staging)'{-s,--staging}'[Release to the staging counterpart of the auto-detected repo]'
 	'(-t --testing)'{-t,--testing}'[Release to the testing counterpart of the auto-detected repo]'
 	'(-u --db-update)'{-u,--db-update}'[Automatically update the pacman database after uploading]'
diff --git a/doc/man/pkgctl-build.1.asciidoc b/doc/man/pkgctl-build.1.asciidoc
index e7ec714..f7abdeb 100644
--- a/doc/man/pkgctl-build.1.asciidoc
+++ b/doc/man/pkgctl-build.1.asciidoc
@@ -21,7 +21,10 @@ Build Options
 	Specify architectures to build for (disables auto-detection)
 
 *--repo* 'REPO'::
-	Specify a target repository (disables auto-detection)
+	Specify target repository for new packages not in any official repo.
+	Fallback to `'extra'` when building packages that are not present in any
+	official repository yet. Using this option is disallowed if the package is
+	already released, as it would circumvent the auto-detection safeguard.
 
 *-s, --staging*::
 	Build against the staging counterpart of the auto-detected repo
diff --git a/doc/man/pkgctl-release.1.asciidoc b/doc/man/pkgctl-release.1.asciidoc
index c991db4..01a0c9e 100644
--- a/doc/man/pkgctl-release.1.asciidoc
+++ b/doc/man/pkgctl-release.1.asciidoc
@@ -27,7 +27,9 @@ Options
 	Use the given <msg> as the commit message
 
 *-r, --repo* 'REPO'::
-	Specify a target repository (disables auto-detection)
+	Specify target repository for new packages not in any official repo.
+	Using this option is disallowed if the package is already released, as it
+	would circumvent the auto-detection safeguard.
 
 *-s, --staging*::
 	Build against the staging counterpart of the auto-detected repo
diff --git a/src/lib/build/build.sh b/src/lib/build/build.sh
index 64a6ce3..8e9a3bb 100644
--- a/src/lib/build/build.sh
+++ b/src/lib/build/build.sh
@@ -49,7 +49,7 @@ pkgctl_build_usage() {
 
 		BUILD OPTIONS
 		    --arch ARCH          Specify architectures to build for (disables auto-detection)
-		    --repo REPO          Specify a target repository (disables auto-detection)
+		    --repo REPO          Specify target repository for new packages not in any official repo
 		    -s, --staging        Build against the staging counterpart of the auto-detected repo
 		    -t, --testing        Build against the testing counterpart of the auto-detected repo
 		    -o, --offload        Build on a remote server and transfer artifacts afterwards
@@ -89,8 +89,7 @@ pkgctl_build_check_option_group_repo() {
 	local repo=$2
 	local testing=$3
 	local staging=$4
-	if ( (( testing )) && (( staging )) ) ||
-		( [[ $repo =~ ^.*-(staging|testing)$ ]] && ( (( testing )) || (( staging )) )); then
+	if [[ -n "${repo}" ]] || (( testing )) || (( staging )); then
 		die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
 		exit 1
 	fi
@@ -153,8 +152,8 @@ pkgctl_build() {
 				;;
 			--repo)
 				(( $# <= 1 )) && die "missing argument for %s" "$1"
-				REPO="${2}"
 				pkgctl_build_check_option_group_repo '--repo' "${REPO}" "${TESTING}" "${STAGING}"
+				REPO="${2}"
 				shift 2
 				;;
 			--arch)
@@ -203,13 +202,13 @@ pkgctl_build() {
 				shift
 				;;
 			-s|--staging)
-				STAGING=1
 				pkgctl_build_check_option_group_repo '--staging' "${REPO}" "${TESTING}" "${STAGING}"
+				STAGING=1
 				shift
 				;;
 			-t|--testing)
-				TESTING=1
 				pkgctl_build_check_option_group_repo '--testing' "${REPO}" "${TESTING}" "${STAGING}"
+				TESTING=1
 				shift
 				;;
 			-c|--clean)
@@ -331,14 +330,22 @@ pkgctl_build() {
 		pkgbuild_checksum=$(b2sum PKGBUILD | awk '{print $1}')
 		msg "Building ${pkgbase}"
 
-		# auto-detection of build target
-		if [[ -z ${pkgrepo} ]]; then
-			if ! pkgrepo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
-				die 'failed to get pacman repo'
-			fi
-			if [[ -z "${pkgrepo}" ]]; then
-				die 'unknown repo, specify --repo for packages not currently in any official repo'
-			fi
+		# auto-detect target repository
+		if ! repo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
+			die 'Failed to query pacman repo'
+		fi
+
+		# fail if an existing package specifies --repo
+		if [[ -n "${repo}" ]] && [[ -n ${pkgrepo} ]]; then
+			die 'Using --repo for packages that exist in official repositories is disallowed'
+		fi
+
+		# assign auto-detected target repository
+		if [[ -n ${repo} ]]; then
+			pkgrepo=${repo}
+		# fallback to extra for unreleased packages
+		elif [[ -z ${pkgrepo} ]]; then
+			pkgrepo=extra
 		fi
 
 		# special cases to resolve final build target
diff --git a/src/lib/release.sh b/src/lib/release.sh
index 028d92e..700b2b0 100644
--- a/src/lib/release.sh
+++ b/src/lib/release.sh
@@ -35,7 +35,7 @@ pkgctl_release_usage() {
 
 		OPTIONS
 		    -m, --message MSG   Use the given <msg> as the commit message
-		    -r, --repo REPO     Specify a target repository (disables auto-detection)
+		    -r, --repo REPO     Specify target repository for new packages not in any official repo
 		    -s, --staging       Release to the staging counterpart of the auto-detected repo
 		    -t, --testing       Release to the testing counterpart of the auto-detected repo
 		    -u, --db-update     Automatically update the pacman database after uploading
@@ -43,8 +43,8 @@ pkgctl_release_usage() {
 
 		EXAMPLES
 		    $ ${COMMAND}
-		    $ ${COMMAND} --repo core-testing --message 'libyay 0.42 rebuild' libfoo libbar
-		    $ ${COMMAND} --staging --db-update libfoo
+		    $ ${COMMAND} --staging --message 'libyay 0.42 rebuild' libfoo libbar
+		    $ ${COMMAND} --repo extra --db-update new-package
 _EOF_
 }
 
@@ -134,15 +134,22 @@ pkgctl_release() {
 		pushd "${path}" >/dev/null
 		pkgbase=$(basename "${path}")
 
-		if [[ -n ${REPO} ]]; then
-			repo=${REPO}
-		else
-			if ! repo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
-				die 'Failed to get pacman repo'
-			fi
-			if [[ -z "${repo}" ]]; then
-				die 'Unknown repo, please specify --repo for new packages'
+		# auto-detect target repository
+		if ! repo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
+			die 'Failed to query pacman repo'
+		fi
+
+		# fail if an existing package specifies --repo
+		if [[ -n "${repo}" ]] && [[ -n ${REPO} ]]; then
+			die 'Using --repo for packages that exist in official repositories is disallowed'
+		fi
+
+		# fail if a new package does not specify --repo
+		if [[ -z "${repo}" ]]; then
+			if [[ -z ${REPO} ]]; then
+				die 'Specify --repo for packages that do not yet exist in official repositories'
 			fi
+			repo=${REPO}
 		fi
 
 		if (( TESTING )); then
diff --git a/src/lib/util/pacman.sh b/src/lib/util/pacman.sh
index 82a227b..620e1a8 100644
--- a/src/lib/util/pacman.sh
+++ b/src/lib/util/pacman.sh
@@ -38,6 +38,11 @@ get_pacman_repo_from_pkgbuild() {
 		return
 	fi
 
+	# update the pacman repo cache if it doesn't exist yet
+	if [[ ! -d "${_DEVTOOLS_PACMAN_CACHE_DIR}" ]]; then
+		update_pacman_repo_cache
+	fi
+
 	slock 10 "${_DEVTOOLS_PACMAN_CACHE_DIR}.lock" "Locking pacman database cache"
 	# query repo of passed pkgname, specify --nodeps twice to skip all dependency checks
 	mapfile -t repos < <(pacman --config "${_DEVTOOLS_PACMAN_CONF_DIR}/multilib.conf" \
@@ -47,7 +52,7 @@ get_pacman_repo_from_pkgbuild() {
 		--nodeps \
 		--print \
 		--print-format '%n %r' \
-		"${pkgnames[0]}" | awk '$1=="'"${pkgnames[0]}"'"{print $2}'
+		"${pkgnames[0]}" 2>/dev/null | awk '$1=="'"${pkgnames[0]}"'"{print $2}'
 	)
 	lock_close 10
 
-- 
cgit v1.2.3-70-g09d2

