forked from OKEAMAH/bolt
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocesses.js
More file actions
118 lines (98 loc) · 2.85 KB
/
processes.js
File metadata and controls
118 lines (98 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// @flow
import crossSpawn from 'cross-spawn';
import * as logger from './logger';
import * as cleanUp from './cleanUp';
import type Package from '../Package';
import type Project from '../Project';
import pLimit from 'p-limit';
import os from 'os';
import path from 'path';
import { globalOptions, type GlobalOptions } from '../GlobalOptions';
const limit = pLimit(os.cpus().length);
const processes = new Set();
export function handleSignals() {
cleanUp.handleAllSignals(() => {
for (let child of processes) {
child.kill('SIGTERM');
}
processes.clear();
});
}
export class ChildProcessError extends Error {
code: number;
stdout: string;
stderr: string;
constructor(code: number, stdout: string, stderr: string) {
super(stderr);
Error.captureStackTrace(this, this.constructor);
this.code = code;
this.stdout = stdout;
this.stderr = stderr;
}
}
export type SpawnOptions = {
...GlobalOptions,
cwd?: string,
pkg?: Package,
silent?: boolean,
tty?: boolean,
useBasename?: boolean,
env?: { [key: string]: ?string }
};
export function spawn(
cmd: string,
args: Array<string>,
opts: SpawnOptions = {}
) {
return limit(
() =>
new Promise((resolve, reject) => {
let stdoutBuf = Buffer.from('');
let stderrBuf = Buffer.from('');
let isTTY = process.stdout.isTTY && opts.tty;
let cmdDisplayName = opts.useBasename ? path.basename(cmd) : cmd;
let displayCmd =
opts.disableCmdPrefix != null
? opts.disableCmdPrefix
: globalOptions.get('disableCmdPrefix');
let cmdStr = displayCmd ? '' : cmdDisplayName + ' ' + args.join(' ');
let spawnOpts: child_process$spawnOpts = {
cwd: opts.cwd,
env: opts.env || process.env
};
if (isTTY) {
spawnOpts.shell = true;
spawnOpts.stdio = 'inherit';
}
let child = crossSpawn(cmd, args, spawnOpts);
processes.add(child);
if (child.stdout) {
child.stdout.on('data', data => {
if (!opts.silent) {
logger.stdout(cmdStr, data, opts.pkg);
}
stdoutBuf = Buffer.concat([stdoutBuf, data]);
});
}
if (child.stderr) {
child.stderr.on('data', data => {
if (!opts.silent) {
logger.stderr(cmdStr, data, opts.pkg);
}
stderrBuf = Buffer.concat([stderrBuf, data]);
});
}
child.on('error', reject);
child.on('close', code => {
let stdout = stdoutBuf.toString();
let stderr = stderrBuf.toString();
processes.delete(child);
if (code === 0) {
resolve({ code, stdout, stderr });
} else {
reject(new ChildProcessError(code, stdout, stderr));
}
});
})
);
}