Files
delta-backup/lib/spawn.js

48 lines
1.4 KiB
JavaScript

/**
* Process spawning — always explicit argument arrays, never shell strings.
*/
import { spawn } from 'child_process';
/**
* Spawn a process and stream its output to stdout/stderr.
* @param {string} cmd
* @param {string[]} args
* @param {{ dryRun?: boolean }} opts
* @returns {Promise<void>}
*/
export async function run(cmd, args, { dryRun = false } = {}) {
console.log(`$ ${[cmd, ...args].join(' ')}`);
if (dryRun) return;
return new Promise((resolve, reject) => {
const child = spawn(cmd, args, { stdio: 'inherit' });
child.on('error', reject);
child.on('close', code => {
if (code === 0) resolve();
else reject(new Error(`${cmd} exited with code ${code}`));
});
});
}
/**
* Spawn a process and capture stdout as a string.
* stderr is inherited (shown to user). Never used in dry-run context.
* @param {string} cmd
* @param {string[]} args
* @returns {Promise<string>}
*/
export async function capture(cmd, args) {
console.log(`$ ${[cmd, ...args].join(' ')}`);
return new Promise((resolve, reject) => {
const child = spawn(cmd, args, { stdio: ['inherit', 'pipe', 'inherit'] });
const chunks = [];
child.stdout.on('data', chunk => chunks.push(chunk));
child.on('error', reject);
child.on('close', code => {
if (code === 0) resolve(Buffer.concat(chunks).toString('utf8'));
else reject(new Error(`${cmd} exited with code ${code}`));
});
});
}