mirror of
https://github.com/neovim/neovim.git
synced 2026-11-06 13:26:57 +00:00
Problem: - remote_ssh.sh detects ssh disconnect by writing a heartbeat every 1s, which the local side buffers for the whole session. - The server's stdout (e.g. `io.write()` from a random plugin) writes to the tunnel, which in theory may contain a bogus "NVIM_READY". - A nightly install is never updated on the remote. Solution: - Supervise the server in `vim.net._ssh.serve()` (Lua). It detects disconnect via stdin EOF and discards server stdout. The script only finds or installs `nvim`. - Also a step toward Windows remotes. - User may choose "Update Nvim" to reinstall the nightly.
70 lines
2.3 KiB
Bash
70 lines
2.3 KiB
Bash
#!/bin/sh
|
|
|
|
# Bootstraps the headless Nvim server of a |remote-ssh| session: finds or installs `nvim`, which then
|
|
# runs and supervises the server (vim.net._ssh.serve()).
|
|
#
|
|
# Usage: remote_ssh.sh [--update] {sock} {dir} {url} [{version}]
|
|
# Runs `nvim` from $PATH if it is {version} or newer, else the release {url}, which it installs
|
|
# to {dir} (relative to $HOME) unless present, or always with --update. E.g.
|
|
# remote_ssh.sh /tmp/nvim-remote.0123abcd/nvim.sock .local/share/nvim-remote/releases/v0.12.0-linux-x86_64 https://…/nvim-linux-x86_64.tar.gz v0.12.0
|
|
|
|
set -eu
|
|
# dash (Debian's sh) has no pipefail; tar still fails on an empty or truncated stream.
|
|
# shellcheck disable=SC3040
|
|
if (set -o pipefail) 2>/dev/null; then
|
|
set -o pipefail
|
|
fi
|
|
|
|
# Prints the path of `nvim` on $PATH, if it is $want or newer. It checks its own version, so an old
|
|
# or broken one fails.
|
|
# TODO: $PATH is that of a non-login shell, so it may lack e.g. `~/.local/bin`. Could take it from
|
|
# a throwaway login shell: `"$SHELL" -lc 'printf %s "$PATH"'`.
|
|
system_nvim() {
|
|
[ -n "$want" ] || return 1
|
|
nvim=$(command -v nvim) || return 1
|
|
want=$want "$nvim" --clean -es \
|
|
+'lua os.exit(vim.version.ge(vim.version(), os.getenv("want")) and 0 or 1)' \
|
|
</dev/null >/dev/null 2>&1 || return 1
|
|
echo "$nvim"
|
|
}
|
|
|
|
# Installs the release to $dest, unless present (and not $update).
|
|
install_release() (
|
|
if [ -x "$dest/bin/nvim" ] && [ -z "$update" ]; then
|
|
exit 0
|
|
fi
|
|
echo "Installing $dest..." >&2
|
|
mkdir -p "${dest%/*}"
|
|
tmp=$(mktemp -d "$dest.XXXXXX")
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
mkdir "$tmp/new"
|
|
curl -fsSL "$url" | tar -xzf - -C "$tmp/new"
|
|
if [ -n "$update" ]; then
|
|
# Removed with $tmp. Gone already if a concurrent update moved it.
|
|
mv "$dest" "$tmp/old" 2>/dev/null || :
|
|
fi
|
|
# The archive holds one top-level dir, e.g. `nvim-linux-x86_64/`. Atomic rename; keeps a
|
|
# concurrent install that finished first.
|
|
[ -e "$dest" ] || mv "$tmp"/new/* "$dest"
|
|
)
|
|
|
|
main() {
|
|
update=
|
|
if [ "$1" = --update ]; then
|
|
update=1
|
|
shift
|
|
fi
|
|
sock=$1
|
|
dest="$HOME/$2"
|
|
url=$3
|
|
want=${4-}
|
|
if ! nvim=$(system_nvim); then
|
|
install_release
|
|
nvim="$dest/bin/nvim"
|
|
fi
|
|
# Nvim inherits stdin from `sh -s` (i.e. from ssh), so EOF tells serve() that ssh disconnected.
|
|
exec "$nvim" --clean -n --headless +"lua require('vim.net._ssh').serve('$sock')" +qa!
|
|
}
|
|
|
|
main "$@"
|