-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathbase_init.sh
More file actions
executable file
·170 lines (143 loc) · 5.17 KB
/
base_init.sh
File metadata and controls
executable file
·170 lines (143 loc) · 5.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env bash
#
# base_init.sh
# Base runtime bootstrap for Bash commands and Base-enabled Bash shells.
#
# Loaded by:
# - bin/basectl before it sources a Base command implementation
# - bin/basectl before it sources an explicit Base-enabled Bash script
# - lib/bash/runtime/bashrc for `basectl` and `basectl shell` sessions
#
# Not loaded by:
# - normal Bash/Zsh dotfile startup managed by lib/shell/*
#
# Runtime contract:
# - validate that the runtime is Bash 4.2 or newer
# - derive or validate BASE_HOME
# - export the BASE_* paths that downstream scripts may rely on
# - export BASE_OS and BASE_HOST runtime metadata
# - source Base's Bash standard library
# - add BASE_BIN_DIR to PATH
# - provide import_base_lib for convention-based Base Bash library imports
#
# Downstream scripts should not rediscover Base's directory layout on their own.
# They should use the exported BASE_* variables and import libraries with:
#
# import_base_lib file/lib_file.sh
#
# import_base_lib reports missing or invalid libraries through Base stdlib error
# handling and fails immediately, so callers do not need duplicate checks.
#
[[ -n "${__base_init_sourced__:-}" ]] && return 0
readonly __base_init_sourced__=1
base_init_error() {
printf 'ERROR: %s\n' "$*" >&2
}
base_init_resolve_path() {
local source_path="${1:-}"
local link_dir
local target
[[ -n "$source_path" ]] || return 1
while [[ -L "$source_path" ]]; do
link_dir="$(cd -- "$(dirname -- "$source_path")" && pwd -P)" || return 1
target="$(readlink "$source_path")" || return 1
if [[ "$target" == /* ]]; then
source_path="$target"
else
source_path="$link_dir/$target"
fi
done
link_dir="$(cd -- "$(dirname -- "$source_path")" && pwd -P)" || return 1
printf '%s/%s\n' "$link_dir" "$(basename -- "$source_path")"
}
base_init_require_bash() {
local current_version
if [[ -z "${BASH_VERSION:-}" ]]; then
base_init_error "Base runtime requires Bash."
return 1
fi
current_version="${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}"
if ((current_version < 42)); then
base_init_error "Base runtime requires Bash 4.2 or newer; current version is ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}."
return 1
fi
}
base_init_resolve_home() {
local source_path
local source_dir
if [[ -n "${BASE_HOME:-}" ]]; then
[[ -d "$BASE_HOME" ]] || {
base_init_error "BASE_HOME '$BASE_HOME' is not a directory or is not accessible."
return 1
}
(cd -- "$BASE_HOME" && pwd -P)
return $?
fi
source_path="$(base_init_resolve_path "${BASH_SOURCE[0]}")" || return 1
source_dir="$(cd -- "$(dirname -- "$source_path")" && pwd -P)" || return 1
printf '%s\n' "$source_dir"
}
base_init_export_contract() {
local base_home base_os base_host
base_home="$(base_init_resolve_home)" || return 1
base_os="$(uname -s)" || {
base_init_error "Unable to determine BASE_OS with uname."
return 1
}
[[ -n "$base_os" ]] || {
base_init_error "Unable to determine BASE_OS with uname."
return 1
}
base_host="$(hostname -s)" || {
base_init_error "Unable to determine BASE_HOST with hostname."
return 1
}
[[ -n "$base_host" ]] || {
base_init_error "Unable to determine BASE_HOST with hostname."
return 1
}
BASE_HOME="$base_home"
BASE_BIN_DIR="$BASE_HOME/bin"
BASE_CLI_DIR="$BASE_HOME/cli"
BASE_BASH_DIR="$BASE_CLI_DIR/bash"
BASE_BASH_COMMANDS_DIR="$BASE_BASH_DIR/commands"
BASE_LIB_DIR="$BASE_HOME/lib"
BASE_BASH_LIB_DIR="$BASE_LIB_DIR/bash"
BASE_SHELL_DIR="$BASE_LIB_DIR/shell"
BASE_OS="$base_os"
BASE_HOST="$base_host"
export BASE_HOME BASE_BIN_DIR BASE_CLI_DIR BASE_BASH_DIR BASE_BASH_COMMANDS_DIR
export BASE_LIB_DIR BASE_BASH_LIB_DIR BASE_SHELL_DIR BASE_OS BASE_HOST
}
base_init_source_stdlib() {
local stdlib_path="$BASE_BASH_LIB_DIR/std/lib_std.sh"
[[ -f "$stdlib_path" ]] || {
base_init_error "Base Bash stdlib '$stdlib_path' was not found."
return 1
}
# shellcheck source=/dev/null
source "$stdlib_path"
}
import_base_lib() {
local relative_path="${1:-}"
local lib_path
[[ -n "$relative_path" ]] || fatal_error "import_base_lib: no library path provided."
[[ "$relative_path" != /* ]] || fatal_error "import_base_lib: expected a path relative to '$BASE_BASH_LIB_DIR', got '$relative_path'."
case "$relative_path" in
..|../*|*/..|*/../*)
fatal_error "import_base_lib: refusing path outside Base Bash library root: '$relative_path'."
;;
esac
lib_path="$BASE_BASH_LIB_DIR/$relative_path"
[[ -f "$lib_path" ]] || fatal_error "Base library '$relative_path' was not found at '$lib_path'."
# shellcheck source=/dev/null
source "$lib_path" || fatal_error "Failed to import Base library '$lib_path'."
}
base_init_main() {
base_init_require_bash || return 1
base_init_export_contract || return 1
base_init_source_stdlib "$@" || return 1
add_to_path -p "$BASE_BIN_DIR"
export PATH
}
base_init_main "$@" || return $?