-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix build on Windows for user paths with spaces
Fix incorrect command and argument handling on Windows by spawning the command in a shell and by wrapping command and arguments containing spaces in quotes. See nodejs/node#5060 Fix #25 Change-Id: Ieb32892946e9a779b67b5842f4f58d18be847b0f
- Loading branch information
Showing
2 changed files
with
96 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,37 @@ | ||
const os = require('os'); | ||
const {spawnSync} = require('child_process'); | ||
const proc = require('child_process'); | ||
const log = require('./log'); | ||
|
||
function execSync(cmd, args, opts = {}) { | ||
let cmdName = os.platform() === 'win32' ? cmd + '.cmd' : cmd; | ||
log.command([cmdName, ...args].join(' '), opts.cwd); | ||
const ps = spawnSync(cmdName, args, Object.assign({stdio: 'inherit'}, opts)); | ||
let normalizedCmd = normalizeCommand(cmd); | ||
let normalizedArgs = normalizeArguments(args); | ||
log.command([normalizedCmd, ...normalizedArgs].join(' '), opts.cwd); | ||
const ps = proc.spawnSync(normalizedCmd, normalizedArgs, Object.assign({ | ||
stdio: 'inherit', | ||
shell: isWindows() | ||
}, opts)); | ||
if (ps.status !== 0) { | ||
throw new Error(`The command ${cmd} exited with ${ps.status}`); | ||
} | ||
return ps; | ||
} | ||
|
||
function normalizeArguments(args) { | ||
if (isWindows()) { | ||
return args.map(arg => arg.indexOf(' ') >= 0 ? `"${arg}"` : arg); | ||
} | ||
return args; | ||
} | ||
|
||
function normalizeCommand(cmd) { | ||
if (isWindows()) { | ||
return cmd.indexOf(' ') >= 0 ? `"${cmd}"` : cmd; | ||
} | ||
return cmd; | ||
} | ||
|
||
function isWindows() { | ||
return os.platform() === 'win32'; | ||
} | ||
|
||
module.exports = {execSync}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
const os = require('os'); | ||
const childProcess = require('child_process'); | ||
const proc = require('../src/helpers/proc'); | ||
const log = require('../src/helpers/log'); | ||
const {expect, stub, restore, match} = require('./test'); | ||
|
||
describe('proc', function() { | ||
|
||
describe('execSync', function() { | ||
|
||
let status, platform; | ||
|
||
beforeEach(function() { | ||
status = 0; | ||
platform = 'linux'; | ||
stub(log, 'command'); | ||
stub(os, 'platform').callsFake(() => platform); | ||
stub(childProcess, 'spawnSync').callsFake(() => ({status})); | ||
}); | ||
|
||
afterEach(restore); | ||
|
||
it('spawns command with options', function() { | ||
proc.execSync('foo', ['ba r', 'bak'], {option: 'value'}); | ||
|
||
expect(childProcess.spawnSync).to.have.been.calledWithMatch('foo', ['ba r', 'bak'], { | ||
stdio: 'inherit', | ||
shell: false, | ||
option: 'value' | ||
}); | ||
}); | ||
|
||
it('runs command inside of a shell on Windows', function() { | ||
platform = 'win32'; | ||
|
||
proc.execSync('foo', ['bar'], {option: 'value'}); | ||
|
||
expect(childProcess.spawnSync).to.have.been.calledWithMatch(match.any, match.any, { | ||
shell: true | ||
}); | ||
}); | ||
|
||
it('throws an error when process exits with non 0 status', function() { | ||
status = 123; | ||
|
||
expect(() => { | ||
proc.execSync('foo', ['bar'], {option: 'value'}); | ||
}).to.throw('The command foo exited with 123'); | ||
}); | ||
|
||
it('normalizes command on Windows', function() { | ||
platform = 'win32'; | ||
|
||
proc.execSync('fo o', ['bar'], {option: 'value'}); | ||
|
||
expect(childProcess.spawnSync).to.have.been.calledWithMatch('"fo o"'); | ||
}); | ||
|
||
it('normalizes arguments on Windows', function() { | ||
platform = 'win32'; | ||
|
||
proc.execSync('foo', ['bar', 'ba k'], {option: 'value'}); | ||
|
||
expect(childProcess.spawnSync).to.have.been.calledWithMatch(match.any, ['bar', '"ba k"']); | ||
}); | ||
|
||
}); | ||
|
||
}); | ||
|