Skip to content

Commit 087e31d

Browse files
committed
feat: lower bash support from 3.2 to 3.0
1 parent 01a7621 commit 087e31d

File tree

14 files changed

+47
-24
lines changed

14 files changed

+47
-24
lines changed

.github/CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Contributions are licensed under the [MIT License](https://github.com/TypedDevs/
3131

3232
### Prerequisites
3333

34-
- Bash 3.2+
34+
- Bash 3.0+
3535
- Git
3636
- Make
3737
- [ShellCheck](https://github.com/koalaman/shellcheck#installing)

.github/copilot-instructions.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ An open-source **library** providing a fast, portable Bash testing framework: **
2828
* Minimal overhead, plain Bash test files.
2929
* Rich **assertions**, **test doubles (mock/spy)**, **data providers**, **snapshots**, **skip/todo**, **globals utilities**, **custom assertions**, **benchmarks**, and **standalone** runs.
3030

31-
**Compatibility**: Bash 3.2+ (macOS, Linux, WSL). No external dependencies beyond standard Unix tools.
31+
**Compatibility**: Bash 3.0+ (macOS, Linux, WSL). No external dependencies beyond standard Unix tools.
3232

3333
---
3434

@@ -284,7 +284,7 @@ We practice two nested feedback loops to deliver behavior safely and quickly.
284284

285285
### Compatibility & Portability
286286
```bash
287-
# ✅ GOOD - Works on Bash 3.2+
287+
# ✅ GOOD - Works on Bash 3.0+
288288
[[ -n "${var:-}" ]] && echo "set"
289289
array=("item1" "item2")
290290

@@ -1000,7 +1000,7 @@ Use this template for internal changes, fixes, refactors, documentation.
10001000
- **All tests pass** (`./bashunit tests/`)
10011001
- **Shellcheck passes** with existing exceptions (`shellcheck -x $(find . -name "*.sh")`)
10021002
- **Code formatted** (`shfmt -w .`)
1003-
- **Bash 3.2+ compatible** (no `declare -A`, no `readarray`, no `${var^^}`)
1003+
- **Bash 3.0+ compatible** (no `declare -A`, no `readarray`, no `${var^^}`)
10041004
- **Follows established module namespacing** patterns
10051005
10061006
### ✅ Testing (following observed patterns)

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- tear_down
1313
- set_up_before_script
1414
- tear_down_after_script
15+
- Support Bash 3.0 (Previously 3.2)
1516

1617
## [0.24.0](https://github.com/TypedDevs/bashunit/compare/0.23.0...0.24.0) - 2025-09-14
1718

bashunit

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4-
declare -r BASHUNIT_MIN_BASH_VERSION="3.2"
4+
declare -r BASHUNIT_MIN_BASH_VERSION="3.0"
55

66
function _check_bash_version() {
77
local current_version
@@ -19,7 +19,7 @@ function _check_bash_version() {
1919
local major minor
2020
IFS=. read -r major minor _ <<< "$current_version"
2121

22-
if (( major < 3 )) || { (( major == 3 )) && (( minor < 2 )); }; then
22+
if (( major < 3 )); then
2323
printf 'Bashunit requires Bash >= %s. Current version: %s\n' "$BASHUNIT_MIN_BASH_VERSION" "$current_version" >&2
2424
exit 1
2525
fi

build.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ function build::process_file() {
7171
sourced_file=$(eval echo "$sourced_file")
7272

7373
# Handle relative paths if necessary
74-
if [[ ! "$sourced_file" =~ ^/ ]]; then
74+
local absolute_path_pattern='^/'
75+
if [[ ! "$sourced_file" =~ $absolute_path_pattern ]]; then
7576
sourced_file="$(dirname "$file")/$sourced_file"
7677
fi
7778

install.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ DIR="lib"
6868
VERSION="latest"
6969

7070
function is_version() {
71-
[[ "$1" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ || "$1" == "latest" || "$1" == "beta" ]]
71+
local version_pattern='^[0-9]+\.[0-9]+\.[0-9]+$'
72+
[[ "$1" =~ $version_pattern || "$1" == "latest" || "$1" == "beta" ]]
7273
}
7374

7475
# Parse arguments flexibly

src/assert.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ function assert_false() {
5151

5252
function run_command_or_eval() {
5353
local cmd="$1"
54+
local eval_pattern='^eval'
55+
local alias_pattern='^alias'
5456

55-
if [[ "$cmd" =~ ^eval ]]; then
57+
if [[ "$cmd" =~ $eval_pattern ]]; then
5658
eval "${cmd#eval }" &> /dev/null
57-
elif [[ "$(command -v "$cmd")" =~ ^alias ]]; then
59+
elif [[ "$(command -v "$cmd")" =~ $alias_pattern ]]; then
5860
eval "$cmd" &> /dev/null
5961
else
6062
"$cmd" &> /dev/null

src/benchmark.sh

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,27 @@ function benchmark::parse_annotations() {
1616
local annotation
1717
annotation=$(awk "/function[[:space:]]+${fn_name}[[:space:]]*\(/ {print prev; exit} {prev=\$0}" "$script")
1818

19-
if [[ $annotation =~ @revs=([0-9]+) ]]; then
19+
local revs_pattern='@revs=([0-9]+)'
20+
local revolutions_pattern='@revolutions=([0-9]+)'
21+
local its_pattern='@its=([0-9]+)'
22+
local iterations_pattern='@iterations=([0-9]+)'
23+
local max_ms_pattern='@max_ms=([0-9.]+)'
24+
25+
if [[ $annotation =~ $revs_pattern ]]; then
2026
revs="${BASH_REMATCH[1]}"
21-
elif [[ $annotation =~ @revolutions=([0-9]+) ]]; then
27+
elif [[ $annotation =~ $revolutions_pattern ]]; then
2228
revs="${BASH_REMATCH[1]}"
2329
fi
2430

25-
if [[ $annotation =~ @its=([0-9]+) ]]; then
31+
if [[ $annotation =~ $its_pattern ]]; then
2632
its="${BASH_REMATCH[1]}"
27-
elif [[ $annotation =~ @iterations=([0-9]+) ]]; then
33+
elif [[ $annotation =~ $iterations_pattern ]]; then
2834
its="${BASH_REMATCH[1]}"
2935
fi
3036

31-
if [[ $annotation =~ @max_ms=([0-9.]+) ]]; then
37+
if [[ $annotation =~ $max_ms_pattern ]]; then
3238
max_ms="${BASH_REMATCH[1]}"
33-
elif [[ $annotation =~ @max_ms=([0-9.]+) ]]; then
39+
elif [[ $annotation =~ $max_ms_pattern ]]; then
3440
max_ms="${BASH_REMATCH[1]}"
3541
fi
3642

src/clock.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ function clock::_choose_impl() {
3737
attempts+=("date")
3838
if ! check_os::is_macos && ! check_os::is_alpine; then
3939
local result
40+
local number_pattern='^[0-9]+$'
4041
result=$(date +%s%N 2>/dev/null)
41-
if [[ "$result" != *N && "$result" =~ ^[0-9]+$ ]]; then
42+
if [[ "$result" != *N && "$result" =~ $number_pattern ]]; then
4243
_CLOCK_NOW_IMPL="date"
4344
return 0
4445
fi

src/helpers.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ function helper::find_files_recursive() {
160160
local pattern="${2:-*[tT]est.sh}"
161161

162162
local alt_pattern=""
163-
if [[ $pattern == *test.sh ]] || [[ $pattern =~ \[tT\]est\.sh$ ]]; then
163+
local test_pattern='\[tT\]est\.sh$'
164+
if [[ $pattern == *test.sh ]] || [[ $pattern =~ $test_pattern ]]; then
164165
alt_pattern="${pattern%.sh}.bash"
165166
fi
166167

@@ -187,7 +188,8 @@ function helper::normalize_variable_name() {
187188

188189
normalized_string="${input_string//[^a-zA-Z0-9_]/_}"
189190

190-
if [[ ! $normalized_string =~ ^[a-zA-Z_] ]]; then
191+
local valid_start_pattern='^[a-zA-Z_]'
192+
if [[ ! $normalized_string =~ $valid_start_pattern ]]; then
191193
normalized_string="_$normalized_string"
192194
fi
193195

0 commit comments

Comments
 (0)