Support more recent VSCode Server versions (#78)

* fix uses of ~ that should be $HOME

* Support for new vscode server directory structure

* Be backwards compatible with previous versions of nixos-vscode-server

by copying the patch marker files
This commit is contained in:
Thomas B 2024-04-24 13:29:08 +02:00 committed by GitHub
parent d0ed9b8cf1
commit fc900c16ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 38 deletions

View File

@ -144,7 +144,7 @@ The installation path for VS Code server is configurable and the default can dif
```nix ```nix
{ {
services.vscode-server.installPath = "~/.vscode-server-oss"; services.vscode-server.installPath = "$HOME/.vscode-server-oss";
} }
``` ```

View File

@ -34,8 +34,8 @@ moduleConfig: {
installPath = mkOption { installPath = mkOption {
type = str; type = str;
default = "~/.vscode-server"; default = "$HOME/.vscode-server";
example = "~/.vscode-server-oss"; example = "$HOME/.vscode-server-oss";
description = '' description = ''
The install path. The install path.
''; '';

View File

@ -21,7 +21,7 @@
enableFHS ? false, enableFHS ? false,
nodejsPackage ? null, nodejsPackage ? null,
extraRuntimeDependencies ? [ ], extraRuntimeDependencies ? [ ],
installPath ? "~/.vscode-server", installPath ? "$HOME/.vscode-server",
postPatch ? "", postPatch ? "",
}: let }: let
inherit (lib) makeBinPath makeLibraryPath optionalString; inherit (lib) makeBinPath makeLibraryPath optionalString;
@ -71,10 +71,8 @@
name = "patchelf-vscode-server"; name = "patchelf-vscode-server";
runtimeInputs = [ coreutils findutils patchelf ]; runtimeInputs = [ coreutils findutils patchelf ];
text = '' text = ''
bin=$1 bin_dir="$1"
bin_dir=${installPath}/bin/$bin patched_file="$bin_dir/.nixos-patched"
patched_file=${installPath}/.$bin.patched
orig_node=${installPath}/.$bin.node
# NOTE: We don't log here because it won't show up in the output of the user service. # NOTE: We don't log here because it won't show up in the output of the user service.
@ -109,7 +107,6 @@
patchelf --shrink-rpath "$elf" patchelf --shrink-rpath "$elf"
} }
patch_elf "$orig_node"
while read -rd ''' elf; do while read -rd ''' elf; do
patch_elf "$elf" patch_elf "$elf"
done < <(find "$bin_dir" -type f -perm -100 -printf '%p\0') done < <(find "$bin_dir" -type f -perm -100 -printf '%p\0')
@ -126,31 +123,41 @@
name = "auto-fix-vscode-server"; name = "auto-fix-vscode-server";
runtimeInputs = [ coreutils findutils inotify-tools ]; runtimeInputs = [ coreutils findutils inotify-tools ];
text = '' text = ''
bins_dir=${installPath}/bin bins_dir_1=${installPath}/bin
bins_dir_2=${installPath}/cli/servers
patch_bin () { patch_bin () {
local bin=$1 local actual_dir="$1"
bin=''${bin:0:40} local patched_file="$actual_dir/.nixos-patched"
local actual_dir=$bins_dir/$1
local patched_file=${installPath}/.$bin.patched
if [[ -e $patched_file ]]; then if [[ -e $patched_file ]]; then
return 0 return 0
fi fi
# Backwards compatibility with previous versions of nixos-vscode-server.
local old_patched_file
old_patched_file="$(basename "$actual_dir")"
if [[ $old_patched_file == "server" ]]; then
old_patched_file="$(basename "$(dirname "$actual_dir")")"
old_patched_file="${installPath}/.''${old_patched_file%%.*}.patched"
else
old_patched_file="${installPath}/.''${old_patched_file%%-*}.patched"
fi
if [[ -e $old_patched_file ]]; then
echo "Migrating old nixos-vscode-server patch marker file to new location in $actual_dir." >&2
cp "$old_patched_file" "$patched_file"
return 0
fi
echo "Patching Node.js of VS Code server installation in $actual_dir..." >&2 echo "Patching Node.js of VS Code server installation in $actual_dir..." >&2
${optionalString (nodejs != null) '' mv "$actual_dir/node" "$actual_dir/node.patched"
ln -sfT ${
if enableFHS ${optionalString (enableFHS) ''
then nodejsFHS ln -sfT ${nodejsFHS}/bin/node "$actual_dir/node"
else nodejs
}/bin/node "$actual_dir/node"
''} ''}
${optionalString (!enableFHS || postPatch != "") '' ${optionalString (!enableFHS || postPatch != "") ''
local orig_node=${installPath}/.$bin.node
mv "$actual_dir/node" "$orig_node"
cat <<EOF > "$actual_dir/node" cat <<EOF > "$actual_dir/node"
#!${runtimeShell} #!${runtimeShell}
@ -159,10 +166,15 @@
# We leave the rest up to the Bash script # We leave the rest up to the Bash script
# to keep having to deal with 'sh' compatibility to a minimum. # to keep having to deal with 'sh' compatibility to a minimum.
${patchELFScript}/bin/patchelf-vscode-server '$bin' ${patchELFScript}/bin/patchelf-vscode-server \$(dirname "\$0")
# Let Node.js take over as if this script never existed. # Let Node.js take over as if this script never existed.
exec '$orig_node' "\$@" ${
let nodePath = (if (nodejs != null)
then "${if enableFHS then nodejsFHS else nodejs}/bin/node"
else ''\$(dirname "\$0")/node.patched'');
in ''exec "${nodePath}" "\$@"''
}
EOF EOF
chmod +x "$actual_dir/node" chmod +x "$actual_dir/node"
''} ''}
@ -171,30 +183,39 @@
echo 0 > "$patched_file" echo 0 > "$patched_file"
} }
# Fix any existing symlinks before we enter the inotify loop. mkdir -p "$bins_dir_1" "$bins_dir_2"
if [[ -e $bins_dir ]]; then while read -rd ''' bin; do
while read -rd ''' bin; do if [[ $bin == "$bins_dir_2"* ]]; then
patch_bin "$bin" bin="$bin/server"
done < <(find "$bins_dir" -mindepth 1 -maxdepth 1 -type d -printf '%P\0') fi
else patch_bin "$bin"
mkdir -p "$bins_dir" done < <(find "$bins_dir_1" "$bins_dir_2" -mindepth 1 -maxdepth 1 -type d -printf '%p\0')
fi
while IFS=: read -r bins_dir bin event; do
while IFS=: read -r bin event; do
# A new version of the VS Code Server is being created. # A new version of the VS Code Server is being created.
if [[ $event == 'CREATE,ISDIR' ]]; then if [[ $event == 'CREATE,ISDIR' ]]; then
actual_dir=$bins_dir/$bin actual_dir="$bins_dir$bin"
if [[ "$bins_dir" == "$bins_dir_2/" ]]; then
actual_dir="$actual_dir/server"
# Hope that VSCode will not die if the directory exists when it tries to install, otherwise we'll need to
# use a coproc to wait for the directory to be created without entering in a race, then watch for the node
# file to be created (probably while also avoiding a race)
# https://unix.stackexchange.com/a/185370
mkdir -p "$actual_dir"
fi
echo "VS Code server is being installed in $actual_dir..." >&2 echo "VS Code server is being installed in $actual_dir..." >&2
# Quickly create a node file, which will be removed when vscode installs its own version
touch "$actual_dir/node" touch "$actual_dir/node"
# Hope we don't race...
inotifywait -qq -e DELETE_SELF "$actual_dir/node" inotifywait -qq -e DELETE_SELF "$actual_dir/node"
patch_bin "$bin" patch_bin "$actual_dir"
# The monitored directory is deleted, e.g. when "Uninstall VS Code Server from Host" has been run. # The monitored directory is deleted, e.g. when "Uninstall VS Code Server from Host" has been run.
elif [[ $event == DELETE_SELF ]]; then elif [[ $event == DELETE_SELF ]]; then
# See the comments above Restart in the service config. # See the comments above Restart in the service config.
exit 0 exit 0
fi fi
done < <(inotifywait -q -m -e CREATE,ISDIR -e DELETE_SELF --format '%f:%e' "$bins_dir") done < <(inotifywait -q -m -e CREATE,ISDIR -e DELETE_SELF --format '%w:%f:%e' "$bins_dir_1" "$bins_dir_2")
''; '';
}; };
in in
autoFixScript autoFixScript