diff --git a/.github/workflows/verify-split-files.yml b/.github/workflows/verify-split-files.yml index 361c586..9823dca 100644 --- a/.github/workflows/verify-split-files.yml +++ b/.github/workflows/verify-split-files.yml @@ -70,6 +70,7 @@ on: - "tests/vm-dialog-esc.sh" - "tests/forge-clean-install.sh" - "tests/db-helper-context.sh" + - "tests/forge-tag-spelling.sh" - "tests/cs-clear.sh" - "tests/forge-appversion-scope.sh" - "tests/forge-singlefile-compressed.sh" @@ -139,6 +140,7 @@ on: - "tests/vm-dialog-esc.sh" - "tests/forge-clean-install.sh" - "tests/db-helper-context.sh" + - "tests/forge-tag-spelling.sh" - "tests/cs-clear.sh" - "tests/forge-appversion-scope.sh" - "tests/forge-singlefile-compressed.sh" @@ -297,6 +299,8 @@ jobs: run: bash tests/forge-clean-install.sh - name: Database helpers outside an install tests run: bash tests/db-helper-context.sh + - name: Pinned tag with or without its v tests + run: bash tests/forge-tag-spelling.sh - name: Screen clear without a terminal tests run: bash tests/cs-clear.sh - name: App version pin and .deb stamp tests diff --git a/lib/forge.func b/lib/forge.func index 6f6a67e..2cdcbff 100644 --- a/lib/forge.func +++ b/lib/forge.func @@ -1699,7 +1699,7 @@ _forge_release_json() { fi local -a timeouts=(60 120 240) - local raw attempt=1 delay=2 code ok=false curl_rc + local raw attempt=1 delay=2 code ok=false curl_rc other_spelling="" raw="$(mktemp /tmp/tools-forge-rel-XXXXXX)" || return 73 [[ "$forge" == "github" ]] && _github_token_from_vars @@ -1787,6 +1787,15 @@ _forge_release_json() { return 22 fi + # Ask once for the other spelling of the pinned tag, with or without the v. + if [[ "$single" == "true" && "$code" == "404" ]]; then + [[ -n "$other_spelling" ]] && break + other_spelling="v${version}" + [[ "$version" == v* ]] && other_spelling="${version#v}" + api_url="${base}/${repo_path}${one}/${other_spelling//\//%2F}" + continue + fi + attempt=$((attempt + 1)) done diff --git a/tests/forge-tag-spelling.sh b/tests/forge-tag-spelling.sh new file mode 100644 index 0000000..6ec3260 --- /dev/null +++ b/tests/forge-tag-spelling.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -uo pipefail + +CORE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" +eval "$(sed -n '/^_FORGE_JQ_VKEY_DEF=/,/^_FORGE_JQ_VKEY=/p' "$CORE_DIR/lib/forge.func")" +eval "$(awk '/^_forge_(descriptor|curl|designated_release|stable_filter|keep_raw|release_json|explain_failure|require_jq)[(][)] [{]/,/^}/' "$CORE_DIR/lib/forge.func")" + +TEST_DIR="$(mktemp -d)" +trap 'rm -rf -- "$TEST_DIR" "${TOOLS_GH_REL_JSON:-}"' EXIT +CALLS="$TEST_DIR/calls" +LOG="$TEST_DIR/log" +OUT="$TEST_DIR/out" +passed=0 failed=0 + +msg_info() { :; } +msg_ok() { :; } +msg_warn() { echo "warn: $*" >>"$LOG"; } +msg_error() { echo "error: $*" >>"$LOG"; } +getent() { return 0; } +sleep() { :; } +_github_release_noapi() { return 1; } +ensure_dependencies() { :; } +curl() { + local out="" url="" i tag + local -a args=("$@") + for ((i = 0; i < ${#args[@]}; i++)); do + case "${args[$i]}" in + -o) out="${args[$((i + 1))]}" ;; + https://*) url="${args[$i]}" ;; + esac + done + echo "$url" >>"$CALLS" + tag="${url##*/}" + if [[ " $TAGS " == *" $tag "* ]]; then + printf '{"tag_name":"%s"}' "$tag" >"$out" + printf '200' + else + printf '{"message":"Not Found"}' >"$out" + printf '404' + fi +} + +check() { + if [[ "$3" == "$2" ]]; then + echo "PASS $1" + passed=$((passed + 1)) + else + echo "FAIL $1: expected <$2>, got <$3>" >&2 + sed 's/^/ /' "$CALLS" "$LOG" >&2 2>/dev/null + failed=$((failed + 1)) + fi +} +lookup() { + : >"$CALLS" + : >"$LOG" + : >"$OUT" + local rc=0 + _forge_release_json github owner/app "$1" "" "$OUT" >/dev/null 2>&1 || rc=$? + printf '%s %s' "$rc" "$(jq -r '.tag_name // empty' "$OUT" 2>/dev/null | tr -d '\r')" +} + +TAGS="v0.35.11" +check "pin without v finds the v tag" "0 v0.35.11" "$(lookup 0.35.11)" +check "and asks twice, not more" "2" "$(wc -l <"$CALLS" | tr -d ' ')" +check "pin with v still direct" "0 v0.35.11" "$(lookup v0.35.11)" +check "a direct hit asks once" "1" "$(wc -l <"$CALLS" | tr -d ' ')" + +TAGS="12.4" +check "pin with v finds the plain tag" "0 12.4" "$(lookup v12.4)" + +TAGS="v1.0.0" +check "a tag missing both ways fails" "22 " "$(lookup 9.9.9)" +check "without retrying the 404" "2" "$(wc -l <"$CALLS" | tr -d ' ')" +check "and names the HTTP code" "1" "$(grep -c 'HTTP 404' "$LOG")" + +echo "${passed} passed, ${failed} failed" +[[ "$failed" -eq 0 ]]