-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathbase_init.sh
executable file
·170 lines (151 loc) · 5.39 KB
/
base_init.sh
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: top level script that should be sourced in by login/interactive shells
#
# lib/bashrc invokes this
#
[[ $__base_init_sourced__ ]] && return
__base_init_sourced__=1
check_bash_version() {
local major=${1:-4}
local minor=$2
local rc=0
local num_re='^[0-9]+$'
if [[ ! $major =~ $num_re ]] || [[ $minor && ! $minor =~ $num_re ]]; then
printf '%s\n' "ERROR: version numbers should be numeric"
return 1
fi
if [[ $minor ]]; then
local bv=${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}
local vstring=$major.$minor
local vnum=$major$minor
else
local bv=${BASH_VERSINFO[0]}
local vstring=$major
local vnum=$major
fi
((bv < vnum)) && {
printf '%s\n' "ERROR: Base needs Bash version $vstring or above, your version is ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
rc=1
}
return $rc
}
do_init() {
local rc=0
[[ -f $HOME/.base_debug ]] && export BASE_DEBUG=1
if [[ $BASH ]]; then
# Bash
base_debug() { [[ $BASE_DEBUG ]] && printf '%(%Y-%m-%d:%H:%M:%S)T %s\n' -1 "DEBUG ${BASH_SOURCE[0]}:${BASH_LINENO[1]} $@" >&2; }
base_error() { printf '%(%Y-%m-%d:%H:%M:%S)T %s\n' -1 "ERROR ${BASH_SOURCE[0]}:${BASH_LINENO[1]} $@" >&2; }
elif [[ $ZSH_VERSION ]]; then
#
# for zsh - it doesn't support time in printf
#
base_debug() { [[ $BASE_DEBUG ]] && printf '%s\n' "$(date) DEBUG ${BASH_SOURCE[0]}:${BASH_LINENO[1]} $@" >&2; }
base_error() { printf '%s\n' "$(date) ERROR ${BASH_SOURCE[0]}:${BASH_LINENO[1]} $@" >&2; }
else
printf '%s\n' "ERROR: Unsupported shell - need Bash or zsh" >&2
rc=1
fi
BASE_OS=$(uname -s)
BASE_HOST=$(hostname -s)
export BASE_SOURCES=() BASE_OS BASE_HOST
return $rc
}
set_base_home() {
script=$HOME/.baserc
[[ -f $script ]] && [[ -z $_baserc_sourced ]] && {
base_debug "Sourcing $script"
# shellcheck source=/dev/null
source "$script"
_baserc_sourced=1
}
# set BASE_HOME to default in case it is not set
[[ -z $BASE_HOME ]] && {
local dir=$HOME/base
base_debug "BASE_HOME not set; defaulting it to '$dir'"
BASE_HOME=$dir
}
export BASE_HOME
}
#
# check for existence of the library, source it, add its name to BASE_SOURCES array
# Usage: source_it [-i] library_file
# -i - source only if the shell is interactive
#
source_it() {
local lib iflag=0 sourced=0
[[ $1 = "-i" ]] && { iflag=1; shift; }
lib=$1
if ((iflag)); then
# shellcheck source=/dev/null
((_interactive)) && [[ -f $lib ]] && { base_debug "(interactive) Sourcing $lib"; source "$lib"; sourced=1; }
else
# shellcheck source=/dev/null
[[ -f $lib ]] && { base_debug "Sourcing $lib"; source "$lib"; sourced=1; }
fi
((sourced)) && BASE_SOURCES+=("$lib")
}
#
# source in libraries, starting from the top (lowest precedence) to the bottom (highest precedence)
#
import_libs_and_profiles() {
local lib script team
local -A teams
source_it "$BASE_HOME/lib/stdlib.sh" # common library
source_it "$BASE_HOME/company/lib/company.sh" # company specific library
source_it -i "$BASE_HOME/company/lib/bashrc" # company specific bashrc for interactive shells
source_it -i "$BASE_HOME/user/$USER.sh" # user specific bashrc in the repo for interactive shells
source_it -i "$HOME/.baserc-$USER" # user specific bashrc outside the repo for interactive shells
#
# team specific actions
#
# Users choose teams by setting the "BASE_TEAM" variable in their user specific startup script
# For example: BASE_TEAM=teamX
#
# Users can also set "BASE_SHARED_TEAMS" to more teams so as to share from those teams.
# For example: BASE_SHARED_TEAMS="teamY teamZ" or
# BASE_SHARED_TEAMS=(teamY teamZ)
#
# We source the team specific startup script add the team bin directory to PATH, in the same order
#
teams=()
for team in $BASE_TEAM $BASE_SHARED_TEAMS "${BASE_SHARED_TEAMS[@]}"; do
[[ ${teams[$team]} ]] && continue # skip if team was seen already
source_it "$BASE_HOME/team/$team/lib/$team.sh" # team specific library
source_it -i "$BASE_HOME/team/$team/lib/bashrc" # team specific bashrc for interactive shells
add_to_path "$BASE_HOME/team/$team/bin" # add team bin to PATH (gets priority over company bin)
teams[$team]=1
done
# add company bin to PATH; team bins, if any, take priority over company bin
add_to_path "$BASE_HOME/company/bin"
}
#
# A shortcut to refresh the base git repo; users can add it to user/<user>.sh file so that base is automatically
# updated upon login.
#
base_update() (
[[ -d $BASE_HOME ]] && {
cd "$BASE_HOME" && git pull --rebase
}
)
base_main() {
check_bash_version 4 2 || return $?
do_init || return $?
[[ $- = *i* ]] && _interactive=1 || _interactive=0
set_base_home
if [[ -d $BASE_HOME ]]; then
import_libs_and_profiles
add_to_path "$BASE_HOME/bin"
else
base_error "BASE_HOME '$BASE_HOME' is not a directory or is not accessible"
fi
#
# these functions need to be available to user's subprocesses
#
export -f base_update import
}
#
# start here
#
base_main