Skip to content

feat: respect XDG_CONFIG_HOME for argv.json on Linux#300881

Open
murataslan1 wants to merge 1 commit intomicrosoft:mainfrom
murataslan1:feature/xdg-config-home-argv
Open

feat: respect XDG_CONFIG_HOME for argv.json on Linux#300881
murataslan1 wants to merge 1 commit intomicrosoft:mainfrom
murataslan1:feature/xdg-config-home-argv

Conversation

@murataslan1
Copy link
Contributor

Summary

Resolves the long-standing inconsistency where argv.json was placed under ~/.vscode/ even when XDG_CONFIG_HOME is set, while all other user data already respects it (via userDataPath.ts).

Fixes #162712

Changes

2 files changed, 28 additions, 1 deletion

File Change
src/main.ts Update getArgvConfigPath() to use XDG_CONFIG_HOME on Linux (falling back to ~/.config). Adds migration from legacy path.
src/vs/platform/environment/common/environmentService.ts Update argvResource getter to resolve under XDG_CONFIG_HOME on Linux.

Behavior

Platform XDG_CONFIG_HOME set? argv.json location
Linux Yes (/custom/config) /custom/config/.vscode/argv.json
Linux No ~/.config/.vscode/argv.json (same as userDataPath)
macOS/Windows N/A Unchanged (~/.vscode/argv.json / AppData)

Migration

When XDG_CONFIG_HOME is set on Linux:

  1. Checks if legacy ~/.vscode/argv.json exists
  2. If new location doesn't exist yet → moves file to XDG-compliant path
  3. Errors are caught and logged (no crash on permission issues)
  4. If both exist → uses new location (no data loss)

Prior Art

  • Previous PR Fix use platform specific datapath #16712 #170364 attempted this but was closed (CI issues, no error handling)
  • This implementation adds proper error handling, mkdirSync for the target directory, and aligns with the existing XDG pattern in userDataPath.ts (line 90)
  • Follows @bpasero's guidance: "respect the XDG_CONFIG_HOME variable as we do [in userDataPath.ts]"

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
Copilot AI review requested due to automatic review settings March 11, 2026 19:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.argvResource to use XDG_CONFIG_HOME on Linux.
  • Update src/main.ts startup argv.json resolution to use XDG_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.

Comment on lines +441 to +448
// 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']) {
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

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

Suggested change
// 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) {

Copilot uses AI. Check for mistakes.
Comment on lines +447 to +455
// 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);
}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

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

Copilot uses AI. Check for mistakes.
Comment on lines +451 to +458
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})`);
}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +104
// 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'));
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
// 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'));

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support XDG_CONFIG_HOME for the argv.json file

3 participants