From 55c2ca1312e649916a9a4469b7e88464f2f20c38 Mon Sep 17 00:00:00 2001
From: Robin Candau <robincandau@protonmail.com>
Date: Fri, 23 Feb 2024 11:04:03 +0100
Subject: feat(version): let upgrade subcommand also update checksums

This commit aims to make 'pkgctl version upgrade' also update checksums
in addition of bumping the pkgver and reseting the pkgrel.

Component: pkgctl version upgrade
---
 doc/man/pkgctl-version-upgrade.1.asciidoc | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

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

diff --git a/doc/man/pkgctl-version-upgrade.1.asciidoc b/doc/man/pkgctl-version-upgrade.1.asciidoc
index 044545d..02ceff9 100644
--- a/doc/man/pkgctl-version-upgrade.1.asciidoc
+++ b/doc/man/pkgctl-version-upgrade.1.asciidoc
@@ -18,7 +18,7 @@ upstream versions.
 Upon execution, it automatically adjusts the PKGBUILD file, ensuring that the
 pkgver field is set to match the latest version available from the upstream
 source. In addition to updating the pkgver, this command also resets the pkgrel
-to 1.
+to 1 and updates checksums.
 
 Outputs a summary of upgraded packages, up-to-date packages, and any check
 failures.
@@ -35,6 +35,9 @@ PKGBUILD. Refer to the configuration section in pkgctl-version(1).
 Options
 -------
 
+*--no-update-checksums*::
+	Disable computation and update of the checksums
+
 *-v, --verbose*::
 	Display results including up-to-date versions
 
@@ -46,5 +49,6 @@ See Also
 
 pkgctl-version(1)
 nvchecker(1)
+updpkgsums(8)
 
 include::include/footer.asciidoc[]
-- 
cgit v1.2.3-70-g09d2


From 9a5181db5bfa78d33d3123145ea4c84375f2e8f2 Mon Sep 17 00:00:00 2001
From: Levente Polyak <anthraxx@archlinux.org>
Date: Fri, 19 Apr 2024 21:16:06 +0200
Subject: feat(pkgctl): add internal update checksums to better control output

This allows us to have more control over the output and status logs.
Using this method we are able to avoid cluttering the version upgrade
subcommand while downloading sources for updating the checksums.

Having this internally will also allow us in the future to have smart
checksums updating by only trying to change the checksums of sources
that have actually changed, for example when adjusting a patch file we
should avoid trying to overwrite the archive checksums unintentionally.

Component: pkgctl version upgrade
---
 README.md                                 |  1 -
 doc/man/pkgctl-version-upgrade.1.asciidoc |  1 -
 src/lib/build/build.sh                    |  5 ++--
 src/lib/util/makepkg.sh                   | 20 +++++++++++++
 src/lib/util/pkgbuild.sh                  | 50 ++++++++++++++++++++++++++++++-
 src/lib/version/upgrade.sh                | 39 +++++++++++++++++-------
 6 files changed, 101 insertions(+), 15 deletions(-)

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

diff --git a/README.md b/README.md
index 2682aa4..eea9c0a 100644
--- a/README.md
+++ b/README.md
@@ -91,7 +91,6 @@ Component: pkgctl db remove
 
 - bat (pretty printing)
 - nvchecker (version checking)
-- pacman-contrib (--update-checksums and --pkgver=*PKGVER* options for pkgctl build, pkgctl version upgrade)
 
 ### Development Dependencies
 
diff --git a/doc/man/pkgctl-version-upgrade.1.asciidoc b/doc/man/pkgctl-version-upgrade.1.asciidoc
index 02ceff9..0cec0b6 100644
--- a/doc/man/pkgctl-version-upgrade.1.asciidoc
+++ b/doc/man/pkgctl-version-upgrade.1.asciidoc
@@ -49,6 +49,5 @@ See Also
 
 pkgctl-version(1)
 nvchecker(1)
-updpkgsums(8)
 
 include::include/footer.asciidoc[]
diff --git a/src/lib/build/build.sh b/src/lib/build/build.sh
index c35d70f..c3e05be 100644
--- a/src/lib/build/build.sh
+++ b/src/lib/build/build.sh
@@ -437,10 +437,11 @@ pkgctl_build() {
 			stat_done
 		fi
 
-
 		# update checksums if any sources are declared
 		if (( UPDATE_CHECKSUMS )) && (( ${#source[@]} >= 1 )); then
-			updpkgsums
+			if ! result=$(pkgbuild_update_checksums /dev/stderr); then
+				die "${result}"
+			fi
 		fi
 
 		# re-source the PKGBUILD if it changed
diff --git a/src/lib/util/makepkg.sh b/src/lib/util/makepkg.sh
index 22df247..d7ec74c 100644
--- a/src/lib/util/makepkg.sh
+++ b/src/lib/util/makepkg.sh
@@ -22,9 +22,11 @@ makepkg_source_package() {
 		return
 	fi
 	(
+		# shellcheck disable=SC2030 disable=SC2031
 		export LIBMAKEPKG_LINT_PKGBUILD_SH=1
 		lint_pkgbuild() { :; }
 
+		# shellcheck disable=SC2030 disable=SC2031
 		export LIBMAKEPKG_SRCINFO_SH=1
 		write_srcinfo() { print_srcinfo; }
 
@@ -35,3 +37,21 @@ makepkg_source_package() {
 		source "$(command -v makepkg)"
 	)
 }
+
+makepkg_generate_integrity() {
+	if [[ -z ${DEVTOOLS_GENERATE_INTEGRITY} ]]; then
+		[[ -z ${WORKDIR:-} ]] && setup_workdir
+		export WORKDIR DEVTOOLS_INCLUDE_COMMON_SH
+		bash -$- -c "DEVTOOLS_GENERATE_INTEGRITY=1; source '${BASH_SOURCE[0]}' && ${FUNCNAME[0]}"
+		return
+	fi
+	(
+		# shellcheck disable=SC2030 disable=SC2031
+		export LIBMAKEPKG_LINT_PKGBUILD_SH=1
+		lint_pkgbuild() { :; }
+
+		set +e -- --geninteg
+		# shellcheck source=/usr/bin/makepkg
+		source "$(command -v makepkg)"
+	)
+}
diff --git a/src/lib/util/pkgbuild.sh b/src/lib/util/pkgbuild.sh
index ebf8e5f..245a82f 100644
--- a/src/lib/util/pkgbuild.sh
+++ b/src/lib/util/pkgbuild.sh
@@ -6,10 +6,13 @@
 DEVTOOLS_INCLUDE_UTIL_PKGBUILD_SH=1
 
 _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
+# shellcheck source=src/lib/util/makepkg.sh
+source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/makepkg.sh
 
 source /usr/share/makepkg/util/message.sh
+source /usr/share/makepkg/util/schema.sh
 
-set -e
+set -eo pipefail
 
 
 # set the pkgver variable in a PKGBUILD
@@ -41,3 +44,48 @@ pkgbuild_set_pkgrel() {
 	sed --regexp-extended "s|^(pkgrel=)${pkgrel}$|\1${new_pkgrel}|g" --in-place PKGBUILD
 }
 
+pkgbuild_update_checksums() {
+	local status_file=$1
+	local builddir newbuildfile sumtypes newsums
+
+	[[ -z ${WORKDIR:-} ]] && setup_workdir
+
+	builddir=$(mktemp --tmpdir="${WORKDIR}" --directory update-checksums.XXXXXX)
+	newbuildfile="${builddir}/PKGBUILD"
+
+	# generate new integrity checksums
+	if ! newsums=$(BUILDDIR=${builddir} makepkg_generate_integrity 2>"${status_file}"); then
+		printf 'Failed to generate new checksums'
+		return 1
+	fi
+
+	# early exit if no integrity checksums are needed
+	if [[ -z ${newsums} ]]; then
+		return 0
+	fi
+
+	# replace the integrity sums and write it to a temporary file
+	sumtypes=$(IFS='|'; echo "${known_hash_algos[*]}")
+	if ! awk --assign=sumtypes="${sumtypes}" --assign=newsums="${newsums}" '
+		$0 ~"^[[:blank:]]*(" sumtypes ")sums(_[^=]+)?\\+?=", $0 ~ "\\)[[:blank:]]*(#.*)?$" {
+			if (!w) {
+				print newsums
+				w++
+			}
+			next
+		}
+
+		1
+		END { if (!w) print newsums }' PKGBUILD > "${newbuildfile}"; then
+		printf 'Failed to replace the generated checksums'
+		return 1
+	fi
+
+	# overwrite the original PKGBUILD while preserving permissions
+	if ! cat -- "${newbuildfile}" > PKGBUILD; then
+		printf "Failed to write to the PKGBUILD file"
+		return 1
+	fi
+
+	return 0
+}
diff --git a/src/lib/version/upgrade.sh b/src/lib/version/upgrade.sh
index 2885182..c57171c 100644
--- a/src/lib/version/upgrade.sh
+++ b/src/lib/version/upgrade.sh
@@ -115,6 +115,12 @@ pkgctl_version_upgrade() {
 			die "No PKGBUILD found for ${path}"
 		fi
 
+		# reset common PKGBUILD variables
+		unset pkgbase pkgname arch source pkgver pkgrel validpgpkeys
+		# shellcheck source=contrib/makepkg/PKGBUILD.proto
+		. ./PKGBUILD
+		pkgbase=${pkgbase:-$pkgname}
+
 		# update the current terminal spinner status
 		(( ++current_item ))
 		pkgctl_version_upgrade_spinner \
@@ -123,13 +129,9 @@ pkgctl_version_upgrade() {
 			"${#out_of_date[@]}" \
 			"${#failure[@]}" \
 			"${current_item}" \
-			"${#pkgbases[@]}"
-
-		# reset common PKGBUILD variables
-		unset pkgbase pkgname arch source pkgver pkgrel validpgpkeys
-		# shellcheck source=contrib/makepkg/PKGBUILD.proto
-		. ./PKGBUILD
-		pkgbase=${pkgbase:-$pkgname}
+			"${#pkgbases[@]}" \
+			"${pkgbase}" \
+			"query latest version"
 
 		if ! result=$(get_upstream_version); then
 			result="${BOLD}${pkgbase}${ALL_OFF}: ${result}"
@@ -162,7 +164,20 @@ pkgctl_version_upgrade() {
 
 			# download sources and update the checksums
 			if (( update_checksums )); then
-				updpkgsums
+				pkgctl_version_upgrade_spinner \
+					"${status_dir}" \
+					"${#up_to_date[@]}" \
+					"${#out_of_date[@]}" \
+					"${#failure[@]}" \
+					"${current_item}" \
+					"${#pkgbases[@]}" \
+					"${pkgbase}" \
+					"updating checksums"
+
+				if ! result=$(pkgbuild_update_checksums /dev/null); then
+					result="${BOLD}${pkgbase}${ALL_OFF}: failed to update checksums for version ${DARK_GREEN}${upstream_version}${ALL_OFF}"
+					failure+=("${result}")
+				fi
 			fi
 		fi
 
@@ -242,6 +257,8 @@ pkgctl_version_upgrade_spinner() {
 	local failure_count=$4
 	local current=$5
 	local total=$6
+	local pkgbase=$7
+	local message=$8
 
 	local percentage=$(( 100 * current / total ))
 	local tmp_file="${status_dir}/tmp"
@@ -254,8 +271,10 @@ pkgctl_version_upgrade_spinner() {
 		"${failure_count}" > "${tmp_file}"
 
 	# print the progress status
-	printf "📡 Upgrading: %s/%s [%s] %%spinner%%" \
-		"${BOLD}${current}" "${total}" "${percentage}%${ALL_OFF}"  \
+	printf "📡 %s: %s\n" \
+		"${pkgbase}" "${BOLD}${message}${ALL_OFF}" >> "${tmp_file}"
+	printf "⌛ Upgrading: %s/%s [%s] %%spinner%%" \
+		"${BOLD}${current}" "${total}" "${percentage}%${ALL_OFF}" \
 		>> "${tmp_file}"
 
 	# swap the status file
-- 
cgit v1.2.3-70-g09d2

