1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.execvp = exports.pipevp = exports.EndStrategy = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const fslib_1 = require("@yarnpkg/fslib");
|
6 | const cross_spawn_1 = tslib_1.__importDefault(require("cross-spawn"));
|
7 | var EndStrategy;
|
8 | (function (EndStrategy) {
|
9 | EndStrategy[EndStrategy["Never"] = 0] = "Never";
|
10 | EndStrategy[EndStrategy["ErrorCode"] = 1] = "ErrorCode";
|
11 | EndStrategy[EndStrategy["Always"] = 2] = "Always";
|
12 | })(EndStrategy = exports.EndStrategy || (exports.EndStrategy = {}));
|
13 | function hasFd(stream) {
|
14 |
|
15 | return stream !== null && typeof stream.fd === `number`;
|
16 | }
|
17 | function sigintHandler() {
|
18 |
|
19 |
|
20 | }
|
21 |
|
22 |
|
23 |
|
24 | let sigintRefCount = 0;
|
25 | async function pipevp(fileName, args, { cwd, env = process.env, strict = false, stdin = null, stdout, stderr, end = EndStrategy.Always }) {
|
26 | const stdio = [`pipe`, `pipe`, `pipe`];
|
27 | if (stdin === null)
|
28 | stdio[0] = `ignore`;
|
29 | else if (hasFd(stdin))
|
30 | stdio[0] = stdin;
|
31 | if (hasFd(stdout))
|
32 | stdio[1] = stdout;
|
33 | if (hasFd(stderr))
|
34 | stdio[2] = stderr;
|
35 | if (sigintRefCount++ === 0)
|
36 | process.on(`SIGINT`, sigintHandler);
|
37 | const child = cross_spawn_1.default(fileName, args, {
|
38 | cwd: fslib_1.npath.fromPortablePath(cwd),
|
39 | env: {
|
40 | ...env,
|
41 | PWD: fslib_1.npath.fromPortablePath(cwd),
|
42 | },
|
43 | stdio,
|
44 | });
|
45 | if (!hasFd(stdin) && stdin !== null)
|
46 | stdin.pipe(child.stdin);
|
47 | if (!hasFd(stdout))
|
48 | child.stdout.pipe(stdout, { end: false });
|
49 | if (!hasFd(stderr))
|
50 | child.stderr.pipe(stderr, { end: false });
|
51 | const closeStreams = () => {
|
52 | for (const stream of new Set([stdout, stderr])) {
|
53 | if (!hasFd(stream)) {
|
54 | stream.end();
|
55 | }
|
56 | }
|
57 | };
|
58 | return new Promise((resolve, reject) => {
|
59 | child.on(`error`, error => {
|
60 | if (--sigintRefCount === 0)
|
61 | process.off(`SIGINT`, sigintHandler);
|
62 | if (end === EndStrategy.Always || end === EndStrategy.ErrorCode)
|
63 | closeStreams();
|
64 | reject(error);
|
65 | });
|
66 | child.on(`close`, (code, sig) => {
|
67 | if (--sigintRefCount === 0)
|
68 | process.off(`SIGINT`, sigintHandler);
|
69 | if (end === EndStrategy.Always || (end === EndStrategy.ErrorCode && code > 0))
|
70 | closeStreams();
|
71 | if (code === 0 || !strict) {
|
72 | resolve({ code: getExitCode(code, sig) });
|
73 | }
|
74 | else if (code !== null) {
|
75 | reject(new Error(`Child "${fileName}" exited with exit code ${code}`));
|
76 | }
|
77 | else {
|
78 | reject(new Error(`Child "${fileName}" exited with signal ${sig}`));
|
79 | }
|
80 | });
|
81 | });
|
82 | }
|
83 | exports.pipevp = pipevp;
|
84 | async function execvp(fileName, args, { cwd, env = process.env, encoding = `utf8`, strict = false }) {
|
85 | const stdio = [`ignore`, `pipe`, `pipe`];
|
86 | const stdoutChunks = [];
|
87 | const stderrChunks = [];
|
88 | const nativeCwd = fslib_1.npath.fromPortablePath(cwd);
|
89 | if (typeof env.PWD !== `undefined`)
|
90 | env = { ...env, PWD: nativeCwd };
|
91 | const subprocess = cross_spawn_1.default(fileName, args, {
|
92 | cwd: nativeCwd,
|
93 | env,
|
94 | stdio,
|
95 | });
|
96 | subprocess.stdout.on(`data`, (chunk) => {
|
97 | stdoutChunks.push(chunk);
|
98 | });
|
99 | subprocess.stderr.on(`data`, (chunk) => {
|
100 | stderrChunks.push(chunk);
|
101 | });
|
102 | return await new Promise((resolve, reject) => {
|
103 | subprocess.on(`error`, reject);
|
104 | subprocess.on(`close`, (code, signal) => {
|
105 | const stdout = encoding === `buffer`
|
106 | ? Buffer.concat(stdoutChunks)
|
107 | : Buffer.concat(stdoutChunks).toString(encoding);
|
108 | const stderr = encoding === `buffer`
|
109 | ? Buffer.concat(stderrChunks)
|
110 | : Buffer.concat(stderrChunks).toString(encoding);
|
111 | if (code === 0 || !strict) {
|
112 | resolve({
|
113 | code: getExitCode(code, signal), stdout, stderr,
|
114 | });
|
115 | }
|
116 | else {
|
117 | reject(Object.assign(new Error(`Child "${fileName}" exited with exit code ${code}\n\n${stderr}`), {
|
118 | code: getExitCode(code, signal), stdout, stderr,
|
119 | }));
|
120 | }
|
121 | });
|
122 | });
|
123 | }
|
124 | exports.execvp = execvp;
|
125 | const signalToCodeMap = new Map([
|
126 | [`SIGINT`, 2],
|
127 | [`SIGQUIT`, 3],
|
128 | [`SIGKILL`, 9],
|
129 | [`SIGTERM`, 15],
|
130 | ]);
|
131 | function getExitCode(code, signal) {
|
132 | const signalCode = signalToCodeMap.get(signal);
|
133 | if (typeof signalCode !== `undefined`) {
|
134 | return 128 + signalCode;
|
135 | }
|
136 | else {
|
137 | return code !== null && code !== void 0 ? code : 1;
|
138 | }
|
139 | }
|