dartokloning ревизий этого фрагмента . К ревизии
1 file changed, 204 insertions, 128 deletions
sync-zshrc-all.sh
| @@ -1,173 +1,249 @@ | |||
| 1 | - | #!/usr/bin/env bash | |
| 1 | + | #!/bin/bash | |
| 2 | 2 | # | |
| 3 | - | # sync-zshrc-all.sh - macOS Tahoe / Apple Silicon | |
| 3 | + | # sync-zshrc-all.sh | |
| 4 | 4 | # | |
| 5 | - | # Menyinkronkan: | |
| 6 | - | # 1. template .zshrc | |
| 7 | - | # 2. /usr/local/etc/shell-prompt.zsh | |
| 8 | - | # 3. config Fastfetch per-user | |
| 9 | - | # 4. dependency Homebrew: vivid, fastfetch, coreutils, tree | |
| 5 | + | # Sinkronisasi konfigurasi Zsh GLOBAL untuk macOS dari Gist. | |
| 10 | 6 | # | |
| 11 | - | # Jalankan sebagai USER ADMIN biasa, BUKAN dengan "sudo bash ...". | |
| 12 | - | # Script akan meminta sudo hanya ketika diperlukan. | |
| 7 | + | # Remote Gist: | |
| 8 | + | # .zshrc -> /usr/local/etc/global-zshrc.zsh | |
| 9 | + | # shell-prompt.zsh -> /usr/local/etc/shell-prompt.zsh | |
| 10 | + | # config.jsonc -> /usr/local/etc/fastfetch/config.jsonc | |
| 13 | 11 | # | |
| 14 | - | # Default: mengambil tiga file dari direktori yang sama dengan script ini. | |
| 15 | - | # Untuk mode remote/Gist, isi URL melalui environment variable: | |
| 16 | - | # ZSHRC_URL=https://... PROMPT_URL=https://... FASTFETCH_CONFIG_URL=https://... ./sync-zshrc-all.sh | |
| 12 | + | # /etc/zshrc TIDAK ditimpa. | |
| 13 | + | # Skrip hanya menambahkan managed block agar /etc/zshrc me-load: | |
| 14 | + | # /usr/local/etc/global-zshrc.zsh | |
| 15 | + | # | |
| 16 | + | # Dengan demikian konfigurasi berlaku untuk SEMUA user yang menggunakan Zsh. | |
| 17 | + | # | |
| 18 | + | # Jalankan sebagai user administrator biasa: | |
| 19 | + | # | |
| 20 | + | # chmod +x sync-zshrc-all.sh | |
| 21 | + | # ./sync-zshrc-all.sh | |
| 22 | + | # | |
| 23 | + | # Jangan jalankan dengan: | |
| 24 | + | # | |
| 25 | + | # sudo ./sync-zshrc-all.sh | |
| 26 | + | # | |
| 27 | + | # Skrip akan meminta sudo sendiri saat diperlukan. | |
| 17 | 28 | ||
| 18 | 29 | set -euo pipefail | |
| 19 | 30 | ||
| 31 | + | # --------------------------------------------------------------------------- | |
| 32 | + | # Remote Gist | |
| 33 | + | # --------------------------------------------------------------------------- | |
| 34 | + | ||
| 35 | + | ZSHRC_URL="https://gist.darto.id/dartokloning/6aac33d413ae4bfea0c26665276aa7f0/download/HEAD/.zshrc" | |
| 36 | + | PROMPT_URL="https://gist.darto.id/dartokloning/8e9865f5d4be4166912208f3ef2d4cf2/download/HEAD/shell-prompt.zsh" | |
| 37 | + | FASTFETCH_CONFIG_URL="https://gist.darto.id/dartokloning/09cffd6151554d50a5cae1d22674f134/download/HEAD/config.jsonc" | |
| 38 | + | ||
| 39 | + | # --------------------------------------------------------------------------- | |
| 40 | + | # Global destination | |
| 41 | + | # --------------------------------------------------------------------------- | |
| 42 | + | ||
| 43 | + | GLOBAL_ZSHRC="/usr/local/etc/global-zshrc.zsh" | |
| 44 | + | PROMPT_FILE="/usr/local/etc/shell-prompt.zsh" | |
| 45 | + | FASTFETCH_CONFIG_FILE="/usr/local/etc/fastfetch/config.jsonc" | |
| 46 | + | SYSTEM_ZSHRC="/etc/zshrc" | |
| 47 | + | ||
| 48 | + | MANAGED_BEGIN="# >>> dartokloning global zsh >>>" | |
| 49 | + | MANAGED_END="# <<< dartokloning global zsh <<<" | |
| 50 | + | ||
| 51 | + | # --------------------------------------------------------------------------- | |
| 52 | + | # Basic validation | |
| 53 | + | # --------------------------------------------------------------------------- | |
| 54 | + | ||
| 20 | 55 | if [[ "$(uname -s)" != "Darwin" ]]; then | |
| 21 | - | echo "Error: script ini hanya untuk macOS." >&2 | |
| 56 | + | echo "Error: skrip ini khusus untuk macOS." >&2 | |
| 22 | 57 | exit 1 | |
| 23 | 58 | fi | |
| 24 | 59 | ||
| 25 | 60 | if [[ "$(id -u)" -eq 0 ]]; then | |
| 26 | - | echo "Jangan jalankan script ini sebagai root." >&2 | |
| 27 | - | echo "Jalankan sebagai user admin biasa: ./sync-zshrc-all.sh" >&2 | |
| 61 | + | echo "Error: jangan jalankan skrip ini menggunakan sudo/root." >&2 | |
| 62 | + | echo "Jalankan sebagai user administrator biasa:" >&2 | |
| 63 | + | echo " ./sync-zshrc-all.sh" >&2 | |
| 28 | 64 | exit 1 | |
| 29 | 65 | fi | |
| 30 | 66 | ||
| 31 | - | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| 32 | - | LOCAL_ZSHRC="$SCRIPT_DIR/zshrc" | |
| 33 | - | LOCAL_PROMPT="$SCRIPT_DIR/shell-prompt.zsh" | |
| 34 | - | LOCAL_FASTFETCH="$SCRIPT_DIR/config.jsonc" | |
| 35 | - | ||
| 36 | - | ZSHRC_URL="${ZSHRC_URL:-}" | |
| 37 | - | PROMPT_URL="${PROMPT_URL:-}" | |
| 38 | - | FASTFETCH_CONFIG_URL="${FASTFETCH_CONFIG_URL:-}" | |
| 39 | - | ||
| 40 | - | GLOBAL_ZSHRC_TEMPLATE="/usr/local/etc/zshrc-template" | |
| 41 | - | PROMPT_FILE="/usr/local/etc/shell-prompt.zsh" | |
| 67 | + | if ! command -v curl >/dev/null 2>&1; then | |
| 68 | + | echo "Error: curl tidak ditemukan." >&2 | |
| 69 | + | exit 1 | |
| 70 | + | fi | |
| 42 | 71 | ||
| 43 | 72 | TMP_DIR="$(mktemp -d)" | |
| 44 | 73 | trap 'rm -rf "$TMP_DIR"' EXIT | |
| 45 | 74 | ||
| 46 | - | need_cmd() { | |
| 47 | - | command -v "$1" >/dev/null 2>&1 | |
| 75 | + | # --------------------------------------------------------------------------- | |
| 76 | + | # Helper functions | |
| 77 | + | # --------------------------------------------------------------------------- | |
| 78 | + | ||
| 79 | + | fetch() { | |
| 80 | + | local url="$1" | |
| 81 | + | local dest="$2" | |
| 82 | + | ||
| 83 | + | if ! curl -fL --silent --show-error "$url" -o "$dest"; then | |
| 84 | + | echo "Error: gagal download:" >&2 | |
| 85 | + | echo " $url" >&2 | |
| 86 | + | exit 1 | |
| 87 | + | fi | |
| 88 | + | ||
| 89 | + | if [[ ! -s "$dest" ]]; then | |
| 90 | + | echo "Error: file hasil download kosong:" >&2 | |
| 91 | + | echo " $url" >&2 | |
| 92 | + | exit 1 | |
| 93 | + | fi | |
| 48 | 94 | } | |
| 49 | 95 | ||
| 50 | - | fetch_or_local() { | |
| 51 | - | # fetch_or_local URL LOCAL_FILE DEST_TMP | |
| 52 | - | local url="$1" local_file="$2" dest="$3" | |
| 53 | - | if [[ -n "$url" ]]; then | |
| 54 | - | if ! curl -fsSL "$url" -o "$dest"; then | |
| 55 | - | echo "Error: gagal download $url" >&2 | |
| 56 | - | exit 1 | |
| 57 | - | fi | |
| 58 | - | else | |
| 59 | - | if [[ ! -f "$local_file" ]]; then | |
| 60 | - | echo "Error: file lokal tidak ditemukan: $local_file" >&2 | |
| 61 | - | exit 1 | |
| 62 | - | fi | |
| 63 | - | cp "$local_file" "$dest" | |
| 96 | + | sync_global_file() { | |
| 97 | + | # sync_global_file URL DEST LABEL | |
| 98 | + | local url="$1" | |
| 99 | + | local dest="$2" | |
| 100 | + | local label="$3" | |
| 101 | + | local tmp="$TMP_DIR/$(basename "$dest").$$" | |
| 102 | + | ||
| 103 | + | fetch "$url" "$tmp" | |
| 104 | + | ||
| 105 | + | if sudo test -f "$dest" && sudo cmp -s "$tmp" "$dest"; then | |
| 106 | + | echo " -> $label sudah sama dengan Gist, skip." | |
| 107 | + | return 0 | |
| 108 | + | fi | |
| 109 | + | ||
| 110 | + | sudo mkdir -p "$(dirname "$dest")" | |
| 111 | + | ||
| 112 | + | # Backup hanya sekali, agar file sebelum pertama kali dikelola tetap tersimpan. | |
| 113 | + | if sudo test -f "$dest" && ! sudo test -f "${dest}.original"; then | |
| 114 | + | sudo cp -p "$dest" "${dest}.original" | |
| 115 | + | echo " -> Backup awal: ${dest}.original" | |
| 64 | 116 | fi | |
| 117 | + | ||
| 118 | + | sudo install -o root -g wheel -m 0644 "$tmp" "$dest" | |
| 119 | + | echo " -> $label diperbarui." | |
| 65 | 120 | } | |
| 66 | 121 | ||
| 67 | - | sync_root_file() { | |
| 68 | - | # sync_root_file SOURCE DEST LABEL MODE | |
| 69 | - | local src="$1" dest="$2" label="$3" mode="$4" | |
| 70 | - | if [[ ! -f "$dest" ]] || ! cmp -s "$src" "$dest"; then | |
| 71 | - | sudo mkdir -p "$(dirname "$dest")" | |
| 72 | - | sudo cp "$src" "$dest" | |
| 73 | - | sudo chown root:wheel "$dest" | |
| 74 | - | sudo chmod "$mode" "$dest" | |
| 75 | - | echo " -> $label diperbarui." | |
| 122 | + | ensure_system_zshrc_loader() { | |
| 123 | + | local tmp="$TMP_DIR/zshrc.new" | |
| 124 | + | local current="$TMP_DIR/zshrc.current" | |
| 125 | + | ||
| 126 | + | if sudo test -f "$SYSTEM_ZSHRC"; then | |
| 127 | + | sudo cat "$SYSTEM_ZSHRC" > "$current" | |
| 76 | 128 | else | |
| 77 | - | echo " -> $label sudah sesuai, tidak ada perubahan." | |
| 129 | + | : > "$current" | |
| 130 | + | fi | |
| 131 | + | ||
| 132 | + | # Jika managed block sudah benar, tidak perlu menyentuh /etc/zshrc. | |
| 133 | + | if grep -Fqx "$MANAGED_BEGIN" "$current" && | |
| 134 | + | grep -Fqx '[[ -r /usr/local/etc/global-zshrc.zsh ]] && source /usr/local/etc/global-zshrc.zsh' "$current" && | |
| 135 | + | grep -Fqx "$MANAGED_END" "$current"; then | |
| 136 | + | echo " -> Loader global sudah ada di $SYSTEM_ZSHRC, skip." | |
| 137 | + | return 0 | |
| 78 | 138 | fi | |
| 139 | + | ||
| 140 | + | # Hapus managed block versi lama bila ada, lalu tambahkan versi terbaru. | |
| 141 | + | awk -v begin="$MANAGED_BEGIN" -v end="$MANAGED_END" ' | |
| 142 | + | $0 == begin {skip=1; next} | |
| 143 | + | $0 == end {skip=0; next} | |
| 144 | + | !skip {print} | |
| 145 | + | ' "$current" > "$tmp" | |
| 146 | + | ||
| 147 | + | # Rapikan newline sebelum managed block. | |
| 148 | + | printf '\n%s\n' "$MANAGED_BEGIN" >> "$tmp" | |
| 149 | + | printf '%s\n' '[[ -r /usr/local/etc/global-zshrc.zsh ]] && source /usr/local/etc/global-zshrc.zsh' >> "$tmp" | |
| 150 | + | printf '%s\n' "$MANAGED_END" >> "$tmp" | |
| 151 | + | ||
| 152 | + | # Backup /etc/zshrc hanya sekali. | |
| 153 | + | if sudo test -f "$SYSTEM_ZSHRC" && ! sudo test -f "${SYSTEM_ZSHRC}.original"; then | |
| 154 | + | sudo cp -p "$SYSTEM_ZSHRC" "${SYSTEM_ZSHRC}.original" | |
| 155 | + | echo " -> Backup awal: ${SYSTEM_ZSHRC}.original" | |
| 156 | + | fi | |
| 157 | + | ||
| 158 | + | sudo install -o root -g wheel -m 0644 "$tmp" "$SYSTEM_ZSHRC" | |
| 159 | + | echo " -> Loader global dipasang ke $SYSTEM_ZSHRC." | |
| 79 | 160 | } | |
| 80 | 161 | ||
| 81 | - | echo "== 0. Pastikan Homebrew tersedia ==" | |
| 82 | - | if ! need_cmd brew; then | |
| 83 | - | echo "Error: Homebrew belum terinstall." >&2 | |
| 84 | - | echo "Install Homebrew terlebih dahulu dari https://brew.sh" >&2 | |
| 85 | - | exit 1 | |
| 86 | - | fi | |
| 162 | + | # --------------------------------------------------------------------------- | |
| 163 | + | # Dependency | |
| 164 | + | # --------------------------------------------------------------------------- | |
| 87 | 165 | ||
| 88 | - | eval "$(brew shellenv)" | |
| 166 | + | echo "== 0. Cek dependency ==" | |
| 167 | + | ||
| 168 | + | if ! command -v brew >/dev/null 2>&1; then | |
| 169 | + | # Coba lokasi standar Homebrew bila PATH shell saat ini belum memuatnya. | |
| 170 | + | if [[ -x /opt/homebrew/bin/brew ]]; then | |
| 171 | + | eval "$(/opt/homebrew/bin/brew shellenv)" | |
| 172 | + | elif [[ -x /usr/local/bin/brew ]]; then | |
| 173 | + | eval "$(/usr/local/bin/brew shellenv)" | |
| 174 | + | else | |
| 175 | + | echo "Error: Homebrew belum terinstall." >&2 | |
| 176 | + | echo "Install Homebrew terlebih dahulu lalu jalankan ulang skrip." >&2 | |
| 177 | + | exit 1 | |
| 178 | + | fi | |
| 179 | + | fi | |
| 89 | 180 | ||
| 90 | - | echo | |
| 91 | - | echo "== 1. Pastikan dependency terinstall ==" | |
| 92 | 181 | need_install=() | |
| 93 | - | need_cmd vivid || need_install+=(vivid) | |
| 94 | - | need_cmd fastfetch || need_install+=(fastfetch) | |
| 95 | - | need_cmd gls || need_install+=(coreutils) | |
| 96 | - | need_cmd tree || need_install+=(tree) | |
| 97 | 182 | ||
| 98 | - | if (( ${#need_install[@]} > 0 )); then | |
| 99 | - | echo " -> Menginstall: ${need_install[*]}" | |
| 183 | + | command -v vivid >/dev/null 2>&1 || need_install+=("vivid") | |
| 184 | + | command -v fastfetch >/dev/null 2>&1 || need_install+=("fastfetch") | |
| 185 | + | ||
| 186 | + | if [[ "${#need_install[@]}" -gt 0 ]]; then | |
| 187 | + | echo " -> Install via Homebrew: ${need_install[*]}" | |
| 100 | 188 | brew install "${need_install[@]}" | |
| 101 | 189 | else | |
| 102 | - | echo " -> vivid, fastfetch, coreutils, tree sudah tersedia." | |
| 190 | + | echo " -> vivid dan fastfetch sudah tersedia, skip." | |
| 103 | 191 | fi | |
| 104 | 192 | ||
| 193 | + | # Minta credential sudo di awal agar proses berikutnya lebih jelas. | |
| 105 | 194 | echo | |
| 106 | - | echo "== 2. Siapkan source file ==" | |
| 107 | - | tmp_zshrc="$TMP_DIR/zshrc" | |
| 108 | - | tmp_prompt="$TMP_DIR/shell-prompt.zsh" | |
| 109 | - | tmp_fastfetch="$TMP_DIR/config.jsonc" | |
| 110 | - | fetch_or_local "$ZSHRC_URL" "$LOCAL_ZSHRC" "$tmp_zshrc" | |
| 111 | - | fetch_or_local "$PROMPT_URL" "$LOCAL_PROMPT" "$tmp_prompt" | |
| 112 | - | fetch_or_local "$FASTFETCH_CONFIG_URL" "$LOCAL_FASTFETCH" "$tmp_fastfetch" | |
| 113 | - | echo " -> source file siap." | |
| 195 | + | echo "== 1. Validasi akses administrator ==" | |
| 196 | + | sudo -v | |
| 197 | + | ||
| 198 | + | # --------------------------------------------------------------------------- | |
| 199 | + | # Global configuration | |
| 200 | + | # --------------------------------------------------------------------------- | |
| 114 | 201 | ||
| 115 | 202 | echo | |
| 116 | - | echo "== 3. Sinkronkan template dan prompt global ==" | |
| 117 | - | sync_root_file "$tmp_zshrc" "$GLOBAL_ZSHRC_TEMPLATE" "$GLOBAL_ZSHRC_TEMPLATE" 644 | |
| 118 | - | sync_root_file "$tmp_prompt" "$PROMPT_FILE" "$PROMPT_FILE" 644 | |
| 203 | + | echo "== 2. Sinkronisasi global Zsh config ==" | |
| 204 | + | sync_global_file \ | |
| 205 | + | "$ZSHRC_URL" \ | |
| 206 | + | "$GLOBAL_ZSHRC" \ | |
| 207 | + | "$GLOBAL_ZSHRC" | |
| 119 | 208 | ||
| 120 | 209 | echo | |
| 121 | - | echo "== 4. Terapkan .zshrc dan Fastfetch ke user manusia di /Users ==" | |
| 122 | - | while IFS=: read -r user _ uid _ _ home shell; do | |
| 123 | - | # macOS human users umumnya UID >= 501. Skip system/shared/guest users. | |
| 124 | - | (( uid >= 501 )) || continue | |
| 125 | - | [[ "$user" == "Guest" ]] && continue | |
| 126 | - | [[ "$user" == _* ]] && continue | |
| 127 | - | [[ -d "$home" ]] || continue | |
| 128 | - | [[ "$home" == /Users/* ]] || continue | |
| 129 | - | [[ "$shell" == */zsh || "$shell" == */bash ]] || continue | |
| 130 | - | ||
| 131 | - | target_zshrc="$home/.zshrc" | |
| 132 | - | ff_dir="$home/.config/fastfetch" | |
| 133 | - | target_fastfetch="$ff_dir/config.jsonc" | |
| 134 | - | group="$(id -gn "$user" 2>/dev/null || echo staff)" | |
| 135 | - | ||
| 136 | - | if [[ -f "$target_zshrc" ]] && cmp -s "$tmp_zshrc" "$target_zshrc"; then | |
| 137 | - | echo "[SKIP] $user - .zshrc sudah sesuai template" | |
| 138 | - | else | |
| 139 | - | if [[ -f "$target_zshrc" && ! -f "$home/.zshrc.original" ]]; then | |
| 140 | - | sudo cp -p "$target_zshrc" "$home/.zshrc.original" | |
| 141 | - | sudo chown "$user:$group" "$home/.zshrc.original" | |
| 142 | - | echo "[BACKUP] $user - .zshrc lama -> .zshrc.original" | |
| 143 | - | fi | |
| 144 | - | sudo cp "$tmp_zshrc" "$target_zshrc" | |
| 145 | - | sudo chown "$user:$group" "$target_zshrc" | |
| 146 | - | sudo chmod 644 "$target_zshrc" | |
| 147 | - | echo "[APPLY] $user - .zshrc diperbarui" | |
| 148 | - | fi | |
| 210 | + | echo "== 3. Sinkronisasi global shell prompt ==" | |
| 211 | + | sync_global_file \ | |
| 212 | + | "$PROMPT_URL" \ | |
| 213 | + | "$PROMPT_FILE" \ | |
| 214 | + | "$PROMPT_FILE" | |
| 149 | 215 | ||
| 150 | - | sudo mkdir -p "$ff_dir" | |
| 151 | - | if [[ ! -f "$target_fastfetch" ]] || ! cmp -s "$tmp_fastfetch" "$target_fastfetch"; then | |
| 152 | - | if [[ -f "$target_fastfetch" && ! -f "$target_fastfetch.original" ]]; then | |
| 153 | - | sudo cp -p "$target_fastfetch" "$target_fastfetch.original" | |
| 154 | - | sudo chown "$user:$group" "$target_fastfetch.original" | |
| 155 | - | echo "[BACKUP] $user - Fastfetch config lama -> config.jsonc.original" | |
| 156 | - | fi | |
| 157 | - | sudo cp "$tmp_fastfetch" "$target_fastfetch" | |
| 158 | - | sudo chown -R "$user:$group" "$home/.config" | |
| 159 | - | sudo chmod 644 "$target_fastfetch" | |
| 160 | - | echo "[APPLY] $user - Fastfetch config diperbarui" | |
| 161 | - | else | |
| 162 | - | echo "[SKIP] $user - Fastfetch config sudah sesuai" | |
| 163 | - | fi | |
| 216 | + | echo | |
| 217 | + | echo "== 4. Sinkronisasi global Fastfetch config ==" | |
| 218 | + | sync_global_file \ | |
| 219 | + | "$FASTFETCH_CONFIG_URL" \ | |
| 220 | + | "$FASTFETCH_CONFIG_FILE" \ | |
| 221 | + | "$FASTFETCH_CONFIG_FILE" | |
| 164 | 222 | ||
| 165 | - | done < <(dscl . -list /Users UniqueID | awk '{print $1":"$2}' | while IFS=: read -r u uid; do | |
| 166 | - | home=$(dscl . -read "/Users/$u" NFSHomeDirectory 2>/dev/null | awk '{print $2}') | |
| 167 | - | shell=$(dscl . -read "/Users/$u" UserShell 2>/dev/null | awk '{print $2}') | |
| 168 | - | printf '%s:x:%s:x:x:%s:%s\n' "$u" "$uid" "$home" "$shell" | |
| 169 | - | done) | |
| 223 | + | echo | |
| 224 | + | echo "== 5. Pastikan /etc/zshrc me-load konfigurasi global ==" | |
| 225 | + | ensure_system_zshrc_loader | |
| 226 | + | ||
| 227 | + | # --------------------------------------------------------------------------- | |
| 228 | + | # Finish | |
| 229 | + | # --------------------------------------------------------------------------- | |
| 170 | 230 | ||
| 171 | 231 | echo | |
| 172 | - | echo "Selesai." | |
| 173 | - | echo "Buka terminal baru atau jalankan: exec zsh" | |
| 232 | + | echo "============================================================" | |
| 233 | + | echo "Sinkronisasi selesai." | |
| 234 | + | echo "============================================================" | |
| 235 | + | echo | |
| 236 | + | echo "Konfigurasi GLOBAL:" | |
| 237 | + | echo " Zsh : $GLOBAL_ZSHRC" | |
| 238 | + | echo " Prompt : $PROMPT_FILE" | |
| 239 | + | echo " Fastfetch : $FASTFETCH_CONFIG_FILE" | |
| 240 | + | echo | |
| 241 | + | echo "Loader:" | |
| 242 | + | echo " $SYSTEM_ZSHRC" | |
| 243 | + | echo " -> source $GLOBAL_ZSHRC" | |
| 244 | + | echo | |
| 245 | + | echo "Konfigurasi ini berlaku untuk semua user Zsh." | |
| 246 | + | echo | |
| 247 | + | echo "Untuk shell yang sedang aktif, buka Terminal baru atau jalankan:" | |
| 248 | + | echo " exec zsh" | |
| 249 | + | echo | |
dartokloning ревизий этого фрагмента . К ревизии
1 file changed, 173 insertions
sync-zshrc-all.sh(файл создан)
| @@ -0,0 +1,173 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | # | |
| 3 | + | # sync-zshrc-all.sh - macOS Tahoe / Apple Silicon | |
| 4 | + | # | |
| 5 | + | # Menyinkronkan: | |
| 6 | + | # 1. template .zshrc | |
| 7 | + | # 2. /usr/local/etc/shell-prompt.zsh | |
| 8 | + | # 3. config Fastfetch per-user | |
| 9 | + | # 4. dependency Homebrew: vivid, fastfetch, coreutils, tree | |
| 10 | + | # | |
| 11 | + | # Jalankan sebagai USER ADMIN biasa, BUKAN dengan "sudo bash ...". | |
| 12 | + | # Script akan meminta sudo hanya ketika diperlukan. | |
| 13 | + | # | |
| 14 | + | # Default: mengambil tiga file dari direktori yang sama dengan script ini. | |
| 15 | + | # Untuk mode remote/Gist, isi URL melalui environment variable: | |
| 16 | + | # ZSHRC_URL=https://... PROMPT_URL=https://... FASTFETCH_CONFIG_URL=https://... ./sync-zshrc-all.sh | |
| 17 | + | ||
| 18 | + | set -euo pipefail | |
| 19 | + | ||
| 20 | + | if [[ "$(uname -s)" != "Darwin" ]]; then | |
| 21 | + | echo "Error: script ini hanya untuk macOS." >&2 | |
| 22 | + | exit 1 | |
| 23 | + | fi | |
| 24 | + | ||
| 25 | + | if [[ "$(id -u)" -eq 0 ]]; then | |
| 26 | + | echo "Jangan jalankan script ini sebagai root." >&2 | |
| 27 | + | echo "Jalankan sebagai user admin biasa: ./sync-zshrc-all.sh" >&2 | |
| 28 | + | exit 1 | |
| 29 | + | fi | |
| 30 | + | ||
| 31 | + | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| 32 | + | LOCAL_ZSHRC="$SCRIPT_DIR/zshrc" | |
| 33 | + | LOCAL_PROMPT="$SCRIPT_DIR/shell-prompt.zsh" | |
| 34 | + | LOCAL_FASTFETCH="$SCRIPT_DIR/config.jsonc" | |
| 35 | + | ||
| 36 | + | ZSHRC_URL="${ZSHRC_URL:-}" | |
| 37 | + | PROMPT_URL="${PROMPT_URL:-}" | |
| 38 | + | FASTFETCH_CONFIG_URL="${FASTFETCH_CONFIG_URL:-}" | |
| 39 | + | ||
| 40 | + | GLOBAL_ZSHRC_TEMPLATE="/usr/local/etc/zshrc-template" | |
| 41 | + | PROMPT_FILE="/usr/local/etc/shell-prompt.zsh" | |
| 42 | + | ||
| 43 | + | TMP_DIR="$(mktemp -d)" | |
| 44 | + | trap 'rm -rf "$TMP_DIR"' EXIT | |
| 45 | + | ||
| 46 | + | need_cmd() { | |
| 47 | + | command -v "$1" >/dev/null 2>&1 | |
| 48 | + | } | |
| 49 | + | ||
| 50 | + | fetch_or_local() { | |
| 51 | + | # fetch_or_local URL LOCAL_FILE DEST_TMP | |
| 52 | + | local url="$1" local_file="$2" dest="$3" | |
| 53 | + | if [[ -n "$url" ]]; then | |
| 54 | + | if ! curl -fsSL "$url" -o "$dest"; then | |
| 55 | + | echo "Error: gagal download $url" >&2 | |
| 56 | + | exit 1 | |
| 57 | + | fi | |
| 58 | + | else | |
| 59 | + | if [[ ! -f "$local_file" ]]; then | |
| 60 | + | echo "Error: file lokal tidak ditemukan: $local_file" >&2 | |
| 61 | + | exit 1 | |
| 62 | + | fi | |
| 63 | + | cp "$local_file" "$dest" | |
| 64 | + | fi | |
| 65 | + | } | |
| 66 | + | ||
| 67 | + | sync_root_file() { | |
| 68 | + | # sync_root_file SOURCE DEST LABEL MODE | |
| 69 | + | local src="$1" dest="$2" label="$3" mode="$4" | |
| 70 | + | if [[ ! -f "$dest" ]] || ! cmp -s "$src" "$dest"; then | |
| 71 | + | sudo mkdir -p "$(dirname "$dest")" | |
| 72 | + | sudo cp "$src" "$dest" | |
| 73 | + | sudo chown root:wheel "$dest" | |
| 74 | + | sudo chmod "$mode" "$dest" | |
| 75 | + | echo " -> $label diperbarui." | |
| 76 | + | else | |
| 77 | + | echo " -> $label sudah sesuai, tidak ada perubahan." | |
| 78 | + | fi | |
| 79 | + | } | |
| 80 | + | ||
| 81 | + | echo "== 0. Pastikan Homebrew tersedia ==" | |
| 82 | + | if ! need_cmd brew; then | |
| 83 | + | echo "Error: Homebrew belum terinstall." >&2 | |
| 84 | + | echo "Install Homebrew terlebih dahulu dari https://brew.sh" >&2 | |
| 85 | + | exit 1 | |
| 86 | + | fi | |
| 87 | + | ||
| 88 | + | eval "$(brew shellenv)" | |
| 89 | + | ||
| 90 | + | echo | |
| 91 | + | echo "== 1. Pastikan dependency terinstall ==" | |
| 92 | + | need_install=() | |
| 93 | + | need_cmd vivid || need_install+=(vivid) | |
| 94 | + | need_cmd fastfetch || need_install+=(fastfetch) | |
| 95 | + | need_cmd gls || need_install+=(coreutils) | |
| 96 | + | need_cmd tree || need_install+=(tree) | |
| 97 | + | ||
| 98 | + | if (( ${#need_install[@]} > 0 )); then | |
| 99 | + | echo " -> Menginstall: ${need_install[*]}" | |
| 100 | + | brew install "${need_install[@]}" | |
| 101 | + | else | |
| 102 | + | echo " -> vivid, fastfetch, coreutils, tree sudah tersedia." | |
| 103 | + | fi | |
| 104 | + | ||
| 105 | + | echo | |
| 106 | + | echo "== 2. Siapkan source file ==" | |
| 107 | + | tmp_zshrc="$TMP_DIR/zshrc" | |
| 108 | + | tmp_prompt="$TMP_DIR/shell-prompt.zsh" | |
| 109 | + | tmp_fastfetch="$TMP_DIR/config.jsonc" | |
| 110 | + | fetch_or_local "$ZSHRC_URL" "$LOCAL_ZSHRC" "$tmp_zshrc" | |
| 111 | + | fetch_or_local "$PROMPT_URL" "$LOCAL_PROMPT" "$tmp_prompt" | |
| 112 | + | fetch_or_local "$FASTFETCH_CONFIG_URL" "$LOCAL_FASTFETCH" "$tmp_fastfetch" | |
| 113 | + | echo " -> source file siap." | |
| 114 | + | ||
| 115 | + | echo | |
| 116 | + | echo "== 3. Sinkronkan template dan prompt global ==" | |
| 117 | + | sync_root_file "$tmp_zshrc" "$GLOBAL_ZSHRC_TEMPLATE" "$GLOBAL_ZSHRC_TEMPLATE" 644 | |
| 118 | + | sync_root_file "$tmp_prompt" "$PROMPT_FILE" "$PROMPT_FILE" 644 | |
| 119 | + | ||
| 120 | + | echo | |
| 121 | + | echo "== 4. Terapkan .zshrc dan Fastfetch ke user manusia di /Users ==" | |
| 122 | + | while IFS=: read -r user _ uid _ _ home shell; do | |
| 123 | + | # macOS human users umumnya UID >= 501. Skip system/shared/guest users. | |
| 124 | + | (( uid >= 501 )) || continue | |
| 125 | + | [[ "$user" == "Guest" ]] && continue | |
| 126 | + | [[ "$user" == _* ]] && continue | |
| 127 | + | [[ -d "$home" ]] || continue | |
| 128 | + | [[ "$home" == /Users/* ]] || continue | |
| 129 | + | [[ "$shell" == */zsh || "$shell" == */bash ]] || continue | |
| 130 | + | ||
| 131 | + | target_zshrc="$home/.zshrc" | |
| 132 | + | ff_dir="$home/.config/fastfetch" | |
| 133 | + | target_fastfetch="$ff_dir/config.jsonc" | |
| 134 | + | group="$(id -gn "$user" 2>/dev/null || echo staff)" | |
| 135 | + | ||
| 136 | + | if [[ -f "$target_zshrc" ]] && cmp -s "$tmp_zshrc" "$target_zshrc"; then | |
| 137 | + | echo "[SKIP] $user - .zshrc sudah sesuai template" | |
| 138 | + | else | |
| 139 | + | if [[ -f "$target_zshrc" && ! -f "$home/.zshrc.original" ]]; then | |
| 140 | + | sudo cp -p "$target_zshrc" "$home/.zshrc.original" | |
| 141 | + | sudo chown "$user:$group" "$home/.zshrc.original" | |
| 142 | + | echo "[BACKUP] $user - .zshrc lama -> .zshrc.original" | |
| 143 | + | fi | |
| 144 | + | sudo cp "$tmp_zshrc" "$target_zshrc" | |
| 145 | + | sudo chown "$user:$group" "$target_zshrc" | |
| 146 | + | sudo chmod 644 "$target_zshrc" | |
| 147 | + | echo "[APPLY] $user - .zshrc diperbarui" | |
| 148 | + | fi | |
| 149 | + | ||
| 150 | + | sudo mkdir -p "$ff_dir" | |
| 151 | + | if [[ ! -f "$target_fastfetch" ]] || ! cmp -s "$tmp_fastfetch" "$target_fastfetch"; then | |
| 152 | + | if [[ -f "$target_fastfetch" && ! -f "$target_fastfetch.original" ]]; then | |
| 153 | + | sudo cp -p "$target_fastfetch" "$target_fastfetch.original" | |
| 154 | + | sudo chown "$user:$group" "$target_fastfetch.original" | |
| 155 | + | echo "[BACKUP] $user - Fastfetch config lama -> config.jsonc.original" | |
| 156 | + | fi | |
| 157 | + | sudo cp "$tmp_fastfetch" "$target_fastfetch" | |
| 158 | + | sudo chown -R "$user:$group" "$home/.config" | |
| 159 | + | sudo chmod 644 "$target_fastfetch" | |
| 160 | + | echo "[APPLY] $user - Fastfetch config diperbarui" | |
| 161 | + | else | |
| 162 | + | echo "[SKIP] $user - Fastfetch config sudah sesuai" | |
| 163 | + | fi | |
| 164 | + | ||
| 165 | + | done < <(dscl . -list /Users UniqueID | awk '{print $1":"$2}' | while IFS=: read -r u uid; do | |
| 166 | + | home=$(dscl . -read "/Users/$u" NFSHomeDirectory 2>/dev/null | awk '{print $2}') | |
| 167 | + | shell=$(dscl . -read "/Users/$u" UserShell 2>/dev/null | awk '{print $2}') | |
| 168 | + | printf '%s:x:%s:x:x:%s:%s\n' "$u" "$uid" "$home" "$shell" | |
| 169 | + | done) | |
| 170 | + | ||
| 171 | + | echo | |
| 172 | + | echo "Selesai." | |
| 173 | + | echo "Buka terminal baru atau jalankan: exec zsh" | |