diff --git a/src/main/startup/configure-process.test.ts b/src/main/startup/configure-process.test.ts index 512467eb724..eaf9f42aeec 100644 --- a/src/main/startup/configure-process.test.ts +++ b/src/main/startup/configure-process.test.ts @@ -77,6 +77,66 @@ describe('patchPackagedProcessPath', () => { expect(segments).toContain(join('/Users/tester', 'bin')) }) + it('omits Linux-only snap/Linuxbrew dirs but keeps Nix on packaged darwin runs', async () => { + const { app } = await import('electron') + const { patchPackagedProcessPath } = await import('./configure-process') + + setPlatform('darwin') + Object.defineProperty(app, 'isPackaged', { configurable: true, value: true }) + process.env.HOME = '/Users/tester' + process.env.PATH = '/usr/bin:/bin' + + patchPackagedProcessPath() + + const segments = (process.env.PATH ?? '').split(':') + // Why: neither has a macOS installer, so both are phantom PATH entries. + expect(segments).not.toContain('/snap/bin') + expect(segments).not.toContain('/home/linuxbrew/.linuxbrew/bin') + // Why: Nix does ship a macOS default profile, so it stays seeded. + expect(segments).toContain('/nix/var/nix/profiles/default/bin') + expect(segments).toContain('/opt/homebrew/bin') + expect(segments).toContain('/usr/local/bin') + }) + + it('keeps snap, Linuxbrew, and Nix dirs for packaged linux runs', async () => { + const { app } = await import('electron') + const { patchPackagedProcessPath } = await import('./configure-process') + + setPlatform('linux') + Object.defineProperty(app, 'isPackaged', { configurable: true, value: true }) + process.env.HOME = '/home/tester' + process.env.PATH = '/usr/bin:/bin' + + patchPackagedProcessPath() + + const segments = (process.env.PATH ?? '').split(':') + expect(segments).toContain('/snap/bin') + expect(segments).toContain('/home/linuxbrew/.linuxbrew/bin') + expect(segments).toContain('/nix/var/nix/profiles/default/bin') + expect(segments.indexOf('/usr/local/sbin')).toBeLessThan(segments.indexOf('/snap/bin')) + expect(segments.indexOf('/home/linuxbrew/.linuxbrew/bin')).toBeLessThan( + segments.indexOf('/nix/var/nix/profiles/default/bin') + ) + }) + + it('omits snap/Linuxbrew but keeps Nix on non-Linux POSIX platforms', async () => { + const { app } = await import('electron') + const { patchPackagedProcessPath } = await import('./configure-process') + + setPlatform('freebsd') + Object.defineProperty(app, 'isPackaged', { configurable: true, value: true }) + process.env.HOME = '/home/tester' + process.env.PATH = '/usr/bin:/bin' + + patchPackagedProcessPath() + + const segments = (process.env.PATH ?? '').split(':') + expect(segments).not.toContain('/snap/bin') + expect(segments).not.toContain('/home/linuxbrew/.linuxbrew/bin') + expect(segments).toContain('/nix/var/nix/profiles/default/bin') + expect(segments).toContain('/usr/local/bin') + }) + it('leaves PATH untouched when the app is not packaged', async () => { const { app } = await import('electron') const { patchPackagedProcessPath } = await import('./configure-process') diff --git a/src/main/startup/configure-process.ts b/src/main/startup/configure-process.ts index 292f6195258..e545d89da9c 100644 --- a/src/main/startup/configure-process.ts +++ b/src/main/startup/configure-process.ts @@ -99,15 +99,14 @@ export function patchPackagedProcessPath(): void { const extraPaths: string[] = [] if (process.platform !== 'win32') { - extraPaths.push( - '/opt/homebrew/bin', - '/opt/homebrew/sbin', - '/usr/local/bin', - '/usr/local/sbin', - '/snap/bin', - '/home/linuxbrew/.linuxbrew/bin', - '/nix/var/nix/profiles/default/bin' - ) + extraPaths.push('/opt/homebrew/bin', '/opt/homebrew/sbin', '/usr/local/bin', '/usr/local/sbin') + + if (process.platform === 'linux') { + // Why: snap and Linuxbrew ship on Linux only, so seeding them elsewhere adds phantom PATH entries every spawn must stat. + extraPaths.push('/snap/bin', '/home/linuxbrew/.linuxbrew/bin') + } + + extraPaths.push('/nix/var/nix/profiles/default/bin') if (home) { extraPaths.push(