diff --git a/README b/README new file mode 100644 index 0000000..b2db367 --- /dev/null +++ b/README @@ -0,0 +1,21 @@ +Usage: cramp [ --] [] + +Cram, in parallel. + +If are given, they must be separated from test by "--". + +cramp options: + -jN, --jobs=N number of tests to run in parallel + -h, --help show this help message and exit + -V, --version show version information and exit + +cram options: + -q, --quiet don't print diffs + -v, --verbose show filenames and test status + -d, --debug write script output directly to the terminal + -E, --preserve-env don't reset common environment variables + --keep-tmpdir keep temporary directories + --shell=PATH shell to use for running tests (default: /bin/sh) + --shell-opts=OPTS arguments to invoke shell with + --indent=NUM number of spaces to use for indentation (default: 2) + --xunit-file=PATH path to write xUnit XML output diff --git a/cram-log-merge b/cram-log-merge new file mode 100755 index 0000000..aa89fca --- /dev/null +++ b/cram-log-merge @@ -0,0 +1,41 @@ +#!/usr/bin/env perl +# Merge output from multiple invocations of Cram into one. +use strict; +use warnings; + +$|++; # unbuffer stdout + +my $ok = 0; +my $skip = 0; +my $fail = 0; +my $buf = ""; +my $kept = ""; + +while (<<>>) { + if (/^# Ran (\d+) tests, (\d+) skipped, (\d+) failed[.]/) { + # End of a Cram run; track counts and print output. + $ok += $1; + $skip += $2; + $fail += $3; + + chomp $buf if $buf =~ /^[.s!]+$/; + print $buf; + $buf = ""; + } + elsif (/^# Kept temporary directory:/) { + # Hold --keep-tmpdir output till very end. + $kept .= $_; + } + else { + # Accumulate output from a Cram run + $buf .= $_; + } +} + +die if $buf; # assert empty + +print "\n"; +print "# Ran $ok tests, $skip skipped, $fail failed.\n"; +print $kept if $kept; + +exit $fail; diff --git a/cramp b/cramp new file mode 100755 index 0000000..ece0892 --- /dev/null +++ b/cramp @@ -0,0 +1,81 @@ +#!/bin/bash +set -euo pipefail + +main() { + # Separate options, if any, from paths. If options are given, they must be + # delimited from paths with "--". + local -a cram_opts + local job_opt="--jobs=+0" + + if [[ $# -eq 0 ]]; then + exit-with-help + fi + if [[ "${1:-}" == -* ]]; then + while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) + exit-with-help;; + + --version|-V) + exit-with-version;; + + --jobs=?*|-j?*) + job_opt="$1" + shift;; + + --jobs|-j) + job_opt="--jobs=$2" + shift 2;; + + --interactive|-i|--yes|-y|--no|-n) + echo "cram's interactivity options (e.g. $1) are not supported under cramp" >&2 + exit 1;; + + --) + shift + break;; + + *) + cram_opts+=("$1") + shift;; + esac + done + fi + + find "$@" -type f -name '*.t' -print0 \ + | sort --zero-terminated \ + | parallel --null --line-buffer --keep-order "$job_opt" -- cram "${cram_opts[@]}" \ + | "$(dirname "$0")"/cram-log-merge +} + +exit-with-help() { + cram --help | sed -Ee ' + /^Usage: /c Usage: cramp [ --] [] + + /^Options:/ { + i Cram, in parallel. + i + i If are given, they must be separated from test by "--". + i + i cramp options: + i \ \ -jN, --jobs=N number of tests to run in parallel + i \ \ -h, --help show this help message and exit + i \ \ -V, --version show version information and exit + i + c cram options: + } + /\s--(help|version)\s/d # takeover help and version + /\s--(interactive|yes|no)\s/d # no interactivity + ' + exit +} + +exit-with-version() { + echo "Cram, parallel (version 0)" + echo "Copyright 2024 Thomas Sibley " + echo + cram --version + exit +} + +main "$@"