Merge pull request #88 from zeyugao/master

Support monitor multiple install path simultaneously

(e.g. using vscode, vscode-insiders, cursor etc simultaneously)
This commit is contained in:
Thomas B
2025-06-19 19:10:31 +02:00
committed by GitHub
3 changed files with 57 additions and 22 deletions
+14 -2
View File
@@ -140,14 +140,26 @@ This same list is also used to determine the `RPATH` when automatically patching
```
### `installPath`
The installation path for VS Code server is configurable and the default can differ for alternative builds (e.g. oss and insider), so this option allows you to configure which installation path should be monitered and automatically fixed.
The installation path for VS Code server is configurable. You can specify either a single path as a string or multiple paths as a list. If you have multiple installations (e.g., stable, OSS, and insider builds), you can specify all of them to be monitored and automatically fixed.
```nix
# Single path (string)
{
services.vscode-server.installPath = "$HOME/.vscode-server-oss";
services.vscode-server.installPath = "$HOME/.vscode-server";
}
# Multiple paths (list)
{
services.vscode-server.installPath = [
"$HOME/.vscode-server"
"$HOME/.vscode-server-oss"
"$HOME/.vscode-server-insiders"
];
}
```
String values are automatically coerced to a single-element list for backwards compatibility.
### `postPatch`
The goal of this project is to make VS Code server work with NixOS, anything more is outside of the scope of the project, but if you want additional things to be done, you can use this hook to run a shell script after the patching is done.
+7 -5
View File
@@ -33,11 +33,13 @@ moduleConfig: {
};
installPath = mkOption {
type = str;
default = "$HOME/.vscode-server";
example = "$HOME/.vscode-server-oss";
type = lib.types.coercedTo str (x: [x]) (listOf str);
default = [ "$HOME/.vscode-server" ];
example = [ "$HOME/.vscode-server" "$HOME/.vscode-server-oss" "$HOME/.vscode-server-insiders" ];
description = ''
The install path.
Path(s) where VS Code Server will be installed.
Accepts either a single path string or a list of paths.
String values are automatically coerced to a single-element list for backwards compatibility.
'';
};
@@ -71,7 +73,7 @@ moduleConfig: {
# Unfortunately the monitor does not kill itself when it stops monitoring,
# so rather than creating our own restart mechanism, we leverage systemd to do this for us.
Restart = "always";
RestartSec = 0;
RestartSec = 5;
ExecStart = "${auto-fix-vscode-server}/bin/auto-fix-vscode-server";
};
})
+36 -15
View File
@@ -21,7 +21,7 @@
enableFHS ? false,
nodejsPackage ? null,
extraRuntimeDependencies ? [ ],
installPath ? "$HOME/.vscode-server",
installPath ? [ "$HOME/.vscode-server" ],
postPatch ? "",
}: let
inherit (lib) makeBinPath makeLibraryPath optionalString;
@@ -123,11 +123,12 @@
name = "auto-fix-vscode-server";
runtimeInputs = [ coreutils findutils inotify-tools ];
text = ''
bins_dir_1=${installPath}/bin
bins_dir_2=${installPath}/cli/servers
# Convert installPath list to an array
IFS=':' read -r -a installPaths <<< "${lib.concatStringsSep ":" installPath}"
patch_bin () {
local actual_dir="$1"
local current_install_path="$2"
local patched_file="$actual_dir/.nixos-patched"
if [[ -e $patched_file ]]; then
@@ -139,9 +140,9 @@
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"
old_patched_file="$current_install_path/.''${old_patched_file%%.*}.patched"
else
old_patched_file="${installPath}/.''${old_patched_file%%-*}.patched"
old_patched_file="$current_install_path/.''${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
@@ -183,38 +184,58 @@
echo 0 > "$patched_file"
}
mkdir -p "$bins_dir_1" "$bins_dir_2"
while read -rd ''' bin; do
if [[ $bin == "$bins_dir_2"* ]]; then
# Initialize arrays for bins_dirs_1 and bins_dirs_2
bins_dirs_1=()
bins_dirs_2=()
# Populate bins_dirs_1 and bins_dirs_2 based on installPaths
for current_install_path in "''${installPaths[@]}"; do
bins_dirs_1+=("$current_install_path/bin")
bins_dirs_2+=("$current_install_path/cli/servers")
done
# Create directories and patch existing bins
for bins_dir_1 in "''${bins_dirs_1[@]}"; do
mkdir -p "$bins_dir_1"
while read -rd ''' bin; do
patch_bin "$bin" "$(dirname "$(dirname "$bin")")"
done < <(find "$bins_dir_1" -mindepth 1 -maxdepth 1 -type d -printf '%p\0')
done
for bins_dir_2 in "''${bins_dirs_2[@]}"; do
mkdir -p "$bins_dir_2"
while read -rd ''' bin; do
bin="$bin/server"
fi
patch_bin "$bin"
done < <(find "$bins_dir_1" "$bins_dir_2" -mindepth 1 -maxdepth 1 -type d -printf '%p\0')
patch_bin "$bin" "$(dirname "$(dirname "$bin")")"
done < <(find "$bins_dir_2" -mindepth 1 -maxdepth 1 -type d -printf '%p\0')
done
# Watch for new installations
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"
if [[ "$bins_dir" == "$bins_dir_2/" ]]; then
actual_install_path="$(dirname "$bins_dir")"
if [[ "$bins_dir" == */cli/servers/ ]]; 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"
actual_install_path="$(dirname "$(dirname "$bins_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 "$actual_dir"
patch_bin "$actual_dir" "$actual_install_path"
# 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 '%w:%f:%e' "$bins_dir_1" "$bins_dir_2")
done < <(inotifywait -q -m -e CREATE,ISDIR -e DELETE_SELF --format '%w:%f:%e' "''${bins_dirs_1[@]}" "''${bins_dirs_2[@]}")
'';
};
in