From 86adadf9fc1e5b2ec635634b00f0204aa8aae0a2 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sat, 1 Aug 2026 15:47:33 +0200 Subject: [PATCH] refactor(config): group run configuration and persisted state into src/config/ Fourth group under #949. src/env.sh -> src/config/env.sh src/parallel.sh -> src/config/parallel.sh src/rerun.sh -> src/config/rerun.sh Not a junk drawer: the three have real internal edges. env reads rerun's setting, parallel reads env's, and parallel::is_enabled is called from eleven files across runner, coverage, console and main -- a cross-cutting mode predicate, the same shape as env.sh's 33 is_* predicates. src/config/parallel.sh stays a different concern from src/runner/parallel.sh: this one answers "is this run parallel" and owns the stop flag; that one waits on job slots and drives the spinner. The index says so, and the build.sh comment about the same-basename collision (#923) is repointed rather than left stale. env.sh is the one file here that executes at source time -- it loads .bashunitrc and .env and creates the scratch dirs. Its file-scope block calls only bashunit::env:: functions defined above it in the same file, verified before moving, so the ordering inside the module is free. The module is sourced where parallel.sh and env.sh sat, ahead of console/, whose palette is built at file scope from these values. rerun.sh moves earlier than it was, which is inert: its only file-scope statement is a variable initialiser. tests/unit/env_deprecated_aliases_test.sh derives the unprefixed-alias contract by grepping env.sh, so it is repointed. Verified it did not go vacuous: mutating an alias declaration still reddens it. env.sh is not split here; #931 recorded it as deliberately whole. A relocation: git records all three as renames with a zero-line diff, the built artifact's code content is identical, and `set -euo pipefail` still lands on line 121 of the artifact. Related #949 --- .claude/rules/architecture-map.md | 8 +++++--- bashunit | 4 +--- build.sh | 2 +- src/{ => config}/env.sh | 0 src/config/index.sh | 23 +++++++++++++++++++++++ src/{ => config}/parallel.sh | 0 src/{ => config}/rerun.sh | 0 tests/unit/build_test.sh | 2 +- tests/unit/env_deprecated_aliases_test.sh | 2 +- 9 files changed, 32 insertions(+), 9 deletions(-) rename src/{ => config}/env.sh (100%) create mode 100644 src/config/index.sh rename src/{ => config}/parallel.sh (100%) rename src/{ => config}/rerun.sh (100%) diff --git a/.claude/rules/architecture-map.md b/.claude/rules/architecture-map.md index 3d439cdc..e6a99867 100644 --- a/.claude/rules/architecture-map.md +++ b/.claude/rules/architecture-map.md @@ -70,8 +70,10 @@ shell (or, in parallel, in per-test `.result` files aggregated at the end). | `state/context.sh` | per-test output buffer, exit code, title, hook failure, and the per-test reset | | `state/payload.sh` | the encoded per-test result payload and the base64 capability probe | | `state/parallel.sh` | aggregating per-test result files after a `--parallel` run | -| `env.sh` | all `BASHUNIT_*` defaults/config files, scratch dirs (`_BASHUNIT_RUN_OUTPUT_DIR` + EXIT-trap cleanup) | -| `parallel.sh` | worker temp tree, aggregation, stop-on-failure flag file | +| `config/index.sh` | aggregator only — sources the `src/config/` module below | +| `config/env.sh` | all `BASHUNIT_*` defaults/config files, scratch dirs (`_BASHUNIT_RUN_OUTPUT_DIR` + EXIT-trap cleanup); executes at source time | +| `config/rerun.sh` | the `.bashunit/last-failed` cache for `--rerun-failed` | +| `config/parallel.sh` | is this run parallel; worker temp tree and stop-on-failure flag file (not `runner/parallel.sh`, which waits on job slots) | | `console/index.sh` | aggregator only — sources the `src/console/` module below | | `console/colors.sh` | the `_BASHUNIT_COLOR_*` palette and `bashunit::sgr` | | `console/header.sh` | the "Running N tests" header | @@ -104,7 +106,7 @@ shell (or, in parallel, in per-test `.result` files aggregated at the end). | `coverage/branches.sh` | branch extraction + hit computation; **one file on purpose** — the `_branch_*` helpers mutate `extract_branches`'s locals via dynamic scoping | | `coverage/report_text.sh` / `report_lcov.sh` / `report_html.sh` | the three renderers | | `coverage/html_index.sh` / `html_file.sh` | HTML page emitters; the only two files exempt from `max_line_length` | -| `rerun.sh` | `.bashunit/last-failed` cache for `--rerun-failed` | + | `reports.sh` | JUnit/HTML/TAP/JSON writers | | `system/index.sh` | aggregator only — sources the `src/system/` module below | | `system/check_os.sh` / `system/dependencies.sh` | one-fork OS detect; `command -v` probes (builtins, not forks) | diff --git a/bashunit b/bashunit index ebc36ab2..754ea106 100755 --- a/bashunit +++ b/bashunit @@ -68,8 +68,7 @@ source "$BASHUNIT_ROOT_DIR/src/dev/debug.sh" source "$BASHUNIT_ROOT_DIR/src/system/index.sh" source "$BASHUNIT_ROOT_DIR/src/util/index.sh" source "$BASHUNIT_ROOT_DIR/src/api/index.sh" -source "$BASHUNIT_ROOT_DIR/src/parallel.sh" -source "$BASHUNIT_ROOT_DIR/src/env.sh" +source "$BASHUNIT_ROOT_DIR/src/config/index.sh" source "$BASHUNIT_ROOT_DIR/src/coverage/index.sh" source "$BASHUNIT_ROOT_DIR/src/state/index.sh" source "$BASHUNIT_ROOT_DIR/src/console/index.sh" @@ -77,7 +76,6 @@ source "$BASHUNIT_ROOT_DIR/src/helper/index.sh" source "$BASHUNIT_ROOT_DIR/src/cli/index.sh" source "$BASHUNIT_ROOT_DIR/src/assert/index.sh" source "$BASHUNIT_ROOT_DIR/src/reports/index.sh" -source "$BASHUNIT_ROOT_DIR/src/rerun.sh" source "$BASHUNIT_ROOT_DIR/src/runner/index.sh" source "$BASHUNIT_ROOT_DIR/src/benchmark.sh" source "$BASHUNIT_ROOT_DIR/src/learn/index.sh" diff --git a/build.sh b/build.sh index aaa56792..0949a678 100755 --- a/build.sh +++ b/build.sh @@ -72,7 +72,7 @@ function build::process_file() { # Key the dedupe and the marker on a repo-relative path, never a basename: the # top-level loop passes `src/x.sh` while the recursion passes an absolute path, - # and two modules can hold the same basename (src/parallel.sh vs + # and two modules can hold the same basename (src/config/parallel.sh vs # src/runner/parallel.sh). `$file` itself stays untouched so the `tail` and # `dirname` below work on whichever form the caller passed. local marker="${file#"$BASHUNIT_ROOT_DIR"/}" diff --git a/src/env.sh b/src/config/env.sh similarity index 100% rename from src/env.sh rename to src/config/env.sh diff --git a/src/config/index.sh b/src/config/index.sh new file mode 100644 index 00000000..c667191e --- /dev/null +++ b/src/config/index.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Entry point for the src/config/ module: only `source` lines and comments belong +# here. build.sh emits a file's body before recursing into its `source` lines, so +# any statement here would run before its dependencies in the built binary +# (adrs/adr-010-src-module-directories.md). +# +# Run-scoped configuration and the state a run persists: every BASHUNIT_* default +# and its scratch dirs (env), whether this run is parallel and its stop flag +# (parallel), and the last-failed cache the next run reads (rerun). They cluster +# for real -- env reads rerun's setting, parallel reads env's. +# +# env.sh is the one file here that executes at source time: it loads .bashunitrc +# and .env and creates the scratch dirs. Its file-scope block calls only +# bashunit::env:: functions defined above it in the same file, so the order below +# is free -- but this module must stay where parallel.sh and env.sh sat, ahead of +# console/, whose palette is built at file scope from these values. +# +# Note src/config/parallel.sh is a different concern from src/runner/parallel.sh: +# this one answers "is this run parallel", that one waits on job slots. +source "$BASHUNIT_ROOT_DIR/src/config/parallel.sh" +source "$BASHUNIT_ROOT_DIR/src/config/env.sh" +source "$BASHUNIT_ROOT_DIR/src/config/rerun.sh" diff --git a/src/parallel.sh b/src/config/parallel.sh similarity index 100% rename from src/parallel.sh rename to src/config/parallel.sh diff --git a/src/rerun.sh b/src/config/rerun.sh similarity index 100% rename from src/rerun.sh rename to src/config/rerun.sh diff --git a/tests/unit/build_test.sh b/tests/unit/build_test.sh index 281f4bb8..eecf385c 100644 --- a/tests/unit/build_test.sh +++ b/tests/unit/build_test.sh @@ -238,7 +238,7 @@ function test_build_process_file_emits_a_file_before_the_files_it_sources() { # The embed dedupe keys on the repo-relative path (#923). Two modules holding the # same basename must both survive -- the situation every further module split -# creates (src/parallel.sh vs src/runner/parallel.sh today). +# creates (src/config/parallel.sh vs src/runner/parallel.sh today). function test_build_process_file_embeds_same_basename_from_two_module_dirs() { local dir dir=$(bashunit::temp_dir) diff --git a/tests/unit/env_deprecated_aliases_test.sh b/tests/unit/env_deprecated_aliases_test.sh index de25ff9c..267a7f99 100644 --- a/tests/unit/env_deprecated_aliases_test.sh +++ b/tests/unit/env_deprecated_aliases_test.sh @@ -9,7 +9,7 @@ # Every `: "${BASHUNIT_X:=${X:=...}}"` line in env.sh declares an unprefixed # alias for X. That is the source of truth. function bashunit::test::aliases_declared_in_env_sh() { - grep -oE '^: "\$\{BASHUNIT_[A-Z0-9_]+:=\$\{[A-Z0-9_]+:=' src/env.sh | + grep -oE '^: "\$\{BASHUNIT_[A-Z0-9_]+:=\$\{[A-Z0-9_]+:=' src/config/env.sh | sed -E 's/^: "\$\{BASHUNIT_[A-Z0-9_]+:=\$\{([A-Z0-9_]+):=$/\1/' | sort }