#!/usr/bin/env bash set -Eeuo pipefail DEST='/usr/local/share/fonts/nerd-fonts' API='https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest' if [[ ! -t 0 ]]; then echo 'Jalankan secara interaktif di terminal.' >&2; exit 1; fi if [[ $EUID -eq 0 ]]; then echo 'Jalankan sebagai user biasa (tanpa sudo); script akan meminta sudo saat perlu.' >&2; exit 1; fi for cmd in curl python3 tar find mktemp sudo fc-cache; do if ! command -v "$cmd" >/dev/null 2>&1; then echo "Dependency belum tersedia: $cmd" >&2 echo 'Install dahulu: sudo apt update && sudo apt install curl python3 xz-utils fontconfig sudo ca-certificates' >&2 exit 1 fi done if ! tar --help 2>/dev/null | grep -q -- '--xz'; then echo 'tar tidak mendukung xz. Install: sudo apt install xz-utils' >&2; exit 1 fi WORK=$(mktemp -d) trap 'rm -rf "$WORK"' EXIT printf 'Mengambil katalog rilis Nerd Fonts resmi...\n' if ! curl -fLsS --retry 3 --connect-timeout 15 --max-time 90 \ -H 'Accept: application/vnd.github+json' -H 'User-Agent: Debian-Nerd-Fonts-Installer' \ "$API" -o "$WORK/release.json"; then echo 'Gagal mengambil data GitHub API (periksa internet atau rate limit).' >&2; exit 1 fi if ! python3 - "$WORK/release.json" "$WORK/catalog.tsv" "$WORK/version" <<'PY' import json,sys with open(sys.argv[1],encoding='utf-8') as f: data=json.load(f) assets=[] for a in data.get('assets',[]): name=a.get('name','') if name.endswith('.tar.xz') and not name.endswith('xv.tar.xz'): url=a.get('browser_download_url','') if url.startswith('https://github.com/ryanoasis/nerd-fonts/releases/download/'): assets.append((name[:-7],url,a.get('digest') or '')) assets.sort(key=lambda x:x[0].lower()) if not assets: raise SystemExit('Tidak ada arsip font .tar.xz pada rilis.') with open(sys.argv[2],'w',encoding='utf-8') as f: for name,url,digest in assets: f.write(f'{name}\t{url}\t{digest}\n') with open(sys.argv[3],'w') as f:f.write(data.get('tag_name','unknown')) PY then echo 'Katalog rilis tidak valid.' >&2; exit 1; fi mapfile -t LINES < "$WORK/catalog.tsv" VERSION=$(cat "$WORK/version") printf '\nNerd Fonts %s | Tujuan: %s\n\n' "$VERSION" "$DEST" for i in "${!LINES[@]}"; do IFS=$'\t' read -r name url digest <<< "${LINES[$i]}" status='' [[ -d "$DEST/$name" ]] && status=' [TERPASANG]' printf '%3d. %-28s%s\n' "$((i+1))" "$name" "$status" done printf '\nMasukkan nomor, contoh 1,2,4 (atau all untuk semua; q untuk keluar): ' read -r selection [[ $selection == q || $selection == Q ]] && exit 0 indices=() if [[ $selection == all || $selection == ALL ]]; then for i in "${!LINES[@]}"; do indices+=("$i"); done else selection=${selection//[[:space:]]/} if [[ ! $selection =~ ^[0-9]+(,[0-9]+)*$ ]]; then echo 'Format pilihan tidak valid.' >&2; exit 1; fi declare -A seen=() IFS=',' read -ra choices <<< "$selection" for n in "${choices[@]}"; do n=$((10#$n)) if (( n < 1 || n > ${#LINES[@]} )); then echo "Nomor tidak tersedia: $n" >&2; exit 1; fi if [[ ! ${seen[$n]+x} ]]; then indices+=("$((n-1))"); seen[$n]=1; fi done fi printf '\nAkan memasang %d keluarga font secara GLOBAL. Lanjutkan? [y/N]: ' "${#indices[@]}" read -r confirm [[ $confirm == y || $confirm == Y ]] || exit 0 sudo -v sudo install -d -m 755 "$DEST" installed=0; failed=0 for idx in "${indices[@]}"; do IFS=$'\t' read -r name url digest <<< "${LINES[$idx]}" printf '\n==> %s\n' "$name" archive="$WORK/$name.tar.xz" stage="$WORK/stage-$idx" mkdir -p "$stage" if ! curl -fL --retry 3 --connect-timeout 15 "$url" -o "$archive"; then echo "GAGAL download: $name" >&2; ((failed+=1)); continue fi if [[ $digest == sha256:* ]]; then if ! printf '%s %s\n' "${digest#sha256:}" "$archive" | sha256sum -c --status; then echo "GAGAL checksum SHA256: $name" >&2; ((failed+=1)); continue fi fi if ! tar -tJf "$archive" >/dev/null 2>&1 || ! tar -xJf "$archive" -C "$stage" --no-same-owner --no-same-permissions; then echo "GAGAL ekstraksi: $name" >&2; ((failed+=1)); continue fi mapfile -d '' fontfiles < <(find "$stage" -type f \( -iname '*.ttf' -o -iname '*.otf' \) -print0) if (( ${#fontfiles[@]} == 0 )); then echo "Tidak ada file font: $name" >&2; ((failed+=1)); continue; fi target="$DEST/$name" # Staging pada filesystem tujuan, lalu ganti direktori font setelah semua file disalin. tmp_target="$DEST/.${name}.new.$$" sudo install -d -m 755 "$tmp_target" ok=1 for font in "${fontfiles[@]}"; do if ! sudo install -m 644 "$font" "$tmp_target/$(basename "$font")"; then ok=0; break; fi done if (( ok == 0 )); then sudo rm -rf -- "$tmp_target"; echo "GAGAL copy: $name" >&2; ((failed+=1)); continue; fi if ! sudo rm -rf -- "$target" || ! sudo mv -- "$tmp_target" "$target"; then echo "GAGAL finalisasi: $name" >&2; ((failed+=1)); continue fi printf 'OK: %s (%d file font)\n' "$name" "${#fontfiles[@]}" ((installed+=1)) done printf '\nMemperbarui font cache...\n' sudo fc-cache -f "$DEST" printf '\nSelesai. Berhasil: %d | Gagal: %d\n' "$installed" "$failed" printf 'Verifikasi: fc-list | grep -i "Nerd Font"\n' (( failed == 0 ))