diff --git a/kittens/ssh/main.py b/kittens/ssh/main.py index c9a630094..015db4198 100644 --- a/kittens/ssh/main.py +++ b/kittens/ssh/main.py @@ -30,7 +30,7 @@ from typing import ( from kitty.constants import ( cache_dir, runtime_dir, shell_integration_dir, ssh_control_master_template, - terminfo_dir + str_version, terminfo_dir ) from kitty.options.types import Options from kitty.shm import SharedMemory @@ -171,6 +171,9 @@ def make_tarfile(ssh_opts: SSHOptions, base_env: Dict[str, str], compression: st f'{arcname}/ssh/*', # bootstrap files are sent as command line args f'{arcname}/zsh/kitty.zsh', # present for legacy compat not needed by ssh kitten )) + arcname = 'home/' + rd + '/kitty' + add_data_as_file(tf, arcname + '/version', str_version.encode('ascii')) + tf.add(shell_integration_dir + '/ssh/kitty', arcname=arcname + '/bin/kitty', filter=normalize_tarinfo) tf.add(f'{terminfo_dir}/kitty.terminfo', arcname='home/.terminfo/kitty.terminfo', filter=normalize_tarinfo) tf.add(glob.glob(f'{terminfo_dir}/*/xterm-kitty')[0], arcname='home/.terminfo/x/xterm-kitty', filter=normalize_tarinfo) return buf.getvalue() diff --git a/kitty_tests/ssh.py b/kitty_tests/ssh.py index 919a9d362..1f4241466 100644 --- a/kitty_tests/ssh.py +++ b/kitty_tests/ssh.py @@ -136,7 +136,8 @@ copy --exclude */w.* d1 contents.discard(f'{tname}/x/xterm-kitty') contents.discard(f'{tname}/78/xterm-kitty') self.ae(contents, { - 'g.1', 'g.2', f'{tname}/kitty.terminfo', 'simple-file', 'd1/d2/x', 'd1/y', 'a/sfa' + 'g.1', 'g.2', f'{tname}/kitty.terminfo', 'simple-file', 'd1/d2/x', 'd1/y', 'a/sfa', + '.local/share/kitty-ssh-kitten/kitty/version', '.local/share/kitty-ssh-kitten/kitty/bin/kitty' }) self.ae(len(glob.glob(f'{remote_home}/{tname}/*/xterm-kitty')), 2) diff --git a/shell-integration/ssh/kitty b/shell-integration/ssh/kitty new file mode 100755 index 000000000..78ecdde7b --- /dev/null +++ b/shell-integration/ssh/kitty @@ -0,0 +1,92 @@ +#!/bin/sh + +{ \unalias command; \unset -f command; } >/dev/null 2>&1 + + +die() { printf "\033[31m%s\033[m\n\r" "$*" > /dev/stderr; exit 1; } + +exec_kitty() { + exec "$kitty_exe" "$@" + die "Failed to execute kitty" +} + +script_path=$(command readlink -f "$0" 2> /dev/null) +[ $? == 0 ] || script_path="$0" +script_dir=$(command dirname "$script_path") +install_dir="$(command dirname "$script_dir")/install" +kitty_exe="$install_dir/bin/kitty" +if [ -e "$kitty_exe" ]; then + local_kitty_version=$("$kitty_exe" +runpy "from kitty.constants import str_version; print(str_version)") + if [ $? = 0 ]; then + version_sort_key() { + printf "%05d%05d%05d" $(echo "$1" | command tr '.' '\n' | command head -n 3) + } + remote_kitty_version=$(command cat "$script_dir"/../version) + [ $? = 0 ] || die "Failed to read remote kitty version" + [ $(version_sort_key "$remote_kitty_version") -le $(version_sort_key "$local_kitty_version") ] && exec_kitty "$@" + fi +fi + +if command -v curl 2> /dev/null > /dev/null; then + fetch() { + command curl -fL "$1" + } + fetch_quiet() { + command curl -fsSL "$1" + } +elif command -v wget 2> /dev/null > /dev/null; then + fetch() { + command wget -O- "$1" + } + fetch_quiet() { + command wget --quiet -O- "$1" + } +else + die "Neither curl nor wget available, cannot download kitty" +fi + +case "$(command uname)" in + 'Linux') OS="linux";; + 'Darwin') OS="macos";; + *) die "kitty pre-built binaries are not available for the $(command uname) operating system";; +esac + +release_version=$(fetch_quiet "https://api.github.com/repos/kovidgoyal/kitty/releases/latest" | command grep tag_name | command cut -dv -f2 | command cut -d '"' -f1) +[ -z "$release_version" ] && die "Could not get kitty latest release version" +command rm -rf "$install_dir" + +if [ "$OS" = "linux" ]; then + case "$(command uname -m)" in + x86_64) arch="x86_64";; + aarch64*) arch="arm64";; + armv8*) arch="arm64";; + i386) arch="i686";; + i686) arch="i686";; + *) die "Unknown CPU architecture $(command uname -m)";; + esac + url="https://github.com/kovidgoyal/kitty/releases/download/v$release_version/kitty-$release_version-$arch.txz" +else + url="https://github.com/kovidgoyal/kitty/releases/download/v$release_version/kitty-$release_version.dmg" +fi + +printf "Downloading kitty from: \033[32m%s\033[m\n\n" "$url" +command mkdir -p "$install_dir" + +if [ "$OS" = "linux" ]; then + fetch "$url" | command tar -C "$install_dir" -xJof - + [ $? = 0 ] || die "Failed to download and install kitty" +else + tdir=$(command mktemp -d "$install_dir/tmp-for-dmg-XXXXXXXXXXXX") + [ $? = 0 ] || die "Creating temp directory failed" + fetch "$url" > "$tdir/kitty.dmg" + command mkdir "$tdir/mp" + command hdiutil attach "$tdir/kitty.dmg" "-mountpoint" "$tdir/mp" || die "Failed to mount kitty.dmg" + command ditto -v "$tdir/mp/kitty.app" "$install_dir/kitty.app" + rc="$?" + command hdiutil detach "$tdir/mp" + command rm -rf "$tdir" + [ "$rc" != "0" ] && die "Failed to copy kitty.app from mounted dmg" + command mkdir "$install_dir/bin" + command ln -sf "$install_dir/kitty.app/Contents/MacOS/kitty" "$install_dir/bin/kitty" +fi +exec_kitty "$@"