1 | const sh = require('shelljs');
|
2 | const execa = require('execa');
|
3 | const debug = require('debug')('release-it:shell');
|
4 | const { format } = require('./util');
|
5 |
|
6 | sh.config.silent = !debug.enabled;
|
7 |
|
8 | const noop = Promise.resolve();
|
9 |
|
10 | class Shell {
|
11 | constructor({ global = {}, container }) {
|
12 | this.global = global;
|
13 | this.log = container.log;
|
14 | this.config = container.config;
|
15 | }
|
16 |
|
17 | exec(command, options = {}, context = {}) {
|
18 | if (!command || !command.length) return;
|
19 | return typeof command === 'string'
|
20 | ? this.execFormattedCommand(format(command, context), options)
|
21 | : this.execFormattedCommand(command, options);
|
22 | }
|
23 |
|
24 | async execFormattedCommand(command, options = {}) {
|
25 | const isDryRun = this.global.isDryRun;
|
26 | const isWrite = options.write !== false;
|
27 | const isExternal = options.external === true;
|
28 |
|
29 | if (isDryRun && isWrite) {
|
30 | this.log.exec(command, { isDryRun });
|
31 | return noop;
|
32 | }
|
33 |
|
34 | this.log.exec(command, { isExternal });
|
35 |
|
36 | if (typeof command === 'string') {
|
37 | return this.execStringCommand(command, options, { isExternal });
|
38 | } else {
|
39 | return this.execWithArguments(command, options, { isExternal });
|
40 | }
|
41 | }
|
42 |
|
43 | execStringCommand(command, options, { isExternal }) {
|
44 | return new Promise((resolve, reject) => {
|
45 | sh.exec(command, { async: true }, (code, stdout, stderr) => {
|
46 | stdout = stdout.toString().trim();
|
47 | this.log.verbose(stdout, { isExternal });
|
48 | debug({ command, options, code, stdout, stderr });
|
49 | if (code === 0) {
|
50 | resolve(stdout);
|
51 | } else {
|
52 | if (stdout && stderr) {
|
53 | this.log.log(`\n${stdout}`);
|
54 | }
|
55 | reject(new Error(stderr || stdout));
|
56 | }
|
57 | });
|
58 | });
|
59 | }
|
60 |
|
61 | async execWithArguments(command, options, { isExternal }) {
|
62 | const [program, ...programArgs] = command;
|
63 |
|
64 | try {
|
65 | const { stdout: out, stderr } = await execa(program, programArgs);
|
66 | const stdout = out === '""' ? '' : out;
|
67 | this.log.verbose(stdout, { isExternal });
|
68 | debug({ command, options, stdout, stderr });
|
69 | return Promise.resolve(stdout || stderr);
|
70 | } catch (error) {
|
71 | if (error.stdout) {
|
72 | this.log.log(`\n${error.stdout}`);
|
73 | }
|
74 | debug({ error });
|
75 | return Promise.reject(new Error(error.stderr || error.message));
|
76 | }
|
77 | }
|
78 | }
|
79 |
|
80 | module.exports = Shell;
|