-
Notifications
You must be signed in to change notification settings - Fork 3
/
install
executable file
·427 lines (349 loc) · 16.7 KB
/
install
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#!/bin/bash
# basic functions -- we need this for color definitions etc.
. ./shell/.shell_basic
if [ "$1" == "--help" ] || [ "$1" == "-h" ]; then
printf "${MAGENTA}∞ DMT ∞ ${CYAN}v$(cat "$DMT_PATH/.version")${NC}\n"
echo
printf "${WHITE}Install or update ${MAGENTA}.dmt${NC} scripts and shortcuts on this or any remote ${CYAN}Linux / macOS ${NC}machine (by using ssh).\n"
echo
printf "${YELLOW}Usage:${NC}\n"
printf "${GREEN}$0${GRAY} install on this device${NC}\n"
printf "${GREEN}$0 user@host ${GRAY}installs on user@host, shortcut ${GREEN}$0 ap ${GRAY}installs on ${DMT_AP_DEFAULT_HOST}${NC}\n"
exit
fi
# this install script is used in two scenarios:
#
# A) after we get the ~/.dmt directory (for example by cloning the https://github.com/uniqpath/dmt repo)
# it sets up basic things and doesn't do anything outside of ~/.dmt directory except add one line to
# ~/.bash_profile, ~/.bashrc or ~/.zshrc (as appropriate) which then enables the user to have access
# to "dmt" command to be able to manipulate (start, stop, restart) the "dmt-proc" (dmt process -
# a main component of dmt-system).
#
# B) if install script is called with one argument (user@host), then it will
# - first rsync our entire ~/.dmt directory to that device
# - call this same ./install script without any arguments on that device to set it up in the same way
# as it set up this device
DMT_BASH_PATH="$HOME/.dmt/shell"
function compile {
local cwd="`pwd`"
cd "$DMT_BASH_PATH"
./compile
cd "$cwd"
}
function check_node_js_version {
which node > /dev/null 2>&1
if [ $? -eq 0 ]; then # node command exists
node_version=$(node -v | sed "s/v//")
a=( ${node_version//./ } ) # replace points, split into array
major=${a[0]}
minor=${a[1]}
b=( ${DMT_MIN_NODEJS_VERSION//./ } ) # DMT_MIN_NODEJS_VERSION comes from .bash_dmt_vars
min_major=${b[0]}
min_minor=${b[1]}
if (( ${major} < $min_major )) || ( (( ${major} == $min_major )) && (( ${minor} < $min_minor )) ); then
echo
printf "⚠️ ${RED}Your node.js version is ${YELLOW}${node_version}${GRAY}, please install ${CYAN}${DMT_MIN_NODEJS_VERSION} (recommended) ${GRAY}or higher.${NC}\n"
which n > /dev/null 2>&1
if [ $? -eq 0 ]; then # n command exists
printf "${GRAY}It seems that you are using ${CYAN}n ${GRAY}node.js version manager. ${GRAY}Use ${GREEN}n ${DMT_MIN_NODEJS_VERSION} ${GRAY}to install the recommended version.${NC}\n"
fi
fi
else
echo
printf "⚠️ ${CYAN}node.js ${RED}is not installed${GRAY}, please install ${YELLOW}node.js v${DMT_MIN_NODEJS_VERSION} ${GRAY}or higher${NC}\n"
fi
}
function user_dir_sync_info {
local text="Syncing"
if [ "$1" ]; then
text="Synced"
fi
printf "ℹ️ ${YELLOW}— ${text} just your ${CYAN}dmt user directory ${YELLOW}since remote device is most likely set up to ${MAGENTA}auto-update ${CYAN}DMT ENGINE ${NC}...${NC}\n"
}
#🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀
# -----------------------------------
# ENTRY POINT WHEN INSTALLING TO
# REMOTE HOSTS (we passed arguments)
# -----------------------------------
#🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀
if [ -n "$1" ]; then
#💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡
# -----------------------------------
# Install on remote device(s)
# -----------------------------------
#💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡
# we need this for dirsync, remote and get_full_host functions
. ./shell/.shell_advanced
flags=""
#excludes="--exclude apps/**/node_modules --exclude user/apps/**/node_modules"
excludes=""
compress=""
RESTART=false
PARALLEL=false
# bash cli parser, source: https://medium.com/@Drew_Stokes/bash-argument-parsing-54f3b81a6a8f
ARGS=()
while (( "$#" )); do
case "$1" in
--shell)
excludes="${excludes} --exclude core --exclude bin --exclude user/wallpapers --exclude etc/sounds --exclude etc/videotest"
flags="${flags} --shell"
shift 1
;;
--no-apps)
#⚠️ possible issue here? does this really exclude just './apps' or is broader? CHECK
excludes="${excludes} --exclude apps" # wrapping directory in single quotes won't work in this case by the time it reaches rsync command inside dirsync.. but it's ok, we don't need it
flags="${flags} --no-apps"
shift 1
;;
# --no-user)
# excludes="${excludes} --exclude user"
# flags="${flags} --no-user"
# shift 1
# ;;
--restart)
flags="${flags} --restart"
RESTART=true
shift 1
;;
--parallel)
PARALLEL=true
# note: we don't add to flags here because we only pass this flag on when mode 2b
# (updating multiple hosts), when we're at 2a (single host) we reach the leaf of the tree
# and decide based on this flag but don't pass it on again because this would cause infinite loop
shift 1
;;
--compress)
flags="${flags} --compress"
compress="--compress"
shift 1
;;
--) # end argument parsing
shift
break
;;
-*|--*=) # unsupported flags
echo "Error: Unsupported flag $1" >&2
exit 1
;;
*) # preserve positional arguments
ARGS+=($1)
shift
;;
esac
done
len=${#ARGS[@]}
#💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡
# ----------------------------------------------------------
# STEP 0 — RECURSIVE CALL WHEN INSTALING ON MULTIPLE DEVICES
# ----------------------------------------------------------
#💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡💡
if [ $len -gt 1 ]; then
for host in "${ARGS[@]}"
do
# if we're doing parallel update
# we have to pass this flag when calling this script
# with each host individually, script will then
# execute in background (screen) at final step
if $PARALLEL; then
flags="${flags} --parallel"
fi
./install $flags "$host"
done
else
#✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
# ---------------------------------------
# STEP 1 — INSTALL ON SINGLE REMOTE HOST
# ---------------------------------------
#✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
host=${ARGS[0]}
#✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
# 💡 STEP 1a when --parallel
#✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
if $PARALLEL; then
#./install $flags "$host"
type="copy"
if $RESTART; then
type="update"
fi
printf "${CYAN}🎌 Parallel ${MAGENTA}(background) ${CYAN}${type}${NC} ${MAGENTA}${host}${NC}\n"
# - won't load the entire bash_bundle, basic shell which this install script loads is fine!
# "se" command helper from dmt would make everything slow because of bundle loading, we did this before buy not anymore :)
# - will not pass --parallel flag here, that would make a loop
screen -S dmt_update -dm bash -c "./install ${flags} ${host}"
exit
else
printf "✨ ${CYAN}Updating ${MAGENTA}${host}${NC}\n"
fi
#✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
# 💡 STEP 1b when not --parallel
#✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
#
# (either it was not --parallel in the first place)
# (STEP 0 ->) STEP 1 -> STEP 1b
#
# OR it was and we're now running in background screen
# (STEP 0 ->) STEP 1 -> STEP 1a -> STEP 1b
# 💡 STEP 1b →
# - dirsync to remote host
# - call install on remote host ()
# - restart
if [ "$host" == "ap" ] || [ "$host" == "hub" ]; then
host="$DMT_AP_DEFAULT_HOST"
ssh_port=22
else
matching_host=''
ssh_port=''
_compress=''
get_full_host matching_host ssh_port _compress "$host"
if [ $? -ne 1 ]; then # no error
host="$matching_host"
fi
# compress regardless if passed in argument if device has globalIp defined (get_full_host will return "--compress")
if [[ $_compress == "--compress" ]]; then
compress=$_compress # yes, please compress :)
fi
fi
if [ -n "$DMT_SSH_PORT" ]; then
printf "${GREEN}ssh port set via environment variable ${MAGENTA}\$DMT_SSH_PORT${NC}: ${CYAN}$DMT_SSH_PORT${NC}\n"
ssh_port=$DMT_SSH_PORT
fi
if [ -z "$host" ]; then
printf "${RED}Host not known${NC}\n"
else
# check if we're accidentaly deploying to a git(hub) repo and abort in this case
# either we get dmt from github or not (eg. sync to that device from elsewhere), cannot have a mixture
ssh -p $ssh_port "$host" 'if [ -f ~/.dmt/etc/scripts/dmt_via_git ]; then ~/.dmt/etc/scripts/dmt_via_git; fi' # exit code from remote script will carry over and we can check it!
if [ $? -eq 1 ]; then # dmt_via_git script will return 1 if ~/.dmt/.git directory exists on the remote machine
echo
printf "⚠️ ${CYAN}~/.dmt${NC} on remote device ${YELLOW}is a git repository${NC}, origin is probably ${CYAN}github: uniqpath/dmt. ${GREEN}This is ok.${NC} ↴\n"
printf "${WHITE}↳ but refusing to override remote DMT ENGINE because this is most likely not desirable.${NC}\n"
echo
printf "${CYAN}Please ssh into remote device and issue ${GREEN}dmt autoupdate off ${CYAN}to stop it from being updated from github source.${NC}\n"
echo
user_dir_sync_info
# printf "${YELLOW}— Sync just your ${CYAN}dmt user directory ${YELLOW}since remote device is most likely set up to ${MAGENTA}auto-update ${CYAN}DMT ENGINE${NC}?${NC}\n"
# echo
# # sync just user directory ? -- perhaps do this without asking soon !
# read -r -p "Do you want to sync just your ~/.dmt/user directory to the remote DMT ENGINE? [Y/n] " response
# if [[ $response =~ ^([nN])$ ]]
# then
# printf "${GRAY}↳ Exiting ...${NC}\n"
# echo
# return
# fi
echo
printf "${CYAN}Updating ${CYAN}~/.dmt/user${MAGENTA} on ${MAGENTA}$host:$ssh_port …${NC}\n"
echo
target="${host}:.dmt/user"
dirsync $excludes $compress --port $ssh_port ~/.dmt/user "$target"
if [ $? -ne 0 ]; then # error
exit
fi
# IMPORTANT
# ~/.dmt/.deployignore ==>
# ...
# /user/devices/this
# /devices/this <- this line is needed for 'this pointer' to be correctly ignored when deploying only user directory
# keys.def
# ...
echo
user_dir_sync_info true
else
# full sync - update remote DMT ENGINE together with its user directory
printf "${CYAN}Determined exact remote address: ${MAGENTA}$host:$ssh_port${NC}\n"
echo
target="${host}:.dmt"
dirsync $excludes $compress --port $ssh_port ~/.dmt "$target"
if [ $? -ne 0 ]; then # error
exit
fi
echo
fi
# restart remote dmt-proc
if $RESTART; then
# 🌀 EXECUTE FINAL STEP 2 on remote machine AND then restart the remote process
#restart_cmd="source ~/.dmt/etc/.bash_aliases_slim && se \\\"if [ -f ~/.dmt/user/devices/this/before-update ]; then ~/.dmt/user/devices/this/before-update; fi; if [ -f ~/.dmt/etc/deploy_hooks/before-update ]; then ~/.dmt/etc/deploy_hooks/before-update; fi; ~/.dmt/etc/onboot/daemons restart_and_notify_on_fail\\\""
INSTALL_AND_RESTART_CMD="screen -S dmt -dm bash -c \\\"cd ~/.dmt; ./install; ~/.dmt/etc/onboot/daemons restart_and_notify_on_fail\\\""
dmt_ssh_execute -h "$host" --port "$ssh_port" "$INSTALL_AND_RESTART_CMD"
else
# 🌀 JUST EXECUTE FINAL STEP 2 on remote machine
dmt_ssh_execute --silent -h "$host" --port "$ssh_port" "screen -S dmt -dm bash -c \\\"cd ~/.dmt; ./install\\\""
fi
echo
fi
fi
else
#🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀
# -----------------------------------
#
# ~~ STEP 2 ~~
#
# ACTUAL INSTALL CODE - LOCAL MACHINE
#
# -----------------------------------
#🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀🌀
COMPILED_BASH_ALIASES="$HOME/.dmt/etc/.bash_aliases_bundle"
# 1.) we concatenate all dmt shell scripts into one file -- .bash_aliases_bundle
# this file is sourced from some scripts as needed but is not loaded by default in user's shell
compile
if [ ! -f "$COMPILED_BASH_ALIASES" ]; then
printf "${RED}Error: compilation was supposed to produce $COMPILED_BASH_ALIASES${NC}\n"
exit
fi
# 2.) we create some needed empty dirs
mkdir -p "$DMT_STATE"
mkdir -p "$DMT_PATH/log"
# 3.) if there is no ~/.dmt/user directory, we copy the pre-defined sample user from ~/.dmt/etc/sample_user
if [ ! -d "$DMT_PATH/user" ] && [ -d "$DMT_PATH/etc/sample_user" ]; then
cp -r "$DMT_PATH/etc/sample_user" "$DMT_PATH"
mv "$DMT_PATH/sample_user" "$DMT_PATH/user"
cwd="`pwd`"
cd "$DMT_PATH/user/devices"
ln -s "dmt-new" "this"
cd "$cwd"
fi
# 4.) ~/.dmt/shell/.inject script will add one line to the end of ~/.bash_profile, ~/.bashrc or ~/.zshrc:
# if [ -f ~/.dmt/shell/.loader ]; then . ~/.dmt/shell/.loader; fi # Added by dmt-system (see https://github.com/uniqpath/dmt)
# this line sources our .loader which then sources only the "dmt" shell command by default but can source more if
# an appropriate option "shell: full" is found inside ~/.dmt/user/def/user.def
"$DMT_PATH/shell/.inject"
# 5.) fix stuff for apps loading .. dmt-here/apps
# # we do this in prepare_engine as well upon "dmt start" or "dmt run"
# but prepare_engine is not run on remote machine during update or copy (dmt update / copy)
# but install is and so we ./prepare_apps here as well
prepare_dir="$DMT_PATH/etc/scripts/prepare_apps_and_user_engine"
cwd="`pwd`"
cd "$prepare_dir"
./prepare_apps
cd "$prepare_dir"
./prepare_user_engine
cd "$cwd"
# run after-install (=after-update) hooks
# This is useful mostly only in the second (B) case after we ./install is called on remote device (via "dmt update user@host")
# "$HOME/.dmt/etc/deploy_hooks/after-update" contains just one important line
# node "${DMT_NODE_CORE}/dmt-gui/gui-backend/ws_servers/index.js" localhost reload gui
# -- this is used to send the "reload" command to all connected guis so that they reload possible changes that arrived on update (sync)
#dmt link
# general deploy hooks -- all devices
# was called after_copy b efore
on_install_hook="$HOME/.dmt/etc/deploy_hooks/oninstall"
if [ -f "$on_install_hook" ]; then
"$on_install_hook" #> /dev/null 2>&1 # redirected to /dev/null because we get ws exception if dmt-proc is not running when trying to restart gui by sending a websocket message
fi
# (possibly defined) for each particular device
on_install_hook="$HOME/.dmt/user/devices/this/oninstall"
if [ -f "$on_install_hook" ]; then
"$on_install_hook"
fi
echo
printf "${YELLOW}Congrats!${NC} ${MAGENTA}∞ DMT ∞${NC} installed on ${CYAN}$(hostname).${NC}\n"
echo
printf "${GRAY}Project website — ${MAGENTA}dmt-system.com ${GRAY}/ ${CYAN}github.com/uniqpath/dmt${NC}\n"
echo
printf "💡 Type ${GREEN}${UNDERLINE}dmt${NC} ${GRAY}[enter]${NC} to see the options${YELLOW}\n"
printf "${GRAY}----------------------------------------${NC}\n"
printf "To start ${CYAN}dmt-proc${NC} enter ${GREEN}${UNDERLINE}dmt start${NC} 🚀\n\n"
printf "⚠️ If ${GREEN}dmt${NC} command is not working please ${MAGENTA}open new terminal${GRAY} or ${GREEN}${UNDERLINE}source ~/.dmt/shell/.loader${RESET}${NC}\n"
check_node_js_version
echo
fi