Arcadelux update script added.
This commit is contained in:
1 parent
82edcc66b8
commit
fd72a85003
5 files changed
+193
-4
No files matched your search
@@ -251,3 +251,166 @@ install_with_progress() {
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Return the latest GitHub release tag and one matching asset URL, one per line.
|
||||
github_latest_release() {
|
||||
local repo="$1"
|
||||
local assetFilter="$2"
|
||||
local response tag
|
||||
local -a assetUrls=()
|
||||
|
||||
if [[ -z "$repo" || "$repo" != */* ]]; then
|
||||
echo "Expected a GitHub repository in owner/repo format." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! response="$(curl -fsSL --retry 3 "https://api.github.com/repos/${repo}/releases/latest")"; then
|
||||
echo "Could not fetch the latest release for ${repo}." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
tag="$(sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' <<< "$response" | head -n1)"
|
||||
mapfile -t assetUrls < <(
|
||||
sed -n 's/.*"browser_download_url"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' <<< "$response"
|
||||
)
|
||||
if [[ -n "$assetFilter" ]]; then
|
||||
mapfile -t assetUrls < <(
|
||||
printf '%s\n' "${assetUrls[@]}" | grep -iF -- "$assetFilter"
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ -z "$tag" || ${#assetUrls[@]} -ne 1 ]]; then
|
||||
echo "Could not identify one matching release asset for ${repo}." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s\n%s\n' "$tag" "${assetUrls[0]}"
|
||||
}
|
||||
|
||||
# Install or replace a game from its latest GitHub release.
|
||||
# Arguments: repository, asset filter, destination, expected executable, and
|
||||
# zero or more relative paths or files to preserve from the old installation.
|
||||
update_github_release_game() {
|
||||
local repo="$1"
|
||||
local assetFilter="$2"
|
||||
local destination="$3"
|
||||
local expectedExecutable="$4"
|
||||
shift 4
|
||||
local -a preservePaths=("$@")
|
||||
local -a releaseInfo=() executablePaths=() pathParts=()
|
||||
local releaseInfoText installedVersion latestTag latestUrl archiveFile
|
||||
local stageRoot archiveRoot newRoot executablePath preservePath sourcePath targetPath pathPart
|
||||
local updateFailed="false"
|
||||
|
||||
githubReleaseGameStatus="checking"
|
||||
destination="${destination%/}"
|
||||
if [[ -z "$destination" || "$destination" != /* ]]; then
|
||||
echo "The game destination must be an absolute path." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
for preservePath in "${preservePaths[@]}"; do
|
||||
if [[ "$preservePath" == /* ]]; then
|
||||
echo "Preserve paths must be relative to the game directory: ${preservePath}" >&2
|
||||
return 1
|
||||
fi
|
||||
IFS='/' read -r -a pathParts <<< "$preservePath"
|
||||
for pathPart in "${pathParts[@]}"; do
|
||||
if [[ -z "$pathPart" || "$pathPart" == "." || "$pathPart" == ".." ]]; then
|
||||
echo "Invalid preserve path: ${preservePath}" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if ! releaseInfoText="$(github_latest_release "$repo" "$assetFilter")"; then
|
||||
return 1
|
||||
fi
|
||||
mapfile -t releaseInfo <<< "$releaseInfoText"
|
||||
latestTag="${releaseInfo[0]}"
|
||||
latestUrl="${releaseInfo[1]}"
|
||||
|
||||
if [[ -f "${destination}/.agm-version" ]]; then
|
||||
installedVersion="$(<"${destination}/.agm-version")"
|
||||
if [[ "$installedVersion" == "$latestTag" && -f "${destination}/${expectedExecutable}" ]]; then
|
||||
githubReleaseGameStatus="up-to-date"
|
||||
echo "${game:-The game} is already at ${latestTag}."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
archiveFile="${latestUrl##*/}"
|
||||
archiveFile="${archiveFile//%20/ }"
|
||||
archiveFile="${archiveFile#*\?filename=}"
|
||||
archiveFile="${archiveFile%\?*}"
|
||||
rm -f "${cache}/${archiveFile}"
|
||||
download "$latestUrl"
|
||||
|
||||
mkdir -p "$(dirname "$destination")"
|
||||
stageRoot="${destination}.agm-update.$$"
|
||||
archiveRoot="${stageRoot}/archive"
|
||||
mkdir -p "$archiveRoot"
|
||||
|
||||
if ! unzip -q "${cache}/${archiveFile}" -d "$archiveRoot"; then
|
||||
echo "Could not extract ${archiveFile}." >&2
|
||||
rm -rf "$stageRoot"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mapfile -t executablePaths < <(find "$archiveRoot" -type f -name "$expectedExecutable" -print)
|
||||
if [[ ${#executablePaths[@]} -ne 1 ]]; then
|
||||
echo "The release did not contain exactly one ${expectedExecutable}." >&2
|
||||
rm -rf "$stageRoot"
|
||||
return 1
|
||||
fi
|
||||
executablePath="${executablePaths[0]}"
|
||||
newRoot="${executablePath%/*}"
|
||||
|
||||
for preservePath in "${preservePaths[@]}"; do
|
||||
sourcePath="${destination}/${preservePath}"
|
||||
[[ -e "$sourcePath" ]] || continue
|
||||
targetPath="${newRoot}/${preservePath}"
|
||||
if [[ -d "$sourcePath" ]]; then
|
||||
mkdir -p "$targetPath"
|
||||
if ! cp -a "${sourcePath}/." "$targetPath/"; then
|
||||
echo "Could not preserve ${preservePath}." >&2
|
||||
updateFailed="true"
|
||||
break
|
||||
fi
|
||||
else
|
||||
mkdir -p "${targetPath%/*}"
|
||||
if ! cp -a "$sourcePath" "$targetPath"; then
|
||||
echo "Could not preserve ${preservePath}." >&2
|
||||
updateFailed="true"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$updateFailed" == "true" ]]; then
|
||||
rm -rf "$stageRoot"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$latestTag" > "${newRoot}/.agm-version"
|
||||
if [[ -e "$destination" ]]; then
|
||||
if ! mv "$destination" "${stageRoot}/old"; then
|
||||
echo "Could not move the old installation aside." >&2
|
||||
rm -rf "$stageRoot"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! mv "$newRoot" "$destination"; then
|
||||
echo "Could not install the new version." >&2
|
||||
if [[ -e "${stageRoot}/old" ]]; then
|
||||
mv "${stageRoot}/old" "$destination"
|
||||
fi
|
||||
rm -rf "$stageRoot"
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -rf "$stageRoot"
|
||||
githubReleaseGameStatus="updated"
|
||||
echo "${game:-The game} has been updated to ${latestTag}."
|
||||
}
|
||||
Reference in new issue
Block a user