diff --git a/README.md b/README.md index cd41ab6..46f2b66 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ The installation path for VS Code server is configurable and the default can dif ```nix { - services.vscode-server.installPath = "~/.vscode-server-oss"; + services.vscode-server.installPath = "$HOME/.vscode-server-oss"; } ``` diff --git a/modules/vscode-server/module.nix b/modules/vscode-server/module.nix index 0658aed..4bf714b 100644 --- a/modules/vscode-server/module.nix +++ b/modules/vscode-server/module.nix @@ -34,8 +34,8 @@ moduleConfig: { installPath = mkOption { type = str; - default = "~/.vscode-server"; - example = "~/.vscode-server-oss"; + default = "$HOME/.vscode-server"; + example = "$HOME/.vscode-server-oss"; description = '' The install path. ''; diff --git a/pkgs/auto-fix-vscode-server.nix b/pkgs/auto-fix-vscode-server.nix index 94f8a16..2649e40 100644 --- a/pkgs/auto-fix-vscode-server.nix +++ b/pkgs/auto-fix-vscode-server.nix @@ -21,7 +21,7 @@ enableFHS ? false, nodejsPackage ? null, extraRuntimeDependencies ? [ ], - installPath ? "~/.vscode-server", + installPath ? "$HOME/.vscode-server", postPatch ? "", }: let inherit (lib) makeBinPath makeLibraryPath optionalString; @@ -71,10 +71,8 @@ name = "patchelf-vscode-server"; runtimeInputs = [ coreutils findutils patchelf ]; text = '' - bin=$1 - bin_dir=${installPath}/bin/$bin - patched_file=${installPath}/.$bin.patched - orig_node=${installPath}/.$bin.node + bin_dir="$1" + patched_file="$bin_dir/.nixos-patched" # 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" } - patch_elf "$orig_node" while read -rd ''' elf; do patch_elf "$elf" done < <(find "$bin_dir" -type f -perm -100 -printf '%p\0') @@ -126,31 +123,41 @@ name = "auto-fix-vscode-server"; runtimeInputs = [ coreutils findutils inotify-tools ]; text = '' - bins_dir=${installPath}/bin + bins_dir_1=${installPath}/bin + bins_dir_2=${installPath}/cli/servers patch_bin () { - local bin=$1 - bin=''${bin:0:40} - local actual_dir=$bins_dir/$1 - local patched_file=${installPath}/.$bin.patched + local actual_dir="$1" + local patched_file="$actual_dir/.nixos-patched" if [[ -e $patched_file ]]; then return 0 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 - ${optionalString (nodejs != null) '' - ln -sfT ${ - if enableFHS - then nodejsFHS - else nodejs - }/bin/node "$actual_dir/node" + mv "$actual_dir/node" "$actual_dir/node.patched" + + ${optionalString (enableFHS) '' + ln -sfT ${nodejsFHS}/bin/node "$actual_dir/node" ''} ${optionalString (!enableFHS || postPatch != "") '' - local orig_node=${installPath}/.$bin.node - mv "$actual_dir/node" "$orig_node" cat < "$actual_dir/node" #!${runtimeShell} @@ -159,10 +166,15 @@ # We leave the rest up to the Bash script # 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. - 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 chmod +x "$actual_dir/node" ''} @@ -171,30 +183,39 @@ echo 0 > "$patched_file" } - # Fix any existing symlinks before we enter the inotify loop. - if [[ -e $bins_dir ]]; then - while read -rd ''' bin; do - patch_bin "$bin" - done < <(find "$bins_dir" -mindepth 1 -maxdepth 1 -type d -printf '%P\0') - else - mkdir -p "$bins_dir" - fi - - while IFS=: read -r bin event; do + mkdir -p "$bins_dir_1" "$bins_dir_2" + while read -rd ''' bin; do + if [[ $bin == "$bins_dir_2"* ]]; then + bin="$bin/server" + fi + patch_bin "$bin" + done < <(find "$bins_dir_1" "$bins_dir_2" -mindepth 1 -maxdepth 1 -type d -printf '%p\0') + + while IFS=: read -r bins_dir bin event; do # A new version of the VS Code Server is being created. 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 + # Quickly create a node file, which will be removed when vscode installs its own version touch "$actual_dir/node" + # Hope we don't race... 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. elif [[ $event == DELETE_SELF ]]; then # See the comments above Restart in the service config. exit 0 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 - autoFixScript +autoFixScript