From 2aaa09d91966391c40623d08b695924fcfec89b2 Mon Sep 17 00:00:00 2001 From: TomIO Date: Tue, 14 Oct 2025 23:13:24 +0200 Subject: [PATCH 1/5] fix(main/perl): fix linter issue with version --- packages/perl/build.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/perl/build.sh b/packages/perl/build.sh index 1e2e67bd731f2ee..88cecf53785dbf5 100644 --- a/packages/perl/build.sh +++ b/packages/perl/build.sh @@ -10,12 +10,12 @@ TERMUX_PKG_MAINTAINER="@termux" # - psutils (currently a disabled package) # - subversion TERMUX_PKG_VERSION=(5.40.3 - b1b26b20d5146271b13007fc77c6bb43b6555443) + 1.6.2) +TERMUX_PKG_REVISION=1 TERMUX_PKG_SHA256=(65f63b4763ab6cb9bb3d5731dd10369e1705be3c59be9847d453eb60b349ab43 - 8d2c68270fb475a301b349724852ec19fb2272751d9f757497e648d8ed4db8b0) + f74ab2a6cacc574c98398ae9d36660b4cc0ba0e3d34e87b24d27b9cd2a27787d) TERMUX_PKG_SRCURL=(https://www.cpan.org/src/5.0/perl-${TERMUX_PKG_VERSION[0]}.tar.xz https://github.com/arsv/perl-cross/archive/${TERMUX_PKG_VERSION[1]}.tar.gz) -# https://github.com/arsv/perl-cross/releases/download/${TERMUX_PKG_VERSION[1]}/perl-cross-${TERMUX_PKG_VERSION[1]}.tar.gz) TERMUX_PKG_DEPENDS=libandroid-utimes TERMUX_PKG_BUILD_IN_SRC=true TERMUX_PKG_MAKE_PROCESSES=1 From a0c583a23c91aeca68a5901a5b8d086d91940a24 Mon Sep 17 00:00:00 2001 From: TomIO Date: Sun, 5 Oct 2025 20:57:27 +0200 Subject: [PATCH 2/5] enhance(scripts/lint-packages.sh): make version check more robust --- scripts/lint-packages.sh | 130 +++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 53 deletions(-) diff --git a/scripts/lint-packages.sh b/scripts/lint-packages.sh index 497de05faab7ed1..d7f636b81fbbe1e 100755 --- a/scripts/lint-packages.sh +++ b/scripts/lint-packages.sh @@ -121,43 +121,92 @@ check_indentation() { return 0 } -# Check the latest commit that modified `$package` -# It must either: -# - Modify TERMUX_PKG_REVISION -# - Modify TERMUX_PKG_VERSION -# - Or specify one of the CI skip tags -check_version_change() { - # !!! vvv TEMPORARY - REMOVE WHEN THIS FUNCTION IS FIXED vvv !!! - return - # !!! ^^^ TEMPORARY - REMOVE WHEN THIS FUNCTION IS FIXED ^^^ !!! +# We'll need the 'origin/master' as a base commit when running the version check. +# So try fetching it now if it doesn't exist. +if ! base_commit="HEAD~$(git rev-list --count FETCH_HEAD..)"; then + git fetch https://github.com/termux/termux-packages.git + base_commit="HEAD~$(git rev-list --count FETCH_HEAD..)" +fi - local base_commit commit_diff package_dir="${1%/*}" - base_commit="$(< "$TERMUX_SCRIPTDIR/.git/refs/remotes/origin/master")" +check_version() { + local package_dir="${1%/*}" [[ -z "$base_commit" ]] && { - echo - echo - echo "Couldn't determine base commit of branch." - echo "This shouldn't be able to happen..." - ls -AR "$TERMUX_SCRIPTDIR/.git/refs" - exit 1 + printf '%s\n' "FAIL" \ + "Couldn't determine HEAD commit of 'origin/master'." \ + "This shouldn't be able to happen..." + ls -AR "$TERMUX_SCRIPTDIR/.git/refs/remotes/origin" + return 1 } >&2 - commit_diff="$(git log --patch "${base_commit}.." -- "$package_dir")" + # If TERMUX_PKG_VERSION is an array that changes the formatting. + local version i=-1 error=0 is_array="${TERMUX_PKG_VERSION@a}" + printf '%s' "${is_array:+$'ARRAY\n'}" + + for version in "${TERMUX_PKG_VERSION[@]}"; do + printf '%s' "${is_array:+$'\t'}" + (( i++ )) + + # Is this version valid? + dpkg --validate-version "${version}" &>/dev/null || { + printf 'INVALID %s\n' "$(dpkg --validate-version "${version}" 2>&1)" + (( error++ )) + continue + } - # If the diff is empty there's no commit modifying that package on this branch, which is a PASS. - [[ -z "$commit_diff" ]] && return + # Was the package modified in this branch? + git diff --exit-code "${base_commit}" -- "${package_dir}" 2> /dev/null && { + printf '%s\n' "PASS - ${version} (not modified in this branch)" + continue + } - grep -q \ - -e '^+TERMUX_PKG_REVISION=' \ - -e '^+TERMUX_PKG_VERSION=' \ - -e '\[no version check\]' <<< "$commit_diff" \ - || return 1 + local version_new version_old + version_new="${version}-${TERMUX_PKG_REVISION:-0}" + version_old=$( + unset TERMUX_PKG_VERSION TERMUX_PKG_REVISION + # shellcheck source=/dev/null + . <(git -P show "${base_commit}:${package_dir}/build.sh" 2> /dev/null) + if [[ -n "$is_array" ]]; then + echo "${TERMUX_PKG_VERSION[$i]:-0}-${TERMUX_PKG_REVISION:-0}" + else + echo "${TERMUX_PKG_VERSION:-0}-${TERMUX_PKG_REVISION:-0}" + fi + ) + + # Is ${version_old} valid? + local version_old_is_bad="" + dpkg --validate-version "${version_old}" &>/dev/null || version_old_is_bad="0~invalid" + + # If ${version_new} isn't greater than "$version_old" that's an issue. + # If ${version_old} isn't valid this check is a no-op. + if dpkg --compare-versions "$version_new" le "${version_old_is_bad:-$version_old}"; then + printf '%s\n' \ + "FAILED" \ + "" \ + "Version of '$package_name' has not been incremented." \ + "Either 'TERMUX_PKG_VERSION' or 'TERMUX_PKG_REVISION'" \ + "need to be modified in the build.sh when changing a package build." + + # If the version decreased throw in a suggestion for how to downgrade packages + dpkg --compare-versions "$version_new" lt "$version_old" && \ + printf '%s\n' \ + "" \ + "- If you are reverting '$package_name' to an older version use the '+really' suffix" \ + "e.g. TERMUX_PKG_VERSION=${version_new%-*}+really${version_old%-*}" \ + "- If ${package_name}'s version scheme has changed completely an epoch may be needed." \ + "For more information see:" \ + "https://www.debian.org/doc/debian-policy/ch-controlfields.html#epochs-should-be-used-sparingly" + + echo "" + return 1 + fi + echo "PASS - ${version_old%-0}${version_old_is_bad:+" (INVALID)"} -> ${version_new%-0}" + done + return $error } lint_package() { - local package_script - local package_name + local package_script package_name package_script="$1" package_name="$(basename "$(dirname "$package_script")")" @@ -248,21 +297,6 @@ lint_package() { fi echo "PASS" - echo -n "Version change check: " - if ! check_version_change "$package_script"; then - echo "FAILED" - echo - echo "Version of '$package_name' has not changed." - echo "Either 'TERMUX_PKG_REVISION' or 'TERMUX_PKG_VERSION'" - echo "need to be modified in the build.sh when changing a package build." - echo "Alternatively you can add '[no version check]'." - echo "To the commit message to skip this check." - echo - return 1 - fi - echo "PASS" - echo - # Fields checking is done in subshell since we will source build.sh. (set +e +u local pkg_lint_error @@ -346,17 +380,7 @@ lint_package() { fi echo -n "TERMUX_PKG_VERSION: " - if (( ${#TERMUX_PKG_VERSION} )); then - if dpkg --validate-version "${TERMUX_PKG_VERSION}"; then - echo "PASS" - else - echo "INVALID (contains characters that are not allowed)" - pkg_lint_error=true - fi - else - echo "NOT SET" - pkg_lint_error=true - fi + check_version "$package_script" || pkg_lint_error=true if (( ${#TERMUX_PKG_REVISION} )); then echo -n "TERMUX_PKG_REVISION: " From af8e2c53b7e8250695f5fb9827400e7412eb64e1 Mon Sep 17 00:00:00 2001 From: TomIO Date: Mon, 6 Oct 2025 04:09:22 +0200 Subject: [PATCH 3/5] enhance(scripts/lint-packages.sh): replace external `grep` with Bash alternatives --- scripts/lint-packages.sh | 95 ++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/scripts/lint-packages.sh b/scripts/lint-packages.sh index d7f636b81fbbe1e..58b70224abe3f0f 100755 --- a/scripts/lint-packages.sh +++ b/scripts/lint-packages.sh @@ -76,39 +76,42 @@ check_indentation() { local pkg_script="$1" local line='' heredoc_terminator='' in_array=0 i=0 local -a issues=('' '') bad_lines=('FAILED') + local heredoc_regex="[^\(/%#]<{2}-?\s*(['\"]?(\w*(\\\.)?)*['\"]?)" + # We don't wanna hit version constraints "(<< x.y.z)" with this, so don't match "(<<". + # We also wouldn't wanna hit parameter expansions "${var/<<}", ${var%<<}, ${var#<<} # parse leading whitespace while IFS=$'\n' read -r line; do ((i++)) # make sure it's a heredoc, not a herestring - if ! [[ "$line" == *'<<<'* ]]; then + if [[ "$line" != *'<<<'* ]]; then # Skip this check in entirely within heredocs - # (see packages/ghc-libs for an example of why) - [[ "$line" =~ [^\(]\<{2}-?[\'\"]?([^\'\"]+) ]] && { + [[ "$line" =~ $heredoc_regex ]] && { heredoc_terminator="${BASH_REMATCH[1]}" } - (( ${#heredoc_terminator} )) && \ - grep -qP "^\s*${heredoc_terminator}" <<< "$line" && { + [[ -n ${heredoc_terminator} && "$line" == [[:space:]]*"${heredoc_terminator//[\'\"]}" ]] && { heredoc_terminator='' } (( ${#heredoc_terminator} )) && continue fi # check for mixed indentation - grep -qP '^(\t+ +| +\t+)' <<< "$line" && { + [[ "$line" =~ ^($'\t'+ +| +$'\t'+) ]] && { issues[0]='Mixed indentation' - bad_lines[$i]="${pkg_script}:${i}:$line" + bad_lines[i]="${pkg_script}:${i}:$line" } [[ "$line" == *'=('* ]] && in_array=1 - if (( ! in_array )); then # spaces for indentation are okay for aligning arrays - grep -qP '^ +' <<< "$line" && { # check for spaces as indentation - issues[1]='Use tabs for indentation' - bad_lines[$i]="${pkg_script}:${i}:$line" - } - fi + + # spaces for indentation are okay for aligning arrays + [[ "$in_array" == 0 && "$line" == " "* ]] && { + # but otherwise we use spaces + issues[1]='Use tabs for indentation' + bad_lines[i]="${pkg_script}:${i}:$line" + } + [[ "$line" == *')' ]] && in_array=0 done < "$pkg_script" @@ -289,10 +292,9 @@ lint_package() { echo "PASS" echo -n "Trailing whitespace check: " - local trailing_whitespace - trailing_whitespace=$(grep -Hn '[[:blank:]]$' "$package_script") - if (( ${#trailing_whitespace} )); then - echo -e "FAILED\n\n${trailing_whitespace}\n" + local re=$'[\t ]\n' + if [[ "$(< "$package_script")" =~ $re ]]; then + echo -e "FAILED\n\n$(grep -Hn '[[:space:]]$' "$package_script")\n" return 1 fi echo "PASS" @@ -312,7 +314,7 @@ lint_package() { echo -n "TERMUX_PKG_HOMEPAGE: " if (( ${#TERMUX_PKG_HOMEPAGE} )); then - if ! grep -qP '^https://.+' <<< "$TERMUX_PKG_HOMEPAGE"; then + if [[ ! "$TERMUX_PKG_HOMEPAGE" == 'https://'* ]]; then echo "NON-HTTPS (acceptable)" else echo "PASS" @@ -366,7 +368,7 @@ lint_package() { if (( ${#TERMUX_PKG_API_LEVEL} )); then echo -n "TERMUX_PKG_API_LEVEL: " - if grep -qP '^[1-9][0-9]$' <<< "$TERMUX_PKG_API_LEVEL"; then + if [[ "$TERMUX_PKG_API_LEVEL" == [1-9][0-9] ]]; then if (( TERMUX_PKG_API_LEVEL < 24 )); then echo "INVALID (allowed: number in range >= 24)" pkg_lint_error=true @@ -410,11 +412,10 @@ lint_package() { urls_ok=true for url in "${TERMUX_PKG_SRCURL[@]}"; do if (( ${#url} )); then - if ! grep -qP '^git\+https://.+' <<< "$url" && ! grep -qP '^https://.+' <<< "$url"; then - echo "NON-HTTPS (acceptable)" - urls_ok=false - break - fi + case "$url" in + https://*|git+https://*) continue;; + *) echo "NON-HTTPS (acceptable)" ; urls_ok=false; break ;; + esac else echo "NOT SET (one of the array elements)" urls_ok=false @@ -432,24 +433,22 @@ lint_package() { echo -n "TERMUX_PKG_SHA256: " if (( ${#TERMUX_PKG_SHA256} )); then if (( ${#TERMUX_PKG_SRCURL[@]} == ${#TERMUX_PKG_SHA256[@]} )); then - sha256_ok=true + sha256_ok="PASS" for sha256 in "${TERMUX_PKG_SHA256[@]}"; do - if ! grep -qP '^[0-9a-fA-F]{64}$' <<< "${sha256}" && [[ "$sha256" != 'SKIP_CHECKSUM' ]]; then + if [[ "$sha256" == 'SKIP_CHECKSUM' ]]; then + sha256_ok="PASS (SKIP_CHECKSUM)" + elif [[ ! "$sha256" =~ [0-9a-f]{64} ]]; then echo "MALFORMED (SHA-256 should contain 64 hexadecimal numbers)" - sha256_ok=false pkg_lint_error=true break fi done - unset sha256 - if $sha256_ok; then - echo "PASS" - fi - unset sha256_ok + echo "$sha256_ok" + unset sha256 sha256_ok else - echo "LENGTHS OF 'TERMUX_PKG_SRCURL' AND 'TERMUX_PKG_SHA256' ARE NOT EQUAL" + echo "LENGTHS OF 'TERMUX_PKG_SRCURL' AND 'TERMUX_PKG_SHA256' ARRAYS ARE NOT EQUAL" pkg_lint_error=true fi elif [[ "${TERMUX_PKG_SRCURL:0:4}" == 'git+' ]]; then @@ -569,14 +568,14 @@ lint_package() { file_path_ok=true while read -r file_path; do - [[ -z "$file_path" ]] && continue - - if grep -qP '^(\.\.)?/' <<< "$file_path"; then - echo "INVALID (file path should be relative to prefix)" - file_path_ok=false - pkg_lint_error=true + case "$file_path" in + /*|./*|../*) + echo "INVALID (file path should be relative to prefix)" + file_path_ok=false + pkg_lint_error=true break - fi + ;; + esac done <<< "$TERMUX_PKG_RM_AFTER_INSTALL" unset file_path @@ -591,14 +590,14 @@ lint_package() { file_path_ok=true while read -r file_path; do - [[ -z "$file_path" ]] && continue - - if grep -qP '^(\.\.)?/' <<< "$file_path"; then - echo "INVALID (file path should be relative to prefix)" - file_path_ok=false - pkg_lint_error=true - break - fi + case "$file_path" in + /*|./*|../*) + echo "INVALID (file path should be relative to prefix)" + file_path_ok=false + pkg_lint_error=true + break + ;; + esac done <<< "$TERMUX_PKG_CONFFILES" unset file_path From 47be86a1f3b7008d50a018c032a242cadd39ab57 Mon Sep 17 00:00:00 2001 From: TomIO Date: Mon, 6 Oct 2025 04:42:14 +0200 Subject: [PATCH 4/5] enhance(scripts/lint-packages.sh): remove external `sed` and `awk` call from checks and minor license sorting cleanup --- scripts/lint-packages.sh | 41 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/scripts/lint-packages.sh b/scripts/lint-packages.sh index 58b70224abe3f0f..bc2783036a22940 100755 --- a/scripts/lint-packages.sh +++ b/scripts/lint-packages.sh @@ -6,15 +6,10 @@ TERMUX_SCRIPTDIR=$(realpath "$(dirname "$0")/../") . "$TERMUX_SCRIPTDIR/scripts/properties.sh" check_package_license() { - local pkg_licenses="$1" - local license - local license_ok=true - local IFS - - IFS="," - for license in $pkg_licenses; do - license=$(sed -r 's/^\s*(\S+(\s+\S+)*)\s*$/\1/' <<< "$license") + local pkg_licenses license license_ok=true + IFS=',' read -ra pkg_licenses <<< "${1//, /,}" + for license in "${pkg_licenses[@]}"; do case "$license" in AFL-2.1|AFL-3.0|AGPL-V3|APL-1.0|APSL-2.0);; Apache-1.0|Apache-1.1|Apache-2.0|Artistic-License-2.0|Attribution);; @@ -25,8 +20,8 @@ check_package_license() { EUPL-1.1|EUPL-1.2|Eiffel-2.0|Entessa-1.0|Facebook-Platform|Fair|Frameworx-1.0);; GPL-2.0|GPL-2.0-only|GPL-2.0-or-later);; GPL-3.0|GPL-3.0-only|GPL-3.0-or-later);; - Go|hdparm|HSQLDB|Historical|HPND|IBMPL-1.0|IJG|IPAFont-1.0|ISC|IU-Extreme-1.1.1);; - ImageMagick|JA-SIG|JSON|JTidy);; + Go|hdparm|HPND|HSQLDB|Historical|IBMPL-1.0|IJG|IPAFont-1.0);; + ISC|IU-Extreme-1.1.1|ImageMagick|JA-SIG|JSON|JTidy);; LGPL-2.0|LGPL-2.0-only|LGPL-2.0-or-later);; LGPL-2.1|LGPL-2.1-only|LGPL-2.1-or-later);; LGPL-3.0|LGPL-3.0-only|LGPL-3.0-or-later);; @@ -37,19 +32,21 @@ check_package_license() { "Public Domain"|"Public Domain - SUN"|PythonPL|PythonSoftFoundation);; QTPL-1.0|RPL-1.5|Real-1.0|RicohPL|SUNPublic-1.0|Scala|SimPL-2.0|Sleepycat);; Sybase-1.0|TMate|UPL-1.0|Unicode-DFS-2015|Unlicense|UoI-NCSA|"VIM License");; - VovidaPL-1.0|W3C|WTFPL|Xnet|ZLIB|ZPL-2.0|wxWindows|X11);; + VovidaPL-1.0|W3C|WTFPL|wxWindows|X11|Xnet|ZLIB|ZPL-2.0);; *) license_ok=false break - ;; + ;; esac done if [[ "$license_ok" == 'false' ]]; then + echo "INVALID" return 1 fi + echo "PASS" return 0 } @@ -248,7 +245,7 @@ lint_package() { echo -n "End of line check: " local last2octet - last2octet=$(xxd -s -2 "$package_script" | awk '{ print $2 }') + read -r _ last2octet _ < <(xxd -s -2 "$package_script") if [[ "$last2octet" == "0a0a" ]]; then echo -e "FAILED (duplicate newlines at the end)\n" tail -n5 "$package_script" | sed -e "s|^| |" -e "5s|^ |>>|" @@ -340,18 +337,12 @@ lint_package() { echo -n "TERMUX_PKG_LICENSE: " if (( ${#TERMUX_PKG_LICENSE} )); then - if [[ "$TERMUX_PKG_LICENSE" == *'custom'* ]]; then - echo "CUSTOM" - elif [[ "$TERMUX_PKG_LICENSE" == 'non-free' ]]; then - echo "NON-FREE" - else - if check_package_license "$TERMUX_PKG_LICENSE"; then - echo "PASS" - else - echo "INVALID" - pkg_lint_error=true - fi - fi + case "$TERMUX_PKG_LICENSE" in + *custom*) echo "CUSTOM" ;; + 'non-free') echo "NON-FREE";; + *) check_package_license "$TERMUX_PKG_LICENSE" || pkg_lint_error=true + ;; + esac else echo "NOT SET" pkg_lint_error=true From bb06339976b70af85cd987f55a32a65d9601af8a Mon Sep 17 00:00:00 2001 From: TomIO Date: Wed, 15 Oct 2025 02:25:56 +0200 Subject: [PATCH 5/5] enhance(scripts/lint-packages.sh): check proper revision use --- scripts/lint-packages.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/scripts/lint-packages.sh b/scripts/lint-packages.sh index bc2783036a22940..65d8e71c4fdb67c 100755 --- a/scripts/lint-packages.sh +++ b/scripts/lint-packages.sh @@ -200,6 +200,36 @@ check_version() { echo "" return 1 fi + + local new_revision="${version_new##*-}" old_revision="${version_old##*-}" + + # If the version hasn't changed the revision must be incremented by 1 + # A decrease or no increase would have been caught above. + # But we want to additionally enforce sequential increase. + if [[ "${version_new%-*}" == "${version_old%-*}" && "$new_revision" != "$((old_revision + 1))" ]]; then + (( error++ )) # Not incremented sequentially + printf '%s\n' "FAILED " \ + "TERMUX_PKG_REVISION should be incremented sequentially" \ + "when a package is rebuilt with no new upstream release." \ + "" \ + "Got : ${version_old} -> ${version_new}" \ + "Expected: ${version_old} -> ${version}-$((old_revision + 1))" + continue + # If that check passed the TERMUX_PKG_VERSION must have changed, + # in which case TERMUX_PKG_REVISION should be reset to 0. + # This check isn't useful past the first index when $TERMUX_PKG_VERSION is an array + # since the main version of such a package may remain unchanged when another is changed. + elif [[ "${version_new%-*}" != "${version_old%-*}" && "$new_revision" != "0" && "$i" == 0 ]]; then + (( error++ )) # Not reset + printf '%s\n' \ + "FAILED - $version_old -> $version_new" \ + "" \ + "TERMUX_PKG_VERSION was bumped but TERMUX_PKG_REVISION wasn't reset." \ + "Please remove the 'TERMUX_PKG_REVISION=${new_revision}' line." \ + "" + continue + fi + echo "PASS - ${version_old%-0}${version_old_is_bad:+" (INVALID)"} -> ${version_new%-0}" done return $error