geelen / shellac

Coat your shell scripts in something a bit more beautiful
MIT License
156 stars 4 forks source link

Doesn't work on Windows when Bash is installed through Scoop #14

Open Macil opened 5 months ago

Macil commented 5 months ago

If I have bash installed through Scoop (a system like Homebrew for Windows), then when I try to use shellac for anything, an empty command prompt is opened and the original script hangs at the shellac call.

import shellac from 'shellac';

await shellac`
$ echo "End-to-end CLI testing made nice"
$ node -p "5 * 9"
stdout >> ${(answer) => console.log(answer)}
`

image

If close the empty command prompt, then my script continues like this:

PS E:\chris\Coding\shellac> node .\testrun.js
EXIT WHEN NOT EXPECTED

SHELLAC COMMAND FAILED!
Executing: echo "End-to-end CLI testing made nice" in E:\chris\Coding\shellac

STDOUT:

STDERR:

node:internal/process/esm_loader:34
      internalBinding('errors').triggerUncaughtException(
                                ^
{
  retCode: undefined,
  cmd: 'echo "End-to-end CLI testing made nice"',
  stdout: '',
  stderr: ''
}

Node.js v21.7.3

With Scoop, when you install one or more packages containing bash.exe, you get multiple files like this:

~\scoop\shims\bash.exe
~\scoop\apps\gow\0.8.0\bin\bash.exe
~\scoop\apps\git\2.42.0.2\bin\bash.exe

Only the ~\scoop\shims directory is added to the PATH. The shims directory has exe files that call one of the exe files inside an installed package. (This is very similar to what NPM and Homebrew do.)

The issue specifically seems to do with shellac when it uses one of these Scoop-installed shim exe files. If I manually add either ~\scoop\apps\gow\0.8.0\bin or ~\scoop\apps\git\2.42.0.2\bin to the front of my PATH so a Scoop shim file is not used, then shellac works correctly and no extra visible command prompt appears while using it.

I don't know if Scoop is doing something wrong here or if shellac is being strict in a way that's not compatible with it.

Background

I originally ran into this while trying to use the "npm run preview" script within Cloudflare's Nextjs template which failed the same way as it uses https://github.com/cloudflare/next-on-pages/tree/main/packages/next-on-pages which uses https://github.com/james-elicx/package-manager-manager which uses shellac.

Possible Solution

I've found that if I disable detached: true here then shellac works correctly for me:

https://github.com/geelen/shellac/blob/575432978baed152a85328c27881effd00347b22/src/child-subshell/shell.ts#L15-L18

I'm not sure if the detached setting is important for some situations. My suggested fix would be to continue to have it be true on non-Windows platforms and make it false on Windows specifically:

import os from 'os'

// ...
    this.process = child_process.spawn('bash', ['--noprofile', '--norc'], {
      env,
      // use detached mode except on Windows where it's not compatible with all builds of bash
      detached: os.platform() !== "win32",
    })

(I imagine a fuller solution might be to make shellac not use Bash on Windows and instead use cmd.exe or Windows Powershell (which is installed by default on Windows) so that shellac's behavior doesn't depend on the specific version of Bash installed and so that it can work on a default Windows install (related: https://github.com/geelen/shellac/issues/13).)