From 22b2d700db97d654053250ad1505601764520b7b Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sat, 26 Aug 2023 15:37:30 +0300 Subject: [PATCH] add helper functions for async spawning of processes --- src/util/process.ts | 60 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/util/process.ts b/src/util/process.ts index 1c70199..79bf37f 100644 --- a/src/util/process.ts +++ b/src/util/process.ts @@ -1,5 +1,6 @@ +import assert from 'assert' +import child_process, { exec as execCb } from 'child_process' import util from 'util' -import { exec as execCb } from 'child_process' const exec = util.promisify(execCb) @@ -12,3 +13,60 @@ export async function run(command: string) { export async function aapt2(path: string, ...args: Array) { return await run(`${path} ${args.join(' ')}`) } + +export async function spawnAsyncNoOut( + command: string, + args: ReadonlyArray, + isStderrLineAllowed?: (s: string) => boolean, +) { + let stdout = await spawnAsync(command, args, isStderrLineAllowed) + assert(stdout.length === 0, `unexpected stdout for ${command} ${args}: ${stdout}`) +} + +// Returns stdout. If there's stderr output, all lines of it should pass the isStderrLineAllowed check +export async function spawnAsync( + command: string, + args: ReadonlyArray, + isStderrLineAllowed?: (s: string) => boolean, + allowedExitCodes: number[] = [0], +) { + let proc = child_process.spawn(command, args) + let promise = new Promise((resolve, reject) => { + let stdoutBufs: Buffer[] = [] + let stderrBufs: Buffer[] = [] + + proc.stdout.on('data', data => { + stdoutBufs.push(data) + }) + proc.stderr.on('data', data => { + stderrBufs.push(data) + }) + + proc.on('close', code => { + let stderr = '' + + if (stderrBufs.length > 0) { + stderr = Buffer.concat(stderrBufs).toString() + } + + if (code !== null && allowedExitCodes.includes(code)) { + if (stderr.length > 0) { + if (isStderrLineAllowed === undefined) { + reject(new Error('unexpected stderr ' + stderr)) + } else { + for (let line of stderr.split('\n')) { + if (!isStderrLineAllowed(line)) { + reject(new Error('unexpected stderr line ' + line)) + } + } + } + } + resolve(Buffer.concat(stdoutBufs).toString()) + } else { + reject(new Error(proc.spawnargs + ' returned ' + code + (stderr.length > 0 ? ', stderr: ' + stderr : ''))) + } + }) + }) + + return promise as Promise +}