All files / src/tools/shared tool-error.ts

75% Statements 6/8
60% Branches 9/15
75% Functions 3/4
75% Lines 6/8

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                                      2x                 75x 75x                       2x 1x     1x                        
/**
 * The failures a tool expects, and how a tool's command line reports what stopped it.
 *
 * A tool stops with a ToolError for anything the person running it can fix, such as a mistyped face
 * or a failed pebble step, and only its message is worth printing. Anything else is a bug in the
 * tool, so it prints whole, stack and all, to show where it came from.
 */
import os from 'node:os';
 
/**
 * The exit code a tool ends with when a program it ran failed, the way a shell reports it.
 *
 * A signal gives 128 plus the signal's number, so CI reads an out of memory kill as a kill rather
 * than as an ordinary failure.
 *
 * @param run What spawnSync reported for the program.
 * @return The exit code to end with.
 */
export function exitCodeOf(run: { status: number | null; signal: NodeJS.Signals | null }): number {
  return run.signal ? 128 + (os.constants.signals[run.signal] ?? 0) : (run.status ?? 1);
}
 
/** A failure the person running the tool can fix, carrying the exit code the tool ends with. */
export class ToolError extends Error {
  /** The exit code the tool ends with. */
  readonly code: number;
 
  constructor(message: string, code = 1) {
    super(message);
    this.code = code;
  }
}
 
/**
 * What to print for whatever a tool threw. A ToolError gives its message, and anything else is a
 * bug in the tool, so it gives its stack to show where.
 *
 * @param error Whatever the tool threw.
 * @return The text to print.
 */
export function describeFailure(error: unknown): string {
  if (error instanceof ToolError) {
    return error.message;
  }
 
  return error instanceof Error ? (error.stack ?? error.message) : String(error);
}
 
/**
 * Prints what stopped a tool and sets the exit code it ends with.
 *
 * @param error Whatever the tool threw.
 */
export function reportFailure(error: unknown): void {
  console.error(describeFailure(error));
  process.exitCode = error instanceof ToolError ? error.code : 1;
}