All files / lib runner.js

100% Statements 77/77
100% Branches 10/10
100% Functions 3/3
100% Lines 77/77

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 782x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 6x 6x 6x 6x 6x 6x 6x 47x 46x 46x 47x 6x 6x 6x 5x 4x 4x 5x 6x 6x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 2x 2x 2x 2x 2x 2x 2x  
/**
 * Bob command execution module.
 * Handles execution of individual and series commands with output capture.
 *
 * @module runner
 */
"use strict";
import async from "async";
import child from "child_process";
import fs from "fs";
import { mkdirp } from "mkdirp";
import p from "path";
 
/**
 * Execute a single command and capture its output.
 *
 * @param {String} command: the command to execute
 * @param {Object} opts:
 *   - cwd: base directory where the commands should be executed from
 *   - quiet: don't display command output if quiet
 *   - task: Bob task name, used to create output directory
 *   - type: Bob task type name, used to create output directory
 *   - dir: report directory where process output will be written into a file
 * @param {Function} cb: standard cb(err, result) callback
 */
function exec(command, opts, cb) {
  console.log("%s | %s", opts.task.cyan, command);
 
  const cproc = child.exec(command, opts, cb),
    wstream = fs.createWriteStream(p.join(opts.dir, opts.type + ".txt"));
 
  cproc.stdout.on("data", (data) => {
    if (!opts.quiet) {
      process.stdout.write(data);
    }
    wstream.write(data);
  });
 
  cproc.stderr.on("data", (data) => {
    if (!opts.quiet) {
      process.stderr.write(data);
    }
    wstream.write(data);
  });
}
 
/**
 * Execute multiple commands in series.
 *
 * @param {Array} commands: an array of commands, each command contains:
 *   - exec: executable command line, to be executed on shell
 *   - meta: command metadata, task and type
 * @param {Object} opts:
 *   - cwd: base directory where the commands should be executed from
 *   - tmp: temporary directory where the command output will be written
 *   - quiet: don't display command output if quiet
 * @param {Function} cb: standard cb(err, result) callback
 */
function execSeries(commands, opts, cb) {
  function _exec(command, cb) {
    const base = command.meta.task == "clean" ? opts.tmp : opts.cwd;
    const dir = p.join(base, ".bob", command.meta.task);
    mkdirp.sync(dir);
    opts.task = command.meta.task;
    opts.type = command.meta.type;
    opts.dir = dir;
    exec(command.exec, opts, cb);
  }
  async.eachSeries(commands, _exec, cb);
}
 
const exports = {
  exec: exec,
  execSeries: execSeries,
};
 
export { exports as default };