Default to XDG-style file locations#1674
Conversation
The CLI placed its package cache in ~/.pkl/cache and read its settings file from ~/.pkl/settings.pkl. Default these to the XDG-style locations ~/.cache/pkl and ~/.config/pkl/settings.pkl instead, so a default setup no longer writes to $HOME/.pkl. These are fixed defaults; no environment variables (XDG_CACHE_HOME, XDG_CONFIG_HOME) are read, consistent with Pkl not configuring itself from the environment. Existing setups keep working without migration: a pre-existing ~/.pkl/cache is still used so packages aren't re-downloaded, and ~/.pkl/settings.pkl is still read when ~/.config/pkl/settings.pkl is absent.
Extend the XDG-style defaults to the two remaining ~/.pkl users: the CA certificates directory now defaults to ~/.config/pkl/cacerts, and the REPL history to ~/.local/state/pkl/repl-history (XDG state home, where history files belong). Both fall back to their legacy ~/.pkl locations when those exist, so a default setup writes nothing under ~/.pkl. The one-time JLine2 ~/.pkl/repl-history.bin cleanup is left pointing at the legacy path, since that file only ever existed there.
Rename the public PklSettings.loadFromPklHomeDir() to loadFromDefaultLocation() (its behavior now prefers ~/.config/pkl), with a deprecated-for-removal shim delegating from the old name, and record the deprecation in the release notes. Also fix a stale ~/.pkl/settings.pkl reference in the language tutorial, and note in the release notes that Windows uses the XDG-style paths literally rather than mapping to Known Folder locations.
Add path-value tests for the four default-location helpers (via new package-private home-dir overloads) and a pkl-executor test pinning ExecutorOptions.defaultModuleCacheDir() to IoUtils, closing the gap where a wrong path segment would have passed CI. Fix the CA-certs fallback so an empty ~/.config/pkl/cacerts no longer shadows a populated legacy ~/.pkl/cacerts (a directory with no cert files now counts as absent). Update the remaining stale ~/.pkl references in stdlib settings.pkl and ModuleCache, scope the "nothing under ~/.pkl" release note to new setups and qualify the no-re-download claim, add a deprecation `since`, and rename the test-only settings loader.
|
I think I'm open to this, but some considerations:
|
Apply %APPDATA% (config) and %LOCALAPPDATA% (cache/state) on Windows for the four default file locations, instead of using the XDG-style literal paths under the user home. Adds env-injectable overloads so tests can exercise the Windows code path on a Unix CI box. Rename preferXdgLocation -> preferNewLocation; the helper is no longer XDG-specific now that Windows uses Known Folders.
Add the Windows %APPDATA% / %LOCALAPPDATA% paths alongside the existing Unix XDG paths in --cache-dir, --settings, ca-certificates, settings module, and gradle moduleCacheDir documentation.
|
I made apple/pkl-intellij#216 and apple/pkl-lsp#208 to continue this effort. Both also migrate Also took a shot at the Windows paths ( |
|
A little bit of thought needs to be put toward how this change interacts with pkl-go and pkl-swift, as their APIs involve configuration of the cache directory. |
|
We chatted about this a bit: we're on board with following the XDG base directory specification fully on macOS/Linux:
On Windows, using The rationale here is: unlike most environment variables, XDG actually has a specification that is well defined. |
Default the CLI's file locations to XDG-style paths instead of placing everything under
~/.pkl.With this PR, a default Pkl setup writes nothing to
$HOME/.pkl:~/.cache/pkl(was~/.pkl/cache)~/.config/pkl/settings.pkl(was~/.pkl/settings.pkl)~/.config/pkl/cacerts(was~/.pkl/cacerts)~/.local/state/pkl/repl-history(was~/.pkl/repl-history; XDG state home, where history files belong)These are fixed defaults; no environment variables (
XDG_CACHE_HOME,XDG_CONFIG_HOME,XDG_STATE_HOME) are read, matching the design principle that Pkl doesn't configure itself from the environment.Backward compatible, no migration needed: each legacy
~/.pkllocation is still used when it already exists. In particular, a pre-existing~/.pkl/cacheis still used, so cached packages aren't re-downloaded. The one-time JLine2~/.pkl/repl-history.bincleanup is left pointing at the legacy path. An empty~/.config/pkl/cacertsdirectory counts as absent, so it doesn't shadow a populated legacy~/.pkl/cacerts.Public Java-API change:
PklSettings.loadFromPklHomeDir()is renamed toloadFromDefaultLocation()since it no longer loads from the pkl home dir; an embedder that relied on~/.pkl/settings.pklwill now prefer~/.config/pkl/settings.pklwhen both exist. Happy to pick a different name if you'd prefer.pkl-executorcan't depend onpkl-core, so itsdefaultModuleCacheDir()replicates the same fallback (with a keep-in-sync comment).Verified
./gradlew spotlessApplyand the JVM suites pluspkl-cli/pkl-executorcompile. I also built the macOS arm64 native image and ran it. The fresh-home XDG branch isn't directly exercisable on the native binary (macOS resolvesuser.homefrom the OS, not$HOME/-D), but it's the same code path the unit tests cover and GraalVM recomputesuser.homeat runtime.