#!/bin/sh
# AppRun for the SSH Pilot AppImage.
#
# The bundled binaries find their libraries through an $ORIGIN RPATH written by
# packaging/appimage/build-appimage.sh, so this script deliberately does NOT
# export LD_LIBRARY_PATH, PYTHONHOME or PYTHONPATH. That matters more here than
# in most apps: sshpilot spawns the user's shell inside a VTE terminal, plus
# ssh/scp/sshpass, and a leaked library or Python path would break those host
# binaries. The bundled interpreter finds the bundled modules on its own,
# because it sits in the usual $prefix/bin + $prefix/lib layout under usr/.
#
# What is left below is the data GTK can only find through the environment,
# and the choice of C library.

set -eu

SELF=$(readlink -f "$0")
APPDIR=${APPDIR:-$(dirname "$SELF")}
export APPDIR

export XDG_DATA_DIRS="$APPDIR/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
export GI_TYPELIB_PATH="$APPDIR/usr/lib/girepository-1.0"
# Additive in GLib: host schemas stay reachable through XDG_DATA_DIRS.
export GSETTINGS_SCHEMA_DIR="$APPDIR/usr/share/glib-2.0/schemas"
export GIO_MODULE_DIR="$APPDIR/usr/lib/gio/modules"

# WebKitGTK renders out of process and has the helper paths compiled in, which
# point at the build host's /usr. Without these two a WebView just never
# finishes loading: no PyXterm.js terminal and no Host Info tab.
export WEBKIT_EXEC_PATH="$APPDIR/usr/lib/webkitgtk-6.0"
export WEBKIT_INJECTED_BUNDLE_PATH="$APPDIR/usr/lib/webkitgtk-6.0/injected-bundle"

# xterm.js assets: the app prefers the host's /usr/share/javascript/xterm when
# it exists, which for a self-contained bundle is the wrong copy. The env
# override the app already supports points it back at our own.
for xterm_dir in "$APPDIR"/usr/lib/python3*/*-packages/sshpilot/vendor/pyxtermjs/xterm; do
    if [ -f "$xterm_dir/xterm.js" ]; then
        export PYXTERMJS_ASSETS_DIR="$xterm_dir"
        break
    fi
done

# The loaders.cache has to name the loaders by absolute path, which is only
# known once the AppImage is mounted. Materialise it per user rather than
# writing into the read-only mount; a fixed path keeps this from piling up.
pixbuf_template="$APPDIR/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache.in"
if [ -f "$pixbuf_template" ]; then
    pixbuf_cache_dir="${XDG_CACHE_HOME:-${HOME:-/tmp}/.cache}/sshpilot/appimage"
    if mkdir -p "$pixbuf_cache_dir" 2>/dev/null &&
       sed "s|@APPDIR@|$APPDIR|g" "$pixbuf_template" \
           > "$pixbuf_cache_dir/loaders.cache" 2>/dev/null; then
        export GDK_PIXBUF_MODULEDIR="$APPDIR/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders"
        export GDK_PIXBUF_MODULE_FILE="$pixbuf_cache_dir/loaders.cache"
    fi
fi

# The C library. Everything bundled was linked against the build host's glibc,
# which the image also carries in usr/lib/libc. A host at least that new runs
# the app on its own glibc, as any other package would; an older one gets the
# bundled glibc through the wrappers the build writes, which run the
# interpreter and the WebKit helpers through the bundled loader. The host's
# glibc is preferred whenever it can work because the libraries still taken
# from the host (GL drivers, X11, fonts) are built against it, and a newer
# host's copies would not load on an older bundled glibc.
#
# SSHPILOT_APPIMAGE_LIBC=host|bundled overrides the choice, for diagnosis.
version_older() { # $1 < $2, both "major.minor"
    [ "${1%%.*}" -lt "${2%%.*}" ] ||
        { [ "${1%%.*}" -eq "${2%%.*}" ] && [ "${1#*.}" -lt "${2#*.}" ]; }
}

use_bundled_libc() {
    case "${SSHPILOT_APPIMAGE_LIBC:-auto}" in
        bundled) return 0 ;;
        host) return 1 ;;
    esac
    bundled=$(cat "$APPDIR/usr/lib/libc/VERSION" 2>/dev/null) || return 1
    # getconf is part of glibc itself; a host without it has nothing better to
    # offer than its own C library, so keep to the host there.
    host=$(getconf GNU_LIBC_VERSION 2>/dev/null) || return 1
    host=${host#glibc }
    case "$host.$bundled" in
        *[!0-9.]*) return 1 ;;
    esac
    version_older "$host" "$bundled"
}

SSHPILOT_PYTHON="$APPDIR/usr/bin/python3"
if use_bundled_libc; then
    SSHPILOT_PYTHON="$APPDIR/usr/bin/python3-bundled-libc"
    export WEBKIT_EXEC_PATH="$APPDIR/usr/lib/webkitgtk-6.0-bundled-libc"
fi

exec "$SSHPILOT_PYTHON" "$APPDIR/usr/bin/sshpilot" "$@"
