(shell?: string)
| 392 | * @returns The user's PATH in that shell. |
| 393 | */ |
| 394 | export async function getMacPATH(shell?: string): Promise<string> { |
| 395 | // If we weren't given a shell override, detect the user's default shell. |
| 396 | if (!shell) { |
| 397 | // Read the user's shell using dscl. No clue how it works, deal with it. |
| 398 | const shellDetector = child_process.spawn('dscl', ['.', '-read', os.homedir(), 'UserShell'], { |
| 399 | shell: false |
| 400 | }); |
| 401 | // Get the full output and wait for the process to exit. |
| 402 | let builder = ''; |
| 403 | shellDetector.stdout.on('data', (chunk) => { |
| 404 | builder += chunk; |
| 405 | }); |
| 406 | await new Promise<void>(resolve => { |
| 407 | shellDetector.on('exit', () => { |
| 408 | resolve(); |
| 409 | }); |
| 410 | }); |
| 411 | // Look for a known shell in the output. |
| 412 | for (const option of ['bash', 'zsh', 'ksh', 'tcsh', 'csh']) { |
| 413 | const matchresult = builder.match(new RegExp('/.*' + option)); |
| 414 | if (matchresult) { |
| 415 | shell = matchresult[0]; |
| 416 | break; |
| 417 | } |
| 418 | } |
| 419 | } |
| 420 | // Default to bash if none of the other shells are found. |
| 421 | shell = shell ?? '/bin/bash'; |
| 422 | const spawnOpts: child_process.SpawnOptionsWithoutStdio = { |
| 423 | shell: false |
| 424 | }; |
| 425 | // Different shells require different arguments to start in "login" (profile-reading) mode. |
| 426 | const loginArgs = []; |
| 427 | switch (shell.slice(shell.lastIndexOf('/') + 1)) { |
| 428 | case 'bash': |
| 429 | case 'zsh': |
| 430 | case 'ksh': |
| 431 | loginArgs.push('-i', '-l'); |
| 432 | break; |
| 433 | case 'tcsh': |
| 434 | case 'csh': |
| 435 | loginArgs.push('-i'); |
| 436 | spawnOpts.argv0 = '-' + shell.slice(shell.lastIndexOf('/') + 1); |
| 437 | break; |
| 438 | } |
| 439 | // Run the shell, tell it to echo $PATH when it's done with init. |
| 440 | const pathDetector = child_process.spawn(shell, [...loginArgs, '-c', 'echo $PATH'], spawnOpts); |
| 441 | // Get the full output and wait for the process to exit. |
| 442 | let builder = ''; |
| 443 | pathDetector.stdout.on('data', (chunk) => { |
| 444 | builder += chunk; |
| 445 | }); |
| 446 | await new Promise<void>(resolve => { |
| 447 | pathDetector.on('exit', () => { |
| 448 | resolve(); |
| 449 | }); |
| 450 | }); |
| 451 | // Trim any whitespace, etc. |
no test coverage detected