-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbootstrap.sh
532 lines (450 loc) · 15.9 KB
/
bootstrap.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
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
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
#!/bin/sh
# shellcheck disable=SC1091,SC2059,SC3010
# shellcheck source-path=SCRIPTDIR
CURRENT_LOCATION=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)
export CURRENT_LOCATION
export SHARED_DIR="$CURRENT_LOCATION/shared"
export SCRIPTS_DIR="$CURRENT_LOCATION/scripts"
# Colors output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m'
GITHUB="https://github.com"
print_title() {
title="$1"
echo; i=0; while [ "$i" -lt ${#title} ]; do printf "${BLUE}#${NC}"; i=$((i+1)); done; echo
printf "${BLUE}$title${NC}"
echo; i=0; while [ "$i" -lt ${#title} ]; do printf "${BLUE}#${NC}"; i=$((i+1)); done; echo
}
load_envs() {
set -o allexport && \. "$SHARED_DIR/.env" && set +o allexport
\. "$SHARED_DIR/path.sh"
\. "$SHARED_DIR/brew.sh"
}
main() {
# Specify ditribution name of the machine
if type lsb_release >/dev/null 2>&1; then
DISTRO="$(lsb_release -i | cut -f2 | tr '[:lower:]' '[:upper:]')"
else
DISTRO="$(awk -F'=' '/^ID=/ {print toupper($2)}' /etc/*-release | tr -d '"')"
fi
print_title "Start Setup for $DISTRO Machine"
load_envs
# Define package manager
PACKAGER=""
for pm in apt dnf yum pacman; do
if command -v $pm >/dev/null 2>&1; then
PACKAGER="$pm"
fi
done
unset pm
if [ -z "$PACKAGER" ]; then
printf "${RED}Your machine is currently not supported. Exiting...${NC}\n"
exit 1
fi
case "$PACKAGER" in
dnf | yum) \. "$SCRIPTS_DIR/fedora.sh" ;;
apt) \. "$SCRIPTS_DIR/debian.sh" ;;
pacman) \. "$SCRIPTS_DIR/arch.sh" ;;
esac
}
command_exists() {
command -v "$@" >/dev/null 2>&1
}
checkout() {
[ -d "$2" ] || git -c advice.detachedHead=0 clone --branch "$3" --depth 1 "$1" "$2" >/dev/null 2>&1
}
create_dirs() {
# Create XDG directories
print_title 'Create XDG Directories'
load_envs
LOCATIONS="$XDG_CONFIG_HOME $XDG_CACHE_HOME $XDG_DATA_HOME $XDG_STATE_HOME $XDG_BIN_HOME $XDG_RUNTIME_DIR $XDG_PROJECTS_DIR $XDG_CACHE_HOME/backup"
echo "$LOCATIONS" | tr ' ' '\n' | while read -r loc; do
sleep 0.05
if [ ! -d "$loc" ]; then
mkdir -p "$loc"
if [ $? -eq 0 ]; then printf "${GREEN}$loc${NC} created successfully.\n"; fi
else
printf "${YELLOW}$loc${NC} already exists.\n"
fi
done
unset loc
}
eval_brew() {
BREW_LOCATION=""
if [ -f /opt/homebrew/bin/brew ]; then
BREW_LOCATION="/opt/homebrew/bin/brew"
elif [ -f /usr/local/bin/brew ]; then
BREW_LOCATION="/usr/local/bin/brew"
elif [ -f /home/linuxbrew/.linuxbrew/bin/brew ]; then
BREW_LOCATION="/home/linuxbrew/.linuxbrew/bin/brew"
elif [ -f "$HOME/.linuxbrew/bin/brew" ]; then
BREW_LOCATION="$HOME/.linuxbrew/bin/brew"
else
return
fi
eval "$("${BREW_LOCATION}" shellenv)"
unset BREW_LOCATION
}
setup_docker() {
print_title 'Setup Docker & Docker Rootless Mode'
load_envs
cleanup_docker
# shellcheck disable=SC3010
if [[ "$(uname -r)" != *"icrosoft"* ]]; then
if ! command_exists docker; then
printf "${PURPLE}Start installing Docker...${NC}\n"
sudo sh "$SCRIPTS_DIR/docker_engine.sh"
sudo systemctl enable --now docker containerd
sudo usermod -aG docker "$USER"
else
printf "${YELLOW}Docker Engine${NC} already exists. Skipping...\n"
fi
if [ ! -f "$HOME/.config/systemd/user/docker.service" ]; then
printf "${PURPLE}Setup Docker Rootless Mode? (y/N)${NC} " && read -r yn
case $yn in
[yY]*) sh "$SCRIPTS_DIR/docker_rootless.sh" ;;
[nN]* | [qQ]*) echo "Skipped setting up Docker Rootless Mode..." ;;
*)
echo "Invalid choice. Exiting..."
exit 0
;;
esac
else
printf "${GREEN}Docker Rootless Mode${NC} already setup. Exiting...\n"
fi
else
if ! command_exists docker; then
printf "${RED}Docker Desktop not found. Please install Docker Desktop for your Windows machine!${NC}\n"
else
printf "${GREEN}Docker already installed.${NC}\n"
fi
fi
}
setup_homebrew() {
print_title "Setup Homebrew"
load_envs
eval_brew
# Setup Homebrew
if ! command_exists brew; then
NON_INTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew doctor
echo
eval_brew
else
printf "${GREEN}Homebrew already installed.${NC}\n"
fi
brew bundle install --file="$CURRENT_LOCATION/Brewfile" --quiet
}
setup_gitconfig() {
print_title "Setup Git"
# Git name & email
GIT_NAME=$(git config user.name)
GIT_EMAIL=$(git config user.email)
if [ -z "$GIT_NAME" ]; then
GIT_NAME=$(gum input --prompt="▶ Input Git Name: " --prompt.foreground="#cba6f7" --placeholder="Your Name" --placeholder.foreground="#6c7086")
git config --global user.name "$GIT_NAME"
fi
if [ -z "$GIT_EMAIL" ]; then
GIT_EMAIL=$(gum input --prompt="▶ Input Git Email: " --prompt.foreground="#cba6f7" --placeholder="[email protected]" --placeholder.foreground="#6c7086")
git config --global user.email "$GIT_EMAIL"
fi
unset GIT_NAME GIT_EMAIL
# Git Credential Manager setup
# https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-git#git-credential-manager-setup
if grep -i 'icrosoft' /proc/version >/dev/null; then
current_git="$(git --version | cut -d ' ' -f3)"
required_ver="2.36.1"
if [ "$(printf '%s\n' "$required_ver" "$current_git" | sort -V | head -n1)" = "$required_ver" ]; then
if [ "$(printf '%s\n' "2.39.0" "$current_git" | sort -V | head -n1)" = "2.39.0" ]; then
echo "Git Version is greater than or equal v2.39.0."
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe"
else
echo "Git Version is greater than or equal v${required_ver}."
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager.exe"
fi
else
echo "Git Version is less than v${required_ver}."
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager-core.exe"
fi
unset current_git required_ver
fi
# Delta config
if [ -z $(git config include.path | grep "$HOME/.config/delta/themes/catppuccin.gitconfig") ]; then
git config --global include.path "$HOME/.config/delta/themes/catppuccin.gitconfig"
fi
git config --global core.pager delta
git config --global interactive.diffFilter "delta --color-only"
git config --global delta.navigate "true"
git config --global delta.dark "true"
git config --global delta.side-by-side "true"
git config --global delta.hyperlinks "true"
git config --global delta.features "catppuccin-macchiato"
git config --global merge.conflictstyle "zdiff3"
# Gh auth login
if command_exists gh; then
if ! gh auth status; then
printf "${YELLOW}Log into GitHub hosts${NC}\n"
gh auth login
else
printf "${GREEN}Already logged in to GitHub host.${NC}\n"
fi
fi
}
# shellcheck disable=SC2016
stow_dotfiles() {
print_title "Stow Dotfiles"
if ! command_exists stow; then brew install stow --quiet; fi
if ! grep -q '$HOME/dotfiles.sh' "$HOME/.bashrc"; then
{
echo ''
echo '# Get dotfiles directory'
echo 'if [ -f "$HOME/dotfiles.sh" ]; then'
echo ' source "$HOME/dotfiles.sh"'
echo 'fi'
} >>"$HOME/.bashrc"
fi
if ! grep -q '$HOME/.config/bash/bashrc' "$HOME/.bashrc"; then
{
echo ''
echo '# Source custom bashrc'
echo 'if [ -f "$HOME/.config/bash/bashrc" ]; then'
echo ' source "$HOME/.config/bash/bashrc"'
echo 'fi'
} >>"$HOME/.bashrc"
fi
if [ -f "$HOME/.zshenv" ]; then mv "$HOME/.zshenv" "$HOME/.cache/backup/.zshenv.bak"; fi
stow .
sleep 5
}
setup_devtools() {
print_title "Setup Development Tools"
# gum settings
export ALIGN="center"
export BORDER_FOREGROUND="#89b4fa"
export BORDER="rounded"
export FOREGROUND="#cba6f7"
export GUM_CHOOSE_HEADER_FOREGROUND="#f9e2af"
export GUM_SPIN_SPINNER_FOREGROUND="#fab387"
export GUM_SPIN_TITLE_FOREGROUND="#94e2d5"
export PADDING="1 2"
# Dev tools
devtools_choose=$(gum choose --no-limit --header="Choose Dev Tools to setup your local machine:" '1) NVM (Node Version Manager)' '2) GOENV (Go Version Manager)' '3) PYENV (Python Version Manager)' '4) RBENV (Ruby Version Manager)' '5) RUSTUP (Rust Installer Tool)' '6) SDKMAN (Software Development Kit Manager)')
devtools=$(echo "$devtools_choose" | cut -f2 -d ' ' | tr '[:upper:]' '[:lower:]')
# Setup NVM
setup_nvm() {
echo
gum style "Setup NVM (Node Version Manager)"
load_envs
if ! command_exists nvm || ! command_exists node || ! command_exists npm; then
export NVM_DIR="$HOME/.local/share/nvm"
if [ -d "$NVM_DIR" ]; then rm -rf "$NVM_DIR"; fi
mkdir -p "$NVM_DIR"
curl --silent -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
gum confirm "Use LTS (Y) or latest (n) node?" && nvm install --lts || nvm install node
nvm install-latest-npm
npm install --global pnpm@latest
fi
PATH="$(npm config get prefix)/bin:$PNPM_HOME:$PATH"
export PATH
if command_exists pnpm; then
npm_c='pnpm add -g'
npm_l='pnpm ls -g'
else
npm_c='npm install -g'
npm_l='npm ls -g'
fi
for pkg in bun commitizen cz-git; do
if ! $npm_l | grep -q "$pkg"; then
$npm_c $pkg
fi
done
unset npm_c npm_l
sleep 5
}
# Setup GOENV
setup_goenv() {
echo
gum style "Setup GOENV (Go Version Manager)"
load_envs
if ! command_exists goenv; then
export GOENV_ROOT="$HOME/.local/share/goenv"
if [ -d "$GOENV_ROOT" ]; then rm -rf "$GOENV_ROOT"; fi
git clone --quiet "$GITHUB/go-nv/goenv.git" "$GOENV_ROOT"
load_envs
# Initialize goenv
eval "$(goenv init -)"
fi
if command_exists goenv && ! command_exists go; then
go_version=$(goenv install --list | grep '^ 1.' | sed 's/[[:space:]]//g' | gum choose --height=15 --header="Choose a Go version to install:")
goenv install "$go_version"
goenv global "$go_version"
ln -sf "$GOENV_ROOT/versions/$go_version" "$GOENV_ROOT/versions/global"
goenv rehash
fi
sleep 5
}
# Setup PYENV
setup_pyenv() {
echo
gum style "Setup PYENV (Python Version Manager)"
load_envs
setup_python_deps
if [[ "$(command -v pyenv)" == */pyenv-win/* && "$(uname -r)" == *icrosoft* ]]; then
PYENV_AVAIL=0
elif ! command_exists pyenv >/dev/null 2>&1; then
PYENV_AVAIL=0
else
PYENV_AVAIL=1
fi
if [[ $PYENV_AVAIL -eq 0 ]]; then
export PYENV_ROOT="$HOME/.local/share/pyenv"
if [ -d "$PYENV_ROOT" ]; then rm -rf "$PYENV_ROOT"; fi
checkout "${GITHUB}/pyenv/pyenv.git" "$PYENV_ROOT" "master"
pyenv_plugins="pyenv-doctor pyenv-update pyenv-virtualenv pyenv-ccache pyenv-pip-migrate"
echo "$pyenv_plugins" | tr ' ' '\n' | while read -r plugin; do
if [ ! -d "$PYENV_ROOT/plugins/$plugin" ]; then
checkout "${GITHUB}/pyenv/$plugin.git" "$PYENV_ROOT/plugins/$plugin" "master"
fi
done
cd "$PYENV_ROOT" && src/configure && make -C src >/dev/null
cd "$CURRENT_LOCATION" || exit 1
{
"$PYENV_ROOT/bin/pyenv" init
"$PYENV_ROOT/bin/pyenv" virtualenv-init
} >&2
load_envs
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
python_version=$(pyenv install --list | grep '^ 3.' | sed 's/[[:space:]]//g' | gum choose --height=15 --header="Choose a Python Version to install:")
pyenv install "$python_version"
pyenv global "$python_version"
ln -sf "$PYENV_ROOT/versions/$python_version" "$PYENV_ROOT/versions/global"
pyenv rehash
sleep 5
fi
gum confirm "Install Python Tools for your machine? (pipx|pipenv|pdm|poetry|rye|uv)" && \. "$SCRIPTS_DIR/python_tools.sh" || echo "Skip installing python tools."
sleep 5
}
# setup RBENV
setup_rbenv() {
echo
gum style "Setup RBENV (Ruby Version Manager)"
load_envs
setup_ruby_deps
if ! command_exists rbenv; then
export RBENV_ROOT="$HOME/.local/share/rbenv"
if [ -d "$RBENV_ROOT" ]; then rm -rf "$RBENV_ROOT"; fi
checkout "${GITHUB}/rbenv/rbenv.git" "$RBENV_ROOT" "master"
rbenv_plugin="rbenv/ruby-build rbenv/rbenv-default-gems jf/rbenv-gemset rkh/rbenv-update rkh/rbenv-use rkh/rbenv-whatis yyuu/rbenv-ccache"
echo "$rbenv_plugin" | tr ' ' '\n' | while read -r plugin; do
dir=$(basename "$plugin")
if [ ! -d "$RBENV_ROOT/plugins/$dir" ]; then
checkout "${GITHUB}/$plugin.git" "${RBENV_ROOT}/plugins/$dir" "master"
fi
done
"$RBENV_ROOT/bin/rbenv" init
fi
eval "$("$RBENV_ROOT/bin/rbenv" init -)"
if command_exists rbenv && rbenv version | grep -q 'system'; then
ruby_version=$(rbenv install --list | gum choose --header="Choose A Ruby Version to install:")
rbenv install "$ruby_version"
rbenv global "$ruby_version"
ln -sf "$RBENV_ROOT/versions/$ruby_version" "$RBENV_ROOT/versions/global"
rbenv rehash
fi
sleep 5
}
# setup RUSTUP
setup_rustup() {
echo
gum style "Setup RUSTUP (Rust Installer Tool)"
load_envs
if [ -f "$CARGO_HOME/env" ]; then
\. "$CARGO_HOME/env"
elif ! command_exists rustup || ! command_exists cargo || [[ "$(which cargo)" != *"$CARGO_HOME"* ]]; then
export RUSTUP_HOME="$HOME/.local/share/rustup"
export CARGO_HOME="$HOME/.local/share/cargo"
if [ -d "$RUSTUP_HOME" ]; then rm -rf "$RUSTUP_HOME"; fi
if [ -d "$CARGO_HOME" ]; then rm -rf "$CARGO_HOME"; fi
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --quiet --no-modify-path
\. "$CARGO_HOME/env"
fi
if command_exists cargo && ! command_exists cargo-binstall; then
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
fi
if command_exists cargo && command_exists cargo-binstall; then
for pkg in cargo-update cargo-cache cargo-run-bin; do
if ! cargo install --list | grep -q "$pkg"; then
cargo binstall --no-confirm "$pkg"
fi
done
fi
sleep 5
}
setup_sdkman() {
echo
gum style "Setup SDKMAN! (Software Development Kit Manager)"
load_envs
export SDKMAN_DIR="$HOME/.local/share/sdkman"
if [ ! -f "$SDKMAN_DIR/bin/sdkman-init.sh" ] || ! command_exists sdk; then
curl -s "https://get.sdkman.io?rcupdate=false" | bash
\. "$SDKMAN_DIR/bin/sdkman-init.sh"
elif [ -f "$SDKMAN_DIR/bin/sdkman-init.sh" ] && ! command_exists sdk; then
\. "$SDKMAN_DIR/bin/sdkman-init.sh"
fi
if command_exists sdk && ! command_exists java; then sdk install java; fi
sleep 5
}
if [[ " ${devtools[*]} " =~ [[:space:]]nvm[[:space:]] ]]; then setup_nvm; fi
if [[ " ${devtools[*]} " =~ [[:space:]]goenv[[:space:]] ]]; then setup_goenv; fi
if [[ " ${devtools[*]} " =~ [[:space:]]pyenv[[:space:]] ]]; then setup_pyenv; fi
if [[ " ${devtools[*]} " =~ [[:space:]]rbenv[[:space:]] ]]; then setup_rbenv; fi
if [[ " ${devtools[*]} " =~ [[:space:]]rustup[[:space:]] ]]; then setup_rustup; fi
if [[ " ${devtools[*]} " =~ [[:space:]]sdkman[[:space:]] ]]; then setup_sdkman; fi
}
setup_bat() {
# Bat theme
if command_exists bat; then
gum spin --title="Cleaning bat cache..." -- bat cache --clear
gum spin --title="Building bat theme..." -- bat cache --build
fi
}
setup_yazi() {
# Yazi plugins
if command_exists yazi && command_exists ya; then
gum spin --title="Installing yazi plugins..." -- ya pack -i
gum spin --title="Upgrading yazi plugins..." -- ya pack -u
fi
}
create_dirs
main
setup_docker
setup_homebrew
setup_gitconfig
stow_dotfiles
setup_devtools
setup_bat
setup_yazi
unset CURRENT_LOCATION SCRIPTS_DIR SHARED_DIR
echo; echo
echo "$(tput bold)$(tput setaf 3)NOTES:$(tput sgr0)"
echo "To suppress new file creation of $HOME/.sudo_as_admin_successful"
echo "In your terminal, type 'sudo visudo' and add the following to the file:"
echo
echo "Defaults !admin_flag"
echo
# END SCRIPT
# --------------------------------------------------------------------------------
echo
echo "$(tput setaf 8)--------------------------------------------------------------------------$(tput sgr0)"
echo "$(tput setaf 7)For more information, please visit: $(tput setaf 4)https://github.com/jacquindev/dotfiles"
echo "$(tput setaf 7)- Submit an issue via: $(tput setaf 4)https://github.com/jacquindev/dotfiles/issues/new"
echo "$(tput setaf 7)- Contact me via email: $(tput setaf 4)[email protected]"
echo; echo