Skip to content

feat: XDG directory layout via VpDirs - #2346

Open
forehalo wants to merge 10 commits into
voidzero-dev:mainfrom
forehalo:feat/dirs-path-resolution
Open

feat: XDG directory layout via VpDirs#2346
forehalo wants to merge 10 commits into
voidzero-dev:mainfrom
forehalo:feat/dirs-path-resolution

Conversation

@forehalo

@forehalo forehalo commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Close #827

Summary

Centralize on-disk paths in vp_shared::VpDirs and default fresh installs to the split XDG/platform layout. Existing default installs under ~/.vite-plus remain on the legacy monolithic root for now (grandfathered via existence-gated resolution). Automatic layout migration is out of scope here and tracked as follow-up work.

Resolution (high level)

Ordered sources (per category): deprecated VP_HOME (custom full-root pin) → existing ~/.vite-plus (exist-gated legacy mapping) → VP_BIN_DIR / VP_DATA_DIR / VP_CACHE_DIRXDG_* → platform defaults.

Category Split default (Unix) Legacy (~/.vite-plus)
bin ~/.local/bin <root>/bin
data ~/.local/share/vite-plus <root>
cache ~/.cache/vite-plus <root>/cache
config ~/.config/vite-plus <root>
state ~/.local/state/vite-plus <root>

Windows split uses %LOCALAPPDATA%\vite-plus\{bin,data,cache,state} and %APPDATA%\vite-plus for config. Relative VP_* / XDG_* values are treated as unset.

Commits (review order)

  1. docs(rfc): document split directory layout via VpDirs

    • Adds rfcs/directory-layout.md describing the resolution chain, grandfathering, installer alignment, and follow-ups (VP_HOME cleanup, migrate-on-upgrade).
    • Historical RFCs (e.g. env-command.md) are left unchanged.
  2. feat(shared): introduce VpDirs with strategy-gated path resolution

    • Replaces get_vp_home / home.rs with VpDirs + dirs/resolution.rs strategy chain.
    • Category roots only; first-level data subdirs (current, js_runtime, …) stay as joins on the owning feature.
    • Wires EnvConfig so tests isolate layout via with_vars / scoped without process-env leaks.
    • Updates AGENTS.md pointer to the central path API.
  3. refactor(cli): route on-disk paths through VpDirs

    • Migrates global CLI, shims, js_runtime, package manager, implode, env setup/doctor, and related helpers onto EnvConfig::get().dirs.
    • Env setup scripts re-export captured layout overrides (dir_envs); implode deletes deduped {data, cache, config, state} and never rm -rfs a shared bin dir.
    • Snapshot runner and fixtures still pin install roots explicitly (layout cleanup is chore: remove remaining VP_HOME usage (especially snapshot tests) #2371).
  4. feat(install): default installers to the split XDG layout

    • install.sh / install.ps1 / vp-setup / trampoline / install-global-cli install into the roots EnvConfig already resolved. Fresh install → split; existing ~/.vite-plus or --install-dir → monolithic root.
    • Directory env vars stay owned by EnvConfig. vp-setup does not read VP_HOME / VP_*_DIR / XDG_* itself. A local vp binary reports <DATA> / <BIN> / <CONFIG> via VP_DUMP_DIRS=1 so scripts and install-global-cli do not re-implement the chain.
    • Unix vp shims target <DATA>/current/bin/vp (not a version dir) after env setup --refresh. The Windows trampoline finds ../current or ../data/current from disk layout only.
    • Installer env docs and standalone-install CI: published-CLI jobs stay VP_HOME-pinned; a local-build job covers fresh split + grandfather.

User impact

Install Impact
Existing ~/.vite-plus Unchanged path (grandfathered until migrate follow-up)
Custom VP_HOME Still works (deprecated pin)
Fresh Split layout; typically only ~/.local/bin needs to be on PATH

Follow-up

Test plan

  • cargo check / unit tests for dirs resolution and layout helpers
  • Snapshot fixtures adapted for layout isolation (pin VP_HOME / disable shared seed where fakes are used)
  • Installer unification (single install.sh / install.ps1)
  • Formatting for RFC + install-global-cli
  • vp-setup / trampoline / Unix shim unit tests for fresh split vs grandfather
  • CI: test-standalone-install (released VP_HOME-pinned + local-build split/grandfather jobs)
  • Manual: fresh install lands on split paths; existing ~/.vite-plus still works without moving

@netlify

netlify Bot commented Aug 5, 2026

Copy link
Copy Markdown

Deploy Preview for viteplus-preview canceled.

Name Link
🔨 Latest commit 2e605c6
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/6a81bac8be79b90008cc8831

@forehalo
forehalo force-pushed the feat/dirs-path-resolution branch 4 times, most recently from b8069a5 to 2f8be03 Compare August 5, 2026 17:13
@forehalo forehalo changed the title feat: introduce Dirs for unified XDG-aware path resolution feat: XDG-compliant directory layout via unified Dirs resolution Aug 6, 2026
@forehalo
forehalo force-pushed the feat/dirs-path-resolution branch 2 times, most recently from 08b7589 to 4e2abdf Compare August 6, 2026 17:25
@forehalo forehalo changed the title feat: XDG-compliant directory layout via unified Dirs resolution feat: XDG directory layout via VpDirs Aug 6, 2026
@fengmk2

fengmk2 commented Aug 7, 2026

Copy link
Copy Markdown
Member

@liangmiQwQ Your refactor needs to wait until this merge is completed first, as the changes are expected to be quite significant.

@socket-security

socket-security Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​temp-env@​0.3.68710093100100

View full report

@forehalo
forehalo force-pushed the feat/dirs-path-resolution branch 3 times, most recently from 6b26e69 to ca9dcca Compare August 7, 2026 12:17
@fengmk2 fengmk2 self-assigned this Aug 7, 2026
@fengmk2

fengmk2 commented Aug 7, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca9dcca689

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread crates/vp_trampoline/src/main.rs Outdated
Comment thread packages/cli/install.ps1 Outdated
Comment thread crates/vp_global_cli/src/commands/env/setup.rs Outdated
Comment thread packages/cli/src/config/hooks.ts Outdated
Comment thread crates/vp_shared/src/dirs/resolution.rs Outdated
Comment thread crates/vp_global_cli/src/commands/implode.rs Outdated
Comment thread crates/vp_shared/src/dirs/resolution.rs Outdated
@liangmiQwQ

liangmiQwQ commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

IMO, I would be a little bit curious about the benefit for this move. The current VP_HOME layout has been working well, the similar single-root approaches are also used by tools like Cargo, Bun, and Volta. Moving to a new layout is not a low-cost change: it affects existing installations, upgrade paths, user workflows, and debugging. For a released tool, I think we should carefully evaluate the trade-offs.

For example, I help maintain the Vite+'s global package installations in several, I'm concerned that using ~/.local/bin may introduce heavier binary conflicts and overlapping issues. I'm not sure if ~/.local/bin, a public bin location, should be managed (even partially) by Vite+.

I'm not against this direction, I just want to understand the motivation and the problem it solves. If it does help Vite+ improve, then now is really a good time to implement it (before RC).

Comment thread rfcs/directory-layout.md Outdated
@fengmk2

fengmk2 commented Aug 10, 2026

Copy link
Copy Markdown
Member

@liangmiQwQ Following the XDG directory convention will allow Vite+ to be more widely accepted, and many mature developer tools follow this convention, such as Claude Code and uv astral-sh/uv#8420

@forehalo
forehalo force-pushed the feat/dirs-path-resolution branch 2 times, most recently from ad9d7dd to 5cc3b6c Compare August 10, 2026 06:07
@fengmk2 fengmk2 added the preview-build Publish this PR's commits to the registry bridge as preview builds label Aug 10, 2026
@forehalo
forehalo marked this pull request as draft August 10, 2026 06:33
@forehalo
forehalo marked this pull request as ready for review August 13, 2026 05:20
@fengmk2 fengmk2 added test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: create-e2e Run `vp create` e2e tests test: sfw preview-build Publish this PR's commits to the registry bridge as preview builds and removed preview-build Publish this PR's commits to the registry bridge as preview builds labels Aug 14, 2026
@fengmk2

fengmk2 commented Aug 14, 2026

Copy link
Copy Markdown
Member

@codex review

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Registry bridge build (f679dcd)

Warning

This build is from the fork forehalo/vite-plus and has not been reviewed.
Installing it runs that code on your machine. Build log

This commit build is published to the registry bridge, which serves these as ordinary npm versions (every other package proxies to npmjs):

Package Version
vite-plus 0.0.0-commit.f679dcd3c606f87ede78ab9c232fcb2352ab9fce
@voidzero-dev/vite-plus-core 0.0.0-commit.f679dcd3c606f87ede78ab9c232fcb2352ab9fce

Install the Vite+ CLI built from this commit, then migrate a project:

# macOS / Linux
curl -fsSL https://deploy-preview-2346--viteplus-preview.netlify.app/install.sh | VP_PR_VERSION=2346 bash
# Windows (PowerShell)
$env:VP_PR_VERSION="2346"; irm https://deploy-preview-2346--viteplus-preview.netlify.app/install.ps1 | iex

After installing, upgrade the current project's vite-plus to this test build with:

vp migrate

Or point your package manager at the bridge registry https://registry-bridge.viteplus.dev/:

Package manager Registry config
npm / pnpm / Bun .npmrc: registry=https://registry-bridge.viteplus.dev/
Yarn (v2+) .yarnrc.yml: npmRegistryServer: "https://registry-bridge.viteplus.dev/"

Then pin the build (vite aliases to vite-plus-core; pnpm can use a catalog, npm an overrides entry):

{
  "devDependencies": {
    "vite-plus": "0.0.0-commit.f679dcd3c606f87ede78ab9c232fcb2352ab9fce",
    "vite": "npm:@voidzero-dev/vite-plus-core@0.0.0-commit.f679dcd3c606f87ede78ab9c232fcb2352ab9fce"
  }
}

chatgpt-codex-connector[bot]

This comment was marked as resolved.

fengmk2

This comment was marked as resolved.

Implode only removes shims that resolve to this install's vp. Generated
env files persist resolved VP_*_DIR. Legacy Windows wrappers pin VP_HOME
to the data root. Upgrade-check cache moves to <CACHE>. Org-tarball cache
goes through EnvConfig.
Independent VP_BIN_DIR / VP_DATA_DIR installs cannot be found by
sibling-path probing. Write <name>.shim next to each trampoline and
resolve vp.exe from that pointer. Align install.ps1 with Windows
known folders so installer roots match EnvConfig.
@fengmk2 fengmk2 added preview-build Publish this PR's commits to the registry bridge as preview builds and removed preview-build Publish this PR's commits to the registry bridge as preview builds labels Aug 16, 2026
install.sh now links <BIN>/vp to the absolute
<DATA>/current/bin/vp path. The grandfather layout job still
asserted the old relative ../current/bin/vp target.
@fengmk2 fengmk2 added preview-build Publish this PR's commits to the registry bridge as preview builds and removed preview-build Publish this PR's commits to the registry bridge as preview builds labels Aug 16, 2026
@fengmk2

fengmk2 commented Aug 16, 2026

Copy link
Copy Markdown
Member

@codex review

Comment thread packages/cli/install.ps1 Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f679dcd3c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread crates/vp_global_cli/src/commands/global/install.rs Outdated
Comment thread crates/vp_trampoline/src/main.rs Outdated
Comment thread crates/vp_shared/src/dirs/resolution.rs
Comment thread crates/vp_shared/src/env_config.rs Outdated
fengmk2 added a commit that referenced this pull request Aug 16, 2026
Fork `pull_request` runs get a read-only token, so `vp-binary-size.yml`
gated every job to same-repo PRs. Fork PRs that change native inputs
(for example #2346, which touches Cargo.lock and many crates) got no
size report at all.

Changes:

- Drop the fork gate from the `inputs` job, so fork PRs run the native
input compare and the base/head builds when inputs changed.
- Let the `comment` job run for fork PRs. It always writes the size
table to the job summary, and returns before the comment API calls when
the PR head is a fork.
- Keep the `cleanup` job same-repo only, because comment deletion needs
a write token.

Same-repo PRs keep the current behavior, summary plus sticky comment.
Fork PRs get the report in the run's job summary.

The build jobs receive no secrets, checkout uses `persist-credentials:
false`, and the Rust cache save is disabled, so the untrusted fork code
runs with the same exposure as the regular CI jobs that already run for
fork PRs.
@fengmk2

fengmk2 commented Aug 16, 2026

Copy link
Copy Markdown
Member

@naokihaba If you have time, could you help take a look at whether this change has any impact on Nushell's functionality?

Avoid the PowerShell 5 $HOME collision in install.ps1. Require a
matching <name>.shim before implode deletes Windows exes. Pin
VP_HOME from the trampoline for single-root bin/data layouts.
Write JetBrains node paths from getVpDirs(). Persist VP_HOME in
dir_envs only when it is an absolute path.
@naokihaba
naokihaba self-requested a review August 16, 2026 13:33
@naokihaba

Copy link
Copy Markdown
Collaborator

@fengmk2 Sure, I'll check it.

@fengmk2 fengmk2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: installing an old release through the new installer can report success with an unusable global CLI

I tested the deployed Windows preview installer in a clean, isolated environment:

  • Installer: https://deploy-preview-2346--viteplus-preview.netlify.app/install.ps1
  • Installer SHA-256: 976CC99AD08E02B70169E43D9548E645899CFD3C609959FB41C4723EB8C98CE3
  • Requested version: VP_VERSION=0.2.9
  • Full dependency installation and managed Node.js enabled

The installer exited 0 and reported success, but the resulting global installation was not usable.

Observed

  • The downloaded payload at <split-data>\current\bin\vp.exe exited 0 and reported vp v0.2.9.
  • The PATH-installed <split-bin>\vp.exe exited 1 because the old trampoline looked for <root>\current\bin\vp.exe instead of <root>\data\current\bin\vp.exe.
  • <split-bin>\vp.shim correctly pointed to the split data root, but the old trampoline did not consume that sidecar.
  • The split bin root did not contain functional vpr.exe, vpx.exe, or managed node.exe shims.
  • Running the old version's environment setup created a second, legacy .vite-plus tree. Its vp.exe and node.exe shims also failed because that tree had no current payload.

A successful direct invocation of the downloaded payload does not make the global installation valid; commands resolved through the installed PATH must work.

Expected contract

Please clarify and enforce one of these behaviors:

  1. Old releases are supported: the new installer must select a layout and shim format compatible with the requested release, likely the legacy monolithic layout for pre-VpDirs versions. The installed vp, vpr, vpx, Node, and npm commands must all work.
  2. Old releases are unsupported: reject the request before creating partial state, exit nonzero, and print an actionable compatibility message.

Exiting 0 with a mixed split/legacy installation and broken PATH commands is a failure under either contract.

This result is confirmed on Windows for install.ps1. Since install.sh exposes the same VP_VERSION contract, it should receive equivalent old-version coverage on Linux and macOS before merge, without assuming that the Windows trampoline failure reproduces identically on Unix.

@fengmk2

fengmk2 commented Aug 17, 2026

Copy link
Copy Markdown
Member

I will take over this PR and fix the issues discovered during the testing process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview-build Publish this PR's commits to the registry bridge as preview builds test: create-e2e Run `vp create` e2e tests test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: sfw

Projects

None yet

Development

Successfully merging this pull request may close these issues.

use xdg config

4 participants