Skip to content

Commit 8e3cd14

Browse files
committed
style: 🎨 prettifying the scripts
1 parent 1eb0a23 commit 8e3cd14

2 files changed

Lines changed: 442 additions & 214 deletions

File tree

bootstrap.sh

Lines changed: 210 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,264 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4-
# Colored output helpers
5-
info() { printf "\033[1;34m[INFO]\033[0m %s\n" "$*"; }
6-
success() { printf "\033[1;32m[SUCCESS]\033[0m %s\n" "$*"; }
7-
warn() { printf "\033[1;33m[WARN]\033[0m %s\n" "$*"; }
8-
error() { printf "\033[1;31m[ERROR]\033[0m %s\n" "$*"; }
9-
10-
# 1. Create base directories
11-
info "Creating base directories..."
4+
# Color codes
5+
RED='\033[0;31m'
6+
GREEN='\033[0;32m'
7+
YELLOW='\033[1;33m'
8+
BLUE='\033[0;34m'
9+
CYAN='\033[0;36m'
10+
MAGENTA='\033[0;35m'
11+
BOLD='\033[1m'
12+
UNDERLINE='\033[4m'
13+
RESET='\033[0m'
14+
15+
# Progress tracking
16+
TOTAL_STEPS=7
17+
CURRENT_STEP=0
18+
19+
# Colored output helpers with emojis
20+
info() {
21+
printf "${BLUE}ℹ️ [INFO]${RESET} %s\n" "$*"
22+
}
23+
success() {
24+
printf "${GREEN}✅ [SUCCESS]${RESET} %s\n" "$*"
25+
}
26+
warn() {
27+
printf "${YELLOW}⚠️ [WARN]${RESET} %s\n" "$*"
28+
}
29+
error() {
30+
printf "${RED}❌ [ERROR]${RESET} %s\n" "$*" >&2
31+
}
32+
33+
# Step counter
34+
step() {
35+
((CURRENT_STEP++))
36+
printf "\n${CYAN}${BOLD}[Step %d/%d]${RESET} ${BOLD}%s${RESET}\n" "$CURRENT_STEP" "$TOTAL_STEPS" "$*"
37+
}
38+
39+
# Section header with border
40+
section() {
41+
local text="$1"
42+
local width=60
43+
printf "\n${MAGENTA}"
44+
printf '═%.0s' $(seq 1 $width)
45+
printf "\n %s\n" "$text"
46+
printf '═%.0s' $(seq 1 $width)
47+
printf "${RESET}\n"
48+
}
49+
50+
# Progress bar
51+
progress_bar() {
52+
local current=$1
53+
local total=$2
54+
local width=40
55+
local percentage=$((current * 100 / total))
56+
local filled=$((width * current / total))
57+
local empty=$((width - filled))
58+
59+
printf "\r${CYAN}["
60+
printf '█%.0s' $(seq 1 $filled)
61+
printf '░%.0s' $(seq 1 $empty)
62+
printf "]${RESET} ${percentage}%%"
63+
64+
if [ "$current" -eq "$total" ]; then
65+
printf "\n"
66+
fi
67+
}
68+
69+
# Banner
70+
print_banner() {
71+
printf "\n${CYAN}${BOLD}"
72+
cat <<"EOF"
73+
╔══════════════════════════════════════════════════════════╗
74+
║ ║
75+
║ 🚀 BOOTSTRAP SCRIPT FOR MACOS DOTFILES 🚀 ║
76+
║ ║
77+
║ Setting up your development ║
78+
║ environment... ║
79+
║ ║
80+
╚══════════════════════════════════════════════════════════╝
81+
EOF
82+
printf "${RESET}\n"
83+
}
84+
85+
# Summary tracking
86+
declare -a SUMMARY_ITEMS=()
87+
add_summary() {
88+
SUMMARY_ITEMS+=("$1")
89+
}
90+
91+
# Print summary at the end
92+
print_summary() {
93+
section "📊 INSTALLATION SUMMARY"
94+
printf "\n${BOLD}Completed actions:${RESET}\n\n"
95+
for item in "${SUMMARY_ITEMS[@]}"; do
96+
printf " ${GREEN}${RESET} %s\n" "$item"
97+
done
98+
printf "\n${GREEN}${BOLD}🎉 Bootstrap completed successfully!${RESET}\n"
99+
printf "${CYAN}Next: Run ${UNDERLINE}setup.sh${RESET}${CYAN} to complete installation${RESET}\n\n"
100+
}
101+
102+
# Start
103+
print_banner
104+
105+
step "Creating base directories"
106+
info "Creating ${BOLD}~/code${RESET} and ${BOLD}~/.ssh${RESET}..."
12107
mkdir -p "$HOME/code" "$HOME/.ssh"
13108
chmod 700 "$HOME/.ssh"
14-
success "Base directories created."
109+
success "Base directories created"
110+
add_summary "Created base directories (~/code, ~/.ssh)"
15111

16-
# 2. Install Xcode command line tools (needed for Git)
17-
info "Installing Xcode command line tools..."
112+
step "Installing Xcode command line tools"
18113
if ! xcode-select -p &>/dev/null; then
19-
xcode-select --install
114+
info "Installing Xcode CLI tools (this may take a while)..."
115+
xcode-select --install
116+
success "Xcode CLI tools installed"
117+
add_summary "Installed Xcode command line tools"
20118
else
21-
success "Xcode CLI already installed."
119+
success "Xcode CLI already installed"
120+
add_summary "Xcode command line tools (already present)"
22121
fi
23122

24-
# 3. Install Homebrew
25-
info "Checking Homebrew..."
123+
step "Installing Homebrew"
26124
ARCH=$(uname -m)
125+
info "Detected architecture: ${BOLD}$ARCH${RESET}"
27126
if ! command -v brew >/dev/null 2>&1; then
28-
info "Installing Homebrew..."
29-
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
30-
# Add Homebrew to PATH based on architecture
31-
if [ "$ARCH" = "arm64" ]; then
32-
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >>"$HOME/.zprofile"
33-
eval "$(/opt/homebrew/bin/brew shellenv)"
34-
else
35-
echo 'eval "$(/usr/local/bin/brew shellenv)"' >>"$HOME/.zprofile"
36-
eval "$(/usr/local/bin/brew shellenv)"
37-
fi
38-
success "Homebrew installed."
127+
info "Installing Homebrew..."
128+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
129+
# Add Homebrew to PATH based on architecture
130+
if [ "$ARCH" = "arm64" ]; then
131+
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >>"$HOME/.zprofile"
132+
eval "$(/opt/homebrew/bin/brew shellenv)"
133+
else
134+
echo 'eval "$(/usr/local/bin/brew shellenv)"' >>"$HOME/.zprofile"
135+
eval "$(/usr/local/bin/brew shellenv)"
136+
fi
137+
success "Homebrew installed"
138+
add_summary "Installed Homebrew package manager"
39139
else
40-
success "Homebrew already installed."
140+
success "Homebrew already installed"
141+
add_summary "Homebrew (already present)"
41142
fi
42143

43-
# 4. Install Git if missing
44-
info "Ensuring Git is installed..."
144+
step "Installing Git"
45145
if ! command -v git >/dev/null 2>&1; then
46-
brew install git
47-
success "Git installed."
146+
info "Installing Git via Homebrew..."
147+
brew install git
148+
success "Git installed"
149+
add_summary "Installed Git version control"
48150
else
49-
success "Git already installed."
151+
success "Git already installed"
152+
add_summary "Git (already present)"
50153
fi
51154

52-
# 5. Fetch SSH keys from iCloud
155+
step "Setting up SSH keys from iCloud"
53156
# Try lowercase first (matches setup.sh), fallback to uppercase
54157
SSH_REMOTE_LOWER="$HOME/Library/Mobile Documents/com~apple~CloudDocs/Documents/ssh"
55158
SSH_REMOTE_UPPER="$HOME/Library/Mobile Documents/com~apple~CloudDocs/Documents/SSH"
56159
if [ -d "$SSH_REMOTE_LOWER" ]; then
57-
SSH_REMOTE="$SSH_REMOTE_LOWER"
160+
SSH_REMOTE="$SSH_REMOTE_LOWER"
58161
elif [ -d "$SSH_REMOTE_UPPER" ]; then
59-
SSH_REMOTE="$SSH_REMOTE_UPPER"
162+
SSH_REMOTE="$SSH_REMOTE_UPPER"
60163
else
61-
SSH_REMOTE=""
164+
SSH_REMOTE=""
62165
fi
63166

64167
SSH_DEST="$HOME/.ssh"
65168
if [ -n "$SSH_REMOTE" ] && [ -d "$SSH_REMOTE" ]; then
66-
info "Copying SSH keys from iCloud..."
67-
# Copy files, forcing overwrite of existing read-only files
68-
for key_file in "$SSH_REMOTE"/*; do
69-
if [ -f "$key_file" ]; then
70-
cp -f "$key_file" "$SSH_DEST/"
71-
fi
72-
done
73-
# Set proper permissions on private keys (600) and public keys (644)
74-
find "$SSH_DEST" -maxdepth 1 -type f ! -name "*.pub" -exec chmod 600 {} \;
75-
find "$SSH_DEST" -maxdepth 1 -type f -name "*.pub" -exec chmod 644 {} \;
76-
# Ensure ownership is correct
77-
chown -R "$(id -un):$(id -gn)" "$SSH_DEST"
78-
success "SSH keys copied to $SSH_DEST."
169+
info "Copying SSH keys from ${BOLD}iCloud${RESET}..."
170+
# Count files for progress bar
171+
total_keys=$(find "$SSH_REMOTE" -maxdepth 1 -type f | wc -l | tr -d ' ')
172+
current_key=0
173+
174+
# Copy files, forcing overwrite of existing read-only files
175+
for key_file in "$SSH_REMOTE"/*; do
176+
if [ -f "$key_file" ]; then
177+
cp -f "$key_file" "$SSH_DEST/"
178+
((current_key++))
179+
progress_bar $current_key $total_keys
180+
fi
181+
done
182+
183+
# Set proper permissions on private keys (600) and public keys (644)
184+
find "$SSH_DEST" -maxdepth 1 -type f ! -name "*.pub" -exec chmod 600 {} \;
185+
find "$SSH_DEST" -maxdepth 1 -type f -name "*.pub" -exec chmod 644 {} \;
186+
# Ensure ownership is correct
187+
chown -R "$(id -un):$(id -gn)" "$SSH_DEST"
188+
success "SSH keys copied to ${BOLD}$SSH_DEST${RESET}"
189+
add_summary "Copied SSH keys from iCloud ($current_key files)"
79190
else
80-
warn "No SSH keys found at $SSH_REMOTE. Please copy manually."
191+
warn "No SSH keys found at iCloud location"
192+
warn "Please copy SSH keys manually to ${BOLD}~/.ssh${RESET}"
193+
add_summary "SSH keys (manual setup required)"
81194
fi
82195

83-
# 5b. Create minimal SSH config for keychain persistence (will be replaced by full config in setup.sh)
196+
# Create minimal SSH config for keychain persistence (will be replaced by full config in setup.sh)
84197
if [ ! -f "$SSH_DEST/config" ]; then
85-
info "Creating minimal SSH config for keychain persistence..."
86-
cat >"$SSH_DEST/config" <<'EOF'
198+
info "Creating minimal SSH config for keychain persistence..."
199+
cat >"$SSH_DEST/config" <<'EOF'
87200
Host *
88201
AddKeysToAgent yes
89202
UseKeychain yes
90203
EOF
91-
chmod 600 "$SSH_DEST/config"
92-
success "Minimal SSH config created."
204+
chmod 600 "$SSH_DEST/config"
205+
success "Minimal SSH config created"
93206
fi
94207

95-
# 6. Add keys to ssh-agent and keychain
208+
# Add keys to ssh-agent and keychain
96209
info "Loading SSH keys into ssh-agent..."
97210
eval "$(ssh-agent -s)"
211+
keys_added=0
98212
for key in "$SSH_DEST"/*; do
99-
# Only add private keys (files that are not .pub, not config, and are regular files)
100-
if [ -f "$key" ] && [[ "$key" != *.pub ]] && [[ "$(basename "$key")" != "config" ]] && [[ "$(basename "$key")" != "known_hosts"* ]]; then
101-
# Use --apple-use-keychain on macOS 12.2+ for keychain integration
102-
if ssh-add --apple-use-keychain "$key" 2>/dev/null || ssh-add -K "$key" 2>/dev/null || ssh-add "$key" 2>/dev/null; then
103-
: # Key added successfully
104-
else
105-
warn "Failed to add key: $(basename "$key")"
106-
fi
107-
fi
213+
# Only add private keys (files that are not .pub, not config, and are regular files)
214+
if [ -f "$key" ] && [[ "$key" != *.pub ]] && [[ "$(basename "$key")" != "config" ]] && [[ "$(basename "$key")" != "known_hosts"* ]]; then
215+
# Use --apple-use-keychain on macOS 12.2+ for keychain integration
216+
if ssh-add --apple-use-keychain "$key" 2>/dev/null || ssh-add -K "$key" 2>/dev/null || ssh-add "$key" 2>/dev/null; then
217+
((keys_added++))
218+
else
219+
warn "Failed to add key: $(basename "$key")"
220+
fi
221+
fi
108222
done
109-
success "SSH keys loaded into ssh-agent and keychain."
223+
success "SSH keys loaded into ssh-agent and keychain ($keys_added keys)"
110224

111-
# 7. Clone dotfiles repo
225+
step "Cloning dotfiles repository"
112226
DOTFILES_DIR="$HOME/code/$USER/dotfiles"
113227
if [ ! -d "$DOTFILES_DIR" ]; then
114-
info "Cloning dotfiles repository..."
115-
if git clone git@github.com:assafdori/dotfiles.git "$DOTFILES_DIR"; then
116-
success "Dotfiles cloned to $DOTFILES_DIR."
117-
else
118-
error "Failed to clone dotfiles repository. Please check your SSH keys and try again."
119-
exit 1
120-
fi
228+
info "Cloning dotfiles from ${BOLD}github.com/assafdori/dotfiles${RESET}..."
229+
if git clone git@github.com:assafdori/dotfiles.git "$DOTFILES_DIR"; then
230+
success "Dotfiles cloned to ${BOLD}$DOTFILES_DIR${RESET}"
231+
add_summary "Cloned dotfiles repository"
232+
else
233+
error "Failed to clone dotfiles repository"
234+
error "Please check your SSH keys and try again"
235+
exit 1
236+
fi
121237
else
122-
warn "Dotfiles repo already exists at $DOTFILES_DIR."
123-
# Check if we can access the repo
124-
if [ -d "$DOTFILES_DIR/.git" ]; then
125-
info "Verifying repository access..."
126-
if git -C "$DOTFILES_DIR" remote get-url origin &>/dev/null; then
127-
success "Repository is accessible."
128-
else
129-
warn "Repository exists but may not be properly configured."
130-
fi
131-
fi
238+
warn "Dotfiles repo already exists at ${BOLD}$DOTFILES_DIR${RESET}"
239+
# Check if we can access the repo
240+
if [ -d "$DOTFILES_DIR/.git" ]; then
241+
info "Verifying repository access..."
242+
if git -C "$DOTFILES_DIR" remote get-url origin &>/dev/null; then
243+
success "Repository is accessible"
244+
add_summary "Dotfiles repository (already present)"
245+
else
246+
warn "Repository exists but may not be properly configured"
247+
fi
248+
fi
132249
fi
133250

134-
info "Bootstrap complete. Running main Mac setup script..."
135-
sleep 1
251+
# Print summary
252+
print_summary
136253

137254
# Run setup.sh if it exists
255+
section "🚀 LAUNCHING MAIN SETUP"
138256
if [ -f "$DOTFILES_DIR/setup.sh" ]; then
139-
info "Starting dotfiles installation..."
140-
# Forward stdin/stdout/stderr properly
141-
bash "$DOTFILES_DIR/setup.sh" </dev/tty
257+
info "Starting dotfiles installation..."
258+
sleep 2
259+
# Forward stdin/stdout/stderr properly
260+
bash "$DOTFILES_DIR/setup.sh" </dev/tty
142261
else
143-
warn "setup.sh not found. Please run it manually from $DOTFILES_DIR"
262+
warn "setup.sh not found"
263+
warn "Please run it manually from ${BOLD}$DOTFILES_DIR${RESET}"
144264
fi

0 commit comments

Comments
 (0)