ci/woodpecker/pr/ci Pipeline was successful
getShellProfilePath() preferred ~/.bashrc when it existed, and ~/.zshrc for
zsh. setupPath() in stages/finalize.ts appends the PATH export to whatever
it returns. Debian's default ~/.bashrc opens with
case $- in *i*) ;; *) return;; esac
so a line appended to the bottom of it never runs for 'bash -lc', for
systemd units, for 'ssh host cmd', or for any agent seat — precisely the
consumers that need the CLI. An install could print its summary and exit 0
while leaving 'mosaic: command not found'. .zshrc has the same problem:
zsh only reads it for interactive shells.
Now ~/.profile, which login shells read and which Debian's copy sources
.bashrc from for interactive shells, so one line covers both. For zsh the
always-sourced file is .zshenv. fish and PowerShell are unchanged.
__tests__/platform/detect.test.ts pins it, including a case asserting that
no shell resolves to an interactive-only rc file. Falsified by inverting
the fix: 5 failed / 1 passed; restored 6/6. Full package suite unchanged at
17 files / 4 tests failing, matching clean origin/next.
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
import { join } from 'node:path';
|
|
import { homedir, platform } from 'node:os';
|
|
|
|
export type ShellType = 'zsh' | 'bash' | 'fish' | 'powershell' | 'unknown';
|
|
|
|
export function detectShell(): ShellType {
|
|
const shell = process.env['SHELL'] ?? '';
|
|
if (shell.includes('zsh')) return 'zsh';
|
|
if (shell.includes('bash')) return 'bash';
|
|
if (shell.includes('fish')) return 'fish';
|
|
if (platform() === 'win32') return 'powershell';
|
|
return 'unknown';
|
|
}
|
|
|
|
export function getShellProfilePath(): string | null {
|
|
const home = homedir();
|
|
|
|
if (platform() === 'win32') {
|
|
return join(home, 'Documents', 'PowerShell', 'Microsoft.PowerShell_profile.ps1');
|
|
}
|
|
|
|
const shell = detectShell();
|
|
switch (shell) {
|
|
// Both of these deliberately avoid the interactive-only rc files.
|
|
// Debian's default .bashrc returns early for non-interactive shells, so a
|
|
// PATH line appended to it never runs for `bash -lc`, systemd units, or
|
|
// agent seats — an install could report success and still leave `mosaic`
|
|
// unreachable. .profile is read by login shells and sources .bashrc for
|
|
// interactive ones, so one line covers both; .zshenv is zsh's equivalent.
|
|
case 'zsh': {
|
|
const zdotdir = process.env['ZDOTDIR'] ?? home;
|
|
return join(zdotdir, '.zshenv');
|
|
}
|
|
case 'bash':
|
|
return join(home, '.profile');
|
|
case 'fish':
|
|
return join(home, '.config', 'fish', 'config.fish');
|
|
default:
|
|
return join(home, '.profile');
|
|
}
|
|
}
|