1 | var common = require('./common');
|
2 | var _tempDir = require('./tempdir').tempDir;
|
3 | var _pwd = require('./pwd');
|
4 | var path = require('path');
|
5 | var fs = require('fs');
|
6 | var child = require('child_process');
|
7 |
|
8 | var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024;
|
9 | var DEFAULT_ERROR_CODE = 1;
|
10 |
|
11 | common.register('exec', _exec, {
|
12 | unix: false,
|
13 | canReceivePipe: true,
|
14 | wrapOutput: false,
|
15 | });
|
16 |
|
17 |
|
18 |
|
19 | function execSync(cmd, opts, pipe) {
|
20 | if (!common.config.execPath) {
|
21 | common.error('Unable to find a path to the node binary. Please manually set config.execPath');
|
22 | }
|
23 |
|
24 | var tempDir = _tempDir();
|
25 | var paramsFile = path.resolve(tempDir + '/' + common.randomFileName());
|
26 | var stderrFile = path.resolve(tempDir + '/' + common.randomFileName());
|
27 | var stdoutFile = path.resolve(tempDir + '/' + common.randomFileName());
|
28 |
|
29 | opts = common.extend({
|
30 | silent: common.config.silent,
|
31 | cwd: _pwd().toString(),
|
32 | env: process.env,
|
33 | maxBuffer: DEFAULT_MAXBUFFER_SIZE,
|
34 | encoding: 'utf8',
|
35 | }, opts);
|
36 |
|
37 | if (fs.existsSync(paramsFile)) common.unlinkSync(paramsFile);
|
38 | if (fs.existsSync(stderrFile)) common.unlinkSync(stderrFile);
|
39 | if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile);
|
40 |
|
41 | opts.cwd = path.resolve(opts.cwd);
|
42 |
|
43 | var paramsToSerialize = {
|
44 | command: cmd,
|
45 | execOptions: opts,
|
46 | pipe: pipe,
|
47 | stdoutFile: stdoutFile,
|
48 | stderrFile: stderrFile,
|
49 | };
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | function writeFileLockedDown(filePath, data) {
|
61 | fs.writeFileSync(filePath, data, {
|
62 | encoding: 'utf8',
|
63 | mode: parseInt('600', 8),
|
64 | });
|
65 | }
|
66 | writeFileLockedDown(stdoutFile, '');
|
67 | writeFileLockedDown(stderrFile, '');
|
68 | writeFileLockedDown(paramsFile, JSON.stringify(paramsToSerialize));
|
69 |
|
70 | var execArgs = [
|
71 | path.join(__dirname, 'exec-child.js'),
|
72 | paramsFile,
|
73 | ];
|
74 |
|
75 |
|
76 | if (opts.silent) {
|
77 | opts.stdio = 'ignore';
|
78 | } else {
|
79 | opts.stdio = [0, 1, 2];
|
80 | }
|
81 |
|
82 | var code = 0;
|
83 |
|
84 |
|
85 | try {
|
86 |
|
87 |
|
88 | delete opts.shell;
|
89 |
|
90 | child.execFileSync(common.config.execPath, execArgs, opts);
|
91 | } catch (e) {
|
92 |
|
93 | code = e.status || DEFAULT_ERROR_CODE;
|
94 | }
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 | var stdout = '';
|
101 | var stderr = '';
|
102 | if (opts.encoding === 'buffer') {
|
103 | stdout = fs.readFileSync(stdoutFile);
|
104 | stderr = fs.readFileSync(stderrFile);
|
105 | } else {
|
106 | stdout = fs.readFileSync(stdoutFile, opts.encoding);
|
107 | stderr = fs.readFileSync(stderrFile, opts.encoding);
|
108 | }
|
109 |
|
110 |
|
111 |
|
112 | try { common.unlinkSync(paramsFile); } catch (e) {}
|
113 | try { common.unlinkSync(stderrFile); } catch (e) {}
|
114 | try { common.unlinkSync(stdoutFile); } catch (e) {}
|
115 |
|
116 | if (code !== 0) {
|
117 |
|
118 |
|
119 |
|
120 | common.error(stderr, code, { continue: true, silent: true });
|
121 | }
|
122 | var obj = common.ShellString(stdout, stderr, code);
|
123 | return obj;
|
124 | }
|
125 |
|
126 |
|
127 | function execAsync(cmd, opts, pipe, callback) {
|
128 | opts = common.extend({
|
129 | silent: common.config.silent,
|
130 | cwd: _pwd().toString(),
|
131 | env: process.env,
|
132 | maxBuffer: DEFAULT_MAXBUFFER_SIZE,
|
133 | encoding: 'utf8',
|
134 | }, opts);
|
135 |
|
136 | var c = child.exec(cmd, opts, function (err, stdout, stderr) {
|
137 | if (callback) {
|
138 | if (!err) {
|
139 | callback(0, stdout, stderr);
|
140 | } else if (err.code === undefined) {
|
141 |
|
142 |
|
143 | callback(1, stdout, stderr);
|
144 | } else {
|
145 | callback(err.code, stdout, stderr);
|
146 | }
|
147 | }
|
148 | });
|
149 |
|
150 | if (pipe) c.stdin.end(pipe);
|
151 |
|
152 | if (!opts.silent) {
|
153 | c.stdout.pipe(process.stdout);
|
154 | c.stderr.pipe(process.stderr);
|
155 | }
|
156 |
|
157 | return c;
|
158 | }
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 | function _exec(command, options, callback) {
|
199 | options = options || {};
|
200 | if (!command) common.error('must specify command');
|
201 |
|
202 | var pipe = common.readFromPipe();
|
203 |
|
204 |
|
205 | if (typeof options === 'function') {
|
206 | callback = options;
|
207 | options = { async: true };
|
208 | }
|
209 |
|
210 |
|
211 | if (typeof options === 'object' && typeof callback === 'function') {
|
212 | options.async = true;
|
213 | }
|
214 |
|
215 | options = common.extend({
|
216 | silent: common.config.silent,
|
217 | async: false,
|
218 | }, options);
|
219 |
|
220 | if (options.async) {
|
221 | return execAsync(command, options, pipe, callback);
|
222 | } else {
|
223 | return execSync(command, options, pipe);
|
224 | }
|
225 | }
|
226 | module.exports = _exec;
|