diff options
author | Levente Polyak <anthraxx@archlinux.org> | 2024-01-13 14:33:09 +0100 |
---|---|---|
committer | Christian Heusel <christian@heusel.eu> | 2024-01-21 23:28:29 +0100 |
commit | 03d5c928cf01e2aee56a4520ac5896c602fb1f75 (patch) | |
tree | a76f2be941bed2ac04ab2f020f6de1c97dc89626 | |
parent | 6054c869e1b9b853aa7408261e477dcb187ff498 (diff) | |
download | devtools-03d5c928cf01e2aee56a4520ac5896c602fb1f75.tar.xz |
fix(version): add error handling to version check subcommand
Add defensive programming to the execution chain of the version check
subcommand for graceful error handling of subprocesses as well as errors
returned from nvchecker itself indicated in the returned JSON.
Furthermore this fixes a bug when processing multiple packages where the
pkgbase variable is stuck for subsequent packages that do not declare a
pkgbase variable itself.
Component: pkgctl version check
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
-rw-r--r-- | src/lib/version/check.sh | 107 |
1 files changed, 93 insertions, 14 deletions
diff --git a/src/lib/version/check.sh b/src/lib/version/check.sh index b93752a..c78e364 100644 --- a/src/lib/version/check.sh +++ b/src/lib/version/check.sh @@ -11,7 +11,7 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh source /usr/share/makepkg/util/message.sh -set -e +set -eo pipefail pkgctl_version_check_usage() { local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}} @@ -34,8 +34,7 @@ _EOF_ pkgctl_version_check() { local path local pkgbases=() - local path pkgbase upstream_version - + local path pkgbase upstream_version result while (( $# )); do case $1 in @@ -78,15 +77,28 @@ pkgctl_version_check() { die "No PKGBUILD found for ${path}" fi - # shellcheck disable=SC2119 - upstream_version=$(get_upstream_version) - - # TODO: parse .SRCINFO file + # reset common PKGBUILD variables + unset pkgbase pkgname arch source pkgver pkgrel validpgpkeys # shellcheck source=contrib/makepkg/PKGBUILD.proto . ./PKGBUILD pkgbase=${pkgbase:-$pkgname} - if (( $(vercmp "${upstream_version}" "${pkgver}") > 0 )); then + if ! result=$(get_upstream_version); then + msg_error "${pkgbase}: ${result}" + popd >/dev/null + continue + fi + upstream_version=${result} + + if ! result=$(vercmp "${upstream_version}" "${pkgver}"); then + result="${BOLD}${pkgbase}${ALL_OFF}: failed to compare version ${upstream_version} against ${pkgver}" + msg_error "${result}" + + popd >/dev/null + continue + fi + + if (( result > 0 )); then msg2 "New ${pkgbase} version ${upstream_version} is available upstream" fi @@ -95,13 +107,80 @@ pkgctl_version_check() { } get_upstream_version() { - local config=${1:-.nvchecker.toml} - local upstream_version + local config=.nvchecker.toml + local output errors upstream_version + local output + + # check nvchecker config file + if ! errors=$(nvchecker_check_config "${config}"); then + printf "%s" "${errors}" + return 1 + fi + + if ! output=$(nvchecker --file "${config}" --logger json 2>&1 | \ + jq --raw-output 'select(.level != "debug")'); then + printf "failed to run nvchecker: %s" "${output}" + return 1 + fi + + if ! errors=$(nvchecker_check_error "${output}"); then + printf "%s" "${errors}" + return 1 + fi + + if ! upstream_version=$(jq --raw-output --exit-status '.version' <<< "${output}"); then + printf "failed to select version from result" + return 1 + fi + + printf "%s" "${upstream_version}" + return 0 +} + +nvchecker_check_config() { + local config=$1 + + local restricted_properties=(keyfile httptoken token) + local property + + # check if the config file exists + if [[ ! -f ${config} ]]; then + printf "configuration file not found: %s" "${config}" + return 1 + fi + + # check if config contains any restricted properties like secrets + for property in "${restricted_properties[@]}"; do + if grep --max-count=1 --quiet "^${property}" < "${config}"; then + printf "restricted property in %s: %s" "${config}" "${property}" + return 1 + fi + done + + # check if the config contains a pkgbase section + if [[ -n ${pkgbase} ]] && ! grep --max-count=1 --quiet "^\\[${pkgbase}\\]" < "${config}"; then + printf "missing pkgbase section in %s: %s" "${config}" "${pkgbase}" + return 1 + fi + + # check if the config contains any section other than pkgbase + if [[ -n ${pkgbase} ]] && property=$(grep --max-count=1 --perl-regexp "^\\[(?!${pkgbase}\\]).+\\]" < "${config}"); then + printf "none pkgbase section not supported in %s: %s" "${config}" "${property}" + return 1 + fi +} + +nvchecker_check_error() { + local result=$1 + local errors - if [[ ! -f $config ]]; then - die "No $config found" + if ! errors=$(jq --raw-output --exit-status \ + 'select(.level == "error") | "\(.event)" + if .error then ": \(.error)" else "" end' \ + <<< "${result}"); then + return 0 fi - upstream_version=$(nvchecker -c "$config" --logger json | jq --raw-output 'select( .version ) | .version') - printf "%s" "$upstream_version" + mapfile -t errors <<< "${errors}" + printf "%s\n" "${errors[@]}" + return 1 } |