arc lint can't run jshint on Windows. Here's how it fails when trying to lint rP:
C:\dev\phorge\phorge>..\arcanist\bin\arc lint Exception Command failed with error #1! COMMAND jshint --version STDOUT (empty) STDERR Call to "proc_open()" to open a subprocess failed: proc_open(): CreateProcess failed, error code - 2 (Run with `--trace` for a full exception trace.)
I do have jshint installed in the usual manner:
C:\dev\phorge\phorge>where jshint C:\Users\a\AppData\Roaming\npm\jshint C:\Users\a\AppData\Roaming\npm\jshint.cmd
(jshint is a Bash script for Linux-like environments; jshint.cmd is the batch script we want to run)
And I can run it:
C:\dev\phorge\phorge>jshint --version jshint v2.13.6
Despite that, the error code 2 indicates ERROR_FILE_NOT_FOUND (https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-).
Through some trial and error, and some Windows documentation spelunking, I have guessed that it's looking for a jshint.exe, which indeed does not exist, and that this is ultimately due to using the 'bypass_shell' option for the PHP function proc_open. The following script demonstrates this:
<?php function test($command, $opts = []) { echo "$command " . json_encode($opts) . "\n"; $desc = [ // silence STDERR output 2 => [ "pipe", "w" ], ]; $pipes = []; $process = @proc_open($command, $desc, $pipes, null, null, $opts); if (is_resource($process)) { var_dump(proc_close($process)); } else { echo "FAIL\n"; } } test('jshint --version'); test('jshint --version', ['bypass_shell' => true]); test('jshint.cmd --version'); test('jshint.cmd --version', ['bypass_shell' => true]); test('jshint.exe --version'); test('jshint.exe --version', ['bypass_shell' => true]);
Output:
jshint --version [] int(0) jshint --version {"bypass_shell":true} FAIL jshint.cmd --version [] int(0) jshint.cmd --version {"bypass_shell":true} int(0) jshint.exe --version [] int(1) jshint.exe --version {"bypass_shell":true} FAIL
As you can see, with bypass_shell, jshint.exe and jshint fail in the same way, while jshint.cmd works.
There seem to be good reasons for using bypass_shell related to problems with escaping command parameters on Windows, so we can't just remove that. Instead, I think we have to find the right executable ourselves, and pass the full path to proc_open. Fortunately, Arcanist already includes an utility for this: Filesystem::resolveBinary. Unfortunately, it does not work correctly – it returns the first result from where, which may not be an executable (and is not, in our case). Fortunately, that's easy enough to fix too.