1#!/bin/sh
2set -eu
3
4# Performs `cat` and `grep` simultaneously for `run-make` tests in the Rust CI.
5#
6# This program will read lines from stdin and print them to stdout immediately.
7# At the same time, it will check if the input line contains the substring or
8# regex specified in the command line. If any match is found, the program will
9# set the exit code to 0, otherwise 1.
10#
11# This is written to simplify debugging runmake tests. Since `grep` swallows all
12# output, when a test involving `grep` failed, it is impossible to know the
13# reason just by reading the failure log. While it is possible to `tee` the
14# output into another stream, it becomes pretty annoying to do this for all test
15# cases.
16
17USAGE='
18cat-and-grep.sh [-v] [-e] [-i] s1 s2 s3 ... < input.txt
19
20Prints the stdin, and exits successfully only if all of `sN` can be found in
21some lines of the input.
22
23Options:
24    -v      Invert match, exits successfully only if all of `sN` cannot be found
25    -e      Regex search, search using extended Regex instead of fixed string
26    -i      Case insensitive search.
27'
28
29GREPPER=fgrep
30INVERT=0
31GREPFLAGS='q'
32while getopts ':vieh' OPTION; do
33    case "$OPTION" in
34        v)
35            INVERT=1
36            ERROR_MSG='should not be found'
37            ;;
38        i)
39            GREPFLAGS="i$GREPFLAGS"
40            ;;
41        e)
42            GREPPER=egrep
43            ;;
44        h)
45            echo "$USAGE"
46            exit 2
47            ;;
48        *)
49            break
50            ;;
51    esac
52done
53
54shift $((OPTIND - 1))
55
56# use gnu version of tool if available (for bsd)
57if command -v "g${GREPPER}"; then
58    GREPPER="g${GREPPER}"
59fi
60
61LOG=$(mktemp -t cgrep.XXXXXX)
62trap "rm -f $LOG" EXIT
63
64printf "[[[ begin stdout ]]]\n\033[90m"
65tee "$LOG"
66echo >> "$LOG"   # ensure at least 1 line of output, otherwise `grep -v` may unconditionally fail.
67printf "\033[0m\n[[[ end stdout ]]]\n"
68
69HAS_ERROR=0
70for MATCH in "$@"; do
71    if "$GREPPER" "-$GREPFLAGS" -- "$MATCH" "$LOG"; then
72        if [ "$INVERT" = 1 ]; then
73            printf "\033[1;31mError: should not match: %s\033[0m\n" "$MATCH"
74            HAS_ERROR=1
75        fi
76    else
77        if [ "$INVERT" = 0 ]; then
78            printf "\033[1;31mError: cannot match: %s\033[0m\n" "$MATCH"
79            HAS_ERROR=1
80        fi
81    fi
82done
83
84exit "$HAS_ERROR"
85