.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / execa / node_modules / cross-spawn / lib / parse.js
1 'use strict';
2
3 var resolveCommand = require('./util/resolveCommand');
4 var hasEmptyArgumentBug = require('./util/hasEmptyArgumentBug');
5 var escapeArgument = require('./util/escapeArgument');
6 var escapeCommand = require('./util/escapeCommand');
7 var readShebang = require('./util/readShebang');
8
9 var isWin = process.platform === 'win32';
10 var skipShellRegExp = /\.(?:com|exe)$/i;
11
12 // Supported in Node >= 6 and >= 4.8
13 var supportsShellOption = parseInt(process.version.substr(1).split('.')[0], 10) >= 6 ||
14  parseInt(process.version.substr(1).split('.')[0], 10) === 4 && parseInt(process.version.substr(1).split('.')[1], 10) >= 8;
15
16 function parseNonShell(parsed) {
17     var shebang;
18     var needsShell;
19     var applyQuotes;
20
21     if (!isWin) {
22         return parsed;
23     }
24
25     // Detect & add support for shebangs
26     parsed.file = resolveCommand(parsed.command);
27     parsed.file = parsed.file || resolveCommand(parsed.command, true);
28     shebang = parsed.file && readShebang(parsed.file);
29
30     if (shebang) {
31         parsed.args.unshift(parsed.file);
32         parsed.command = shebang;
33         needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(resolveCommand(shebang) || resolveCommand(shebang, true));
34     } else {
35         needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(parsed.file);
36     }
37
38     // If a shell is required, use cmd.exe and take care of escaping everything correctly
39     if (needsShell) {
40         // Escape command & arguments
41         applyQuotes = (parsed.command !== 'echo');  // Do not quote arguments for the special "echo" command
42         parsed.command = escapeCommand(parsed.command);
43         parsed.args = parsed.args.map(function (arg) {
44             return escapeArgument(arg, applyQuotes);
45         });
46
47         // Make use of cmd.exe
48         parsed.args = ['/d', '/s', '/c', '"' + parsed.command + (parsed.args.length ? ' ' + parsed.args.join(' ') : '') + '"'];
49         parsed.command = process.env.comspec || 'cmd.exe';
50         parsed.options.windowsVerbatimArguments = true;  // Tell node's spawn that the arguments are already escaped
51     }
52
53     return parsed;
54 }
55
56 function parseShell(parsed) {
57     var shellCommand;
58
59     // If node supports the shell option, there's no need to mimic its behavior
60     if (supportsShellOption) {
61         return parsed;
62     }
63
64     // Mimic node shell option, see: https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335
65     shellCommand = [parsed.command].concat(parsed.args).join(' ');
66
67     if (isWin) {
68         parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe';
69         parsed.args = ['/d', '/s', '/c', '"' + shellCommand + '"'];
70         parsed.options.windowsVerbatimArguments = true;  // Tell node's spawn that the arguments are already escaped
71     } else {
72         if (typeof parsed.options.shell === 'string') {
73             parsed.command = parsed.options.shell;
74         } else if (process.platform === 'android') {
75             parsed.command = '/system/bin/sh';
76         } else {
77             parsed.command = '/bin/sh';
78         }
79
80         parsed.args = ['-c', shellCommand];
81     }
82
83     return parsed;
84 }
85
86 // ------------------------------------------------
87
88 function parse(command, args, options) {
89     var parsed;
90
91     // Normalize arguments, similar to nodejs
92     if (args && !Array.isArray(args)) {
93         options = args;
94         args = null;
95     }
96
97     args = args ? args.slice(0) : [];  // Clone array to avoid changing the original
98     options = options || {};
99
100     // Build our parsed object
101     parsed = {
102         command: command,
103         args: args,
104         options: options,
105         file: undefined,
106         original: command,
107     };
108
109     // Delegate further parsing to shell or non-shell
110     return options.shell ? parseShell(parsed) : parseNonShell(parsed);
111 }
112
113 module.exports = parse;