UNPKG

2.17 kBJavaScriptView Raw
1'use strict';
2const {exec} = require('child_process');
3const chalk = require('chalk');
4const npmRunPath = require('npm-run-path');
5
6const TEN_MEGABYTES = 1000 * 1000 * 10;
7
8module.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 // Increase max buffer
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};