diff --git a/src/scripts/tools/add_tools.ps1 b/src/scripts/tools/add_tools.ps1 index 6212c778..fa4bd759 100644 --- a/src/scripts/tools/add_tools.ps1 +++ b/src/scripts/tools/add_tools.ps1 @@ -237,6 +237,26 @@ Function Add-ToolsHelper() { } } +# Function to find the newest stable release containing a tool asset. +Function Get-LastRelease($url) { + $releases_url = $url.Split('/latest/download/')[0] + $asset = $url.Split('/')[-1] + $page = 1 + do { + $releases = (Get-File -Url "${releases_url}?page=$page&q=prerelease%3Afalse").Content + foreach ($match in [regex]::Matches($releases, 'src="([^"]+/releases/expanded_assets/[^"]+)"')) { + $assets_url = $match.Groups[1].Value + if (-not $assets_url.StartsWith("$releases_url/expanded_assets/")) { continue } + $download_path = $assets_url.Substring('https://github.com'.Length).Replace('/expanded_assets/', '/download/') + "/$asset" + $assets = (Get-File -Url $assets_url).Content + if ($assets.Contains("href=`"$download_path`"")) { + return "https://github.com$download_path" + } + } + $page++ + } while ($releases.Contains('class="next_page"')) +} + # Function to add tools. Function Add-Tool() { Param ( @@ -288,15 +308,17 @@ Function Add-Tool() { try { $status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode } catch { - if($url -match '.*github.com.*releases.*latest.*') { + $status_code = 0 + if($url -match '^https://github\.com/[^/]+/[^/]+/releases/latest/download/[^/?#]+$') { try { - $url = $url.replace("releases/latest/download", "releases/download/" + ([regex]::match((Get-File -Url ($url.split('/release')[0] + "/releases")).Content, "([0-9]+\.[0-9]+\.[0-9]+)/" + ($url.Substring($url.LastIndexOf("/") + 1))).Groups[0].Value).split('/')[0]) - $status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode + $release_url = Get-LastRelease $url + if ($release_url) { + $url = $release_url + $status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode + } } catch { $status_code = 0 } - } else { - $status_code = 0 } } if($status_code -eq 200 -and (Test-Path $tool_path)) { diff --git a/src/scripts/tools/add_tools.sh b/src/scripts/tools/add_tools.sh index f2289f50..7939897f 100644 --- a/src/scripts/tools/add_tools.sh +++ b/src/scripts/tools/add_tools.sh @@ -203,6 +203,27 @@ add_tools_helper() { done } +# Function to find the newest stable release containing a tool asset. +get_last_release() { + local releases_url="${1%/latest/download/*}" + local asset="${1##*/}" + local page=1 releases assets_url tag download_path + while true; do + releases=$(get -s -n "" "$releases_url?page=$page&q=prerelease%3Afalse") || return 1 + while IFS= read -r assets_url; do + [[ "$assets_url" = "$releases_url/expanded_assets/"* ]] || continue + tag="${assets_url#"$releases_url/expanded_assets/"}" + download_path="${releases_url#https://github.com}/download/$tag/$asset" + if get -s -n "" "$assets_url" | grep -Fq "href=\"$download_path\""; then + printf 'https://github.com%s\n' "$download_path" + return 0 + fi + done <<< "$(printf '%s' "$releases" | grep -Eo 'src="[^"]+/releases/expanded_assets/[^"]+"' | cut -d '"' -f 2)" + [[ "$releases" = *'class="next_page"'* ]] || return 1 + page=$((page + 1)) + done +} + # Function to setup a remote tool. add_tool() { url=$1 @@ -243,9 +264,12 @@ add_tool() { else [ -f "$tool_path" ] && sudo cp -a "$tool_path" "$tool_path.bak" status_code=$(get -v -e "$tool_path" "${url[@]}") - if [ "$status_code" != "200" ] && [[ "${url[0]}" =~ .*github.com.*releases.*latest.* ]]; then - url[0]="${url[0]//releases\/latest\/download/releases/download/$(get -s -n "" "$(echo "${url[0]}" | cut -d '/' -f '1-5')/releases" | grep -Eo -m 1 "([0-9]+\.[0-9]+\.[0-9]+)/$(echo "${url[0]}" | sed -e "s/.*\///")" | cut -d '/' -f 1)}" - status_code=$(get -v -e "$tool_path" "${url[0]}") + if [ "$status_code" != "200" ] && [[ "${url[0]}" =~ ^https://github\.com/[^/]+/[^/]+/releases/latest/download/[^/?#]+$ ]]; then + local release_url + if release_url=$(get_last_release "${url[0]}"); then + url[0]="$release_url" + status_code=$(get -v -e "$tool_path" "${url[0]}") + fi fi if [ "$status_code" = "200" ]; then if [ -n "$checksum" ] && ! verify_checksum "$tool_path" "$checksum"; then