-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathBashbox.sh
325 lines (282 loc) · 9.51 KB
/
Bashbox.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
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
# shellcheck disable=SC2034
NAME="dotsh"
CODENAME="dotsh"
AUTHORS=("AXON <[email protected]>")
VERSION="1.0"
DEPENDENCIES=(
std::85df7f3
https://github.com/bashbox/libtmux::2863b38
https://github.com/axonasif/bashenv_zsh::c56d334
)
REPOSITORY="https://github.com/axonasif/dotsh.git"
BASHBOX_COMPAT="0.3.9~"
bashbox::build::after() {
local root_script="$_arg_path/$CODENAME";
cp "$_target_workfile" "$root_script";
chmod +x "$root_script";
}
bashbox::build::before() {
# TODO: Port to std
local git_dir="$_arg_path/.git";
local hooks_dir="$git_dir/hooks";
local pre_commit_hook="$hooks_dir/pre-commit";
if test -e "$git_dir" && test ! -e "$pre_commit_hook"; then {
log::info "Setting up pre-commit git hook";
mkdir -p "$hooks_dir";
printf '%s\n' \
'#!/usr/bin/env sh' \
'bashbox build --release' \
'git add dotsh' > "$pre_commit_hook";
chmod +x "$pre_commit_hook";
} fi
}
function livetest {
function docker() {
DOCKER_BUILDKIT=1 command docker "$@";
}
case "${1:-}" in
"minimg")
CONTAINER_IMAGE="axonasif/dotfiles-testing-min:latest";
;;
"ws")
trim_leading_trailing() {
local _stream="${1:-}";
local _stdin;
if test -z "${_stream}"; then {
read -r _stdin;
_stream="$_stdin";
} fi
# remove leading whitespace characters
_stream="${_stream#"${_stream%%[![:space:]]*}"}"
# remove trailing whitespace characters
_stream="${_stream%"${_stream##*[![:space:]]}"}"
printf '%s\n' "$_stream"
}
export DOTFILES_READ_GITPOD_YML=true;
declare default_gitpod_image="gitpod/workspace-full:latest";
declare CONTAINER_IMAGE="$default_gitpod_image";
declare gitpod_yml=("${GITPOD_REPO_ROOT:-}/".gitpod.y*ml);
if test -e "${gitpod_yml:-}"; then {
gitpod_yml_path="${gitpod_yml[0]}";
if ! yq -o=yaml -reM '""' 1>/dev/null; then {
log::error "Syntax errors were found on $gitpod_yml_path" 1 || exit;
} fi
# Get image source
if res="$(yq -o=yaml -I0 -erM '.image' "$gitpod_yml_path" 2>/dev/null)"; then {
if [[ "$res" == file:* ]]; then {
res="${res##*:}" && res="$(trim_leading_trailing "$res")"; # Trim file: and extra spaces
declare custom_dockerfile="$GITPOD_REPO_ROOT/$res";
if test ! -e "$custom_dockerfile"; then {
log::error "Your custom dockerfile ${BGREEN}$res${RC} doesn't exist at $GITPOD_REPO_ROOT" 1 || exit;
} fi
declare local_container_image_name="workspace-image";
docker build -t "$local_container_image_name" -f "$custom_dockerfile" "$GITPOD_REPO_ROOT";
CONTAINER_IMAGE="$local_container_image_name";
} else {
CONTAINER_IMAGE="$(trim_leading_trailing "$res")";
} fi
} fi
} fi
if [[ "$CONTAINER_IMAGE" == *\ * ]]; then {
log::error "$gitpod_yml_path:image contains illegal spaces" 1 || exit;
} fi
;;
"stress")
export DOTFILES_STRESS_TEST=true;
while livetest; do continue; done
;;
esac
function mount::unloadroot() {
local root="$1";
local _mountpoint;
while read -r _mountpoint; do
sudo umount "$_mountpoint";
done < <(mount | grep "$root" | awk '{print $3}' | sort -r || true);
}
function mount::overlay() {
local namespace="$1";
local lowerdir="$2";
local overlay_root="/tmp/.gitpod_overlay/${namespace}";
local upperdir="${overlay_root}/up";
local workdir="${overlay_root}/work";
local mountdir="${overlay_root}/mount";
mount::unloadroot "$overlay_root";
sudo rm -rf "$overlay_root";
mkdir -p "$overlay_root"/{up,work,mount};
sudo mount -t overlay overlay \
-o lowerdir="${lowerdir}",upperdir="${upperdir}",workdir="${workdir}" "${mountdir}";
# Return mount dir
printf '%s\n' "${mountdir}";
}
declare CONTAINER_IMAGE="${CONTAINER_IMAGE:-"axonasif/dotfiles-testing-full:latest"}"; # From src/dockerfiles/testing-full.Dockerfile
log::info "Running bashbox build --release";
subcommand::build --release;
source "$_target_workdir/utils/common.sh";
local duplicate_workspace_root="$(mount::overlay ws /workspace)";
# local workspace_sources;
# if test -n "${GITPOD_REPO_ROOTS:-}"; then {
# local repo_roots;
# IFS=',' read -ra workspace_sources <<<"$GITPOD_REPO_ROOTS";
# } else {
# workspace_sources=("${_arg_path}");
# } fi
# if test -e /workspace/.gitpod; then {
# workspace_sources+=("/workspace/.gitpod");
# } fi
# log::info "Creating a clone of ${workspace_sources} at $duplicate_workspace_root" && {
# if command::exists rsync; then {
# mkdir -p "$duplicate_workspace_root";
# rsync -ah --info=progress2 --delete "${workspace_sources[@]}" "$duplicate_workspace_root";
# } else {
# rm -rf "$duplicate_workspace_root";
# mkdir -p "$duplicate_workspace_root";
# cp -ra "${workspace_sources[@]}" "$duplicate_workspace_root";
# } fi
# }
local ide_mirror="/tmp/.idem";
if test ! -e "$ide_mirror" && test -e /ide; then {
log::info "Creating /ide mirror";
cp -ra /ide "$ide_mirror";
} fi
## local ide_cmd ide_port;
## ide_cmd="$(ps -p $(pgrep -f 'sh /ide/bin/gitpod-code' | head -n1) -o args --no-headers)";
## ide_port="33000";
## ide_cmd="${ide_cmd//23000/${ide_port}} >/ide/server_log 2>&1";
log::info "Starting a fake Gitpod workspace with headless IDE";
local docker_args=();
docker_args+=(
run
# --rm
--net=host
)
docker_args+=(
# Shared mountpoints
-v "$duplicate_workspace_root:/workspace"
-v "$_arg_path:$HOME/.dotfiles"
)
if is::gitpod; then {
docker_args+=(
# IDE mountpoints
-v "$ide_mirror:/ide"
-v /usr/bin/gp:/usr/bin/gp:ro
# Gitpod specific
-v /.supervisor:/.supervisor
# Required for rclone
--privileged
--device /dev/fuse
# Docker socket
-v /var/run/docker.sock:/var/run/docker.sock
# Add IDE bindir to PATH
)
} fi
# local dotfiles_repos_dir="$HOME/.dotfiles-sh";
# if test -e "$dotfiles_repos_dir"; then {
# docker_args+=(
# -v "$dotfiles_repos_dir:$dotfiles_repos_dir"
# )
# } fi
if is::gitpod; then {
# Pass on local environment variables
declare gitpod_env_vars="${!GITPOD_*}" && {
gitpod_env_vars="${gitpod_env_vars//"GITPOD_TASKS"/}";
}
declare gp_env_vars="${!GP_*}" && {
declare key && for key in GP_PYENV_FAKEROOT GP_PYENV_INIT GP_PYENV_MIRROR; do {
gp_env_vars="${gp_env_vars//"${key}"/}";
} done
}
for key in ${gitpod_env_vars:-} ${gp_env_vars:-}; do {
docker_args+=(-e "${key}");
} done
docker_args+=(
# Fake gitpod tasks for testing
-e GITPOD_TASKS='[{"name":"Test foo","command":"echo This is fooooo; exit 2"},{"name":"Test boo", "command":"echo This is boooo"}]'
# !! Note: the DOTFILES_ env vars could be overwritten by https://gitpod.io/variables even if you set them here.
# Disable ssh:// protocol launch
-e DOTFILES_SPAWN_SSH_PROTO=false
## These options below are also available, see variables.sh for more info
# -e DOTFILES_SHELL=zsh
-e DOTFILES_TMUX=true
# -e DOTFILES_EDITOR=emacs
# The below two are only set conditionally
-e DOTFILES_READ_GITPOD_YML
-e DOTFILES_STRESS_TEST
)
} fi
docker_args+=(
# Container image
-it "$CONTAINER_IMAGE"
)
function startup_command() {
export PATH="$HOME/.nix-profile/bin:/ide/bin/remote-cli:$PATH";
local logfile="$HOME/.dotfiles.log";
# local tail_cmd="less -S -XR +F $logfile";
local tail_cmd="tail -n +0 -F $logfile";
# Load https://gitpod.io/variables into environment
eval "$(gp env -e)";
# Spawn the log pager
$tail_cmd 2>/dev/null & disown;
set +m; # Temporarily disable job control
{ "$HOME/.dotfiles/install.sh" 2>&1; } >"$logfile" 2>&1 & wait;
set -m;
(
until tmux has-session 2>/dev/null; do sleep 1; done;
pkill -9 -f "${tail_cmd//+/\\+}" || :;
tmux new-window -n ".dotfiles.log" "$tail_cmd"\; setw -g mouse on\; set -g visual-activity off;
until test -n "$(tmux list-clients)"; do sleep 1; done;
printf '====== %% %s\n' \
"Run 'tmux detach' to exit from here" \
"Press 'ctrl+c' to exit the log-pager" \
"You can click between tabs/windows in the bottom" >> "$logfile";
if test "${DOTFILES_STRESS_TEST:-}" == true; then {
# tmux select-window -t :1;
sleep 2;
tmux detach-client;
} fi
) & disown;
if test "${DOTFILES_TMUX:-true}" == true; then {
AWAIT_SHIM_PRINT_INDICATOR=true exec tmux attach;
# exec bash -li;
} else {
exec bash -li;
} fi
# Fallback
if test $? != 0; then {
printf '%s\n' "PS1='testing-dots \w \$ '" >> "$HOME/.bashrc";
printf 'INFO: \n\n%s\n\n' "Falling back to debug bash shell";
exec bash -li;
} fi
}
# if is::gitpod; then {
docker_args+=(
# Startup command
/bin/bash -li
)
# } else {
# docker_args+=(
# /bin/bash -li
# )
# } fi
# local confirmed_statfile="/tmp/.confirmed_statfile";
# touch "$confirmed_statfile";
# local confirmed_times="$(( $(<"$confirmed_statfile") + 1 ))";
# if [[ "$confirmed_times" -lt 2 ]]; then {
# printf '\n';
# printf 'INFO: %b\n' "Now this will boot into a simulated Gitpod workspace with shared host resources" \
# "To detach from the tmux session, you can run ${BPURPLE}tmux detach${RC}"
# printf '\n';
# read -r -p ">>> Press Enter/return to continue execution";
# printf '%s\n' "$confirmed_times" > "$confirmed_statfile";
# } fi
# local lckfile="/workspace/.dinit";
# if test -e "$lckfile" && test ! -s "$lckfile"; then {
# printf 'info: %s\n' "Waiting for the '.gitpod.yml:tasks:command' docker-pull to complete ...";
# until test -s "$lckfile"; do {
# sleep 0.5;
# } done
# rm -f "$lckfile";
# } fi
(sleep 2 docker container prune -f >/dev/null 2>&1) & disown;
rm -f /tmp/.{build,install}.lock;
exec docker "${docker_args[@]}" -c "$(printf "%s\n" "$(declare -f startup_command)" "startup_command")";
}