diff --git a/bin/linux-workstation-bootstrap b/bin/linux-workstation-bootstrap index 2cf31e0..74f5da2 100755 --- a/bin/linux-workstation-bootstrap +++ b/bin/linux-workstation-bootstrap @@ -22,4 +22,4 @@ readonly LWBS_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" source "$LWBS_ROOT/lib/bootstrap.sh" # Pass all CLI arguments to the application entry point. -bootstrap_main "$@" \ No newline at end of file +bootstrap_main "$@" diff --git a/config/defaults.sh b/config/defaults.sh index c3ed3cc..0a18d78 100755 --- a/config/defaults.sh +++ b/config/defaults.sh @@ -32,9 +32,9 @@ declare -ar LWBS_SUPPORTED_DISTROS=( # Human-readable names for supported distribution profiles. declare -Ar LWBS_DISTRO_DISPLAY_NAMES=( - [ubuntu]="Ubuntu" - [debian]="Debian" - [kali]="Kali Linux" + ["ubuntu"]="Ubuntu" + ["debian"]="Debian" + ["kali"]="Kali Linux" ) # Default distribution selection behaviour. @@ -53,46 +53,46 @@ readonly LWBS_CONFIG_FILE_NAME="config.conf" # Additional distributions may be detected even when they do not yet # have an installation profile supported by the application. declare -Ar LWBS_DISTRO_FAMILIES=( - [ubuntu]="debian" - [debian]="debian" - [kali]="debian" - [linuxmint]="debian" - [pop]="debian" - [elementary]="debian" - - [fedora]="rpm" - [rhel]="rpm" - [rocky]="rpm" - [almalinux]="rpm" - [centos]="rpm" - - [arch]="arch" - [manjaro]="arch" - [endeavouros]="arch" - - [opensuse-leap]="suse" - [opensuse-tumbleweed]="suse" - [sles]="suse" + ["ubuntu"]="debian" + ["debian"]="debian" + ["kali"]="debian" + ["linuxmint"]="debian" + ["pop"]="debian" + ["elementary"]="debian" + + ["fedora"]="rpm" + ["rhel"]="rpm" + ["rocky"]="rpm" + ["almalinux"]="rpm" + ["centos"]="rpm" + + ["arch"]="arch" + ["manjaro"]="arch" + ["endeavouros"]="arch" + + ["opensuse-leap"]="suse" + ["opensuse-tumbleweed"]="suse" + ["sles"]="suse" ) # Default package manager for each distribution family. declare -Ar LWBS_FAMILY_PACKAGE_MANAGERS=( - [debian]="apt" - [rpm]="dnf" - [arch]="pacman" - [suse]="zypper" + ["debian"]="apt" + ["rpm"]="dnf" + ["arch"]="pacman" + ["suse"]="zypper" ) # Normalize common architecture names used by Linux distributions. declare -Ar LWBS_ARCH_ALIASES=( - [x86_64]="amd64" - [aarch64]="arm64" - [arm64]="arm64" - [armv7l]="armhf" - [i386]="i386" - [i486]="i386" - [i586]="i386" - [i686]="i386" + ["x86_64"]="amd64" + ["aarch64"]="arm64" + ["arm64"]="arm64" + ["armv7l"]="armhf" + ["i386"]="i386" + ["i486"]="i386" + ["i586"]="i386" + ["i686"]="i386" ) # Persistent logging configuration. @@ -102,4 +102,4 @@ readonly LWBS_LOG_FILE_PREFIX="run" # Permissions applied to application state and log files. readonly LWBS_STATE_DIR_MODE="700" readonly LWBS_LOG_DIR_MODE="700" -readonly LWBS_LOG_FILE_MODE="600" \ No newline at end of file +readonly LWBS_LOG_FILE_MODE="600" diff --git a/config/packages/debian.sh b/config/packages/debian.sh index 218ee07..c7479fb 100644 --- a/config/packages/debian.sh +++ b/config/packages/debian.sh @@ -19,4 +19,4 @@ LWBS_CAPABILITY_PACKAGES=( [sed]="sed" [wget]="wget" [xz]="xz-utils" -) \ No newline at end of file +) diff --git a/config/packages/kali.sh b/config/packages/kali.sh index 03bfc35..33ce1af 100644 --- a/config/packages/kali.sh +++ b/config/packages/kali.sh @@ -19,4 +19,4 @@ LWBS_CAPABILITY_PACKAGES=( [sed]="sed" [wget]="wget" [xz]="xz-utils" -) \ No newline at end of file +) diff --git a/config/packages/ubuntu.sh b/config/packages/ubuntu.sh index 356a2b8..2a362af 100644 --- a/config/packages/ubuntu.sh +++ b/config/packages/ubuntu.sh @@ -19,4 +19,4 @@ LWBS_CAPABILITY_PACKAGES=( [sed]="sed" [wget]="wget" [xz]="xz-utils" -) \ No newline at end of file +) diff --git a/distros/debian.sh b/distros/debian.sh index 1f1dda0..1d19387 100644 --- a/distros/debian.sh +++ b/distros/debian.sh @@ -159,4 +159,4 @@ distro_install_local_package() { run_privileged_command \ apt-get install --yes "$package_file" -} \ No newline at end of file +} diff --git a/distros/kali.sh b/distros/kali.sh index ee56374..212a3e9 100644 --- a/distros/kali.sh +++ b/distros/kali.sh @@ -160,4 +160,4 @@ distro_install_local_package() { run_privileged_command \ apt-get install --yes "$package_file" -} \ No newline at end of file +} diff --git a/distros/ubuntu.sh b/distros/ubuntu.sh index 3c58f3a..b10e03c 100644 --- a/distros/ubuntu.sh +++ b/distros/ubuntu.sh @@ -168,4 +168,4 @@ distro_install_local_package() { run_privileged_command \ apt-get install --yes "$package_file" -} \ No newline at end of file +} diff --git a/lib/arguments.sh b/lib/arguments.sh index c9708d1..4b8343c 100755 --- a/lib/arguments.sh +++ b/lib/arguments.sh @@ -75,4 +75,4 @@ parse_arguments() { done return 0 -} \ No newline at end of file +} diff --git a/lib/bootstrap.sh b/lib/bootstrap.sh index 6fba6d0..50e6228 100755 --- a/lib/bootstrap.sh +++ b/lib/bootstrap.sh @@ -190,4 +190,4 @@ select_distro_profile() { fi choose_distro_profile -} \ No newline at end of file +} diff --git a/lib/capability.sh b/lib/capability.sh index d7ed0a1..e1ee585 100644 --- a/lib/capability.sh +++ b/lib/capability.sh @@ -263,4 +263,4 @@ reset_capability_map() { LWBS_CAPABILITY_PROFILE="" LWBS_CAPABILITY_MAP_PATH="" LWBS_CAPABILITY_PACKAGES=() -} \ No newline at end of file +} diff --git a/lib/config.sh b/lib/config.sh index 978a32f..ef6ed2e 100644 --- a/lib/config.sh +++ b/lib/config.sh @@ -218,4 +218,4 @@ load_user_config() { "Configured default distribution profile: $LWBS_CONFIG_DISTRO_PROFILE" return 0 -} \ No newline at end of file +} diff --git a/lib/core.sh b/lib/core.sh index 39864bb..9c8b5f4 100755 --- a/lib/core.sh +++ b/lib/core.sh @@ -63,4 +63,4 @@ is_supported_distro() { done return 1 -} \ No newline at end of file +} diff --git a/lib/detect.sh b/lib/detect.sh index 75236e9..1c9d101 100755 --- a/lib/detect.sh +++ b/lib/detect.sh @@ -114,4 +114,4 @@ detect_architecture() { printf '%s\n' \ "${LWBS_ARCH_ALIASES[$architecture]:-$architecture}" -} \ No newline at end of file +} diff --git a/lib/distro.sh b/lib/distro.sh index 1e33557..e2cca3b 100644 --- a/lib/distro.sh +++ b/lib/distro.sh @@ -119,4 +119,4 @@ reset_distro_adapter_contract() { DISTRO_ADAPTER_PROFILE="" DISTRO_ADAPTER_PATH="" -} \ No newline at end of file +} diff --git a/lib/execution.sh b/lib/execution.sh index daf1255..e0e2422 100644 --- a/lib/execution.sh +++ b/lib/execution.sh @@ -109,4 +109,4 @@ run_privileged_command() { # sudo executes the requested command while run_command retains the # common execution and exit-code handling. run_command sudo -- "$@" -} \ No newline at end of file +} diff --git a/lib/external.sh b/lib/external.sh index 6a86685..2922da4 100644 --- a/lib/external.sh +++ b/lib/external.sh @@ -727,4 +727,4 @@ reset_external_installer_contract() { LWBS_EXTERNAL_METHOD="" LWBS_EXTERNAL_PATH="" LWBS_EXTERNAL_STAGE_DIR="" -} \ No newline at end of file +} diff --git a/lib/logging.sh b/lib/logging.sh index 255e7f9..83d5e26 100755 --- a/lib/logging.sh +++ b/lib/logging.sh @@ -88,4 +88,4 @@ log_warning() { # Write an error event to the session log. log_error() { log_message "ERROR" "$1" -} \ No newline at end of file +} diff --git a/lib/module.sh b/lib/module.sh index 9d432a4..862fb7b 100644 --- a/lib/module.sh +++ b/lib/module.sh @@ -194,10 +194,10 @@ load_module() { done <<<"$external_output" fi - if ((${#LWBS_MODULE_CAPABILITIES[@]} == 0 && + if ((${#LWBS_MODULE_CAPABILITIES[@]} == 0 && \ ${#LWBS_MODULE_EXTERNAL_INSTALLERS[@]} == 0)) && - ! declare -F module_apply >/dev/null 2>&1 && - ! declare -F module_verify >/dev/null 2>&1; then + ! declare -F module_apply >/dev/null 2>&1 && + ! declare -F module_verify >/dev/null 2>&1; then printf 'Error: module %s does not declare any actions.\n' \ "$requested_module" >&2 @@ -390,4 +390,4 @@ reset_module_contract() { LWBS_MODULE_PATH="" LWBS_MODULE_CAPABILITIES=() LWBS_MODULE_EXTERNAL_INSTALLERS=() -} \ No newline at end of file +} diff --git a/lib/plan.sh b/lib/plan.sh index 2cd54f4..5bd52ce 100644 --- a/lib/plan.sh +++ b/lib/plan.sh @@ -308,8 +308,8 @@ show_execution_plan() { } execution_plan_has_changes() { - ((LWBS_PLAN_INSTALL_ACTION_COUNT > 0 || - LWBS_PLAN_CUSTOM_ACTION_COUNT > 0)) + ((LWBS_PLAN_INSTALL_ACTION_COUNT > 0 || \ + LWBS_PLAN_CUSTOM_ACTION_COUNT > 0)) } execute_planned_packages() { @@ -890,4 +890,4 @@ reset_execution_plan() { LWBS_PLAN_EXTERNAL_ACTIONS=() LWBS_PLAN_MODULE_HAS_APPLY=() LWBS_PLAN_MODULE_HAS_VERIFY=() -} \ No newline at end of file +} diff --git a/lib/profile.sh b/lib/profile.sh index 0dfe208..dbce30c 100644 --- a/lib/profile.sh +++ b/lib/profile.sh @@ -235,4 +235,4 @@ reset_profile_contract() { LWBS_PROFILE_DESCRIPTION="" LWBS_PROFILE_PATH="" LWBS_PROFILE_MODULES=() -} \ No newline at end of file +} diff --git a/lib/testlib.sh b/lib/testlib.sh deleted file mode 100644 index 9d9c8c8..0000000 --- a/lib/testlib.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env bash - -# Linux Workstation Bootstrap -# Author: David Kariuki -# -# Minimal test harness used by the repository test suite. -# -# The harness intentionally depends only on Bash so the core test suite can -# run locally and in CI without installing a separate testing framework. - -LWBS_TEST_COUNT=0 -LWBS_TEST_FAILURE_COUNT=0 - -# Execute one test function in an isolated subshell. -run_test() { - local test_name="${1:-}" - local test_function="${2:-}" - - if [[ -z "$test_name" || -z "$test_function" ]]; then - printf 'Error: run_test requires a name and test function.\n' >&2 - return 2 - fi - - ((LWBS_TEST_COUNT += 1)) - - printf 'TEST: %s\n' "$test_name" - - if ( - set -Eeuo pipefail - "$test_function" - ); then - printf 'PASS: %s\n\n' "$test_name" - return 0 - fi - - ((LWBS_TEST_FAILURE_COUNT += 1)) - - printf 'FAIL: %s\n\n' "$test_name" - - return 0 -} - -# Assert that two values are exactly equal. -assert_equal() { - local expected="${1-}" - local actual="${2-}" - local message="${3:-values are not equal}" - - if [[ "$expected" == "$actual" ]]; then - return 0 - fi - - printf 'Assertion failed: %s\n' "$message" >&2 - printf ' Expected: %q\n' "$expected" >&2 - printf ' Actual : %q\n' "$actual" >&2 - - return 1 -} - -# Assert that one string contains another string. -assert_contains() { - local haystack="${1-}" - local needle="${2-}" - local message="${3:-expected text was not found}" - - if [[ "$haystack" == *"$needle"* ]]; then - return 0 - fi - - printf 'Assertion failed: %s\n' "$message" >&2 - printf ' Expected to contain: %q\n' "$needle" >&2 - printf ' Actual : %q\n' "$haystack" >&2 - - return 1 -} - -# Assert that a filesystem path does not exist. -assert_not_exists() { - local path="${1:-}" - local message="${2:-path unexpectedly exists}" - - if [[ ! -e "$path" ]]; then - return 0 - fi - - printf 'Assertion failed: %s\n' "$message" >&2 - printf ' Path: %s\n' "$path" >&2 - - return 1 -} - -# Create an isolated temporary directory for one test. -make_test_temp_dir() { - mktemp -d "${TMPDIR:-/tmp}/lwbs-test.XXXXXX" -} - -# Initialize logging beneath an isolated test directory. -setup_test_logging() { - local test_directory="${1:-}" - - if [[ -z "$test_directory" ]]; then - printf 'Error: setup_test_logging requires a test directory.\n' >&2 - return 2 - fi - - export XDG_STATE_HOME="$test_directory/state" - export HOME="$test_directory/home" - - mkdir -p -- "$HOME" - - init_logging -} - -# Print the result for the current test file. -finish_tests() { - local passed_count - - passed_count=$((LWBS_TEST_COUNT - LWBS_TEST_FAILURE_COUNT)) - - printf 'Tests: %d | Passed: %d | Failed: %d\n' \ - "$LWBS_TEST_COUNT" \ - "$passed_count" \ - "$LWBS_TEST_FAILURE_COUNT" - - if ((LWBS_TEST_FAILURE_COUNT > 0)); then - return 1 - fi - - return 0 -} \ No newline at end of file diff --git a/lib/ui.sh b/lib/ui.sh index 156d720..f4fbc05 100755 --- a/lib/ui.sh +++ b/lib/ui.sh @@ -142,7 +142,7 @@ choose_distro_profile() { if [[ "$choice" =~ ^[0-9]+$ ]]; then selected_index=$((10#$choice - 1)) - if ((selected_index >= 0 && + if ((selected_index >= 0 && \ selected_index < ${#LWBS_SUPPORTED_DISTROS[@]})); then SELECTED_DISTRO_PROFILE="${LWBS_SUPPORTED_DISTROS[$selected_index]}" @@ -217,4 +217,4 @@ EOF show_version() { printf '%s %s\n' "$LWBS_APP_NAME" "$LWBS_VERSION" -} \ No newline at end of file +} diff --git a/lib/verification.sh b/lib/verification.sh index 084dfcb..717e8e4 100644 --- a/lib/verification.sh +++ b/lib/verification.sh @@ -61,8 +61,7 @@ record_execution_result() { fi case "$status" in - successful | skipped | failed | unverifiable) - ;; + successful | skipped | failed | unverifiable) ;; *) printf 'Error: invalid execution result status: %s\n' \ "$status" >&2 @@ -188,4 +187,4 @@ show_execution_summary() { # Return success when no required verification failure was recorded. execution_results_are_successful() { ((LWBS_RESULT_FAILED_COUNT == 0)) -} \ No newline at end of file +} diff --git a/tests/run.sh b/tests/run.sh index 5f1d946..351f3a7 100644 --- a/tests/run.sh +++ b/tests/run.sh @@ -42,4 +42,4 @@ if ((failed_files > 0)); then exit 1 fi -printf 'Test suite passed.\n' \ No newline at end of file +printf 'Test suite passed.\n' diff --git a/tests/test_arguments.sh b/tests/test_arguments.sh index d2fbdc1..6ec922f 100644 --- a/tests/test_arguments.sh +++ b/tests/test_arguments.sh @@ -114,4 +114,4 @@ run_test \ "reject positional arguments" \ test_positional_argument_fails -finish_tests \ No newline at end of file +finish_tests diff --git a/tests/test_config.sh b/tests/test_config.sh index 222fd6d..c621666 100644 --- a/tests/test_config.sh +++ b/tests/test_config.sh @@ -190,4 +190,4 @@ run_test \ "parse user configuration as data rather than shell code" \ test_config_is_not_executed -finish_tests \ No newline at end of file +finish_tests diff --git a/tests/test_core.sh b/tests/test_core.sh index 8eee470..2741a35 100644 --- a/tests/test_core.sh +++ b/tests/test_core.sh @@ -101,4 +101,4 @@ run_test \ "reject non-Linux runtime" \ test_runtime_rejects_non_linux -finish_tests \ No newline at end of file +finish_tests diff --git a/tests/test_detection.sh b/tests/test_detection.sh index 906b420..81c8f86 100644 --- a/tests/test_detection.sh +++ b/tests/test_detection.sh @@ -116,4 +116,4 @@ run_test \ "reject an unreadable os-release source" \ test_missing_os_release_fails -finish_tests \ No newline at end of file +finish_tests diff --git a/tests/test_distro.sh b/tests/test_distro.sh index 9ae3caf..55ca678 100644 --- a/tests/test_distro.sh +++ b/tests/test_distro.sh @@ -250,4 +250,4 @@ run_test \ "keep local package installation safe in dry-run" \ test_local_package_install_is_safe_in_dry_run -finish_tests \ No newline at end of file +finish_tests diff --git a/tests/test_execution.sh b/tests/test_execution.sh index 11bcdf1..464381b 100644 --- a/tests/test_execution.sh +++ b/tests/test_execution.sh @@ -138,4 +138,4 @@ run_test \ "reject empty command execution requests" \ test_execution_requires_command -finish_tests \ No newline at end of file +finish_tests diff --git a/tests/testlib.sh b/tests/testlib.sh index c9fcfee..a6d9afa 100644 --- a/tests/testlib.sh +++ b/tests/testlib.sh @@ -145,4 +145,4 @@ finish_tests() { fi return 0 -} \ No newline at end of file +}