diff --git a/README.md b/README.md index 3ee1b40..07ec4c2 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,23 @@ Two container variants are available: This project uses Podman instead of Docker for license compatibility and rootless container support. +### bash 4.0 or newer — macOS users must install this + +The launcher scripts use associative arrays, so they require **bash 4.0+**. macOS still ships bash **3.2.57** as `/bin/bash` (it has been frozen there since 2007 for licensing reasons), which is not sufficient. + +```bash +brew install bash +``` + +Make sure the new bash precedes `/bin/bash` on your `PATH` — Homebrew's default prefix does this already. The launchers use `#!/usr/bin/env bash`, so invoking them **by name** picks up the right interpreter: + +```bash +localdev # correct — resolves bash via PATH +/bin/bash localdev # wrong — forces macOS's bash 3.2 +``` + +If no suitable bash is found, the launcher aborts with a message naming the version and interpreter it found. Linux distributions ship bash 4+ or 5+ and need nothing here. + ### Install Podman ```bash diff --git a/localdev b/localdev index 1f00c5c..60e3b78 100755 --- a/localdev +++ b/localdev @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # localdev launcher - lightweight container (no Java, single Node LTS) - DEFAULT DIR_NAME=$(basename "$(pwd)") diff --git a/localdev-mounts.sh b/localdev-mounts.sh index e9028e3..b1ac1ba 100644 --- a/localdev-mounts.sh +++ b/localdev-mounts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # localdev-mounts.sh - shared mount-collection logic for the localdev launchers. # # Sourced by localdev, localdevnet, and localfull. The single entry point @@ -19,6 +19,30 @@ # launch directory. Every mount claims one container-side target; two mounts # resolving to the same target is always fatal. +# This library uses associative arrays (declare -A) for target-collision detection, so +# it requires bash 4.0+. macOS still ships bash 3.2.57 as /bin/bash, which does not have +# them. Under 3.2 the failure is silent and wrong rather than loud: `declare -A` fails, +# USED_TARGETS degrades to an indexed array, subscript expansion is evaluated as +# arithmetic, and .localdev-mounts.toml entries are dropped without a word -- so the +# container comes up missing mounts the user believes are present. Fail loudly instead. +# +# The launchers use `#!/usr/bin/env bash` so a PATH-resolved bash 4+ (e.g. Homebrew's) is +# preferred over /bin/bash. This check catches the case where none is available, or where +# a script is invoked explicitly as `/bin/bash localdev`. +if [[ -z "${BASH_VERSINFO[0]:-}" || "${BASH_VERSINFO[0]}" -lt 4 ]]; then + echo "Error: the localdev launchers require bash 4.0 or newer." >&2 + echo " Running under: ${BASH_VERSION:-unknown (not bash?)}" >&2 + echo " Interpreter: ${BASH:-unknown}" >&2 + echo "" >&2 + echo " macOS ships bash 3.2 as /bin/bash, which lacks associative arrays." >&2 + echo " Without them, .localdev-mounts.toml entries are silently dropped." >&2 + echo "" >&2 + echo " Fix: install a modern bash and make sure it precedes /bin/bash on PATH:" >&2 + echo " brew install bash" >&2 + echo " Then invoke the launcher by name ('localdev'), not as '/bin/bash localdev'." >&2 + exit 1 +fi + MOUNT_FILE_NAME=".localdev-mounts.toml" # Container paths the launchers manage themselves. A user mount may not target diff --git a/localdevnet b/localdevnet index 40679c5..74117e0 100755 --- a/localdevnet +++ b/localdevnet @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # localdev launcher - lightweight container (no Java, single Node LTS) with host networking DIR_NAME=$(basename "$(pwd)") diff --git a/localdevpull b/localdevpull index 809d84a..a42166e 100755 --- a/localdevpull +++ b/localdevpull @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Pull the latest localdev container image REGISTRY=ghcr.io diff --git a/localfull b/localfull index 922aa7f..158e45f 100755 --- a/localfull +++ b/localfull @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # localfull launcher - full-featured container (Java, Atlassian CLI, multiple Node versions) DIR_NAME=$(basename "$(pwd)")