diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/assert.nu b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/assert.nu new file mode 100644 index 0000000000..0d1ff1f577 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/assert.nu @@ -0,0 +1,87 @@ +def main [mode: string] { + if $mode not-in ["config", "parent"] { + error make {msg: "Expected config or parent mode"} + } + $env.HOME = ($env.PWD | path join "user") + $env.XDG_CONFIG_HOME = ($env.HOME | path join "config") + $env.XDG_DATA_DIRS = ($env.HOME | path join "system-data") + $env.VP_HOME = ($env.PWD | path join "installation") + $env.VP_SKIP_DEPS_INSTALL = "1" + $env.VP_VERSION = "nushell-test" + $env.VP_NODE_MANAGER = "no" + $env.VP_PM_MANAGER = "no" + $env.CI = "true" + hide-env -i XDG_DATA_HOME + + let config_dir = ($env.XDG_CONFIG_HOME | path join "nushell") + let custom_data = ($env.HOME | path join "custom-data") + # Use a non-default directory on both Linux and macOS so the mismatch is observable. + mkdir $config_dir + '' | save ($config_dir | path join "env.nu") + if $mode == "config" { + '$env.XDG_DATA_HOME = ($env.HOME | path join "custom-data")' + | save ($config_dir | path join "config.nu") + } else { + $env.XDG_DATA_HOME = $custom_data + '' | save ($config_dir | path join "config.nu") + } + + # Real interactive startup loads config.nu before invoking the standalone installer. + let install = (^$nu.current-exe --no-history --execute 'try { source install.nu } catch { |err| print -e $err; exit 1 }; exit 0' | complete) + if $install.exit_code != 0 { + error make {msg: $"Installer session failed: ($install.stdout) ($install.stderr)"} + } + let installed = ($install.stdout | from json) + let session_dir = $installed.directory + if $installed.data_home != $custom_data { + error make {msg: "The installer session did not inherit the configured XDG_DATA_HOME"} + } + let snippet = ($custom_data | path join "nushell/vendor/autoload/vite-plus.nu") + if not ($snippet | path exists) { + error make {msg: "Installer did not write vite-plus.nu into the child-resolved directory"} + } + if not ($env.VP_HOME | path join "current/bin/.vp-setup-complete" | path exists) { + error make {msg: "Installer did not complete setup"} + } + + # Launch from the original parent environment, not from the modified interactive session. + let fresh = (^$nu.current-exe --no-history --execute 'try { source probe.nu } catch { |err| print -e $err; exit 1 }; exit 0' | complete) + if $fresh.exit_code != 0 { + error make {msg: $"Fresh session failed: ($fresh.stdout) ($fresh.stderr)"} + } + let state = ($fresh.stdout | from json) + if $state.data_home != $custom_data { + error make {msg: "The fresh session did not load the configured XDG_DATA_HOME"} + } + let expected_loaded = ($mode == "parent") + if $state.directory != $session_dir { + error make {msg: "Fresh session did not resolve the original session's autoload directory"} + } + if (($snippet | path dirname) == $session_dir) != $expected_loaded { + error make {msg: "Unexpected agreement between installer and session autoload directories"} + } + if $state.loaded != $expected_loaded { + error make {msg: $"Unexpected Vite+ autoload state: ($state.loaded)"} + } + print "Standalone setup completed and wrote vite-plus.nu" + print "Both sessions have the configured XDG_DATA_HOME after startup: true" + print $"Installer and session directories match: ($expected_loaded)" + print $"Fresh session loaded Vite+ environment: ($state.loaded)" + + if $mode == "config" { + # Apply the documented workaround without changing the XDG settings. + # source requires a parse-time path, so write a quoted literal into config.nu. + let env_file = ($env.VP_HOME | path join "env.nu" | to nuon) + $"\nsource ($env_file)\n" | save --append ($config_dir | path join "config.nu") + let repaired = (^$nu.current-exe --no-history --execute 'try { let help = (^vp help | complete); if $help.exit_code != 0 { error make {msg: $help.stderr} }; source probe.nu } catch { |err| print -e $err; exit 1 }; exit 0' | complete) + if $repaired.exit_code != 0 { + error make {msg: $"Session with the documented source line failed: ($repaired.stdout) ($repaired.stderr)"} + } + let repaired_state = ($repaired.stdout | from json) + if not $repaired_state.loaded or $repaired_state.directory != $session_dir or $repaired_state.data_home != $custom_data { + error make {msg: "The source workaround did not load Vite+ with the original XDG configuration"} + } + print "After adding source to config.nu, a fresh session loaded Vite+: true" + print "vp help succeeded in the fresh session" + } +} diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/install.nu b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/install.nu new file mode 100644 index 0000000000..b5cb995cc7 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/install.nu @@ -0,0 +1,8 @@ +let result = (^./external/vp | complete) +if $result.exit_code != 0 or ($result.stderr | str contains "Could not configure shell profiles") { + error make {msg: $"Standalone setup failed: ($result.stdout) ($result.stderr)"} +} +{ + directory: ($nu.vendor-autoload-dirs | last) + data_home: $env.XDG_DATA_HOME +} | to json --raw | print diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/probe.nu b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/probe.nu new file mode 100644 index 0000000000..359576911f --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/probe.nu @@ -0,0 +1,5 @@ +{ + directory: ($nu.vendor-autoload-dirs | last) + data_home: $env.XDG_DATA_HOME + loaded: (($env.VP_HOME | path join "bin") in $env.PATH) +} | to json --raw | print diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots.toml new file mode 100644 index 0000000000..cfc5306ea7 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots.toml @@ -0,0 +1,27 @@ +[[case]] +name = "command_self_setup_nushell_config_xdg_mismatch" +vp = "global" +requires = ["nu"] +skip-platforms = ["windows"] +seed-runtime = false +comment = "Issue #2491: with XDG_DATA_HOME unset in the parent and set in config.nu, installation succeeds but a fresh session does not load Vite+." +steps = [ + { argv = ["vpt", "mkdir", "external"], snapshot = false }, + { argv = ["vpt", "cp", "$VP_HOME/bin/vp", "external/vp"], snapshot = false }, + { argv = ["vpt", "chmod", "+x", "external/vp"], snapshot = false }, + ["nu", "--no-config-file", "assert.nu", "config"], +] + +[[case]] +name = "command_self_setup_nushell_parent_xdg" +vp = "global" +requires = ["nu"] +skip-platforms = ["windows"] +seed-runtime = false +comment = "Setting XDG_DATA_HOME before Nushell starts lets new sessions load the installed snippet." +steps = [ + { argv = ["vpt", "mkdir", "external"], snapshot = false }, + { argv = ["vpt", "cp", "$VP_HOME/bin/vp", "external/vp"], snapshot = false }, + { argv = ["vpt", "chmod", "+x", "external/vp"], snapshot = false }, + ["nu", "--no-config-file", "assert.nu", "parent"], +] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots/command_self_setup_nushell_config_xdg_mismatch.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots/command_self_setup_nushell_config_xdg_mismatch.md new file mode 100644 index 0000000000..b1bc0d55fa --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots/command_self_setup_nushell_config_xdg_mismatch.md @@ -0,0 +1,23 @@ +# command_self_setup_nushell_config_xdg_mismatch + +Issue #2491: with XDG_DATA_HOME unset in the parent and set in config.nu, installation succeeds but a fresh session does not load Vite+. + +## `vpt mkdir external` + + +## `vpt cp $VP_HOME/bin/vp external/vp` + + +## `vpt chmod +x external/vp` + + +## `nu --no-config-file assert.nu config` + +``` +Standalone setup completed and wrote vite-plus.nu +Both sessions have the configured XDG_DATA_HOME after startup: true +Installer and session directories match: false +Fresh session loaded Vite+ environment: false +After adding source to config.nu, a fresh session loaded Vite+: true +vp help succeeded in the fresh session +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots/command_self_setup_nushell_parent_xdg.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots/command_self_setup_nushell_parent_xdg.md new file mode 100644 index 0000000000..0f0d8b4d35 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_self_setup_nushell/snapshots/command_self_setup_nushell_parent_xdg.md @@ -0,0 +1,21 @@ +# command_self_setup_nushell_parent_xdg + +Setting XDG_DATA_HOME before Nushell starts lets new sessions load the installed snippet. + +## `vpt mkdir external` + + +## `vpt cp $VP_HOME/bin/vp external/vp` + + +## `vpt chmod +x external/vp` + + +## `nu --no-config-file assert.nu parent` + +``` +Standalone setup completed and wrote vite-plus.nu +Both sessions have the configured XDG_DATA_HOME after startup: true +Installer and session directories match: true +Fresh session loaded Vite+ environment: true +``` diff --git a/docs/guide/global-cli.md b/docs/guide/global-cli.md index b682286e18..9da7cab16b 100644 --- a/docs/guide/global-cli.md +++ b/docs/guide/global-cli.md @@ -265,6 +265,20 @@ Vite+ sets additional `VP_*` variables during shim dispatch and shell integratio Vite+ also respects these standard environment variables: +#### Nushell and XDG directories + +If you customize `XDG_DATA_HOME` or `XDG_CONFIG_HOME`, set them **before starting Nushell**, through your terminal application, operating system, or parent shell. This is a [Nushell startup requirement](https://www.nushell.sh/book/configuration.html#changing-default-directories); setting them only in `config.nu` or `env.nu` does not configure the running session's startup directories. + +Assignments in those files still affect child processes. The Vite+ installer starts a child Nushell to locate its vendor autoload directory, so it can write `vite-plus.nu` to a directory that normal new sessions do not read. Installation can succeed while `vp` remains unavailable in those sessions. + +If this happens, open your Nushell configuration with `config nu` and add a `source` line pointing to the installed Vite+ `env.nu` file. For a default fresh macOS or Linux installation without a custom `XDG_CONFIG_HOME`, use: + +```nu +source ~/.config/vite-plus/env.nu +``` + +For a custom `XDG_CONFIG_HOME`, use the absolute path to `/vite-plus/env.nu` as resolved during installation. For an installation under `VP_HOME` or an existing `~/.vite-plus` installation, use `/env.nu` or `~/.vite-plus/env.nu` instead. Replace placeholders with actual paths and quote paths containing spaces. Open a new Nushell session and run `vp help` to verify the configuration. + #### `CI` - **Purpose**: Indicates running in CI environment diff --git a/docs/guide/index.md b/docs/guide/index.md index a4b9144188..9d068ee0ef 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -36,6 +36,8 @@ The `vp-setup.exe` is not yet code-signed. Your browser may show a warning when The installer scripts and `vp-setup.exe` read [environment variables](/guide/global-cli#installation-variables) such as `VP_VERSION` and `VP_HOME`. +If you use Nushell with custom XDG directories, read the [Nushell startup requirements](/guide/global-cli#nushell-and-xdg-directories) before installing. + After installation, open a new shell and run: ```bash