diff --git a/binaries.conf b/binaries.conf index ed6004d..f47479e 100644 --- a/binaries.conf +++ b/binaries.conf @@ -30,10 +30,10 @@ gui=false [paracon] version=1.3.0 url=https://github.com/mfncooper/paracon/releases/download/v1.3.0/paracon_1.3.0.pyz -install=$HOME/.local/bin/paracon_1.3.0.pyz +install=$HOME/.local/bin/paracon.pyz gui=true -comment=Weak signal digital modes for amateur radio -exec=python $HOME/.local/bin/paracon_1.3.0.pyz +comment=Packet radio terminal +exec=python $HOME/.local/bin/paracon.pyz icon=$HAMPACK_DIR/desktop/icons/paracon.png categories=HamRadio; diff --git a/compile.conf b/compile.conf index 50328a7..6fa72c3 100644 --- a/compile.conf +++ b/compile.conf @@ -2,7 +2,10 @@ # # Fields: # version= - version string for update checking -# git= - git repository URL to clone (mutually exclusive with wget) +# git= - git repository URL to clone (mutually exclusive with wget). Builds the +# tag named after the version (1.2.3 or v1.2.3), or the default branch +# if the repo has no tags +# ref= - commit to build instead of the version's tag, for repos whose tags are wrong # wget= - URL of a zip/tar archive to download and extract (mutually exclusive with git) # install= - path to the installed binary, used to detect if already installed # steps= - comma-separated build commands, run in order from the source directory @@ -17,11 +20,13 @@ install=$HOME/.local/bin/direwolf steps=mkdir build, cd build, cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local, make -j4, sudo make install, sudo udevadm control --reload-rules, mkdir -p $HOME/.local/state/HamPack/conf.d, cp -n $HAMPACK_DIR/conf.d/direwolf.conf $HOME/.local/state/HamPack/conf.d/ [QtTermTCP] -version=0.39 -wget=http://www.cantab.net/users/john.wiseman/Downloads/QtTermSource.zip +version=0.81 +git=https://github.com/g8bpq/QtTermTCP.git +# Upstream tags are one release behind: tag 0.81 is the 0.0.0.79 commit +ref=00ca15573c4653882265d6bfc884fca619556c30 install=$HOME/.local/bin/QtTermTCP gui=true -steps=qmake, make, mv QtTermTCP $HOME/.local/bin/ +steps=rm -f *.o .qmake.stash Makefile, qmake-qt5, make, mv QtTermTCP $HOME/.local/bin/ [kiwix-desktop] version=2.5.1 @@ -51,7 +56,7 @@ gui=true steps=rm -rf $HOME/.local/bin/yaac, mkdir -p $HOME/.local/bin/yaac, mv /tmp/hampack-build/yaac/* $HOME/.local/bin/yaac/ [potacat] -version=1.10.12 +version=1.11.7 git=https://github.com/Waffleslop/POTACAT.git install=$HOME/.local/bin/POTACAT.AppImage desktop=$HAMPACK_DIR/desktop/potacat.desktop @@ -68,7 +73,7 @@ gui=true steps=mkdir build, cd build, cmake -D CMAKE_INSTALL_PREFIX=/opt/JS8Call-improved .., cmake --build . -- -j 4, mv JS8Call $HOME/.local/bin/JS8Call [graywolf] -version=0.14.13 +version=0.14.14 git=https://github.com/chrissnell/graywolf.git install=$HOME/.local/bin/graywolf steps=getent group dialout || sudo groupadd dialout, make all, install -m 755 bin/graywolf $HOME/.local/bin/graywolf, install -m 755 bin/graywolf-modem $HOME/.local/bin/graywolf-modem, mkdir -p $HOME/.local/share/graywolf, sed "s|HAMPACK_USER|$USER|g; s|HAMPACK_HOME|$HOME|g" $HAMPACK_DIR/systemd/graywolf.service > /tmp/graywolf.service, sudo install -m 644 /tmp/graywolf.service /etc/systemd/system/graywolf.service, sudo systemctl daemon-reload, sudo systemctl enable graywolf diff --git a/hampackcheck b/hampackcheck index 38a0142..9398207 100755 --- a/hampackcheck +++ b/hampackcheck @@ -24,16 +24,29 @@ github_latest() { | sed 's/^v//' } +# Latest release tag in a git repo, stripping leading "v". Only plain version +# tags count (1.2.3 or v1.2.3), not pre-releases like 1.8-beta1. +git_latest_tag() { + local url="$1" + git ls-remote --tags --refs "$url" 2>/dev/null \ + | sed 's|.*refs/tags/||' \ + | grep -E '^v?[0-9]+(\.[0-9]+)+$' \ + | sed 's/^v//' \ + | sort -V \ + | tail -n1 +} + print_result() { local app="$1" local pinned="$2" local latest="$3" local manual_url="$4" + local source="${5:-GitHub API}" if [ -n "$manual_url" ]; then printf " %-20s pinned=%-15s (manual check: %s)\n" "$app" "$pinned" "${manual_url%/*}" elif [ -z "$latest" ]; then - printf " %-20s pinned=%-15s (GitHub API unavailable)\n" "$app" "$pinned" + printf " %-20s pinned=%-15s (%s unavailable)\n" "$app" "$pinned" "$source" elif [ "$pinned" = "$latest" ]; then printf " %-20s up to date (%s)\n" "$app" "$pinned" else @@ -82,6 +95,23 @@ check_binaries() { check_app "$app" "$version" "$url" "" } +# compile.conf builds git= apps from the tag matching their version, so compare +# against the repo's tags rather than GitHub releases +check_compiled_app() { + local app="$1" + local version="$2" + local git_url="$3" + local wget_url="$4" + + [ -z "$app" ] || [ -z "$version" ] && return + + if [ -n "$git_url" ]; then + print_result "$app" "$version" "$(git_latest_tag "$git_url")" "" "version tags" + else + check_app "$app" "$version" "" "$wget_url" + fi +} + check_compiled() { echo "" echo "=== compile.conf ===" @@ -91,7 +121,7 @@ check_compiled() { [[ -z "$line" || "$line" == \#* ]] && continue if [[ "$line" =~ ^\[(.+)\]$ ]]; then - check_app "${name:-$app}" "$version" "$git_url" "$wget_url" + check_compiled_app "${name:-$app}" "$version" "$git_url" "$wget_url" app="${BASH_REMATCH[1]}" name="" version="" git_url="" wget_url="" continue fi @@ -105,7 +135,7 @@ check_compiled() { esac done < "$COMPILE_CONF" - check_app "${name:-$app}" "$version" "$git_url" "$wget_url" + check_compiled_app "${name:-$app}" "$version" "$git_url" "$wget_url" } # --- Main --- diff --git a/hampackremove b/hampackremove index 19d1b2b..435c14e 100755 --- a/hampackremove +++ b/hampackremove @@ -58,6 +58,8 @@ rm -f ~/.local/bin/dump1090 rm -f ~/.local/bin/graywolf rm -f ~/.local/bin/graywolf-modem rm -rf ~/.local/share/graywolf +rm -f ~/.local/bin/ardopcf_amd64_Linux_64 +rm -f ~/.local/bin/paracon.pyz ~/.local/bin/paracon_*.pyz # Remove HamPack scripts and binaries echo "Removing HamPack scripts and binaries..." @@ -164,6 +166,7 @@ rm -f ~/.local/share/applications/js8call.desktop rm -f ~/.local/share/applications/yaac.desktop rm -f ~/.local/share/applications/potacat.desktop rm -f ~/.local/share/applications/qttermtcp.desktop +rm -f ~/.local/share/applications/paracon.desktop update-desktop-database "$HOME/.local/share/applications/" 2>/dev/null || true diff --git a/install-binaries.sh b/install-binaries.sh index 70f77ea..c9fd7c0 100755 --- a/install-binaries.sh +++ b/install-binaries.sh @@ -7,6 +7,7 @@ export HAMPACK_DIR CONF_FILE="${HAMPACK_BINARIES_CONF:-$HAMPACK_DIR/binaries.conf}" TMP_DIR="/tmp/hampack-build" VERSION_FILE="$HOME/.local/state/HamPack/.installed_versions" +FAILED=() # Get the installed version of an app get_installed_version() { @@ -53,14 +54,8 @@ needs_update() { installed=$(get_installed_version "$app") if [ "$installed" = "unknown" ]; then - echo " Warning: could not determine installed version of $app." - echo " binaries.conf specifies version $latest." - read -rp " Download and install $app anyway? [y/N] " response - if [[ "$response" =~ ^[yY] ]]; then - return 0 - else - return 1 - fi + echo " Installed version of $app is unknown, reinstalling version $latest." + return 0 fi echo " Installed version : $installed" @@ -85,7 +80,11 @@ download_binary() { local tmp_file="$TMP_DIR/$filename" echo " Downloading $url..." - wget -q "$url" -O "$tmp_file" + if ! wget -q "$url" -O "$tmp_file"; then + echo " Error: download of $url failed." + rm -f "$tmp_file" + return 1 + fi mkdir -p "$(dirname "$install_path")" mv "$tmp_file" "$install_path" @@ -142,11 +141,13 @@ process_app() { if [ -z "$url" ]; then echo " Error: no url specified for $app, skipping." + FAILED+=("$app") return fi if [ -z "$install_path" ]; then echo " Error: no install path specified for $app, skipping." + FAILED+=("$app") return fi @@ -162,7 +163,10 @@ process_app() { echo " $app is not installed." fi - download_binary "$app" "$url" "$install_path" + if ! download_binary "$app" "$url" "$install_path"; then + FAILED+=("$app") + return + fi if [ "$gui" = "true" ]; then install_desktop "$app" "$install_path" "$exec_cmd" "$comment" "$icon" "$categories" @@ -236,4 +240,9 @@ echo "" echo "Cleaning up..." rm -rf "$TMP_DIR" +if (( ${#FAILED[@]} > 0 )); then + echo "Failed to install: ${FAILED[*]}" + exit 1 +fi + echo "All done." diff --git a/install-compiled.sh b/install-compiled.sh index 4b3ed9f..33240c5 100755 --- a/install-compiled.sh +++ b/install-compiled.sh @@ -7,6 +7,7 @@ export HAMPACK_DIR CONF_FILE="${HAMPACK_COMPILE_CONF:-$HAMPACK_DIR/compile.conf}" TMP_DIR="/tmp/hampack-build" VERSION_FILE="$HOME/.local/state/HamPack/.installed_versions" +FAILED=() # Get the installed version of an app get_installed_version() { @@ -131,31 +132,71 @@ install_desktop() { echo " Desktop file installed." } +# Find the tag for a version, named either "1.2.3" or "v1.2.3". Prints nothing +# if the repo has no tags at all; fails if it has tags but none for the version. +find_version_tag() { + local git_url="$1" + local version="$2" + local tags + + tags=$(git ls-remote --tags --refs "$git_url" | sed 's|.*refs/tags/||') || return 1 + [ -z "$tags" ] && return 0 + + local tag + for tag in "$version" "v$version"; do + if grep -qxF "$tag" <<< "$tags"; then + echo "$tag" + return 0 + fi + done + return 1 +} + # Fetch source via git or wget fetch_source() { local app="$1" local git_url="$2" local wget_url="$3" + local version="$4" + local ref="$5" local src_dir="$TMP_DIR/$app" rm -rf "$src_dir" mkdir -p "$src_dir" - if [ -n "$git_url" ]; then - echo " Cloning $git_url..." - git clone "$git_url" "$src_dir" + if [ -n "$git_url" ] && [ -n "$ref" ]; then + echo " Cloning $git_url at $ref..." + git clone "$git_url" "$src_dir" || return 1 + git -C "$src_dir" -c advice.detachedHead=false checkout "$ref" || return 1 + + elif [ -n "$git_url" ]; then + local tag="" + if [ -n "$version" ]; then + if ! tag=$(find_version_tag "$git_url" "$version"); then + echo " Error: no tag $version or v$version in $git_url" + return 1 + fi + fi + + if [ -n "$tag" ]; then + echo " Cloning $git_url at $tag..." + git -c advice.detachedHead=false clone --branch "$tag" "$git_url" "$src_dir" || return 1 + else + echo " $git_url has no tags; cloning the default branch..." + git clone "$git_url" "$src_dir" || return 1 + fi elif [ -n "$wget_url" ]; then echo " Downloading $wget_url..." local filename="${wget_url##*/}" local filepath="$TMP_DIR/$filename" - wget -q "$wget_url" -O "$filepath" + wget -q "$wget_url" -O "$filepath" || return 1 echo " Extracting $filename..." case "$filename" in *.zip) - unzip -q "$filepath" -d "$src_dir" + unzip -q "$filepath" -d "$src_dir" || return 1 # If the zip extracted into a single subdirectory, flatten it local contents contents=$(ls -1 "$src_dir") @@ -169,24 +210,24 @@ fetch_source() { fi ;; *.tar.gz|*.tgz) - tar -xzf "$filepath" -C "$src_dir" --strip-components=1 + tar -xzf "$filepath" -C "$src_dir" --strip-components=1 || return 1 ;; *.tar.bz2) - tar -xjf "$filepath" -C "$src_dir" --strip-components=1 + tar -xjf "$filepath" -C "$src_dir" --strip-components=1 || return 1 ;; *.tar.xz) - tar -xJf "$filepath" -C "$src_dir" --strip-components=1 + tar -xJf "$filepath" -C "$src_dir" --strip-components=1 || return 1 ;; *) echo " Error: unknown file type for $filename" - exit 1 + return 1 ;; esac rm -f "$filepath" else echo " Error: no git or wget URL specified for $app" - exit 1 + return 1 fi } @@ -224,6 +265,7 @@ process_app() { local version="$6" local desktop="$7" local gui="$8" + local ref="$9" echo "" echo "=== $app ===" @@ -247,7 +289,11 @@ process_app() { return fi - fetch_source "$app" "$git_url" "$wget_url" + if ! fetch_source "$app" "$git_url" "$wget_url" "$version" "$ref"; then + echo " Error: could not fetch $app source, skipping." + FAILED+=("$app") + return + fi run_steps "$app" "$steps" install_desktop "$desktop" save_installed_version "$app" "$version" @@ -260,17 +306,17 @@ process_app() { # Parse compile.conf and process each app process_conf() { - local app="" git_url="" wget_url="" install_path="" steps="" version="" desktop="" gui="" + local app="" git_url="" wget_url="" install_path="" steps="" version="" desktop="" gui="" ref="" while IFS= read -r line || [ -n "$line" ]; do [[ -z "$line" || "$line" == \#* ]] && continue if [[ "$line" =~ ^\[(.+)\]$ ]]; then if [ -n "$app" ]; then - process_app "$app" "$git_url" "$wget_url" "$install_path" "$steps" "$version" "$desktop" "$gui" + process_app "$app" "$git_url" "$wget_url" "$install_path" "$steps" "$version" "$desktop" "$gui" "$ref" fi app="${BASH_REMATCH[1]}" - git_url="" wget_url="" install_path="" steps="" version="" desktop="" gui="" + git_url="" wget_url="" install_path="" steps="" version="" desktop="" gui="" ref="" continue fi @@ -279,6 +325,7 @@ process_conf() { case "$key" in git) git_url="$(eval echo "$value")" ;; + ref) ref="$value" ;; wget) wget_url="$(eval echo "$value")" ;; install) install_path="$(eval echo "$value")" ;; steps) steps="$value" ;; @@ -291,7 +338,7 @@ process_conf() { # Process the last app in the file if [ -n "$app" ]; then - process_app "$app" "$git_url" "$wget_url" "$install_path" "$steps" "$version" "$desktop" "$gui" + process_app "$app" "$git_url" "$wget_url" "$install_path" "$steps" "$version" "$desktop" "$gui" "$ref" fi } @@ -315,4 +362,9 @@ echo "" echo "Cleaning up..." rm -rf "$TMP_DIR" +if (( ${#FAILED[@]} > 0 )); then + echo "Failed to install: ${FAILED[*]}" + exit 1 +fi + echo "All done." \ No newline at end of file diff --git a/packages.conf b/packages.conf index afeaf0c..bbc2154 100644 --- a/packages.conf +++ b/packages.conf @@ -29,6 +29,9 @@ UTILITIES=( pat-bin python-yattag # must come before chirp-next qgis + qt5-base # QtTermTCP builds against Qt 5 + qt5-multimedia + qt5-serialport qt6-base qt6-tools qt6-webengine diff --git a/update.sh b/update.sh index 58fc5cf..cb264ae 100644 --- a/update.sh +++ b/update.sh @@ -28,6 +28,8 @@ remove_stale_files() { rm -f "$HOME/.local/share/applications/hampack.desktop" # Replaced by CoreDesktop's `update` and `sibling add` rm -f "$HOME/.local/bin/hampackupdate" "$HOME/.local/bin/hampackrefresh" + # Paracon is now installed without the version in its file name + rm -f "$HOME"/.local/bin/paracon_*.pyz # Hooks from before HamPack was a sibling; 71-siblings.sh now runs this script rm -f "$COREDESKTOP"/updates.d/[0-9][0-9][0-9]-hampack-* } @@ -70,6 +72,7 @@ step "Removing stale HamPack files" remove_stale_files step "Installing HamPack tools" install_tools step "Installing HamPack packages" install_hampack_packages step "Installing Flatpak applications" bash "$SELF/install-flatpaks.sh" +step "Installing pre-built binaries" bash "$SELF/install-binaries.sh" step "Installing compiled applications" bash "$SELF/install-compiled.sh" step "Installing Windows applications" bash "$SELF/install-windows-apps.sh" step "Installing not1mm" install_not1mm