Files
eos-pkgbuild-setup/delete-release-assets
2023-08-16 14:27:35 +03:00

253 lines
7.8 KiB
Bash
Executable File

#!/bin/bash
RELEASE_ASSETS_VERBOSE=yes
echo2() {
echo "$@" >&2
}
verbose() {
case "$RELEASE_ASSETS_VERBOSE" in
1|yes) echo2 "$@" ;;
esac
}
Usage() {
echo2 "Usage: $(basename "$0") [--quietly] TAG asset-names"
echo2 "where"
echo2 " TAG release tag"
echo2 " asset-names one or more asset names (without path) separated by space"
echo2 " --quietly don't ask confirmation for deletions"
}
DIE() {
local msg="$1"
local file_to_delete="$2" # optional file to delete
test -n "$file_to_delete" && rm -f "$file_to_delete"
echo2 "ERROR: $msg"
Usage
exit 1
}
WARN() {
local msg="$1"
echo2 "Warning: $msg"
}
Info() {
local msg="$1"
verbose "Info: $msg"
}
Prompt() { # prompt if a prompt value is given, no newline at end
local prompt="$1"
test -n "$prompt" && echo2 -n "$prompt: "
}
Promptln() { # prompt if a prompt value is given, newline at end
local prompt="$1"
test -n "$prompt" && echo2 "$prompt:"
}
GetValueFromPipe() { # return the value from pipe's output, second token
awk '{print $2}' | sed -e 's|^"||' -e 's|",$||' -e 's|,$||'
}
GetValueFromPipeAndIndent() { # return the value from pipe's output, second token and indented by four spaces
awk '{print $2}' | sed -e 's|^"| |' -e 's|",$||' -e 's|,$||'
}
GetAssetNamesFromFile() {
local file="$1"
local prompt_optional="$2"
Promptln "$prompt_optional"
grep '^ "name":' "$file" | GetValueFromPipeAndIndent
}
GetReleaseIdFromFile() {
local file="$1"
local prompt_optional="$2"
Prompt "$prompt_optional"
grep '^ "id":' "$1" | GetValueFromPipe
}
GetTagNamesFromFile() {
local file="$1"
local prompt_optional="$2"
Promptln "$prompt_optional"
grep '^ "tag_name":' "$1" | GetValueFromPipeAndIndent
}
GetAssetIdFromFile() {
local file="$1"
local assetname="$2"
local prompt_optional="$3" # optional
Prompt "$prompt_optional"
grep -B2 "\"$assetname\"," "$file" | grep '"id":' | GetValueFromPipe
}
declare -A GITHUB_INFO
PrepareGithubInfo() { # put some useful values to GITHUB_INFO
local reponame="$1"
local tag="$2"
if [ -n "$reponame" ] ; then
GITHUB_INFO["reponame"]="$reponame"
else
test -r .git/config || { echo2 "Need repo name but cannot find .git/config under the working folder $PWD." ; return 1 ; }
GITHUB_INFO["reponame"]="$(basename $(grep "https://github.com" .git/config 2>/dev/null | awk '{print $3}') .git)"
test -n "${GITHUB_INFO["reponame"]}" || { echo2 "Repo name is not available." ; return 1 ; }
fi
if [ -n "$tag" ] ; then
GITHUB_INFO["tag"]="$tag"
else
GITHUB_INFO["tag"]="LATEST"
fi
test -r ~/.config/hub || { echo2 "cannot find ~/.config/hub, is 'hub' installed and initialized?" ; return 1 ; }
#GITHUB_INFO["owner"]="$(grep "user:" ~/.config/hub | awk '{print $NF}')"
GITHUB_INFO["owner"]="$(grep "https://github.com" .git/config | awk '{print $NF}' | sed -e 's|^https://github.com/||' -e 's|/.*$||')"
test -n "${GITHUB_INFO["owner"]}" || { echo2 "Owner info is not available." ; return 1 ; }
GITHUB_INFO["oauth_token"]="$(grep "oauth_token:" ~/.config/hub | awk '{print $NF}')"
test -n "${GITHUB_INFO["oauth_token"]}" || { echo2 "Github API token is not available." ; return 1 ; }
}
GetReleaseInfoToFile()
{
local asset_info_file="$1"
local tag="$2"
local reponame="$3"
local owner
local oauth_token
PrepareGithubInfo "$reponame" "$tag" || DIE "PrepareGithubInfo() failed." "$asset_info_file"
tag="${GITHUB_INFO["tag"]}"
reponame="${GITHUB_INFO["reponame"]}"
owner="${GITHUB_INFO["owner"]}"
oauth_token="${GITHUB_INFO["oauth_token"]}"
local GH_REPO="https://api.github.com/repos/$owner/$reponame"
local GH_TAG="$GH_REPO/releases/tags/$tag"
local AUTH="Authorization: token $oauth_token"
test "$tag" = "LATEST" && GH_TAG="$GH_REPO/releases/latest"
if [ "$(stat -c %s "$asset_info_file")" = "0" ] ; then
#Info "Fetching github info..."
# Validate token.
curl -o /dev/null -sH "$AUTH" $GH_REPO || DIE "Invalid repo, token or network issue!" "$asset_info_file"
# Read asset info into the file.
curl -sH "$AUTH" $GH_TAG > $asset_info_file || DIE "failed to fetch assets info from '$GH_TAG'."
fi
}
DeleteAsset()
{
local asset_info_file="$1"
local asset_name="$2"
local quietly="$3" # if yes, then no questions are asked about deletion
local asset_id="$(GetAssetIdFromFile "$asset_info_file" "$asset_name")"
#local repo="${GITHUB_INFO["reponame"]}"
#local owner="${GITHUB_INFO["owner"]}"
#local oauth_token="${GITHUB_INFO["oauth_token"]}"
local answer
if [ "$asset_id" = "" ]; then
WARN "asset id not found for '$asset_name'."
return 1
fi
case "$quietly" in
no)
# Final chance to prevent deleting ...
read -p "Delete asset '$asset_name' (Y/n)? " answer
case "$answer" in
y|Y|"") ;;
*) return ;;
esac
;;
yes)
echo "deleting asset $asset_name ..."
;;
esac
hub api -t -X "DELETE" "https://api.github.com/repos/{owner}/{repo}/releases/assets/$asset_id"
# local GITHUB_OAUTH_BASIC="" # ??
# curl $GITHUB_OAUTH_BASIC -X "DELETE" -H "Authorization: token $oauth_token" \
# "https://api.github.com/repos/$owner/$repo/releases/assets/$asset_id"
}
Main() # parameters: [--quietly] TAG assetname...
{
local xx
local quietly=no
local shifts=0
for xx in "$@" ; do
case "$xx" in
--quietly) quietly=yes ; ((shifts++)) ;;
esac
done
shift $shifts
local tag="$1"
shift # other parameters are asset names, i.e. file names without any path
local github_asset
local asset
local asset_info_file
local matched_assets=()
# Note: asset names can also be shortened, e.g. "yay-" or "downgrad".
# Then all assets starting with that name are deleted, so be careful.
test -n "$tag" || DIE "TAG is missing."
test -n "$1" || DIE "Assets are missing."
asset_info_file=$(mktemp)
GetReleaseInfoToFile "$asset_info_file" "$tag" # repo
# Check that the given tag exists.
for xx in $(GetTagNamesFromFile "$asset_info_file") ; do
test "$tag" = "$xx" && break
done
test "$tag" = "$xx" || DIE "TAG '$tag' does not exist (find with 'hub release')." "$asset_info_file"
# Match given assets to github assets.
local github_assets="$(GetAssetNamesFromFile "$asset_info_file")"
local delete_all=no
case "$delete_all" in
yes)
for github_asset in $github_assets ; do
matched_assets+=("$github_asset")
done
;;
no)
for asset in "$@" ; do
for github_asset in $github_assets ; do
case "$github_asset" in
${asset}*)
for xx in "${matched_assets[@]}" ; do
test "$xx" = "$github_asset" && break
done
if [ "$xx" != "$github_asset" ] ; then
matched_assets+=("$github_asset")
fi
;;
esac
done
test -n "$matched_assets" || DIE "Asset '$asset' does not match to any asset at github." "$asset_info_file"
done
;;
esac
# Now delete given assets from github.
for asset in "${matched_assets[@]}" ; do
DeleteAsset "$asset_info_file" "$asset" "$quietly" || DIE "Failed to delete asset '$asset'." "$asset_info_file"
#sleep 0.5
done
rm -f "$asset_info_file" # file no more needed
}
Main "$@" # tag asset(s)