-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathinstall.sh
executable file
·261 lines (209 loc) · 6.47 KB
/
install.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
############################## Please use bash ################################
# bash => 3.
if [ -z ${BASH} ]; then
echo "Please run the script using the bash interpreter"
exit 1
else
bash_major_version=${BASH_VERSION:0:1}
if [ ${bash_major_version} -lt 3 ]; then
echo "Please run the script using bash version 3 or greater"
exit 1
fi
fi
# TODO: This is bad.
# First, $SUDO_USER may not be set depending on the sudo version installed on
# the resp. OS. Second, we should better adapt the failing line 27 to work
# a different way.
if [ ! -z ${SUDO_USER} ]; then
echo "Please run the script as root, not via sudo."
exit 1
fi
############################## Global constants ###############################
# Path to install script, no matter from where it is called.
INSTALLER_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
############################## Default configuration ##########################
# Set to 1 to allow only the root user to execute the script.
ROOT_ONLY=0
# Set to 0 to disable the initial touch-all-files action.
INITIAL_TOUCH_ALL=1
# Set to 0 to disable task dependency checking.
TASK_DEPENDENCY_CHECKING=1
# Path to installer utils.
UTILS_DIR=${INSTALLER_PATH}/utils
# Path to installer tasks.
TASKS_DIR=${INSTALLER_PATH}/tasks
# User configuration file.
USER_CONFIG=${INSTALLER_PATH}/config.sh
# Array of log severity values that go both to stdout and the logfile.
LOG_STDOUT=( "ERROR" "IMPORTANT" "WARNING" "INFO" "SKIP" "START" "FINISH" )
# Require various programs to be installed
REQUIRE_GREP=1
REQUIRE_SED=1
REQUIRE_DATE=1
REQUIRE_AWK=1
REQUIRE_WGET=1
############################## User configuration #############################
if [ -f ${USER_CONFIG} ]; then
source ${USER_CONFIG}
fi
############################## Initial checks #################################
# root.
if [ ${ROOT_ONLY} -gt 0 ] && [ $(whoami) != "root" ]; then
echo "Please run the script as root user"
exit 1
fi
# Tools.
if [ ${REQUIRE_GREP} -gt 0 ]; then
grep -V >/dev/null 2>&1 || { echo "Please install 'grep'."; exit 1; }
fi
if [ ${REQUIRE_SED} -gt 0 ]; then
sed --version >/dev/null 2>&1 || { echo "Please install 'sed'."; exit 1; }
fi
if [ ${REQUIRE_DATE} -gt 0 ]; then
date --version >/dev/null 2>&1 || { echo "Please install 'date'."; exit 1; }
fi
if [ ${REQUIRE_AWK} -gt 0 ]; then
awk -W version >/dev/null 2>&1 || { echo "Please install 'awk'."; exit 1; }
fi
if [ ${REQUIRE_WGET} -gt 0 ]; then
wget --version >/dev/null 2>&1 || { echo "Please install 'wget'."; exit 1; }
fi
############################## Initial-touch-all ##############################
# Update all timestamps to avoid any 'file comes from the future' errors.
if [ ${INITIAL_TOUCH_ALL} -gt 0 ]; then
find ${INSTALLER_PATH} -exec touch "{}" \;
fi
############################## Some functions #################################
# Automatic installation.
function run_installation() {
run_all_tasks
if all_tasks_done?; then
dispatch_msg "installation_complete"
return ${E_SUCCESS}
else
dispatch_msg "installation_incomplete"
return ${E_FAILURE}
fi
}
function main_menu() {
# Print the welcome message.
dispatch_msg "welcome"
# Print the status.
tasks_status
# Give the user a nice looping main menu!
local options=( "Run the installation" "Skip/Unskip task" "Run single task" "Exit (Ctrl+D)")
echo -e "\n$(dispatch_msg "main_menu_prompt")"
select opt in "${options[@]}"; do
if [ "${opt}" == "Run the installation" ]; then
run_installation
tasks_status
elif [ "${opt}" == "Skip/Unskip task" ]; then
skip_task_menu
tasks_status
elif [ "${opt}" == "Run single task" ]; then
single_task_menu
tasks_status
elif [ "${opt}" == "Exit (Ctrl+D)" ]; then
exit ${E_SUCCESS}
fi
done
}
function _select_task_menu() {
assert_eq $# 2
assert_function $1
local func=$1 prompt=$2
local options=()
for task in ${TASKS[@]}
do
shortname=$(dictGet ${task} "shortname")
options+=("${shortname}")
done
options+=("Nevermind (Ctrl+D)")
echo -e "\n$(dispatch_msg ${prompt})"
select opt in "${options[@]}"; do
if [ "${opt}" == "Nevermind (Ctrl+D)" ]; then
return ${E_SUCCESS}
else
for task in ${TASKS[@]}
do
if [ "${opt}" = "$(dictGet ${task} "shortname")" ]; then
${func} ${task}
return $?
fi
done
fi
done
return ${E_SUCCESS}
}
function skip_task_menu() {
_select_task_menu "skip_unskip_task" "skip_menu_prompt"
return $?
}
function single_task_menu() {
_select_task_menu "run_task" "task_menu_prompt"
return $?
}
function skip_unwanted_tasks() {
if [ "$(get_command_line_option tasks)" != "all" ]; then
local tasklist_str=$(get_command_line_option "tasks")
local tasklist=(${tasklist_str//,/ })
local skiplist=()
# First check if each task is actually known.
for task in ${tasklist[@]}; do
if ! array_contains? ${task} "${TASKS[@]}"; then
echo "Task ${task} not found." >&2
echo "Tasks are: ${TASKS[@]}"
return ${E_FAILURE}
fi
done
# Skip unselected tasks.
for task in ${TASKS[@]}; do
if ! array_contains? ${task} "${tasklist[@]}"; then
skip_unskip_task ${task}
fi
done
fi
return ${E_SUCCESS}
}
############################## Main app #######################################
# Load our utility modules.
for util in `ls -1 ${UTILS_DIR}`; do
source ${UTILS_DIR}/${util}
done
# Initialize the logfile.
log_init
# Read in tasks.
log_info "Loading tasks..."
for task in `ls -1 ${TASKS_DIR}`
do
task_load ${task}
done
# Add autorun command line option.
add_command_line_switch "run" "run" "r" "Run the installation automatically"
add_command_line_switch "help" "help" "h" "Show this usage information"
add_command_line_switch "debug" "debug" "d" "Enter debug console (for development)"
add_command_line_option "tasks" "tasks" "t" "List of tasks to execute (others will be skipped)" "all"
# Read command line arguments.
log_info "Reading command line arguments..."
process_command_line_options "$@"
if [ $? -ne ${E_SUCCESS} ] || has_command_line_switch? "help"; then
usage
exit ${E_FAILURE}
fi
# Skip other tasks if --tasks was given.
skip_unwanted_tasks
if [ $? -ne ${E_SUCCESS} ]; then
exit ${E_FAILURE}
fi
if has_command_line_switch? "debug"; then
# Debug console.
enter_debug_console
elif has_command_line_switch? "run"; then
# Automatic installation.
run_installation
exit $?
else
# User-driven installation.
main_menu
fi
exit 0