1 | 'use strict';
|
2 | const {exec} = require('child_process');
|
3 | const chalk = require('chalk');
|
4 | const npmRunPath = require('npm-run-path');
|
5 |
|
6 | const TEN_MEGABYTES = 1000 * 1000 * 10;
|
7 |
|
8 | module.exports = grunt => {
|
9 | grunt.registerMultiTask('shell', 'Run shell commands', function (...args) {
|
10 | const callback = this.async();
|
11 | const options = this.options({
|
12 | stdout: true,
|
13 | stderr: true,
|
14 | stdin: true,
|
15 | failOnError: true,
|
16 | stdinRawMode: false,
|
17 | preferLocal: true,
|
18 | execOptions: {
|
19 | env: null
|
20 | }
|
21 | });
|
22 |
|
23 | let cmd = (typeof this.data === 'string' || typeof this.data === 'function') ?
|
24 | this.data :
|
25 | this.data.command;
|
26 |
|
27 | if (cmd === undefined) {
|
28 | throw new Error('`command` required');
|
29 | }
|
30 |
|
31 |
|
32 | options.execOptions = Object.assign({}, options.execOptions);
|
33 | options.execOptions.maxBuffer = options.execOptions.maxBuffer || TEN_MEGABYTES;
|
34 |
|
35 | cmd = grunt.template.process(typeof cmd === 'function' ? cmd.apply(grunt, args) : cmd);
|
36 |
|
37 | if (options.preferLocal === true) {
|
38 | options.execOptions.env = npmRunPath.env({env: options.execOptions.env || process.env});
|
39 | }
|
40 |
|
41 | if (this.data.cwd) {
|
42 | options.execOptions.cwd = this.data.cwd;
|
43 | }
|
44 |
|
45 | const cp = exec(cmd, options.execOptions, (error, stdout, stderr) => {
|
46 | if (typeof options.callback === 'function') {
|
47 | options.callback.call(this, error, stdout, stderr, callback);
|
48 | } else {
|
49 | if (error && options.failOnError) {
|
50 | grunt.warn(error);
|
51 | }
|
52 | callback();
|
53 | }
|
54 | });
|
55 |
|
56 | const captureOutput = (child, output) => {
|
57 | if (grunt.option('color') === false) {
|
58 | child.on('data', data => {
|
59 | output.write(chalk.stripColor(data));
|
60 | });
|
61 | } else {
|
62 | child.pipe(output);
|
63 | }
|
64 | };
|
65 |
|
66 | grunt.verbose.writeln('Command:', chalk.yellow(cmd));
|
67 |
|
68 | if (options.stdout || grunt.option('verbose')) {
|
69 | captureOutput(cp.stdout, process.stdout);
|
70 | }
|
71 |
|
72 | if (options.stderr || grunt.option('verbose')) {
|
73 | captureOutput(cp.stderr, process.stderr);
|
74 | }
|
75 |
|
76 | if (options.stdin) {
|
77 | process.stdin.resume();
|
78 | process.stdin.setEncoding('utf8');
|
79 |
|
80 | if (options.stdinRawMode && process.stdin.isTTY) {
|
81 | process.stdin.setRawMode(true);
|
82 | }
|
83 |
|
84 | process.stdin.pipe(cp.stdin);
|
85 | }
|
86 | });
|
87 | };
|