72 lines
2.6 KiB
Bash
72 lines
2.6 KiB
Bash
![]() |
#!/usr/bin/env bash
|
||
|
#
|
||
|
# Validate file inclusion and cross-references.
|
||
|
#
|
||
|
# This script is parametrized by this environment variable:
|
||
|
# * TOPLEVEL: $TOPLEVEL/rules and $TOPLEVEL/shared_content will be validated.
|
||
|
#
|
||
|
# The script exists with a non-zero value when an unexpected error happened or
|
||
|
# there are asciidoc validation errors.
|
||
|
#
|
||
|
# Validation errors are reported on stderr.
|
||
|
#
|
||
|
# Implementation details:
|
||
|
#
|
||
|
# The validation of file inclusion and cross-references needs to be done
|
||
|
# on all rule descriptions, including the default, language-agnostic
|
||
|
# description, with rspecator-view. Otherwise, a rule could drop an include
|
||
|
# of a shared_content asciidoc and that file could become unused.
|
||
|
#
|
||
|
# We use a custom asciidoctor with extra logging for this purpose.
|
||
|
# The format for the interesting log entries are:
|
||
|
# asciidoctor: INFO: ASCIIDOC LOGGER MAIN FILE: $PATH
|
||
|
# asciidoctor: INFO: ASCIIDOC LOGGER INCLUDED: $PATH
|
||
|
# asciidoctor: INFO: ASCIIDOC LOGGER CROSSREFERENCE: $RULEID cross-references $PATH
|
||
|
|
||
|
set -euo pipefail
|
||
|
|
||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
|
||
|
TOPLEVEL="$(realpath "${TOPLEVEL}")"
|
||
|
RULES_DIR="${TOPLEVEL}/rules"
|
||
|
SHARED_CONTENT_DIR="${TOPLEVEL}/shared_content"
|
||
|
TMPOUT_DIR="$(mktemp -d)"
|
||
|
|
||
|
exit_code=0
|
||
|
|
||
|
grep_nofail() {
|
||
|
# Grep but always exit with 0 when there are no matches.
|
||
|
# Yet, exit with non-zero if an error occured.
|
||
|
grep "$@" || [ "$?" == "1" ]
|
||
|
}
|
||
|
|
||
|
find "${RULES_DIR}" -name 'rule.adoc' \
|
||
|
| xargs "${SCRIPT_DIR}/custom-asciidoctor" -a rspecator-view --verbose -R "${RULES_DIR}" -D "${TMPOUT_DIR}" 2>&1 \
|
||
|
| grep_nofail -e 'ASCIIDOC LOGGER' \
|
||
|
> "${TMPOUT_DIR}/asciidoc_introspection"
|
||
|
|
||
|
grep -ve 'CROSSREFERENCE' "${TMPOUT_DIR}/asciidoc_introspection" \
|
||
|
| cut -d ':' -f 4 \
|
||
|
| sort -u \
|
||
|
> "${TMPOUT_DIR}/used_asciidoc_files"
|
||
|
|
||
|
git ls-files --cached -- "${RULES_DIR}/**.adoc" "${SHARED_CONTENT_DIR}/**.adoc" \
|
||
|
| xargs realpath \
|
||
|
> "${TMPOUT_DIR}/all_asciidoc_files"
|
||
|
|
||
|
cross_references=$(grep_nofail -e 'CROSSREFERENCE' "${TMPOUT_DIR}/asciidoc_introspection" | cut -d ':' -f 4 | sort -u)
|
||
|
if [[ -n "$cross_references" ]]; then
|
||
|
echo >&2 'ERROR: Some rules try to include content from unallowed directories.'
|
||
|
echo >&2 'To share content between rules, you should use the "shared_content" folder at the root of the repository.'
|
||
|
echo >&2 'List of errors:'
|
||
|
echo >&2 "${cross_references}"
|
||
|
exit_code=1
|
||
|
fi
|
||
|
|
||
|
orphans=$(comm -1 -3 <(sort -u "${TMPOUT_DIR}/used_asciidoc_files") <(sort -u "${TMPOUT_DIR}/all_asciidoc_files"))
|
||
|
if [[ -n "$orphans" ]]; then
|
||
|
printf >&2 'ERROR: These adoc files are not included anywhere:\n-----\n%s\n-----\n' "$orphans"
|
||
|
exit_code=1
|
||
|
fi
|
||
|
|
||
|
exit $exit_code
|