From 442174ca9ad08119a7026cef1ea66cefd82e4021 Mon Sep 17 00:00:00 2001 From: Aditya Alok Date: Sat, 2 Apr 2022 16:18:00 +0530 Subject: [PATCH] refactor(auto-update): move checking unique packages to standalone script Hmmm..., why do we even need to check whether package is unique or not if we have TERMUX_PKG_AUTO_UPDATE=true? It should be checked before enabling auto-update. Signed-off-by: Aditya Alok --- scripts/bin/check-auto-update | 235 ++++++++++++++++++++++++++++++++++ scripts/bin/update-packages | 37 ------ 2 files changed, 235 insertions(+), 37 deletions(-) create mode 100755 scripts/bin/check-auto-update diff --git a/scripts/bin/check-auto-update b/scripts/bin/check-auto-update new file mode 100755 index 000000000..e0bd0f874 --- /dev/null +++ b/scripts/bin/check-auto-update @@ -0,0 +1,235 @@ +#!/bin/bash + +# This script is used to check if given package can be auto-updated and optionally enable if it can be. +# NOTE: You should not trust this script if package uses commit hashes for versioning(eg. 'tsu') or +# TERMUX_PKG_VERSION is defined by us and not upstream(i.e we use some arbitrary version. For eg. when only +# getting source files based on commit hash). + +# The MIT License (MIT) + +# Copyright (c) 2022 Aditya Alok + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +set -e + +TERMUX_SCRIPTDIR="$(realpath "$(dirname "$(readlink -f "$0")")/../..")" +declare -a UNIQUE_PACKAGES + +_RESET_COLOR="\033[0m" +_BLUE="\033[1;34m" +_GREEN="\033[0;32m" +_RED="\033[0;31m" +_YELLOW="\033[0;33m" +_TEAL="\033[0;36m" + +warn() { + [[ "${SILENT}" == "true" ]] && return + local warn_color="\033[1;33m" + echo -e "${_BLUE}[${warn_color}*${_BLUE}]${_YELLOW} $*${_RESET_COLOR}" >&2 +} + +error() { + [[ "${SILENT}" == "true" ]] && exit 1 + local error_color="\033[1;31m" + echo -e "${_BLUE}[${error_color}!${_BLUE}]${_RED} $*${_RESET_COLOR}" >&2 + exit 1 +} + +info() { + [[ "${SILENT}" == "true" ]] && return + local info_color="\033[1;32m" + echo -e "${_BLUE}[${info_color}+${_BLUE}]${_TEAL} $*${_RESET_COLOR}" +} + +usage() { + echo -e "${_BLUE}Usage:${_RESET_COLOR} $(basename "$0")" \ + "${_GREEN}[-h|--help]${_RESET_COLOR}" \ + "${_GREEN}[-s|--silent]${_RESET_COLOR}" \ + "${_GREEN}[--enable]${_RESET_COLOR}" \ + "${_GREEN}PACKAGE [PACKAGE...]${_RESET_COLOR}" + echo + echo -e "${_TEAL}Check if packages can be auto-updated and optionally enable if so.${_RESET_COLOR}" + echo + echo -e "${_RED}NOTE: ${_YELLOW}You should not trust this script if\n" \ + "\t${_BLUE}- ${_YELLOW}package uses commit hashes for versioning (eg. 'tsu') or\n" \ + "\t${_BLUE}- ${_GREEN}TERMUX_PKG_VERSION ${_YELLOW}is defined by us and not upstream, i.e we use some arbitrary version.\n" \ + "\t For eg. when only getting source files based on commit hash." + echo + echo -e "${_BLUE}Options:${_RESET_COLOR}" + echo -e "${_GREEN}-h --help${_TEAL} Show this help message.${_RESET_COLOR}" + echo -e "${_GREEN}--enable${_TEAL} Enable auto-updates for packages if it can be." \ + "Writes ${_YELLOW}TERMUX_PKG_AUTO_UPDATE=true${_TEAL} to build.sh${_RESET_COLOR}" +} + +can_be_updated_from_github() { + local url="$1" + if grep -Eq "^https?://github.com" <<<"$url"; then + local stderr + stderr="$( + set -euo pipefail + . "${TERMUX_SCRIPTDIR}/scripts/updates/api/termux_github_api_get_tag.sh" + . "${TERMUX_SCRIPTDIR}/scripts/updates/utils/termux_error_exit.sh" + termux_github_api_get_tag "$url" 2>&1 >/dev/null + )" || { + if grep -q "HTTP code:" <<<"${stderr}"; then + local http_code + http_code="$(grep "HTTP code:" <<<"${stderr}" | cut -d ':' -f 2 | tr -d ' ')" + if [[ "$http_code" == "000" ]]; then + error "Could not connect to GitHub API. Please check your internet connection." + fi + warn "Failed to get tag from github api [HTTP code: $http_code]." + return 1 + elif grep -q "ERROR:" <<<"${stderr}"; then + error "$(grep "ERROR:" <<<"${stderr}" | cut -d ':' -f 2 | sed 's/^[[:space:]]*//')" + return 1 + fi + } + return 0 + else + warn "Not a github url: $url" + return 1 + fi +} + +can_be_updated_from_gitlab() { + local url="$1" + if grep -Eq "^https?://gitlab.com" <<<"$url"; then + stderr="$( + set -euo pipefail + . "${TERMUX_SCRIPTDIR}/scripts/updates/api/termux_gitlab_api_get_tag.sh" + . "${TERMUX_SCRIPTDIR}/scripts/updates/utils/termux_error_exit.sh" + termux_gitlab_api_get_tag "$url" 2>&1 >/dev/null + )" || { + if grep -q "HTTP code:" <<<"${stderr}"; then + local http_code + http_code="$(grep "HTTP code:" <<<"${stderr}" | cut -d ':' -f 2 | tr -d ' ')" + if [[ "$http_code" == "000" ]]; then + error "Could not connect to GitLab API. Please check your internet connection." + fi + warn "Failed to get tag from gitlab api [HTTP code: $http_code]." + return 1 + elif grep -q "ERROR:" <<<"${stderr}"; then + warn "$(grep "ERROR:" <<<"${stderr}" | cut -d ':' -f 2 | sed 's/^[[:space:]]*//')" + return 1 + fi + } + return 0 + else + warn "Not a gitlab url: $url" + return 1 + fi +} + +is_unique_package() { + local package="$1" + if [[ -z "${UNIQUE_PACKAGES[1]}" ]]; then + # NOTE: mapfile requires bash 4+ + mapfile -t UNIQUE_PACKAGES < <( + curl --silent --location --retry 5 --retry-delay 5 --retry-max-time 60 \ + "https://repology.org/api/v1/projects/?inrepo=termux&&repos=1" | + jq -r 'keys[]' + ) + + [[ -z "${UNIQUE_PACKAGES[1]}" ]] && error "Failed to get unique packages from repology.org" + fi + # shellcheck disable=SC2076 + if [[ ! " ${UNIQUE_PACKAGES[*]} " =~ " ${package} " ]]; then + return 0 # Package is not unique, hence can be updated. + else + error "Package '$package' is unique, hence cannot be auto-updated." + fi +} + +write_to_first_empty_line() { + local -r file="$1" + local -r line="$2" + + if ! grep -q "^$line$" "$file"; then + # Find first empty line from top of file: + local -r first_empty_line=$(sed -n '/^$/=' "$file" | head -n 1) + sed -i "${first_empty_line}i$line" "$file" + else + warn "$line already exists in $(basename "$file"). Skipping." + fi +} + +check() { + PKG_NAME="$1" + [[ "${SILENT}" == "true" ]] || echo -e "${_BLUE}==>${_YELLOW} ${PKG_NAME}${_RESET_COLOR}" + SRC_URL="$( + # shellcheck source=/dev/null + . "${TERMUX_SCRIPTDIR}"/packages/"${PKG_NAME}"/build.sh >/dev/null 2>&1 + echo "${TERMUX_PKG_SRCURL}" + )" + + if [[ -z "${SRC_URL}" ]]; then + error "Could not find TERMUX_PKG_SRCURL." + fi + + checks=( + "can_be_updated_from_github" + "can_be_updated_from_gitlab" + "is_unique_package" + ) + can_be_updated=false + for check in "${checks[@]}"; do + info "Checking if package ${check//_/ }..." + if $check "${SRC_URL}"; then + can_be_updated=true + break + fi + done + + if [[ "${can_be_updated}" == "true" ]]; then + info "Package can be auto-updated." + if [[ "${ENABLE}" == "--enable" ]]; then + info "Enabling auto-update..." + write_to_first_empty_line \ + "${TERMUX_SCRIPTDIR}/packages/${PKG_NAME}/build.sh" "TERMUX_PKG_AUTO_UPDATE=true" + info "Done." + return + fi + else + error "Package cannot be auto-updated." + fi +} + +if [[ $# -lt 1 ]] || [[ $# -gt 2 ]]; then + error "Invalid number of arguments. See --help for usage." +fi + +while [[ $# -gt 0 ]]; do + case "$1" in + --enable) + ENABLE="--enable" + ;; + -s | --silent) + SILENT=true + ;; + -h | --help) + usage + ;; + *) + check "$1" + [[ "${SILENT}" == "true" ]] || echo # Newline. + ;; + esac + shift +done diff --git a/scripts/bin/update-packages b/scripts/bin/update-packages index 74469cb4f..4157662f1 100755 --- a/scripts/bin/update-packages +++ b/scripts/bin/update-packages @@ -130,52 +130,15 @@ _run_update() { fi } -_get_unique_packages() { - local -a unique_packages=() - - while read -r pkg; do - unique_packages+=("${pkg}") - done < <(curl --silent --location --retry 5 --retry-delay 5 --retry-max-time 60 \ - "https://repology.org/api/v1/projects/?inrepo=termux&&repos=1" | - jq -r keys) - - echo "${unique_packages[@]}" -} - -declare -a _UNIQUE_PACKAGES -read -r -a _UNIQUE_PACKAGES <<<"$(_get_unique_packages)" - -_unique_to_termux() { - local pkg_dir="$1" - # shellcheck disable=2076 # We want literal match not regex. - if [[ "${_UNIQUE_PACKAGES[*]}" =~ "\"$(basename "${pkg_dir}")\"" ]]; then - return 0 - else - return 1 - fi -} - main() { echo "INFO: Running update for: $*" if [[ "$1" == "@all" ]]; then for pkg_dir in "${TERMUX_SCRIPTDIR}"/packages/*; do - # Skip update if package is unique to Termux. - if _unique_to_termux "${pkg_dir}"; then - echo # Newline. - echo "INFO: Skipping update for unique to Termux package: $(basename "${pkg_dir}")" - continue - fi _run_update "${pkg_dir}" done else for pkg in "$@"; do - # Skip update if package is unique to Termux. - if _unique_to_termux "${TERMUX_SCRIPTDIR}"/packages/"${pkg}"; then - echo # Newline. - echo "INFO: Skipping update for unique to Termux package: ${pkg}" - continue - fi _run_update "${TERMUX_SCRIPTDIR}/packages/${pkg}" done fi