|
|
@@ -0,0 +1,212 @@
|
|
|
+#!/bin/bash
|
|
|
+# compile.sh - Compile installer sources into a single distributable script
|
|
|
+# This script is run during the build process to create the final installer
|
|
|
+
|
|
|
+set -e
|
|
|
+
|
|
|
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
+OUTPUT_FILE="${1:-install-usm.sh}"
|
|
|
+VERSION="${2:-0.1.0}"
|
|
|
+USM_SOURCE_DIR="${3:-$SCRIPT_DIR/../src}"
|
|
|
+
|
|
|
+# Temporary directory for building
|
|
|
+WORK_DIR=$(mktemp -d)
|
|
|
+trap "rm -rf $WORK_DIR" EXIT
|
|
|
+
|
|
|
+echo "Compiling USM installer..."
|
|
|
+echo " Version: $VERSION"
|
|
|
+echo " Output: $OUTPUT_FILE"
|
|
|
+echo " USM Source: $USM_SOURCE_DIR"
|
|
|
+
|
|
|
+# Step 1: Clone external repositories
|
|
|
+echo "Cloning external repositories..."
|
|
|
+SOURCES_DIR="$WORK_DIR/sources"
|
|
|
+mkdir -p "$SOURCES_DIR"
|
|
|
+
|
|
|
+# Clone Invercargill
|
|
|
+if [[ ! -d "$SOURCES_DIR/Invercargill" ]]; then
|
|
|
+ echo " Cloning Invercargill..."
|
|
|
+ git clone --depth 1 https://fabrica.unitatem.net/Tilo15/Invercargill.git "$SOURCES_DIR/Invercargill" 2>/dev/null || {
|
|
|
+ echo "Warning: Could not clone Invercargill, will try without --depth 1"
|
|
|
+ git clone https://fabrica.unitatem.net/Tilo15/Invercargill.git "$SOURCES_DIR/Invercargill" 2>/dev/null || {
|
|
|
+ echo "Error: Could not clone Invercargill repository"
|
|
|
+ exit 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+fi
|
|
|
+
|
|
|
+# Clone Invercargill-Json
|
|
|
+if [[ ! -d "$SOURCES_DIR/Invercargill-Json" ]]; then
|
|
|
+ echo " Cloning Invercargill-Json..."
|
|
|
+ git clone --depth 1 https://git.sr.ht/~tilo15/Invercargill-Json "$SOURCES_DIR/Invercargill-Json" 2>/dev/null || {
|
|
|
+ echo "Warning: Could not clone Invercargill-Json, will try without --depth 1"
|
|
|
+ git clone https://git.sr.ht/~tilo15/Invercargill-Json "$SOURCES_DIR/Invercargill-Json" 2>/dev/null || {
|
|
|
+ echo "Error: Could not clone Invercargill-Json repository"
|
|
|
+ exit 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+fi
|
|
|
+
|
|
|
+# Copy USM source
|
|
|
+echo "Copying USM source..."
|
|
|
+mkdir -p "$SOURCES_DIR/usm"
|
|
|
+cp -r "$USM_SOURCE_DIR" "$SOURCES_DIR/usm/src"
|
|
|
+cp "$USM_SOURCE_DIR/../MANIFEST.usm" "$SOURCES_DIR/usm/" 2>/dev/null || true
|
|
|
+cp "$USM_SOURCE_DIR/../usm.config" "$SOURCES_DIR/usm/" 2>/dev/null || true
|
|
|
+
|
|
|
+# Step 2: Create the combined script header
|
|
|
+echo "Building combined script..."
|
|
|
+HEADER_FILE="$WORK_DIR/header.sh"
|
|
|
+
|
|
|
+cat > "$HEADER_FILE" << SCRIPT_HEADER
|
|
|
+#!/bin/bash
|
|
|
+# USM Installer - self-contained installation script
|
|
|
+# This script was automatically generated. Do not edit.
|
|
|
+# Version: $VERSION
|
|
|
+# Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
|
|
+
|
|
|
+set -e
|
|
|
+
|
|
|
+SCRIPT_HEADER
|
|
|
+
|
|
|
+# Step 3: Combine all shell scripts
|
|
|
+# We need to rename the PM functions to avoid conflicts
|
|
|
+COMBINED_FILE="$WORK_DIR/combined.sh"
|
|
|
+
|
|
|
+# Function to process a bash script (minify and adapt)
|
|
|
+process_script() {
|
|
|
+ local file="$1"
|
|
|
+ local section="$2"
|
|
|
+
|
|
|
+ echo "# === $section ==="
|
|
|
+
|
|
|
+ # For PM files, we need to prefix the functions
|
|
|
+ case "$section" in
|
|
|
+ "Package Manager APT")
|
|
|
+ # Rename functions with apt_ prefix
|
|
|
+ sed -e 's/^pm_is_installed()/pm_apt_is_installed()/' \
|
|
|
+ -e 's/^pm_get_package_name()/pm_apt_get_package_name()/' \
|
|
|
+ -e 's/^pm_update()/pm_apt_update()/' \
|
|
|
+ -e 's/^pm_install()/pm_apt_install()/' \
|
|
|
+ -e 's/^get_missing_deps()/get_missing_deps_apt()/' \
|
|
|
+ "$file"
|
|
|
+ ;;
|
|
|
+ "Package Manager DNF")
|
|
|
+ # Rename functions with dnf_ prefix
|
|
|
+ sed -e 's/^pm_is_installed()/pm_dnf_is_installed()/' \
|
|
|
+ -e 's/^pm_get_package_name()/pm_dnf_get_package_name()/' \
|
|
|
+ -e 's/^pm_update()/pm_dnf_update()/' \
|
|
|
+ -e 's/^pm_install()/pm_dnf_install()/' \
|
|
|
+ -e 's/^get_missing_deps()/get_missing_deps_dnf()/' \
|
|
|
+ "$file"
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ cat "$file"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# Create the dispatcher functions
|
|
|
+DISPATCHER_FILE="$WORK_DIR/dispatcher.sh"
|
|
|
+
|
|
|
+cat > "$DISPATCHER_FILE" << 'DISPATCHER'
|
|
|
+
|
|
|
+# === Package Manager Dispatcher ===
|
|
|
+# These functions dispatch to the appropriate PM implementation
|
|
|
+
|
|
|
+pm_is_installed() {
|
|
|
+ case "$PM_TYPE" in
|
|
|
+ apt) pm_apt_is_installed "$@" ;;
|
|
|
+ dnf) pm_dnf_is_installed "$@" ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+pm_get_package_name() {
|
|
|
+ case "$PM_TYPE" in
|
|
|
+ apt) pm_apt_get_package_name "$@" ;;
|
|
|
+ dnf) pm_dnf_get_package_name "$@" ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+pm_update() {
|
|
|
+ case "$PM_TYPE" in
|
|
|
+ apt) pm_apt_update "$@" ;;
|
|
|
+ dnf) pm_dnf_update "$@" ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+pm_install() {
|
|
|
+ case "$PM_TYPE" in
|
|
|
+ apt) pm_apt_install "$@" ;;
|
|
|
+ dnf) pm_dnf_install "$@" ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+get_missing_deps() {
|
|
|
+ case "$PM_TYPE" in
|
|
|
+ apt) get_missing_deps_apt "$@" ;;
|
|
|
+ dnf) get_missing_deps_dnf "$@" ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+DISPATCHER
|
|
|
+
|
|
|
+# Combine scripts in order - IMPORTANT:
|
|
|
+# 1. PM implementations (apt, dnf) come first with prefixed names
|
|
|
+# 2. Dispatcher comes next to provide the generic interface
|
|
|
+# 3. pm_base.sh uses the generic interface (get_missing_deps, etc.)
|
|
|
+# 4. main.sh and others come last
|
|
|
+{
|
|
|
+ process_script "$SCRIPT_DIR/utils.sh" "Utils"
|
|
|
+ echo ""
|
|
|
+ process_script "$SCRIPT_DIR/ui.sh" "UI"
|
|
|
+ echo ""
|
|
|
+ # PM implementations first (with prefixed function names)
|
|
|
+ process_script "$SCRIPT_DIR/pm_apt.sh" "Package Manager APT"
|
|
|
+ echo ""
|
|
|
+ process_script "$SCRIPT_DIR/pm_dnf.sh" "Package Manager DNF"
|
|
|
+ echo ""
|
|
|
+ # Dispatcher provides the generic interface using PM_TYPE
|
|
|
+ cat "$DISPATCHER_FILE"
|
|
|
+ echo ""
|
|
|
+ # Now pm_base.sh can use the generic interface
|
|
|
+ process_script "$SCRIPT_DIR/pm_base.sh" "Package Manager Base"
|
|
|
+ echo ""
|
|
|
+ process_script "$SCRIPT_DIR/build_config.sh" "Build Config"
|
|
|
+ echo ""
|
|
|
+ process_script "$SCRIPT_DIR/main.sh" "Main"
|
|
|
+ echo ""
|
|
|
+ # Add the main call at the very end
|
|
|
+ echo "# Run main function"
|
|
|
+ echo 'main "$@"'
|
|
|
+} > "$COMBINED_FILE"
|
|
|
+
|
|
|
+# Replace version placeholder in combined file
|
|
|
+sed -i "s/@VERSION@/$VERSION/g" "$COMBINED_FILE"
|
|
|
+
|
|
|
+# Step 4: Create the payload
|
|
|
+echo "Creating compressed payload..."
|
|
|
+PAYLOAD_FILE="$WORK_DIR/payload.tar.xz"
|
|
|
+
|
|
|
+# Use highest compression for smaller file size
|
|
|
+tar -C "$SOURCES_DIR" -cf - . | xz -9 -T0 > "$PAYLOAD_FILE"
|
|
|
+
|
|
|
+# Step 5: Assemble final installer
|
|
|
+echo "Assembling final installer..."
|
|
|
+{
|
|
|
+ cat "$HEADER_FILE"
|
|
|
+ cat "$COMBINED_FILE"
|
|
|
+ echo ""
|
|
|
+ echo "__PAYLOAD_START__"
|
|
|
+ cat "$PAYLOAD_FILE"
|
|
|
+} > "$OUTPUT_FILE"
|
|
|
+
|
|
|
+# Make executable
|
|
|
+chmod +x "$OUTPUT_FILE"
|
|
|
+
|
|
|
+# Calculate output size
|
|
|
+OUTPUT_SIZE=$(du -h "$OUTPUT_FILE" | cut -f1)
|
|
|
+echo ""
|
|
|
+echo "✓ Installer created successfully!"
|
|
|
+echo " Output: $OUTPUT_FILE"
|
|
|
+echo " Size: $OUTPUT_SIZE"
|