| 'use strict';
|
|
|
| const path = require('path');
|
| const resolveCommand = require('./util/resolveCommand');
|
| const escape = require('./util/escape');
|
| const readShebang = require('./util/readShebang');
|
|
|
| const isWin = process.platform === 'win32';
|
| const isExecutableRegExp = /\.(?:com|exe)$/i;
|
| const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
|
|
| function detectShebang(parsed) {
|
| parsed.file = resolveCommand(parsed);
|
|
|
| const shebang = parsed.file && readShebang(parsed.file);
|
|
|
| if (shebang) {
|
| parsed.args.unshift(parsed.file);
|
| parsed.command = shebang;
|
|
|
| return resolveCommand(parsed);
|
| }
|
|
|
| return parsed.file;
|
| }
|
|
|
| function parseNonShell(parsed) {
|
| if (!isWin) {
|
| return parsed;
|
| }
|
|
|
|
|
| const commandFile = detectShebang(parsed);
|
|
|
|
|
| const needsShell = !isExecutableRegExp.test(commandFile);
|
|
|
|
|
|
|
| if (parsed.options.forceShell || needsShell) {
|
|
|
|
|
|
|
|
|
| const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
|
|
|
|
|
| parsed.command = path.normalize(parsed.command);
|
|
|
|
|
| parsed.command = escape.command(parsed.command);
|
| parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
|
|
|
| const shellCommand = [parsed.command].concat(parsed.args).join(' ');
|
|
|
| parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`];
|
| parsed.command = process.env.comspec || 'cmd.exe';
|
| parsed.options.windowsVerbatimArguments = true;
|
| }
|
|
|
| return parsed;
|
| }
|
|
|
| function parse(command, args, options) {
|
|
|
| if (args && !Array.isArray(args)) {
|
| options = args;
|
| args = null;
|
| }
|
|
|
| args = args ? args.slice(0) : [];
|
| options = Object.assign({}, options);
|
|
|
|
|
| const parsed = {
|
| command,
|
| args,
|
| options,
|
| file: undefined,
|
| original: {
|
| command,
|
| args,
|
| },
|
| };
|
|
|
|
|
| return options.shell ? parsed : parseNonShell(parsed);
|
| }
|
|
|
| module.exports = parse;
|
|
|