New approach:
-
spawn('sh', ...)
Find the
-c
arg.Parse, and split up by
&&
and||
and|
and;
, expanding each bit.Then spawn the exploded command line. When we explode it, we need to do the same thing with looking up env and shebang results. However, if there are multiple parts, we can't change the actual thing that gets executed (ie, it must still be executed by calling
sh
, just with the exploded command line). -
spawn('.../node', ...)
Inject the args before the main, if it has a main file, and call spawn with that.
-
spawn('other', ...)
Check if it's a shebang file. If so, explode it to the resulting cli:
$interpreter $file
. In most cases, this will result inenv <envpairs> node <nodeoptions> $file
Note that a shebang is strictly space-delimited arguments. Quotes and escapes are not allowed here, which makes it much simpler. We can simply resolve this to
shebangLine.trim().split(/\s+/)
. If that first item isenv
then handle it just like aspawn(env)
. -
spawn('env', ...)
An env command line is done by looking up the resulting thingy with
which()
, and then resolving it further if it's a shebangK -
Always treat
bash
,ksh
, andzsh
the same assh
, since they have similar cli string behavior.
Different ways to spawn things:
-
spawn('node', ...)
easiest. inject the args, add the envPairs -
spawn('sh', ['-c', 'X=y /path/to/node blah'])
Parse '-c' arg just like a exec line. Windows flavor:spawn('cmd', ['/s', '/c', '"' + command + '"'])
replace ('sh', ['-c', '/path/to/node <inject args> blah'])
I think if we do this right, we don't have to do exec() maybe?
spawn('sh', ['-c', '/usr/bin/env x=y node blah blah'])
This is the hard one, because the indirection capabilities are endless.sh
can spawnbash
which spawnsenv
and so on.
A. replace with spawn('/usr/bin/env', ['x=y', 'node', '...'])
WARNING: requires writing a sh-compatible command line parser.
Splitting based on spaces won't work.
Eg: sh -c 'command "long space"'
B. Write a node program that wraps cli commands, sort of like the
wrap-main.js file. This will let us the just prepend it to the
sh -c
arg, and it can interpret the rest.
C. Maybe we just have our own node
and iojs
scripts (and
node.cmd
and iojs.cmd
for win32 peops), and we put those in a
bin folder that we always prepend to the PATH environ. Then it
almost doesn't matter what shebangs or whatever get run, because
which node
will always return that thing. Something to consider.
(Also, that fakey node
script cannot be a node program, obviously,
because the shell won't know where to find it!)
OOPS! no that won't work because how does the fake node shell
script know what to inject to our wrap-main.js file?
Computers are terrible.
-
spawn('shebangscript', ['arg'])
resolve shebangscript using which() read first line of script#!/some/interpreter some=args
->spawn('/some/interpreter', ['some=args', '$file'])
then handle appropriately -
spawn('/usr/bin/env', ['x=y', 'node', '$file'])
becomes case (1),spawn('node', ['$file')
, but with thex=y
appended to the envPairs list -
spawn('sh', ['-c', 'shebangscript arg'])
-
exec('/path/to/node blah blah')
becomesspawn('sh', ['-c', '/path/to/node blah blah'])
-
exec('/usr/bin/env node blah blah')
becomesspawn('sh', ['-c', '/usr/bin/env node blah blah'])
-
exec('sh -c "shebangscript arg"')
becomesspawn('sh', ['-c', 'sh -c "shebangscript arg"'])
This is a dark pit of oblivion.