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