Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/test-standalone-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ jobs:
VP_LOCAL_TGZ="$FAKE_TGZ" VP_VERSION=local-test bash packages/cli/install.sh

test -f "$GRAND/.vite-plus/.keep"
test ! -e "$GRAND/.vite-plus/.vp-owned"
test -e "$GRAND/.vite-plus/current"
test -e "$GRAND/.vite-plus/bin/vp"
test ! -d "$GRAND/.local/share/vite-plus"
Expand Down Expand Up @@ -2168,6 +2169,9 @@ jobs:
if (-not (Test-Path (Join-Path $env:VP_HOME "current/bin/.vp-setup-complete"))) {
throw "vp-setup.exe did not complete the binary's self-setup"
}
if (Test-Path (Join-Path $env:VP_HOME ".vp-owned")) {
throw "Repair claimed ownership of an unmarked installation root"
}
if ([Environment]::GetEnvironmentVariable("Path", "User") -cne $pathBefore) {
throw "--no-modify-path changed User PATH"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ VITE+ - The Unified Toolchain for the Web
Installation
✓ Bin dir ~/.vite-plus/bin
✓ Data dir ~/.vite-plus
✓ Cache dir ~/.vite-plus/cache (not created yet)
✓ Cache dir ~/.vite-plus/cache
✓ Config dir ~/.vite-plus
✓ State dir ~/.vite-plus

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ skip-platforms = ["windows"]
env = { VP_NODE_MANAGER = "yes", VP_SELF_SETUP_NO_MODIFY_PATH = "1" }
steps = [
{ argv = ["vpt", "mkdir", "-p", "external/bin", "home"], comment = "Prepare isolated external install and VP_HOME", snapshot = false },
{ argv = ["vpt", "write-file", "home/.vp-owned", "vite-plus-owned-directory\n"], comment = "The fixture owns the preseeded runtime directory", snapshot = false },
{ argv = ["vpt", "cp", "$VP_HOME/bin/vp", "external/bin/vp"], comment = "Simulate a Homebrew-style vp outside VP_HOME", snapshot = false },
{ argv = ["vpt", "chmod", "+x", "external/bin/vp"], snapshot = false },
{ argv = ["vpt", "write-file", "external/node_modules/vite-plus/package.json", "{}"], snapshot = false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
Prepare isolated external install and VP_HOME


## `vpt write-file home/.vp-owned 'vite-plus-owned-directory
'`

The fixture owns the preseeded runtime directory


## `vpt cp $VP_HOME/bin/vp external/bin/vp`

Simulate a Homebrew-style vp outside VP_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name = "implode_confirmation"
vp = "global"
seed-runtime = false
steps = [
{ argv = ["vpt", "rm", "$VP_HOME/cache/.vp-owned"], snapshot = false },
{ argv = ["vp", "implode", "--yes"], comment = "A nested cache needs its own ownership marker before any deletion", continue-on-failure = true },
{ argv = ["vpt", "write-file", "$VP_HOME/cache/.vp-owned", "vite-plus-owned-directory\n"], snapshot = false },
{ argv = ["vp", "implode"], comment = "The old confirmation word leaves the installation intact", interactions = [
{ expect-milestone = "text:implode:ready" },
{ write-line = "uninstall" },
Expand All @@ -25,3 +28,23 @@ steps = [
] },
["vpt", "stat-file", "$VP_HOME", "--assert", "missing"],
]

[[case]]
name = "implode_unowned_directory"
vp = "global"
seed-runtime = false
skip-platforms = ["windows"]
env = { VP_SKIP_DEPS_INSTALL = "1", VP_NODE_MANAGER = "no", VP_SELF_SETUP_NO_MODIFY_PATH = "1" }
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 },
{ argv = ["vpt", "write-file", "$HOME/Documents/personal.txt", "keep my documents\n"], snapshot = false },
{ argv = ["vpt", "write-file", "$HOME/.bashrc", "# personal config\n# Vite+ bin\n. \"$HOME/Documents/env\"\n"], snapshot = false },
{ argv = ["./external/vp"], tty = false, envs = [["VP_HOME", "${HOME}/Documents"]], comment = "Setup succeeds without claiming a nonempty personal directory", snapshot = false },
["vpt", "stat-file", "$HOME/Documents/current/bin/.vp-setup-complete", "--assert", "file"],
{ argv = ["vp", "implode", "--yes"], envs = [["VP_HOME", "${HOME}/Documents"]], comment = "Changing VP_HOME cannot authorize recursive deletion", continue-on-failure = true },
["vpt", "stat-file", "$HOME/Documents/.vp-owned", "--assert", "missing"],
["vpt", "print-file", "$HOME/Documents/personal.txt"],
["vpt", "print-file", "$HOME/.bashrc"],
]
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# implode_confirmation

## `vpt rm $VP_HOME/cache/.vp-owned`


## `vp implode --yes`

A nested cache needs its own ownership marker before any deletion

**Exit code:** 1

```
error: Refusing to remove <home>/.vite-plus/cache: Vite+ directory ownership could not be verified. Unmarked directories, including older installations, must be inspected and removed manually.
```

## `vpt write-file $VP_HOME/cache/.vp-owned 'vite-plus-owned-directory
'`


## `vp implode`

The old confirmation word leaves the installation intact
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# implode_unowned_directory

## `vpt mkdir external`


## `vpt cp $VP_HOME/bin/vp external/vp`


## `vpt chmod +x external/vp`


## `vpt write-file $HOME/Documents/personal.txt 'keep my documents
'`


## `vpt write-file $HOME/.bashrc '# personal config
# Vite+ bin
. "$HOME/Documents/env"
'`


## `VP_HOME=${HOME}/Documents ./external/vp`

Setup succeeds without claiming a nonempty personal directory


## `vpt stat-file $HOME/Documents/current/bin/.vp-setup-complete --assert file`

```
<home>/Documents/current/bin/.vp-setup-complete: file
```

## `VP_HOME=${HOME}/Documents vp implode --yes`

Changing VP_HOME cannot authorize recursive deletion

**Exit code:** 1

```
error: Refusing to remove <home>/Documents: Vite+ directory ownership could not be verified. Unmarked directories, including older installations, must be inspected and removed manually.
```

## `vpt stat-file $HOME/Documents/.vp-owned --assert missing`

```
<home>/Documents/.vp-owned: missing
```

## `vpt print-file $HOME/Documents/personal.txt`

```
keep my documents
```

## `vpt print-file $HOME/.bashrc`

```
# personal config
# Vite+ bin
. "$HOME/Documents/env"
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
name = "command_self_setup"
vp = "global"
# The runner provides local dependencies; this case checks setup and dispatch.
env = { VP_SKIP_DEPS_INSTALL = "1" }
env = { VP_SKIP_DEPS_INSTALL = "1", VP_SELF_SETUP_NO_MODIFY_PATH = "1" }
steps = [
{ argv = ["vpt", "rm", "$VP_HOME/current/bin/.vp-setup-complete"], snapshot = false },
{ argv = ["vpt", "rm", "$VP_HOME/current/bin/.vp-setup-complete", "$VP_HOME/.vp-owned"], comment = "An older installation has no directory ownership marker", snapshot = false },
{ argv = ["vp", "--help"], envs = [["VP_SELF_SETUP_SUPPORT_CHECK", "1"]], comment = "The capability probe does not perform setup" },
["vpt", "stat-file", "$VP_HOME/current/bin/.vp-setup-complete", "--assert", "missing"],
{ argv = ["vp", "--help"], comment = "An unmarked deployed binary completes setup and executes the requested command", snapshot = false },
["vpt", "stat-file", "$VP_HOME/current/bin/.vp-setup-complete", "--assert", "file"],
["vpt", "stat-file", "$VP_HOME/.vp-owned", "--assert", "missing"],
{ argv = ["vp", "not-a-command"], comment = "Once marked, the binary dispatches commands normally", continue-on-failure = true },
]

Expand All @@ -19,6 +20,7 @@ requires = ["bash"]
skip-platforms = ["windows"]
steps = [
{ argv = ["vpt", "mkdir", "-p", "external", "project", "home/js_runtime/node"], snapshot = false },
{ argv = ["vpt", "write-file", "home/.vp-owned", "vite-plus-owned-directory\n"], comment = "The fixture owns the preseeded runtime directory", snapshot = false },
{ argv = ["vpt", "cp", "-r", "$VP_HOME/js_runtime/node/22.18.0", "home/js_runtime/node/22.18.0"], snapshot = false },
{ argv = ["vpt", "cp", "$VP_HOME/bin/vp", "external/vp"], snapshot = false },
{ argv = ["vpt", "chmod", "+x", "external/vp"], snapshot = false },
Expand Down Expand Up @@ -54,6 +56,8 @@ steps = [
["vpt", "print-file", "home/config.json"],
["vpt", "print-file", "user/.bashrc"],
["vpt", "stat-file", "user/.zshenv", "--assert", "missing"],
["vpt", "stat-file", "home/.vp-owned", "--assert", "file"],
["vpt", "stat-file", "home/cache/.vp-owned", "--assert", "file"],
]

[[case]]
Expand Down Expand Up @@ -108,6 +112,7 @@ skip-platforms = ["windows"]
env = { VP_SKIP_DEPS_INSTALL = "1", VP_SELF_SETUP_NO_MODIFY_PATH = "1" }
steps = [
{ argv = ["vpt", "mkdir", "-p", "external", "home/bin", "user-bin"], snapshot = false },
{ argv = ["vpt", "write-file", "home/.vp-owned", "vite-plus-owned-directory\n"], comment = "The fixture owns the preseeded shim directory", snapshot = false },
{ argv = ["vpt", "cp", "$VP_HOME/bin/vp", "external/vp"], snapshot = false },
{ argv = ["vpt", "chmod", "+x", "external/vp"], snapshot = false },
{ argv = ["node", "seed-owned-shims.cjs"], snapshot = false },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# command_self_setup

## `vpt rm $VP_HOME/current/bin/.vp-setup-complete`
## `vpt rm $VP_HOME/current/bin/.vp-setup-complete $VP_HOME/.vp-owned`

An older installation has no directory ownership marker


## `VP_SELF_SETUP_SUPPORT_CHECK=1 vp --help`
Expand Down Expand Up @@ -28,6 +30,12 @@ An unmarked deployed binary completes setup and executes the requested command
<home>/.vite-plus/current/bin/.vp-setup-complete: file
```

## `vpt stat-file $VP_HOME/.vp-owned --assert missing`

```
<home>/.vite-plus/.vp-owned: missing
```

## `vp not-a-command`

Once marked, the binary dispatches commands normally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,15 @@ home/current/bin/.vp-setup-complete: file
```
user/.zshenv: missing
```

## `vpt stat-file home/.vp-owned --assert file`

```
home/.vp-owned: file
```

## `vpt stat-file home/cache/.vp-owned --assert file`

```
home/cache/.vp-owned: file
```
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
## `vpt mkdir -p external project home/js_runtime/node`


## `vpt write-file home/.vp-owned 'vite-plus-owned-directory
'`

The fixture owns the preseeded runtime directory


## `vpt cp -r $VP_HOME/js_runtime/node/22.18.0 home/js_runtime/node/22.18.0`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
## `vpt mkdir -p external home/bin user-bin`


## `vpt write-file home/.vp-owned 'vite-plus-owned-directory
'`

The fixture owns the preseeded shim directory


## `vpt cp $VP_HOME/bin/vp external/vp`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ skip-platforms = ["windows"]
env = { VP_SKIP_DEPS_INSTALL = "1", VP_VERSION = "external-test", VP_SELF_SETUP_NO_MODIFY_PATH = "1" }
steps = [
{ argv = ["vpt", "mkdir", "-p", "external", "home/external-test/bin"], snapshot = false },
{ argv = ["vpt", "write-file", "home/.vp-owned", "vite-plus-owned-directory\n"], comment = "An interrupted fresh install already claimed its empty root", snapshot = false },
{ argv = ["vpt", "cp", "$VP_HOME/bin/vp", "external/vp"], snapshot = false },
{ argv = ["vpt", "chmod", "555", "external/vp"], snapshot = false },
{ argv = ["vpt", "cp", "external/vp", "home/external-test/bin/vp"], snapshot = false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
## `vpt mkdir -p external home/external-test/bin`


## `vpt write-file home/.vp-owned 'vite-plus-owned-directory
'`

An interrupted fresh install already claimed its empty root


## `vpt cp $VP_HOME/bin/vp external/vp`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
Homebrew with shims on PATH
CLI source Homebrew
CLI binary <workspace>/doctor/cellar/vite-plus/0.3.2/bin/vp
✓ vp ~/bin/vp
✓ Shim dir ~/bin
✓ vp ~/.vite-plus/bin/vp
✓ Shim dir ~/.vite-plus/bin
Homebrew without shims on PATH
CLI source Homebrew
CLI binary <workspace>/doctor/cellar/vite-plus/0.3.2/bin/vp
Expand All @@ -17,8 +17,8 @@ Missing vp in the shim directory
CLI source Homebrew
CLI binary <workspace>/doctor/cellar/vite-plus/0.3.2/bin/vp
✗ vp not in PATH
✓ Shim dir ~/bin
✓ Shim dir ~/.vite-plus/bin
External package without a Homebrew receipt
✓ vp ~/bin/vp
✓ Shim dir ~/bin
✓ vp ~/.vite-plus/bin/vp
✓ Shim dir ~/.vite-plus/bin
```
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ function createBundle(source, prefix, label) {
}

function createEnvironment(directory) {
const home = path.join(directory, 'home');
const home = path.join(directory, 'home', '.vite-plus');
const system = path.join(directory, 'system/bin');
const runtime = path.join(home, 'js_runtime/node', process.versions.node, 'bin');
fs.mkdirSync(system, { recursive: true });
fs.mkdirSync(runtime, { recursive: true });
fs.writeFileSync(path.join(home, '.vp-owned'), 'vite-plus-owned-directory\n');
fs.symlinkSync(process.execPath, path.join(system, 'node'));
fs.symlinkSync(process.execPath, path.join(runtime, 'node'));
fs.writeFileSync(path.join(directory, '.node-version'), process.versions.node);
Expand All @@ -40,7 +41,7 @@ function createEnvironment(directory) {
}
return {
...env,
HOME: home,
HOME: path.dirname(home),
VP_HOME: home,
VP_SELF_SETUP_NO_MODIFY_PATH: '1',
NPM_CONFIG_REGISTRY: 'http://127.0.0.1:9',
Expand Down
2 changes: 2 additions & 0 deletions crates/vp_cli_snapshots/tests/cli_snapshots/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,8 @@ impl CaseHome {
let this = Self { home: root.join("home") };
let vp_home = this.vp_home();
std::fs::create_dir_all(&vp_home).unwrap();
// Provisioning emulates a fresh install into this case-owned directory.
std::fs::write(vp_home.join(".vp-owned"), b"vite-plus-owned-directory\n").unwrap();
std::fs::create_dir_all(root.join("npm-global/lib")).unwrap();
// Best-effort: if linking fails, the case downloads the runtime.
if seed_runtime && let Some(seed) = flavor::js_runtime_seed_dir() {
Expand Down
Loading
Loading