#!/bin/bash set -e # # Purpose : Compile and install applications from compile.conf CONF_FILE="$HOME/.local/share/HamPackServer/compile.conf" TMP_DIR="$HOME/.cache/hampack-build" VERSION_FILE="$HOME/.local/state/HamPackServer/.installed_versions" # Get the installed version of an app get_installed_version() { local app="$1" local gui="$2" local type="$3" local install_path="$4" # For npm apps, read version from package.json in the install directory if [ "$type" = "npm" ] && [ -f "$install_path/package.json" ]; then local ver ver=$(grep -m1 '"version"' "$install_path/package.json" | grep -oP '\d+\.\d+[\.\d]*') if [ -n "$ver" ]; then echo "$ver" return fi fi # Skip --version check for GUI apps as it would launch them if [ "$gui" != "true" ]; then if command -v "$app" &> /dev/null; then local ver ver=$("$app" --version 2>&1 | grep -oP '\d+\.\d+[\.\d]*' | head -n1) if [ -n "$ver" ]; then echo "$ver" return fi fi fi # Fall back to version file if [ -f "$VERSION_FILE" ]; then local stored stored=$(grep "^$app=" "$VERSION_FILE" | cut -d'=' -f2) if [ -n "$stored" ]; then echo "$stored" return fi fi echo "unknown" } # Save installed version to version file save_installed_version() { local app="$1" local version="$2" touch "$VERSION_FILE" if grep -q "^$app=" "$VERSION_FILE"; then sed -i "s/^$app=.*/$app=$version/" "$VERSION_FILE" else echo "$app=$version" >> "$VERSION_FILE" fi } # Ask the user whether to proceed when version can't be determined ask_user_proceed() { local app="$1" local latest="$2" echo "Warning: could not determine installed version of $app." echo "compile.conf specifies version $latest." read -rp "Compile and install $app anyway? [y/N] " response /dev/null && [ ! -f "$install_path" ] && [ ! -d "$install_path" ]; then echo " $app is not installed." return 0 fi local installed installed=$(get_installed_version "$app" "$gui" "$type" "$install_path") if [ "$installed" = "unknown" ]; then if ask_user_proceed "$app" "$latest"; then return 0 else return 1 fi fi echo " Installed version : $installed" echo " Latest version : $latest" if [ "$installed" = "$latest" ]; then echo " $app is up to date, skipping." return 1 fi echo " Update available for $app." return 0 } # Generate desktop file with absolute paths generate_desktop() { local desktop="$1" local tmp_desktop="/tmp/$(basename "$desktop")" sed "s|\$HOME|$HOME|g" "$desktop" > "$tmp_desktop" echo "$tmp_desktop" } # Install desktop file if specified install_desktop() { local desktop="$1" if [ -z "$desktop" ]; then return fi if [ ! -f "$desktop" ]; then echo " Warning: desktop file $desktop not found, skipping." return fi echo " Installing desktop file..." mkdir -p "$HOME/.local/share/applications" local resolved resolved=$(generate_desktop "$desktop") cp "$resolved" "$HOME/.local/share/applications/$(basename "$desktop")" chmod +x "$HOME/.local/share/applications/$(basename "$desktop")" rm -f "$resolved" echo " Desktop file installed." } # Fetch source via git or wget fetch_source() { local app="$1" local git_url="$2" local wget_url="$3" 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 --depth 1 "$git_url" "$src_dir" elif [ -n "$wget_url" ]; then echo " Downloading $wget_url..." local filename="${wget_url##*/}" local filepath="$TMP_DIR/$filename" wget -q "$wget_url" -O "$filepath" echo " Extracting $filename..." case "$filename" in *.zip) unzip -q "$filepath" -d "$src_dir" # If the zip extracted into a single subdirectory, flatten it local contents contents=$(ls -1 "$src_dir") local count count=$(echo "$contents" | wc -l) if [ "$count" -eq 1 ] && [ -d "$src_dir/$contents" ]; then echo " Descending into $contents..." local inner="$src_dir/$contents" shopt -s dotglob mv "$inner"/* "$src_dir/" shopt -u dotglob rm -rf "$inner" fi ;; *.tar.gz|*.tgz) tar -xzf "$filepath" -C "$src_dir" --strip-components=1 ;; *.tar.bz2) tar -xjf "$filepath" -C "$src_dir" --strip-components=1 ;; *.tar.xz) tar -xJf "$filepath" -C "$src_dir" --strip-components=1 ;; *) echo " Error: unknown file type for $filename" exit 1 ;; esac rm -f "$filepath" else echo " Error: no git or wget URL specified for $app" exit 1 fi } # cd into source directory and run steps run_steps() { local app="$1" local steps="$2" local src_dir="$TMP_DIR/$app" if [ ! -d "$src_dir" ]; then echo " Error: source directory $src_dir not found." exit 1 fi echo " Changing into $src_dir..." cd "$src_dir" echo " Building $app..." IFS='|' read -ra step_list <<< "$steps" for step in "${step_list[@]}"; do step=$(echo "$step" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') echo " Running: $step" eval "$step" done } # Process a single app process_app() { local app="$1" local git_url="$2" local wget_url="$3" local install_path="$4" local steps="$5" local version="$6" local desktop="$7" local gui="$8" local type="$9" echo "" echo "=== $app ===" # Check if already installed if command -v "$app" &> /dev/null || [ -f "$install_path" ] || [ -d "$install_path" ]; then if [ -z "$version" ]; then echo " $app is already installed, skipping." return fi fi if [ -z "$version" ]; then echo " Warning: no version specified in compile.conf for $app." read -rp " Compile and install $app anyway? [y/N] " response