[Service] Upgrade device home as v1.0.1
[platform/framework/web/wrtjs.git] / device_home / node_modules / jake / lib / utils / index.js
1 /*
2  * Jake JavaScript build tool
3  * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17 */
18
19
20 let util = require('util'); // Native Node util module
21 let spawn = require('child_process').spawn;
22 let EventEmitter = require('events').EventEmitter;
23 let logger = require('./logger');
24 let file = require('./file');
25 let Exec;
26
27 const _UUID_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
28
29 let parseArgs = function (argumentsObj) {
30   let args;
31   let arg;
32   let cmds;
33   let callback;
34   let opts = {
35     interactive: false,
36     printStdout: false,
37     printStderr: false,
38     breakOnError: true
39   };
40
41   args = Array.prototype.slice.call(argumentsObj);
42
43   cmds = args.shift();
44   // Arrayize if passed a single string command
45   if (typeof cmds == 'string') {
46     cmds = [cmds];
47   }
48   // Make a copy if it's an actual list
49   else {
50     cmds = cmds.slice();
51   }
52
53   // Get optional callback or opts
54   while((arg = args.shift())) {
55     if (typeof arg == 'function') {
56       callback = arg;
57     }
58     else if (typeof arg == 'object') {
59       opts = Object.assign(opts, arg);
60     }
61   }
62
63   // Backward-compat shim
64   if (typeof opts.stdout != 'undefined') {
65     opts.printStdout = opts.stdout;
66     delete opts.stdout;
67   }
68   if (typeof opts.stderr != 'undefined') {
69     opts.printStderr = opts.stderr;
70     delete opts.stderr;
71   }
72
73   return {
74     cmds: cmds,
75     opts: opts,
76     callback: callback
77   };
78 };
79
80 /**
81   @name jake
82   @namespace jake
83 */
84 let utils = new (function () {
85   /**
86     @name jake.exec
87     @static
88     @function
89     @description Executes shell-commands asynchronously with an optional
90     final callback.
91     `
92     @param {String[]} cmds The list of shell-commands to execute
93     @param {Object} [opts]
94       @param {Boolean} [opts.printStdout=false] Print stdout from each command
95       @param {Boolean} [opts.printStderr=false] Print stderr from each command
96       @param {Boolean} [opts.breakOnError=true] Stop further execution on
97       the first error.
98       @param {Boolean} [opts.windowsVerbatimArguments=false] Don't translate
99       arguments on Windows.
100     @param {Function} [callback] Callback to run after executing  the
101     commands
102
103     @example
104     let cmds = [
105           'echo "showing directories"'
106         , 'ls -al | grep ^d'
107         , 'echo "moving up a directory"'
108         , 'cd ../'
109         ]
110       , callback = function () {
111           console.log('Finished running commands.');
112         }
113     jake.exec(cmds, {stdout: true}, callback);
114    */
115   this.exec = function (a, b, c) {
116     let parsed = parseArgs(arguments);
117     let cmds = parsed.cmds;
118     let opts = parsed.opts;
119     let callback = parsed.callback;
120
121     let ex = new Exec(cmds, opts, callback);
122
123     ex.addListener('error', function (msg, code) {
124       if (opts.breakOnError) {
125         fail(msg, code);
126       }
127     });
128     ex.run();
129
130     return ex;
131   };
132
133   this.createExec = function (a, b, c) {
134     return new Exec(a, b, c);
135   };
136
137   // From Math.uuid.js, https://github.com/broofa/node-uuid
138   // Robert Kieffer (robert@broofa.com), MIT license
139   this.uuid = function (length, radix) {
140     var chars = _UUID_CHARS
141       , uuid = []
142       , r
143       , i;
144
145     radix = radix || chars.length;
146
147     if (length) {
148       // Compact form
149       i = -1;
150       while (++i < length) {
151         uuid[i] = chars[0 | Math.random()*radix];
152       }
153     } else {
154       // rfc4122, version 4 form
155
156       // rfc4122 requires these characters
157       uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
158       uuid[14] = '4';
159
160       // Fill in random data.  At i==19 set the high bits of clock sequence as
161       // per rfc4122, sec. 4.1.5
162       i = -1;
163       while (++i < 36) {
164         if (!uuid[i]) {
165           r = 0 | Math.random()*16;
166           uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
167         }
168       }
169     }
170
171     return uuid.join('');
172   };
173
174 })();
175
176 Exec = function () {
177   let parsed = parseArgs(arguments);
178   let cmds = parsed.cmds;
179   let opts = parsed.opts;
180   let callback = parsed.callback;
181
182   this._cmds = cmds;
183   this._callback = callback;
184   this._config = opts;
185 };
186
187 util.inherits(Exec, EventEmitter);
188
189 Object.assign(Exec.prototype, new (function () {
190
191   let _run = function () {
192     let self = this;
193     let sh;
194     let cmd;
195     let args;
196     let next = this._cmds.shift();
197     let config = this._config;
198     let errData = '';
199     let shStdio;
200     let handleStdoutData = function (data) {
201       self.emit('stdout', data);
202     };
203     let handleStderrData = function (data) {
204       let d = data.toString();
205       self.emit('stderr', data);
206       // Accumulate the error-data so we can use it as the
207       // stack if the process exits with an error
208       errData += d;
209     };
210
211     // Keep running as long as there are commands in the array
212     if (next) {
213       let spawnOpts = {};
214       this.emit('cmdStart', next);
215
216       // Ganking part of Node's child_process.exec to get cmdline args parsed
217       if (process.platform == 'win32') {
218         cmd = 'cmd';
219         args = ['/c', next];
220         if (config.windowsVerbatimArguments) {
221           spawnOpts.windowsVerbatimArguments = true;
222         }
223       }
224       else {
225         cmd = '/bin/sh';
226         args = ['-c', next];
227       }
228
229       if (config.interactive) {
230         spawnOpts.stdio = 'inherit';
231         sh = spawn(cmd, args, spawnOpts);
232       }
233       else {
234         shStdio = [
235           process.stdin
236         ];
237         if (config.printStdout) {
238           shStdio.push(process.stdout);
239         }
240         else {
241           shStdio.push('pipe');
242         }
243         if (config.printStderr) {
244           shStdio.push(process.stderr);
245         }
246         else {
247           shStdio.push('pipe');
248         }
249         spawnOpts.stdio = shStdio;
250         sh = spawn(cmd, args, spawnOpts);
251         if (!config.printStdout) {
252           sh.stdout.addListener('data', handleStdoutData);
253         }
254         if (!config.printStderr) {
255           sh.stderr.addListener('data', handleStderrData);
256         }
257       }
258
259       // Exit, handle err or run next
260       sh.on('exit', function (code) {
261         let msg;
262         if (code !== 0) {
263           msg = errData || 'Process exited with error.';
264           msg = msg.trim();
265           self.emit('error', msg, code);
266         }
267         if (code === 0 || !config.breakOnError) {
268           self.emit('cmdEnd', next);
269           setTimeout(function () { _run.call(self); }, 0);
270         }
271       });
272
273     }
274     else {
275       self.emit('end');
276       if (typeof self._callback == 'function') {
277         self._callback();
278       }
279     }
280   };
281
282   this.append = function (cmd) {
283     this._cmds.push(cmd);
284   };
285
286   this.run = function () {
287     _run.call(this);
288   };
289
290 })());
291
292 utils.Exec = Exec;
293 utils.file = file;
294 utils.logger = logger;
295
296 module.exports = utils;
297