Repository navigation
fix(implode): preserve unrelated data when removing installations - #3228
Conversation
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
fengmk2
left a comment
There was a problem hiding this comment.
The home/root protection works in the targeted Linux tests, but I would like us to complete the directory ownership protection in this PR before merging. A mistaken VP_HOME override can still delete unrelated data. Please address the inline comment and add regression coverage for unowned directories.
|
@codex review |
|
I've made some changes to address your feedback, but I'm not sure if this is the right approach. I'd appreciate it if you could take another look 🙇♂️ |
|
Could you update the PR description to explain the ownership and deletion rules, including how existing installations are handled? With the current implementation, users upgrading in place from 1.4.0 will have non-empty directories without .vp-owned. Setup leaves those directories unmarked, so implode refuses to remove them, even with --yes. This affects normal upgrades, not just custom directory overrides. Please clarify the intended behavior for fresh installs, upgrades from older versions, and custom directories. In particular, how should existing users safely uninstall after upgrading? We should consider the compatibility impact explicitly and cover the upgrade-to-uninstall flow with regression tests, while preserving protection against deleting unrelated data. |
|
Thanks for testing this and for the detailed feedback 🫡 I'm reworking the removal approach so that existing users can still uninstall after upgrading. I'll request another review once I've verified it more thoroughly. |
|
@codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
I’ve updated the implementation so existing users can safely uninstall after upgrading. Existing nonempty directories remain unmarked. Only verified CLI versions, matching links, and owned shims are removed. Unverified data is preserved, and the remaining paths are reported. Could you take another look and confirm whether this partial-removal approach meets your compatibility and safety expectations? |
|
@codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
fengmk2
left a comment
There was a problem hiding this comment.
One remaining P2 issue in ownership-marker creation is noted inline.
fengmk2
left a comment
There was a problem hiding this comment.
@jong-kyung Great job!
Let me take over, I want to run one more round simplify before merge.
Reject protected deletion targets before modifying shell profiles, PATH, or managed files, including with --yes. Check canonical paths to catch symlink aliases and validate all roots before starting split-layout cleanup. Add regression coverage for protected roots, normal installations, symlink aliases, and preservation of files when validation fails.
Require ownership markers for every existing data, cache, config, and state root before changing files, shell profiles, or PATH. Validate nested roots independently and collapse them only when building the final recursive deletion targets. Preserve the home and filesystem root safeguards. Check that new installation roots are empty before recording ownership. Keep nonempty legacy roots unmarked so existing installations remain usable without granting permission to delete unrelated contents. Cover ownership checks, nested and split roots, fresh setup, and legacy setup with isolated unit tests and CLI snapshots.
Recognize an existing current entry without following its target, matching installation directory resolution even when the active binary is missing. Keep repaired legacy roots unmarked so implode still refuses their removal. Extend the existing installer CI cases to verify ownership is not claimed when reusing a legacy root or repairing a dangling junction.
Keep ownership checks focused on recursive removal. Setup may use an existing nonempty root without marking it as owned, so implode still refuses to delete it. Remove the unnecessary existing-install distinction. Verify that setup succeeds without claiming personal files and that implode preserves those files and shell configuration. Keep preflight coverage for invalid roots and update the doctor cache-directory snapshot.
Identify legacy CLI version directories using matching package metadata and frozen installation receipts instead of claiming their parent roots. Preserve unverified data and report the paths left for manual inspection. Keep protected paths and unowned nested categories safe, and remove only verified shims from shared bin directories. Cover the legacy upgrade refresh handoff, partial cleanup, invalid receipts, and symlink boundaries.
Validate parent traversal before preparing roots or planning removal so lexical normalization cannot hide an unowned nested category. Preserve the existing legacy partial-removal rules. Cover unsafe traversal, unchanged directory identities, missing paths, dangling links, and CLI refusal before modifying files, profiles, or shims.
The lexical-path guard and the rejection assertion already cover the alias premise.
Recheck ownership before creating each queued marker so a marker created through another alias does not fail first-time setup. Keep exclusive creation and preserve unowned nonempty directories. Add a regression test for data and cache roots sharing one empty directory through a symlink.
2f49147 to
2ce69bc
Compare
Vite+ 1.5 adds an official Homebrew tap, runs TypeScript through Node.js with `node --import vite-plus/register`, and lets `vp migrate` move `oxnode` and transpile-only `ts-node` scripts to `vpx`. ### Features - Install `vp` from the official Homebrew tap on macOS and glibc Linux ([docs](https://viteplus.dev/guide/homebrew)) ([#2740](#2740)), by @fengmk2: ```bash brew tap voidzero-dev/vite-plus https://github.com/voidzero-dev/vite-plus brew install voidzero-dev/vite-plus/vp ``` - `node --import vite-plus/register` runs TypeScript with the same loader as `vpx`, so tools that start Node.js themselves, such as the Node.js test runner, AVA, or a `NODE_OPTIONS` setting, can run TypeScript files ([docs](https://viteplus.dev/guide/vpx#using-node-js-directly)) ([#3208](#3208)), by @fengmk2. - `vp migrate` moves `oxnode` commands and transpile-only `ts-node` commands to `vpx`, and moves their Node.js preloads and literal `NODE_OPTIONS` values to `vite-plus/register`. `ts-node` commands that type-check stay unchanged with a warning, and the `ts-node` dependency is removed only when nothing still uses it. A project already on Vite+ gets this migration with `vp migrate --full` ([docs](https://viteplus.dev/guide/migrate-rules#oxnode-to-vpx)) ([#3209](#3209), [#3210](#3210)), by @fengmk2. - `vp migrate` warns when it finds Rollup, Rolldown, or Jest dependencies with matching configuration, and explains how to move them to Vite, tsdown, or Vitest. The warnings show during the first migration, or with `vp migrate --full` in a project already on Vite+ ([#3275](#3275)), by @KTrain5169 and @fengmk2. - `vite-plus` exports `resolveConfigFromFile(configFile, options?)`, which resolves a config relative to the config file's directory instead of `process.cwd()`, so editor plugins with several workspace folders load the files of the right project ([#3249](#3249)), by @leaysgur and @fengmk2. - Security: the CLI ships `minimatch@11.0.4`, which fixes a denial of service through glob pattern amplification ([GHSA-g3hv-75wg-m249](GHSA-g3hv-75wg-m249), medium), and `zstd@0.13.4`, which fixes [RUSTSEC-2026-0391](https://rustsec.org/advisories/RUSTSEC-2026-0391), [RUSTSEC-2026-0398](https://rustsec.org/advisories/RUSTSEC-2026-0398), and [RUSTSEC-2026-0403](https://rustsec.org/advisories/RUSTSEC-2026-0403) ([#3328](#3328), [#3331](#3331)), by @renovate[bot] and @wan9chi. - Upgrade the bundled tools ([#3205](#3205), [#3236](#3236), [#3261](#3261), [#3206](#3206), [#3330](#3330), [#3338](#3338)), by @voidzero-guard[bot] and @fengmk2: - `rolldown@1.2.15` to `rolldown@1.2.16`, with `experimentalInlineCommonChunks` in dev mode and no crash when the working directory was deleted. - `tsdown@0.23.1` to `tsdown@0.23.4`: `vp pack --env-file` can be repeated to load several env files, the config has a JSON schema, and `?inline` CSS imported from dependencies is inlined. - `vitest@5.0.5` to `vitest@5.1.0`, with `--last-failed` and `--since-last-run`, fake timers for `node:timers`, and interactive review of failed snapshots. Browser mode now uses port 23315 by default. - `oxlint@1.89.0` to `oxlint@1.91.0` and `oxlint-tsgolint@7.0.2004` to `oxlint-tsgolint@7.0.2005`, with the new type-aware rule `typescript/no-unsafe-enum-assignment`, wider checks in rules such as `array-callback-return`, `no-useless-concat`, and `no-control-regex`, and two rules moved into the `suspicious` category. - `oxfmt@0.74.0` to `oxfmt@0.76.0`, with a new HTML formatter and JavaScript and TypeScript fixes for parentheses, array layout, and line width with wide characters. - The new oxlint and oxfmt versions can flag code that passed before. If your CI runs `vp check`, run `vp fmt` after upgrading. - `vpx` and `vite-plus/register` run on `oxc-node@1.0.1`, which resolves a `.jsx` specifier to its `.tsx` or `.ts` source. ### Fixes & Enhancements - `vp create` into a target path that is a symbolic link removes only the link after confirmation, instead of deleting the contents of the linked directory, and the overwrite prompt names symbolic links and files ([#2418](#2418)), by @leslieeilsel and @fengmk2. - `vp implode` removes only directories and shims that it can verify as Vite+ installations, and refuses the home directory, its parents, and filesystem roots even with `--yes`, so a `VP_HOME` that points at another directory cannot delete unrelated files ([#3228](#3228)), by @jong-kyung. - `vp run` starts faster in workspaces whose tasks share cache `input` and `output` patterns, because each pattern is parsed once. In a 138-package workspace this saves about 2 seconds of CPU on every run ([vite-task#887](voidzero-dev/vite-task#887), [vite-task#890](voidzero-dev/vite-task#890)), by @jasonkuhrt and @wan9chi. - `vp run` and package-manager commands in npm projects start about 110 ms sooner, because `vp` reads the npm version from npm's `package.json` instead of running `npm --version` ([#3259](#3259)), by @magurotuna. - `vp migrate` checks Vitest prerequisites faster in workspaces, because it parses each lockfile once ([#3212](#3212)), by @jong-kyung. - The installer and `vp upgrade` install the global CLI's dependencies with the Node.js version that the release pins (24.22.2 for this release), instead of the latest LTS ([docs](https://viteplus.dev/guide/ci#node-js-during-installation)) ([#3269](#3269)), by @fengmk2. - The Node.js `latest` alias in `vp env use`, `vp env default`, `vp env pin`, `vp env install`, and `.nvmrc` resolves to the newest stable release instead of a `27.0.0-alpha` build, and `vp env list-remote` marks that stable release as latest ([#3335](#3335)), by @voidzero-bot[bot] and @fengmk2. - `VP_NODE_VERSION=22` and other partial versions work for project commands such as `vp build`, `vp run`, and `vp list`, instead of failing with a 404 download error ([#3341](#3341)), by @jong-kyung. - Two `vp install -g` commands that run at the same time no longer delete each other's active package, and a command that starts while a package manager is being installed no longer runs its shim before the shim is executable ([#3185](#3185), [#3248](#3248)), by @jong-kyung. - `vp config` waits and retries when another linked git worktree holds the shared git config lock, so a `prepare` script no longer fails when two worktrees install at the same time ([#3199](#3199)), by @naokihaba. - `vp env doctor` reports Node.js resolution failures, unreadable config, a failing system `node`, and missing shims as errors and exits with code 1. When it finds only warnings, the summary says `Some warnings found` instead of `All checks passed` ([#3215](#3215), [#3222](#3222)), by @liangmiQwQ. - Nushell completions for `vp` and `vpr` use the named completer input, so Nushell 0.116 shows no deprecation warning, and they fall back to file completion when fish is not installed. Run `vp env setup --refresh` to regenerate `env.nu` ([#3267](#3267), [#3276](#3276)), by @naokihaba. - `vp migrate` removes the `tsx` dependency even when a comment still contains a `tsx` command or code fence, and keeps it for JSDoc type imports that need it ([#3299](#3299)), by @voidzero-bot[bot] and @fengmk2. - The `prefer-vite-plus-imports` lint rule and its autofix leave the `vite` and `vitest` imports that `vp migrate` keeps, such as `vitest` imports in a package that lists `vitest` in `peerDependencies`, so `vp lint --fix` no longer breaks the package for its plain Vitest users ([#3192](#3192)), by @Dunqing. - Generated Zed settings no longer force `typeAware` and `unusedDisableDirectives`, so editor diagnostics follow the `lint.options` in `vite.config.ts`. Existing editor settings stay unchanged ([#2357](#2357)), by @pweyck. - `vp dlx` with npm runs the right executable for scoped packages such as `@angular/cli` ([#3229](#3229)), by @jong-kyung. - `vp outdated -r` in npm projects checks the workspaces instead of transitive dependencies, and requires npm 7.14.0 or later ([#3240](#3240)), by @jong-kyung. - Dependency filters such as `--prod` and `--dev` work with npm 6, and filters that npm 6 cannot apply are rejected instead of passed through ([#3251](#3251)), by @jong-kyung. - Package-manager commands that the selected version does not have, such as `vp pm stage` before npm 11.15.0, are skipped with a warning. Unsupported `pnpm dlx` and `pnpm pack` options, and project-only flags on managed global commands such as `vp install -g`, are rejected instead of silently ignored ([#3286](#3286), [#3285](#3285)), by @jong-kyung. - `vp toolchain -g` is short for `vp toolchain --global` ([#3189](#3189)), by @jong-kyung. - On Linux and macOS, programs in tasks with automatic file-access tracking no longer abort when they call `exec` with an empty path or `execl` with 32 or more arguments ([vite-task#896](voidzero-dev/vite-task#896), [vite-task#865](voidzero-dev/vite-task#865)), by @wan9chi and @tlq5l. ### Refactor - Remove the test-only package download wrapper ([#3224](#3224)), by @jong-kyung. ### Docs - Explain that `vp check` stops at formatting failures, and that `vp check` flags go before file paths ([#3262](#3262)), by @SaKaNa-Y. - Show how to align an existing `vite` dependency with its override during a manual npm installation, to avoid `EOVERRIDE` ([#3157](#3157)), by @SaKaNa-Y. - Explain how environment variable prefixes such as `FOO=bar command` work in task commands on every platform ([#3161](#3161)), by @tartelettie. - Restore the `/vp-setup` redirect and the redirects for moved guide pages ([#3271](#3271)), by @fengmk2. - Align the labels of "See [...]" section links with their target titles ([#3231](#3231)), by @yamaurakazuto. ### Chore - Bump vite-task to `40cb9ca`; its user-facing changes are listed above ([#3246](#3246), [#3280](#3280)), by @wan9chi. - Keep CI working on the Node.js 26 LTS and Ubuntu 24.04, cap job runtimes, reduce Node.js downloads, avoid upgrade build and snapshot download timeouts, pin Nushell, and restore Namespace Linux runners ([#3198](#3198), [#3258](#3258), [#3266](#3266), [#3268](#3268), [#3303](#3303), [#3309](#3309), [#3320](#3320), [#3332](#3332)), by @fengmk2 and @wan9chi. - Add automated issue triage ([#3253](#3253), [#3260](#3260)), by @Boshen and @fengmk2. - Run the upstream dependency upgrade with Kimi K3.1 Pro and report its timeouts ([#3314](#3314), [#3304](#3304)), by @Brooooooklyn and @wan9chi. - Stabilize and trim tests: rerun ESLint and Prettier migration fixtures with `--full`, stabilize pnpm setup and Bun snapshots, update the tiptap ecosystem pin, use a recorded package in the install shortcut case, and remove duplicate `devEngines` parse tests ([#3193](#3193), [#3196](#3196), [#3242](#3242), [#3305](#3305), [#3301](#3301)), by @liangmiQwQ, @fengmk2, @wan9chi, and @Brooooooklyn. - Update Rust crates, synchronize workspace dependency requirements, and stop installing `dprint` and `taplo` in `just init` ([#3234](#3234), [#3310](#3310), [#3250](#3250)), by @renovate[bot], @leaysgur, and @fengmk2. - Refine contributor guidance: the release-manager skill, isolated CLI bootstrap checks in `AGENTS.md`, and the Rolldown exports in the CLI bundling notes ([#3207](#3207), [#3238](#3238), [#3316](#3316)), by @fengmk2 and @liangmiQwQ. ### Bundled Versions | Tool | Version | Source | Changelog | | --------------- | ---------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | vite | `8.3.5` | [`981f07f`](vitejs/vite@981f07f) | unchanged | | rolldown | `1.2.16` | [`de6facf`](rolldown/rolldown@de6facf) | [1.2.16](https://github.com/rolldown/rolldown/releases/tag/v1.2.16) | | oxc-node | `1.0.1` | [`7ff14c3`](oxc-project/oxc-node@7ff14c3) | [1.0.1](https://github.com/oxc-project/oxc-node/releases/tag/v1.0.1) | | tsdown | `0.23.4` | [npm](https://npmx.dev/package/tsdown/v/0.23.4) | [0.23.2](https://github.com/rolldown/tsdown/releases/tag/v0.23.2), [0.23.3](https://github.com/rolldown/tsdown/releases/tag/v0.23.3), [0.23.4](https://github.com/rolldown/tsdown/releases/tag/v0.23.4) | | vitest | `5.1.0` | [npm](https://npmx.dev/package/vitest/v/5.1.0) | [5.1.0](https://github.com/vitest-dev/vitest/releases/tag/v5.1.0) | | oxlint | `1.91.0` | [npm](https://npmx.dev/package/oxlint/v/1.91.0) | [1.90.0](https://github.com/oxc-project/oxc/releases/tag/oxlint_v1.90.0), [1.91.0](https://github.com/oxc-project/oxc/releases/tag/oxlint_v1.91.0) | | oxlint-tsgolint | `7.0.2005` | [npm](https://npmx.dev/package/oxlint-tsgolint/v/7.0.2005) | [7.0.2005](https://github.com/oxc-project/tsgolint/releases/tag/v7.0.2005) | | oxfmt | `0.76.0` | [npm](https://npmx.dev/package/oxfmt/v/0.76.0) | [0.75.0](https://github.com/oxc-project/oxc/releases/tag/oxfmt_v0.75.0), [0.76.0](https://github.com/oxc-project/oxc/releases/tag/oxfmt_v0.76.0) | ### Upgrade ```bash vp upgrade ``` ### New Contributors @yamaurakazuto, @tartelettie, @pweyck, @jasonkuhrt **Full Changelog**: v1.4.0...v1.5.0 --- Merging this PR will trigger the release workflow. --------- Co-authored-by: voidzero-guard[bot] <278573678+voidzero-guard[bot]@users.noreply.github.com> Co-authored-by: MK (fengmk2) <fengmk2@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
vp implodecould delete unrelated files when a directory override pointed to the user home or another non-Vite+ directory. This change limits removal to verified Vite+ directories and shims, while allowing existing users to uninstall after upgrading.For example, setting
VP_HOMEto$HOME/Documentsmust not authorize deletion of personal documents. Requiring.vp-ownedeverywhere avoids that deletion, but also blocks users upgrading from older versions whose installation directories have no ownership markers.Approach
Check ownership before changing files, shell profiles, or PATH. An upgrade does not grant Vite+ ownership of preexisting directory contents.
--yes.Installation and removal rules
vp implodebehavior.vp-ownedmarkers.Ownership covers a whole directory, so recursive removal also deletes files added inside that verified unit. It does not extend to an unmarked parent or override the nested-category checks.
Uninstall after upgrading
Existing users can run
vp implodeafter upgrading without manually adding ownership markers. For an unmarked installation:currentlink, and owned shims. Clean the matching shell entries.This allows a successful partial uninstall without treating an old installation's parent directory as disposable.
--yesskips confirmation, not ownership checks.Tests
Added CLI regression tests for upgrading an unmarked legacy installation and then running
vp implode --yes, using both single-root and split directory layouts.The tests verify that: