#!/bin/sh set -eu script_dir="$(CDPATH= cd "$(dirname "$0")" && pwd -P)" repo_root="$(CDPATH= cd "${script_dir}/.." && pwd -P)" build_dir="${repo_root}/build" cache_dir="${repo_root}/.cache" tarball="${cache_dir}/sed-4.10.tar.xz" src_dir="${cache_dir}/sed-4.10-src" gnu_build_dir="${cache_dir}/sed-4.10-build" sedpp_binary="${1:-${SEDPP_BINARY:-}}" make_jobs() { # Keep the upstream build parallel without assuming nproc exists on every # shell environment this script may run under. jobs="$(getconf _NPROCESSORS_ONLN 2>/dev/null || printf '%s\n' 1)" case "${jobs}" in ''|*[!0-9]*|0) jobs=1 ;; esac printf '%s\n' "${jobs}" } mkdir -p "${cache_dir}" if [ -n "${MESON_TEST_ITERATION:-}" ] && [ -z "${SEDPP_GNU_TEST_CAPTURED:-}" ]; then # Meson captures test stdout/stderr through pipes and waits for EOF before it # considers the test complete. A few of GNU sed's shell tests can leave short # lived descendants behind with inherited descriptors, which makes Meson sit # in its own event loop even after this script has already returned. Spooling # the real run to a normal file keeps Meson attached only to this top-level # process, while still replaying the full upstream log for diagnostics. meson_log="${cache_dir}/gnu-sed-tests.meson.log" rm -f "${meson_log}" set +e SEDPP_GNU_TEST_CAPTURED=1 "$0" "$@" >"${meson_log}" 2>&1 status=$? set -e cat "${meson_log}" exit "${status}" fi if [ -z "${sedpp_binary}" ]; then # When invoked manually, build the local Meson target first. Meson tests pass # the freshly built executable explicitly. sedpp_binary="${build_dir}/sed/sed" if [ ! -x "${sedpp_binary}" ]; then meson setup "${build_dir}" "${repo_root}" meson compile -C "${build_dir}" fi fi if [ ! -x "${sedpp_binary}" ]; then printf 'Sed++ binary is not executable: %s\n' "${sedpp_binary}" >&2 exit 1 fi if [ ! -f "${tarball}" ]; then # Cache the pristine GNU sed tarball so repeated compatibility runs only pay # the network cost once. curl -L --fail --show-error \ "https://ftp.gnu.org/gnu/sed/sed-4.10.tar.xz" \ -o "${tarball}" fi if [ ! -d "${src_dir}" ]; then # Extract into a temporary directory and move into place atomically enough that # an interrupted run will be retried cleanly. tmp_extract="${cache_dir}/sed-4.10-src.tmp" rm -rf "${tmp_extract}" mkdir -p "${tmp_extract}" tar -xf "${tarball}" -C "${tmp_extract}" mv "${tmp_extract}/sed-4.10" "${src_dir}" rmdir "${tmp_extract}" fi rm -rf "${gnu_build_dir}" mkdir -p "${gnu_build_dir}" ( cd "${gnu_build_dir}" # Configure and build GNU sed's test harness, then swap only the sed binary so # all upstream shell tests exercise this project through GNU's own Makefile. "${src_dir}/configure" --quiet # Sed++ intentionally carries its own version/license identity. GNU sed's # help-version.sh asserts GNU-specific --version branding and GPL wording, so # keep that policy test out of the compatibility run while retaining the # behavioral sed command tests. perl -0pi -e 's/[ \t]*testsuite\/help-version\.sh\b//g' Makefile make -j"$(make_jobs)" make testsuite/get-mb-cur-max testsuite/test-mbrtowc # GNU sed's automake harness forces PATH to begin with # ${abs_top_builddir}/sed. Copying the native C++ executable over that path # after all prerequisites are built makes every upstream sed test exercise # this project, while avoiding a later make prerequisite relink. mv sed/sed sed/sed.gnu cp "${sedpp_binary}" sed/sed make check-TESTS )