feat: respect XDG_CONFIG_HOME for argv.json on Linux#300881
feat: respect XDG_CONFIG_HOME for argv.json on Linux#300881murataslan1 wants to merge 1 commit intomicrosoft:mainfrom
Conversation
On Linux, the user data path already respects XDG_CONFIG_HOME (see userDataPath.ts), but the argv.json config file was still always placed under ~/.vscode/. This inconsistency meant that users who set XDG_CONFIG_HOME to keep their home directory clean still had a ~/.vscode/ folder created solely for argv.json. Changes: - src/main.ts: Update getArgvConfigPath() to use XDG_CONFIG_HOME on Linux, falling back to ~/.config if not set. Includes migration logic to move argv.json from the legacy path to the new XDG-compliant path, with error handling. - environmentService.ts: Update argvResource getter to resolve argv.json under XDG_CONFIG_HOME on Linux when set. The migration only runs when XDG_CONFIG_HOME is explicitly set and the legacy file exists but the new location does not, ensuring no data loss for existing users. Fixes microsoft#162712
There was a problem hiding this comment.
Pull request overview
This PR updates where VS Code resolves argv.json on Linux to better respect XDG conventions (XDG_CONFIG_HOME / ~/.config) and introduces a migration from the legacy homedir-based location.
Changes:
- Update
AbstractNativeEnvironmentService.argvResourceto useXDG_CONFIG_HOMEon Linux. - Update
src/main.tsstartup argv.json resolution to useXDG_CONFIG_HOME(or~/.config) and attempt to migrate from the legacy path.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/vs/platform/environment/common/environmentService.ts |
Adjusts argvResource resolution on Linux to use XDG_CONFIG_HOME. |
src/main.ts |
Changes early startup argv.json path resolution on Linux and adds legacy-path migration logic. |
| // On Linux, respect XDG_CONFIG_HOME to align with how | ||
| // userDataPath is resolved (see userDataPath.ts) | ||
| const newArgvConfigPath = process.platform === 'linux' | ||
| ? path.join(process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config'), dataFolderName!, 'argv.json') | ||
| : path.join(os.homedir(), dataFolderName!, 'argv.json'); | ||
|
|
||
| // Migrate from the legacy path (~/.vscode/argv.json) if needed | ||
| if (process.platform === 'linux' && process.env['XDG_CONFIG_HOME']) { |
There was a problem hiding this comment.
On Linux without XDG_CONFIG_HOME, main.ts now reads/creates argv.json under ~/.config//argv.json, but AbstractNativeEnvironmentService.argvResource still points to ~//argv.json. This will make early argv parsing (main.ts) and later argv edits/sync (environmentService.argvResource) operate on different files. Align the path resolution logic between these two code paths (either both use XDG_CONFIG_HOME || ~/.config, or both keep the legacy homedir location unless XDG_CONFIG_HOME is explicitly set).
| // On Linux, respect XDG_CONFIG_HOME to align with how | |
| // userDataPath is resolved (see userDataPath.ts) | |
| const newArgvConfigPath = process.platform === 'linux' | |
| ? path.join(process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config'), dataFolderName!, 'argv.json') | |
| : path.join(os.homedir(), dataFolderName!, 'argv.json'); | |
| // Migrate from the legacy path (~/.vscode/argv.json) if needed | |
| if (process.platform === 'linux' && process.env['XDG_CONFIG_HOME']) { | |
| const xdgConfigHome = process.env['XDG_CONFIG_HOME']; | |
| // On Linux, respect XDG_CONFIG_HOME when set to align with how | |
| // userDataPath is resolved (see userDataPath.ts). Otherwise, keep | |
| // using the legacy homedir location so that all code paths agree. | |
| const newArgvConfigPath = process.platform === 'linux' && xdgConfigHome | |
| ? path.join(xdgConfigHome, dataFolderName!, 'argv.json') | |
| : path.join(os.homedir(), dataFolderName!, 'argv.json'); | |
| // Migrate from the legacy path (~/.vscode/argv.json) if needed | |
| if (process.platform === 'linux' && xdgConfigHome) { |
| // Migrate from the legacy path (~/.vscode/argv.json) if needed | ||
| if (process.platform === 'linux' && process.env['XDG_CONFIG_HOME']) { | ||
| const legacyArgvConfigPath = path.join(os.homedir(), dataFolderName!, 'argv.json'); | ||
| if (legacyArgvConfigPath !== newArgvConfigPath) { | ||
| try { | ||
| if (fs.existsSync(legacyArgvConfigPath) && !fs.existsSync(newArgvConfigPath)) { | ||
| fs.mkdirSync(path.dirname(newArgvConfigPath), { recursive: true }); | ||
| fs.renameSync(legacyArgvConfigPath, newArgvConfigPath); | ||
| } |
There was a problem hiding this comment.
The migration only runs when XDG_CONFIG_HOME is set, but the new Linux default path also changes when XDG_CONFIG_HOME is not set (falls back to ~/.config). That means existing ~/./argv.json will be ignored with no migration on most Linux systems. Consider migrating from the legacy homedir location whenever the computed new path differs (regardless of whether XDG_CONFIG_HOME is set).
| try { | ||
| if (fs.existsSync(legacyArgvConfigPath) && !fs.existsSync(newArgvConfigPath)) { | ||
| fs.mkdirSync(path.dirname(newArgvConfigPath), { recursive: true }); | ||
| fs.renameSync(legacyArgvConfigPath, newArgvConfigPath); | ||
| } | ||
| } catch (error) { | ||
| console.error(`Unable to migrate argv.json from ${legacyArgvConfigPath} to ${newArgvConfigPath} (${error})`); | ||
| } |
There was a problem hiding this comment.
fs.renameSync can fail when the legacy and new paths are on different filesystems (EXDEV) or if permissions prevent rename. In that case, the code logs and proceeds, leaving argv.json at the legacy location while subsequent reads use the new location. Consider falling back to a copy+unlink (or using fs.cpSync where available) when rename fails, so the migration is more reliable.
| // On Linux, respect XDG_CONFIG_HOME to align with userDataPath resolution | ||
| if (env['XDG_CONFIG_HOME'] && isLinux) { | ||
| return URI.file(join(env['XDG_CONFIG_HOME'], this.productService.dataFolderName, 'argv.json')); |
There was a problem hiding this comment.
This Linux path change only applies when XDG_CONFIG_HOME is set; otherwise it still uses ~//argv.json. That does not match the Linux userDataPath behavior (XDG_CONFIG_HOME || ~/.config) and also diverges from getArgvConfigPath() in src/main.ts (which falls back to ~/.config). Consider using XDG_CONFIG_HOME || ~/.config consistently here (and possibly resolving XDG_CONFIG_HOME to an absolute path) so argvResource matches the early argv.json read path.
| // On Linux, respect XDG_CONFIG_HOME to align with userDataPath resolution | |
| if (env['XDG_CONFIG_HOME'] && isLinux) { | |
| return URI.file(join(env['XDG_CONFIG_HOME'], this.productService.dataFolderName, 'argv.json')); | |
| // On Linux, align with userDataPath and early argv.json resolution: XDG_CONFIG_HOME || ~/.config | |
| if (isLinux) { | |
| const configHome = env['XDG_CONFIG_HOME'] ? resolve(env['XDG_CONFIG_HOME']) : join(this.paths.homeDir, '.config'); | |
| return URI.file(join(configHome, this.productService.dataFolderName, 'argv.json')); |
Summary
Resolves the long-standing inconsistency where
argv.jsonwas placed under~/.vscode/even whenXDG_CONFIG_HOMEis set, while all other user data already respects it (viauserDataPath.ts).Fixes #162712
Changes
2 files changed, 28 additions, 1 deletion
src/main.tsgetArgvConfigPath()to useXDG_CONFIG_HOMEon Linux (falling back to~/.config). Adds migration from legacy path.src/vs/platform/environment/common/environmentService.tsargvResourcegetter to resolve underXDG_CONFIG_HOMEon Linux.Behavior
/custom/config)/custom/config/.vscode/argv.json~/.config/.vscode/argv.json(same as userDataPath)~/.vscode/argv.json/ AppData)Migration
When
XDG_CONFIG_HOMEis set on Linux:~/.vscode/argv.jsonexistsPrior Art
mkdirSyncfor the target directory, and aligns with the existing XDG pattern inuserDataPath.ts(line 90)