Fix: Ersteinrichtung (Dotfiles, Zsh, Junie) in klare Skripte aufgeteilt und von Hyprland entkoppelt
Das bisherige install-dots-prompt.sh vereinte Dotfiles-Auswahl, Oh-My-Zsh, JetBrains Junie CLI und AwesomeJunieSkills in einem Skript und wurde per exec-once direkt von Hyprland gestartet. Aufgeteilt in eigenständige Skripte (setup-dotfiles.sh, setup-shell.sh, setup-junie-cli.sh, setup-junie-skills.sh) mit gemeinsamer first-login-setup.sh als Orchestrator. Systemweit unter /usr/local/lib/first-login-setup installiert (eine Kopie für alle Nutzer statt Duplikate pro Home) und über einen global aktivierten systemd --user Service (/etc/systemd/user/) gestartet - bewusst nicht über hyprland.conf, damit es unabhängig vom gewählten Compositor funktioniert und Hyprland selbst es nicht mehr ausführt. Der Service sucht das Wayland-Socket eigenständig, statt sich auf importierte Umgebungsvariablen zu verlassen, und wiederholt sich bei Bedarf bis die grafische Sitzung bereit ist. Der Fortschritt liegt in ~/.local/state/first-login-setup (statt ~/.config), da setup-dotfiles.sh ~/.config komplett durch ein eigenes Dotfiles-Repository ersetzen kann - das darf den Fortschritt nicht mit sich reißen. Zusätzlich fragt das Skript jetzt explizit "Jetzt/Später": nur bei "Jetzt" wird der Marker gesetzt, bei "Später" wird beim nächsten Login erneut gefragt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017WMUd2fGsPCtTCVQkSS5TA
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
[Unit]
|
||||
Description=Ersteinrichtung: Dotfiles, Oh-My-Zsh, JetBrains Junie CLI & AwesomeJunieSkills
|
||||
# Systemweit installiert unter /etc/systemd/user/ und global aktiviert
|
||||
# (siehe stages/10-hyprland.sh) - gilt fuer alle Benutzer, ohne dass etwas
|
||||
# in einzelne Home-Verzeichnisse kopiert werden muss. Bewusst NICHT an
|
||||
# Hyprland gebunden - laeuft ueber den systemd --user Manager, unabhaengig
|
||||
# davon, welcher Compositor/welche Desktop-Sitzung gestartet wird.
|
||||
After=default.target
|
||||
StartLimitIntervalSec=300
|
||||
StartLimitBurst=60
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/lib/first-login-setup/first-login-setup.sh
|
||||
# first-login-setup.sh beendet sich mit Exit-Code 1, solange die grafische
|
||||
# Sitzung (Wayland-Socket) noch nicht bereit ist - in diesem Fall einfach
|
||||
# erneut versuchen, bis sie verfuegbar ist. Das Skript selbst entscheidet
|
||||
# anhand von ~/.local/state/first-login-setup/completed (pro Benutzer), ob
|
||||
# es fuer den aktuellen Benutzer ueberhaupt noch etwas zu tun gibt.
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
@@ -90,8 +90,11 @@ input {
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Autostart nach der Anmeldung
|
||||
# Ersteinrichtung
|
||||
# ------------------------------------------------------------------------------
|
||||
# Fragt nach der ersten Anmeldung nach der gewünschten Dotfiles-Konfiguration
|
||||
# (LinuxBeginnings Hyprland-Dots oder eigenes Git-Repository für ~/.config)
|
||||
exec-once = ~/.config/hypr/scripts/install-dots-prompt.sh
|
||||
# Dotfiles-Auswahl, Oh-My-Zsh, JetBrains Junie CLI & AwesomeJunieSkills starten
|
||||
# automatisch beim Login über den systemweiten systemd --user Service
|
||||
# 'first-login-setup.service' (/etc/systemd/user/) - bewusst NICHT hier per
|
||||
# exec-once, damit die Ersteinrichtung unabhängig vom gewählten Compositor
|
||||
# funktioniert. Manueller Aufruf jederzeit möglich mit:
|
||||
# /usr/local/lib/first-login-setup/first-login-setup.sh --force
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# ~/.config/hypr/scripts/install-dots-prompt.sh
|
||||
# Ersteinrichtung beim ersten Login:
|
||||
# 1) Desktop-Konfiguration (LinuxBeginnings Hyprland-Dots oder eigenes Git-Repo)
|
||||
# 2) Installation der JetBrains Junie CLI & AwesomeJunieSkills
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
MARKER_FILE="$HOME/.config/hypr/.dots_prompted"
|
||||
FORCE=0
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Wenn bereits abgefragt und kein --force übergeben wurde, beenden
|
||||
if [[ "$FORCE" -eq 0 && -f "$MARKER_FILE" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Wenn nicht in einem interaktiven Terminal ausgeführt (z. B. via Hyprland exec-once),
|
||||
# starte das Skript in einem Kitty-Fenster:
|
||||
if [[ ! -t 0 || ! -t 1 ]]; then
|
||||
if command -v kitty >/dev/null 2>&1; then
|
||||
exec kitty --title "System-Ersteinrichtung & Dotfiles" bash -c "$0 --in-terminal; echo; read -r -p 'Drücke Enter zum Schließen...' || true"
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# ANSI Farben
|
||||
CLR_RESET='\033[0m'
|
||||
CLR_BOLD='\033[1m'
|
||||
CLR_CYAN='\033[0;36m'
|
||||
CLR_GREEN='\033[0;32m'
|
||||
CLR_YELLOW='\033[0;33m'
|
||||
CLR_RED='\033[0;31m'
|
||||
CLR_BLUE='\033[0;34m'
|
||||
CLR_MAGENTA='\033[0;35m'
|
||||
|
||||
mark_as_prompted() {
|
||||
mkdir -p "$(dirname "$MARKER_FILE")" 2>/dev/null || true
|
||||
touch "$MARKER_FILE" 2>/dev/null || true
|
||||
}
|
||||
|
||||
install_oh_my_zsh() {
|
||||
local zsh_dir="$HOME/.oh-my-zsh"
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN} Oh-My-Zsh & Shell-Konfiguration ${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "\n"
|
||||
|
||||
if [[ ! -d "$zsh_dir" ]]; then
|
||||
printf "%b\n" "${CLR_CYAN}[INFO] Richte Oh-My-Zsh für $USER ein...${CLR_RESET}"
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
if git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$zsh_dir"; then
|
||||
mkdir -p "$zsh_dir/custom/plugins"
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$zsh_dir/custom/plugins/zsh-autosuggestions" 2>/dev/null || true
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "$zsh_dir/custom/plugins/zsh-syntax-highlighting" 2>/dev/null || true
|
||||
printf "%b\n" "${CLR_GREEN}[✓] Oh-My-Zsh erfolgreich eingerichtet.${CLR_RESET}"
|
||||
else
|
||||
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Oh-My-Zsh konnte nicht geklont werden.${CLR_RESET}"
|
||||
fi
|
||||
else
|
||||
printf "%b\n" "${CLR_RED}[FEHLER] 'git' ist nicht installiert. Oh-My-Zsh konnte nicht eingerichtet werden.${CLR_RESET}"
|
||||
fi
|
||||
else
|
||||
# Plugins sicherstellen
|
||||
if [[ ! -d "$zsh_dir/custom/plugins/zsh-autosuggestions" ]] && command -v git >/dev/null 2>&1; then
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$zsh_dir/custom/plugins/zsh-autosuggestions" 2>/dev/null || true
|
||||
fi
|
||||
if [[ ! -d "$zsh_dir/custom/plugins/zsh-syntax-highlighting" ]] && command -v git >/dev/null 2>&1; then
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "$zsh_dir/custom/plugins/zsh-syntax-highlighting" 2>/dev/null || true
|
||||
fi
|
||||
printf "%b\n" "${CLR_GREEN}[✓] Oh-My-Zsh ist bereits vorhanden und konfiguriert.${CLR_RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
install_junie_cli_and_skills() {
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN} JetBrains Junie CLI & AwesomeJunieSkills Installation ${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "\n"
|
||||
|
||||
# 1. JetBrains Junie CLI installieren
|
||||
printf "%b\n" "${CLR_CYAN}[1/2] Installiere JetBrains Junie CLI...${CLR_RESET}"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
if curl -fsSL https://junie.jetbrains.com/install.sh | bash; then
|
||||
printf "%b\n" "${CLR_GREEN}[✓] JetBrains Junie CLI erfolgreich installiert.${CLR_RESET}"
|
||||
else
|
||||
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Installation von JetBrains Junie CLI fehlgeschlagen oder unterbrochen.${CLR_RESET}"
|
||||
fi
|
||||
else
|
||||
printf "%b\n" "${CLR_RED}[FEHLER] 'curl' ist nicht installiert. Junie CLI konnte nicht geladen werden.${CLR_RESET}"
|
||||
fi
|
||||
|
||||
# 2. AwesomeJunieSkills im Benutzer-Skillverzeichnis (~/.junie/skills) klonen / aktualisieren
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_CYAN}[2/2] Installiere AwesomeJunieSkills im Benutzer-Skillverzeichnis (~/.junie/skills)...${CLR_RESET}"
|
||||
local skills_dir="$HOME/.junie/skills"
|
||||
local repo_dir="$skills_dir/awesome-junie-skills"
|
||||
mkdir -p "$skills_dir"
|
||||
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
if [[ -d "$repo_dir/.git" ]]; then
|
||||
printf "%b\n" "${CLR_BLUE}[INFO] Repository existiert bereits in $repo_dir. Führe 'git pull' aus...${CLR_RESET}"
|
||||
if git -C "$repo_dir" pull --ff-only 2>/dev/null; then
|
||||
printf "%b\n" "${CLR_GREEN}[✓] AwesomeJunieSkills erfolgreich aktualisiert.${CLR_RESET}"
|
||||
else
|
||||
printf "%b\n" "${CLR_YELLOW}[WARNUNG] 'git pull' in $repo_dir fehlgeschlagen.${CLR_RESET}"
|
||||
fi
|
||||
else
|
||||
printf "%b\n" "${CLR_BLUE}[INFO] Klone AwesomeJunieSkills nach $repo_dir...${CLR_RESET}"
|
||||
rm -rf "$repo_dir" 2>/dev/null || true
|
||||
if git clone https://github.com/alebaffa/awesome-junie-skills.git "$repo_dir"; then
|
||||
printf "%b\n" "${CLR_GREEN}[✓] AwesomeJunieSkills erfolgreich nach $repo_dir geklont.${CLR_RESET}"
|
||||
else
|
||||
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Klonen von AwesomeJunieSkills fehlgeschlagen.${CLR_RESET}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Symlinks für alle Skills im Skill-Hauptordner erstellen
|
||||
if [[ -d "$repo_dir" ]]; then
|
||||
local count=0
|
||||
for skill_path in "$repo_dir"/*; do
|
||||
if [[ -d "$skill_path" && -f "$skill_path/SKILL.md" ]]; then
|
||||
local s_name
|
||||
s_name="$(basename "$skill_path")"
|
||||
ln -sfn "$skill_path" "$skills_dir/$s_name"
|
||||
((count++)) || true
|
||||
fi
|
||||
done
|
||||
printf "%b\n" "${CLR_GREEN}[✓] $count Skills verknüpft in '$skills_dir' (kann via 'git pull' in '$repo_dir' aktualisiert werden).${CLR_RESET}"
|
||||
fi
|
||||
|
||||
# Junie config.json konfigurieren (skill-locations)
|
||||
mkdir -p "$HOME/.junie"
|
||||
local config_file="$HOME/.junie/config.json"
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
python3 -c "
|
||||
import json, os
|
||||
cfg_path = os.path.expanduser('$config_file')
|
||||
repo_path = os.path.expanduser('$repo_dir')
|
||||
data = {}
|
||||
if os.path.exists(cfg_path):
|
||||
try:
|
||||
with open(cfg_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
except Exception:
|
||||
data = {}
|
||||
locs = data.get('skill-locations', [])
|
||||
if repo_path not in locs:
|
||||
locs.append(repo_path)
|
||||
data['skill-locations'] = locs
|
||||
with open(cfg_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
" 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
printf "%b\n" "${CLR_RED}[FEHLER] 'git' ist nicht installiert. AwesomeJunieSkills konnte nicht eingerichtet werden.${CLR_RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
install_linuxbeginnings() {
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[INFO] Starte Installation der LinuxBeginnings Hyprland-Dotfiles...${CLR_RESET}"
|
||||
printf "\n"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
sh <(curl -fsSL https://raw.githubusercontent.com/LinuxBeginnings/Hyprland-Dots/main/Distro-Hyprland.sh)
|
||||
else
|
||||
printf "%b\n" "${CLR_RED}[FEHLER] 'curl' ist nicht installiert. Bitte installieren Sie curl und wiederholen Sie den Vorgang.${CLR_RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
clone_custom_repo() {
|
||||
if ! command -v git >/dev/null 2>&1; then
|
||||
printf "\n%b\n" "${CLR_RED}[FEHLER] 'git' ist nicht installiert. Bitte installieren Sie git zuerst.${CLR_RESET}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}--- Eigenes Git-Repository für ~/.config klonen ---${CLR_RESET}"
|
||||
printf "%b\n" "Geben Sie die Git-URL Ihres Dotfiles-/Config-Repositories an."
|
||||
printf "%b\n" "Beispiele:"
|
||||
printf "%b\n" " HTTPS : ${CLR_BLUE}https://github.com/Benutzername/mein-config-repo.git${CLR_RESET}"
|
||||
printf "%b\n" " SSH : ${CLR_BLUE}git@github.com:Benutzername/mein-config-repo.git${CLR_RESET}"
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_YELLOW}Hinweise zur Authentifizierung:${CLR_RESET}"
|
||||
printf "%b\n" " - ${CLR_BOLD}HTTPS:${CLR_RESET} Bei privaten Repositories fragt Git nach Benutzername & Personal Access Token (PAT)."
|
||||
printf "%b\n" " - ${CLR_BOLD}SSH:${CLR_RESET} Erfordert einen hinterlegten SSH-Schlüssel (z. B. in ~/.ssh/ oder via ssh-agent)."
|
||||
printf "\n"
|
||||
|
||||
read -r -p "Git-Repository-URL (oder 'q' zum Abbrechen): " repo_url
|
||||
repo_url="$(echo "$repo_url" | xargs)"
|
||||
|
||||
if [[ "$repo_url" == "q" || "$repo_url" == "Q" || -z "$repo_url" ]]; then
|
||||
printf "%b\n" "${CLR_YELLOW}[INFO] Vorgang abgebrochen. Kehre zum Hauptmenü zurück.${CLR_RESET}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# SSH-Prüfung und Hilfestellung
|
||||
if [[ "$repo_url" =~ ^git@ || "$repo_url" =~ ^ssh:// ]]; then
|
||||
local ssh_keys_found=0
|
||||
if [[ -d "$HOME/.ssh" ]]; then
|
||||
for k in "$HOME/.ssh"/id_*; do
|
||||
if [[ -f "$k" && ! "$k" =~ \.pub$ ]]; then
|
||||
ssh_keys_found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "$ssh_keys_found" -eq 0 ]]; then
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Es wurde kein lokaler SSH-Privatschlüssel in ~/.ssh/ gefunden.${CLR_RESET}"
|
||||
read -r -p "Möchten Sie vor dem Klonen ein neues SSH-Schlüsselpaar (ed25519) generieren? [j/N]: " gen_ssh || gen_ssh="n"
|
||||
if [[ "$gen_ssh" =~ ^[JjYy] ]]; then
|
||||
mkdir -p "$HOME/.ssh"
|
||||
chmod 700 "$HOME/.ssh"
|
||||
ssh-keygen -t ed25519 -f "$HOME/.ssh/id_ed25519" -C "$USER@$(hostname)"
|
||||
printf "\n%b\n" "${CLR_GREEN}Neuer öffentlicher SSH-Schlüssel (~/.ssh/id_ed25519.pub):${CLR_RESET}"
|
||||
cat "$HOME/.ssh/id_ed25519.pub"
|
||||
printf "\n%b\n" "Bitte fügen Sie diesen Schlüssel bei GitHub/GitLab zu Ihrem Account hinzu."
|
||||
if command -v wl-copy >/dev/null 2>&1; then
|
||||
if wl-copy < "$HOME/.ssh/id_ed25519.pub" 2>/dev/null; then
|
||||
printf "%b\n" "${CLR_GREEN}(In die Zwischenablage kopiert!)${CLR_RESET}"
|
||||
fi
|
||||
fi
|
||||
read -r -p "Drücken Sie Enter, sobald der SSH-Key hinterlegt wurde..."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Backup und Klon-Vorgang vorbereiten
|
||||
local timestamp
|
||||
timestamp="$(date +%Y%m%d_%H%M%S)"
|
||||
local backup_dir="$HOME/.config.backup_$timestamp"
|
||||
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_CYAN}[1/3] Sichere bestehendes ~/.config-Verzeichnis nach ${backup_dir}...${CLR_RESET}"
|
||||
|
||||
if [[ -d "$HOME/.config" ]]; then
|
||||
mv "$HOME/.config" "$backup_dir"
|
||||
fi
|
||||
|
||||
printf "%b\n" "${CLR_CYAN}[2/3] Klone Repository direkt nach ~/.config...${CLR_RESET}"
|
||||
|
||||
# Git ausführen mit aktivierter Terminal-Eingabeaufforderung für Authentifizierung
|
||||
if env GIT_TERMINAL_PROMPT=1 git clone --recurse-submodules "$repo_url" "$HOME/.config"; then
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[ERFOLG] Repository wurde erfolgreich nach ~/.config geklont!${CLR_RESET}"
|
||||
printf "%b\n" " - Ihr gesamter ${CLR_BOLD}~/.config${CLR_RESET}-Ordner ist nun das Git-Repository."
|
||||
printf "%b\n" " - Vorherige Konfigurationen wurden gesichert in: ${CLR_BOLD}${backup_dir}${CLR_RESET}"
|
||||
|
||||
# Hyprland-Konfiguration neu laden falls aktiv
|
||||
if command -v hyprctl >/dev/null 2>&1; then
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_CYAN}[3/3] Lade Hyprland-Konfiguration neu...${CLR_RESET}"
|
||||
hyprctl reload 2>/dev/null || true
|
||||
printf "%b\n" "${CLR_GREEN}[✓] Hyprland erfolgreich aktualisiert.${CLR_RESET}"
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_GREEN}Dotfiles-Einrichtung abgeschlossen!${CLR_RESET}"
|
||||
return 0
|
||||
else
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_RED}${CLR_BOLD}[FEHLER] Git Clone ist fehlgeschlagen (Authentifizierungsfehler, falsche URL oder Netzwerkproblem).${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_YELLOW}[ROLLBACK] Stelle vorheriges ~/.config-Verzeichnis aus dem Backup wieder her...${CLR_RESET}"
|
||||
rm -rf "$HOME/.config" 2>/dev/null || true
|
||||
if [[ -d "$backup_dir" ]]; then
|
||||
mv "$backup_dir" "$HOME/.config"
|
||||
printf "%b\n" "${CLR_GREEN}[✓] Ursprüngliches ~/.config-Verzeichnis wurde vollständig wiederhergestellt.${CLR_RESET}"
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
read -r -p "Möchten Sie es erneut versuchen? [J/n]: " retry || retry="n"
|
||||
if [[ ! "$retry" =~ ^[JjYy] && -n "$retry" ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
clear 2>/dev/null || true
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN} Hyprland Desktop - Dotfiles Setup & Konfiguration ${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "\n"
|
||||
printf "%b\n" "Willkommen auf Ihrem neuen Debian Unstable Hyprland-System!"
|
||||
printf "\n"
|
||||
printf "%b\n" "Aktuell ist eine rudimentäre Basiskonfiguration aktiv:"
|
||||
printf "%b\n" " - ${CLR_BOLD}SUPER + ENTER${CLR_RESET} : Terminal (Kitty) öffnen"
|
||||
printf "%b\n" " - ${CLR_BOLD}SUPER + Q${CLR_RESET} : Aktives Fenster schließen"
|
||||
printf "\n"
|
||||
printf "%b\n" "Wie möchten Sie Ihre Desktop-Konfiguration (Dotfiles) einrichten?"
|
||||
printf "\n"
|
||||
printf "%b\n" " ${CLR_BOLD}[1]${CLR_RESET} ${CLR_GREEN}LinuxBeginnings Hyprland-Dotfiles installieren${CLR_RESET}"
|
||||
printf "%b\n" " Vollständig vorkonfiguriertes Setup (Waybar, Rofi, Animationen, Themes)"
|
||||
printf "%b\n" " URL: https://github.com/LinuxBeginnings/Hyprland-Dots"
|
||||
printf "\n"
|
||||
printf "%b\n" " ${CLR_BOLD}[2]${CLR_RESET} ${CLR_MAGENTA}Eigenes Git-Repository als ~/.config klonen${CLR_RESET}"
|
||||
printf "%b\n" " Klont Ihr eigenes Git-Repository direkt als vollständigen ~/.config-Ordner."
|
||||
printf "%b\n" " (Unterstützt HTTPS & SSH inkl. Authentifizierung)"
|
||||
printf "\n"
|
||||
printf "%b\n" " ${CLR_BOLD}[3]${CLR_RESET} ${CLR_YELLOW}Überspringen / Basiskonfiguration beibehalten${CLR_RESET}"
|
||||
printf "%b\n" " Keine Änderungen vornehmen (kann später manuell eingerichtet werden)."
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}------------------------------------------------------------------------------${CLR_RESET}"
|
||||
|
||||
while true; do
|
||||
read -r -p "Bitte wählen Sie eine Option [1-3] (Standard: 1): " choice || choice="1"
|
||||
choice="$(echo "$choice" | xargs)"
|
||||
[[ -z "$choice" ]] && choice="1"
|
||||
|
||||
case "$choice" in
|
||||
1)
|
||||
install_linuxbeginnings
|
||||
break
|
||||
;;
|
||||
2)
|
||||
clone_custom_repo
|
||||
break
|
||||
;;
|
||||
3)
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_YELLOW}[INFO] Dotfiles-Einrichtung übersprungen. Die Basiskonfiguration bleibt aktiv.${CLR_RESET}"
|
||||
break
|
||||
;;
|
||||
*)
|
||||
printf "%b\n" "${CLR_RED}Ungültige Eingabe. Bitte 1, 2 oder 3 wählen.${CLR_RESET}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Oh-My-Zsh & Plugins einrichten
|
||||
install_oh_my_zsh
|
||||
|
||||
# JetBrains Junie CLI & AwesomeJunieSkills installieren
|
||||
install_junie_cli_and_skills
|
||||
|
||||
# Marker-Datei setzen
|
||||
mark_as_prompted
|
||||
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[✓] Ersteinrichtung vollständig abgeschlossen!${CLR_RESET}"
|
||||
printf "%b\n" "Sie können dieses Menü jederzeit erneut aufrufen mit:"
|
||||
printf "%b\n" " ${CLR_BOLD}~/.config/hypr/scripts/install-dots-prompt.sh --force${CLR_RESET}"
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# /usr/local/lib/first-login-setup/_lib.sh
|
||||
# Gemeinsame Farbcodes & Ausgabe-Helfer für die first-login-setup.sh Skripte.
|
||||
# Nicht zur direkten Ausführung gedacht - wird von den anderen Skripten source't.
|
||||
# ==============================================================================
|
||||
|
||||
CLR_RESET='\033[0m'
|
||||
CLR_BOLD='\033[1m'
|
||||
CLR_CYAN='\033[0;36m'
|
||||
CLR_GREEN='\033[0;32m'
|
||||
CLR_YELLOW='\033[0;33m'
|
||||
CLR_RED='\033[0;31m'
|
||||
CLR_BLUE='\033[0;34m'
|
||||
CLR_MAGENTA='\033[0;35m'
|
||||
|
||||
print_header() {
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}$1${CLR_RESET}"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
printf "%b\n" "${CLR_CYAN}[INFO] $*${CLR_RESET}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
printf "%b\n" "${CLR_GREEN}[✓] $*${CLR_RESET}"
|
||||
}
|
||||
|
||||
print_warn() {
|
||||
printf "%b\n" "${CLR_YELLOW}[WARNUNG] $*${CLR_RESET}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
printf "%b\n" "${CLR_RED}[FEHLER] $*${CLR_RESET}"
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# /usr/local/lib/first-login-setup/first-login-setup.sh
|
||||
# Ersteinrichtung nach der ersten Anmeldung. Führt der Reihe nach aus:
|
||||
# 1) setup-dotfiles.sh - Desktop-Konfiguration (LinuxBeginnings / eigenes Repo)
|
||||
# 2) setup-shell.sh - Oh-My-Zsh & Plugins
|
||||
# 3) setup-junie-cli.sh - JetBrains Junie CLI
|
||||
# 4) setup-junie-skills.sh- AwesomeJunieSkills
|
||||
#
|
||||
# Wird automatisch beim Login über den systemweiten systemd --user Service
|
||||
# 'first-login-setup.service' (/etc/systemd/user/) gestartet - bewusst NICHT
|
||||
# über hyprland.conf, damit die Ersteinrichtung unabhängig vom gewählten
|
||||
# Compositor funktioniert. Kann jederzeit auch manuell aufgerufen werden.
|
||||
# Jedes der obigen Skripte kann auch einzeln & unabhängig ausgeführt werden.
|
||||
#
|
||||
# Liegt system- statt benutzerweit unter /usr/local/lib (eine gemeinsame
|
||||
# Kopie für alle Benutzer, statt in jedes Home dupliziert zu werden), und
|
||||
# NICHT unter ~/.config: setup-dotfiles.sh kann ~/.config komplett durch ein
|
||||
# eigenes Dotfiles-Repository ersetzen - das darf weder dieses Skript noch
|
||||
# den Fortschritt (siehe MARKER_FILE) mit sich reißen.
|
||||
#
|
||||
# Läuft wirklich nur bei der allerersten Anmeldung eines Benutzers, oder
|
||||
# erneut, wenn zuvor explizit "Später" gewählt wurde (siehe unten) - danach
|
||||
# nie wieder, sobald MARKER_FILE gesetzt ist.
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=_lib.sh
|
||||
source "$SCRIPT_DIR/_lib.sh"
|
||||
|
||||
MARKER_FILE="$HOME/.local/state/first-login-setup/completed"
|
||||
FORCE=0
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Wenn bereits abgeschlossen und kein --force übergeben wurde, beenden.
|
||||
# (Ein zuvor gewähltes "Später" setzt MARKER_FILE bewusst NICHT, siehe unten -
|
||||
# das Skript fragt in diesem Fall beim nächsten Login erneut.)
|
||||
if [[ "$FORCE" -eq 0 && -f "$MARKER_FILE" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Wenn nicht in einem interaktiven Terminal ausgeführt (z. B. via systemd
|
||||
# --user Service oder Keybind ohne Terminal), starte das Skript in einem
|
||||
# Kitty-Fenster:
|
||||
if [[ ! -t 0 || ! -t 1 ]]; then
|
||||
# Beim Start über systemd --user ist WAYLAND_DISPLAY/DISPLAY meist nicht
|
||||
# gesetzt, da der Dienst unabhängig vom Compositor läuft. Das
|
||||
# Wayland-Socket direkt suchen, statt uns auf eine importierte Umgebung
|
||||
# zu verlassen.
|
||||
if [[ -z "${WAYLAND_DISPLAY:-}" && -z "${DISPLAY:-}" && -n "${XDG_RUNTIME_DIR:-}" ]]; then
|
||||
wl_socket="$(find "$XDG_RUNTIME_DIR" -maxdepth 1 -name 'wayland-*' ! -name '*.lock' 2>/dev/null | head -n1)"
|
||||
if [[ -n "$wl_socket" ]]; then
|
||||
export WAYLAND_DISPLAY
|
||||
WAYLAND_DISPLAY="$(basename "$wl_socket")"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "${WAYLAND_DISPLAY:-}" && -z "${DISPLAY:-}" ]]; then
|
||||
# Grafische Sitzung ist noch nicht bereit (z. B. Compositor startet
|
||||
# gerade erst). Mit Exit-Code 1 beenden, damit systemd den Dienst
|
||||
# gemäß 'Restart=on-failure' erneut versucht.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v kitty >/dev/null 2>&1; then
|
||||
exec kitty --title "System-Ersteinrichtung & Dotfiles" bash -c "$0 --in-terminal; echo; read -r -p 'Drücke Enter zum Schließen...' || true"
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
mark_as_prompted() {
|
||||
mkdir -p "$(dirname "$MARKER_FILE")" 2>/dev/null || true
|
||||
touch "$MARKER_FILE" 2>/dev/null || true
|
||||
}
|
||||
|
||||
clear 2>/dev/null || true
|
||||
print_header " Hyprland Desktop - Ersteinrichtung "
|
||||
printf "%b\n" "Willkommen auf Ihrem neuen Debian Unstable Hyprland-System!"
|
||||
printf "\n"
|
||||
printf "%b\n" "Aktuell ist eine rudimentäre Basiskonfiguration aktiv:"
|
||||
printf "%b\n" " - ${CLR_BOLD}SUPER + ENTER${CLR_RESET} : Terminal (Kitty) öffnen"
|
||||
printf "%b\n" " - ${CLR_BOLD}SUPER + Q${CLR_RESET} : Aktives Fenster schließen"
|
||||
printf "\n"
|
||||
printf "%b\n" "Folgende Schritte können nacheinander ausgeführt werden:"
|
||||
printf "%b\n" " 1) Desktop-Konfiguration (Dotfiles)"
|
||||
printf "%b\n" " 2) Oh-My-Zsh & Shell-Plugins"
|
||||
printf "%b\n" " 3) JetBrains Junie CLI"
|
||||
printf "%b\n" " 4) AwesomeJunieSkills"
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}------------------------------------------------------------------------------${CLR_RESET}"
|
||||
|
||||
# Explizite Ja/Später-Abfrage: Nur bei "Jetzt" wird MARKER_FILE gesetzt.
|
||||
# Bei "Später" bricht das Skript ohne Marker ab, sodass es beim nächsten
|
||||
# Login erneut über first-login-setup.service gestartet wird und wieder fragt.
|
||||
answer=""
|
||||
read -r -p "Ersteinrichtung jetzt durchführen? [J]etzt / [S]päter (beim nächsten Login erneut fragen): " answer || answer="j"
|
||||
answer="$(echo "$answer" | xargs)"
|
||||
|
||||
if [[ "$answer" =~ ^[Ss] ]]; then
|
||||
printf "\n"
|
||||
print_warn "Ersteinrichtung verschoben. Sie werden beim nächsten Login erneut gefragt."
|
||||
printf "%b\n" "Manueller Aufruf jederzeit möglich mit: ${CLR_BOLD}/usr/local/lib/first-login-setup/first-login-setup.sh${CLR_RESET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
bash "$SCRIPT_DIR/setup-dotfiles.sh"
|
||||
bash "$SCRIPT_DIR/setup-shell.sh"
|
||||
bash "$SCRIPT_DIR/setup-junie-cli.sh"
|
||||
bash "$SCRIPT_DIR/setup-junie-skills.sh"
|
||||
|
||||
mark_as_prompted
|
||||
|
||||
printf "\n"
|
||||
print_success "Ersteinrichtung vollständig abgeschlossen!"
|
||||
printf "%b\n" "Sie können dieses Menü jederzeit erneut aufrufen mit:"
|
||||
printf "%b\n" " ${CLR_BOLD}/usr/local/lib/first-login-setup/first-login-setup.sh --force${CLR_RESET}"
|
||||
printf "%b\n" "Oder einzelne Schritte direkt erneut ausführen, z. B.:"
|
||||
printf "%b\n" " ${CLR_BOLD}/usr/local/lib/first-login-setup/setup-junie-skills.sh${CLR_RESET}"
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# /usr/local/lib/first-login-setup/setup-dotfiles.sh
|
||||
# Interaktive Auswahl & Einrichtung der Desktop-Konfiguration (Dotfiles):
|
||||
# LinuxBeginnings Hyprland-Dots, eigenes Git-Repository, oder überspringen.
|
||||
#
|
||||
# Kann eigenständig ausgeführt werden, unabhängig von first-login-setup.sh.
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=_lib.sh
|
||||
source "$SCRIPT_DIR/_lib.sh"
|
||||
|
||||
install_linuxbeginnings() {
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[INFO] Starte Installation der LinuxBeginnings Hyprland-Dotfiles...${CLR_RESET}"
|
||||
printf "\n"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
sh <(curl -fsSL https://raw.githubusercontent.com/LinuxBeginnings/Hyprland-Dots/main/Distro-Hyprland.sh)
|
||||
else
|
||||
print_error "'curl' ist nicht installiert. Bitte installieren Sie curl und wiederholen Sie den Vorgang."
|
||||
fi
|
||||
}
|
||||
|
||||
clone_custom_repo() {
|
||||
if ! command -v git >/dev/null 2>&1; then
|
||||
printf "\n"
|
||||
print_error "'git' ist nicht installiert. Bitte installieren Sie git zuerst."
|
||||
return 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}--- Eigenes Git-Repository für ~/.config klonen ---${CLR_RESET}"
|
||||
printf "%b\n" "Geben Sie die Git-URL Ihres Dotfiles-/Config-Repositories an."
|
||||
printf "%b\n" "Beispiele:"
|
||||
printf "%b\n" " HTTPS : ${CLR_BLUE}https://github.com/Benutzername/mein-config-repo.git${CLR_RESET}"
|
||||
printf "%b\n" " SSH : ${CLR_BLUE}git@github.com:Benutzername/mein-config-repo.git${CLR_RESET}"
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_YELLOW}Hinweise zur Authentifizierung:${CLR_RESET}"
|
||||
printf "%b\n" " - ${CLR_BOLD}HTTPS:${CLR_RESET} Bei privaten Repositories fragt Git nach Benutzername & Personal Access Token (PAT)."
|
||||
printf "%b\n" " - ${CLR_BOLD}SSH:${CLR_RESET} Erfordert einen hinterlegten SSH-Schlüssel (z. B. in ~/.ssh/ oder via ssh-agent)."
|
||||
printf "\n"
|
||||
|
||||
read -r -p "Git-Repository-URL (oder 'q' zum Abbrechen): " repo_url
|
||||
repo_url="$(echo "$repo_url" | xargs)"
|
||||
|
||||
if [[ "$repo_url" == "q" || "$repo_url" == "Q" || -z "$repo_url" ]]; then
|
||||
print_warn "Vorgang abgebrochen. Kehre zum Hauptmenü zurück."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# SSH-Prüfung und Hilfestellung
|
||||
if [[ "$repo_url" =~ ^git@ || "$repo_url" =~ ^ssh:// ]]; then
|
||||
local ssh_keys_found=0
|
||||
if [[ -d "$HOME/.ssh" ]]; then
|
||||
for k in "$HOME/.ssh"/id_*; do
|
||||
if [[ -f "$k" && ! "$k" =~ \.pub$ ]]; then
|
||||
ssh_keys_found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "$ssh_keys_found" -eq 0 ]]; then
|
||||
printf "\n"
|
||||
print_warn "Es wurde kein lokaler SSH-Privatschlüssel in ~/.ssh/ gefunden."
|
||||
read -r -p "Möchten Sie vor dem Klonen ein neues SSH-Schlüsselpaar (ed25519) generieren? [j/N]: " gen_ssh || gen_ssh="n"
|
||||
if [[ "$gen_ssh" =~ ^[JjYy] ]]; then
|
||||
mkdir -p "$HOME/.ssh"
|
||||
chmod 700 "$HOME/.ssh"
|
||||
ssh-keygen -t ed25519 -f "$HOME/.ssh/id_ed25519" -C "$USER@$(hostname)"
|
||||
printf "\n%b\n" "${CLR_GREEN}Neuer öffentlicher SSH-Schlüssel (~/.ssh/id_ed25519.pub):${CLR_RESET}"
|
||||
cat "$HOME/.ssh/id_ed25519.pub"
|
||||
printf "\n%b\n" "Bitte fügen Sie diesen Schlüssel bei GitHub/GitLab zu Ihrem Account hinzu."
|
||||
if command -v wl-copy >/dev/null 2>&1; then
|
||||
if wl-copy < "$HOME/.ssh/id_ed25519.pub" 2>/dev/null; then
|
||||
print_success "(In die Zwischenablage kopiert!)"
|
||||
fi
|
||||
fi
|
||||
read -r -p "Drücken Sie Enter, sobald der SSH-Key hinterlegt wurde..."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Backup und Klon-Vorgang vorbereiten
|
||||
local timestamp
|
||||
timestamp="$(date +%Y%m%d_%H%M%S)"
|
||||
local backup_dir="$HOME/.config.backup_$timestamp"
|
||||
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_CYAN}[1/3] Sichere bestehendes ~/.config-Verzeichnis nach ${backup_dir}...${CLR_RESET}"
|
||||
|
||||
if [[ -d "$HOME/.config" ]]; then
|
||||
mv "$HOME/.config" "$backup_dir"
|
||||
fi
|
||||
|
||||
printf "%b\n" "${CLR_CYAN}[2/3] Klone Repository direkt nach ~/.config...${CLR_RESET}"
|
||||
|
||||
# Git ausführen mit aktivierter Terminal-Eingabeaufforderung für Authentifizierung
|
||||
if env GIT_TERMINAL_PROMPT=1 git clone --recurse-submodules "$repo_url" "$HOME/.config"; then
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[ERFOLG] Repository wurde erfolgreich nach ~/.config geklont!${CLR_RESET}"
|
||||
printf "%b\n" " - Ihr gesamter ${CLR_BOLD}~/.config${CLR_RESET}-Ordner ist nun das Git-Repository."
|
||||
printf "%b\n" " - Vorherige Konfigurationen wurden gesichert in: ${CLR_BOLD}${backup_dir}${CLR_RESET}"
|
||||
|
||||
# Hyprland-Konfiguration neu laden falls aktiv
|
||||
if command -v hyprctl >/dev/null 2>&1; then
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_CYAN}[3/3] Lade Hyprland-Konfiguration neu...${CLR_RESET}"
|
||||
hyprctl reload 2>/dev/null || true
|
||||
print_success "Hyprland erfolgreich aktualisiert."
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
print_success "Dotfiles-Einrichtung abgeschlossen!"
|
||||
return 0
|
||||
else
|
||||
printf "\n"
|
||||
print_error "Git Clone ist fehlgeschlagen (Authentifizierungsfehler, falsche URL oder Netzwerkproblem)."
|
||||
print_warn "[ROLLBACK] Stelle vorheriges ~/.config-Verzeichnis aus dem Backup wieder her..."
|
||||
rm -rf "$HOME/.config" 2>/dev/null || true
|
||||
if [[ -d "$backup_dir" ]]; then
|
||||
mv "$backup_dir" "$HOME/.config"
|
||||
print_success "Ursprüngliches ~/.config-Verzeichnis wurde vollständig wiederhergestellt."
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
read -r -p "Möchten Sie es erneut versuchen? [J/n]: " retry || retry="n"
|
||||
if [[ ! "$retry" =~ ^[JjYy] && -n "$retry" ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
run_dotfiles_menu() {
|
||||
print_header " Hyprland Desktop - Dotfiles Setup & Konfiguration "
|
||||
printf "%b\n" "Wie möchten Sie Ihre Desktop-Konfiguration (Dotfiles) einrichten?"
|
||||
printf "\n"
|
||||
printf "%b\n" " ${CLR_BOLD}[1]${CLR_RESET} ${CLR_GREEN}LinuxBeginnings Hyprland-Dotfiles installieren${CLR_RESET}"
|
||||
printf "%b\n" " Vollständig vorkonfiguriertes Setup (Waybar, Rofi, Animationen, Themes)"
|
||||
printf "%b\n" " URL: https://github.com/LinuxBeginnings/Hyprland-Dots"
|
||||
printf "\n"
|
||||
printf "%b\n" " ${CLR_BOLD}[2]${CLR_RESET} ${CLR_MAGENTA}Eigenes Git-Repository als ~/.config klonen${CLR_RESET}"
|
||||
printf "%b\n" " Klont Ihr eigenes Git-Repository direkt als vollständigen ~/.config-Ordner."
|
||||
printf "%b\n" " (Unterstützt HTTPS & SSH inkl. Authentifizierung)"
|
||||
printf "\n"
|
||||
printf "%b\n" " ${CLR_BOLD}[3]${CLR_RESET} ${CLR_YELLOW}Überspringen / Basiskonfiguration beibehalten${CLR_RESET}"
|
||||
printf "%b\n" " Keine Änderungen vornehmen (kann später manuell eingerichtet werden)."
|
||||
printf "\n"
|
||||
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}------------------------------------------------------------------------------${CLR_RESET}"
|
||||
|
||||
while true; do
|
||||
read -r -p "Bitte wählen Sie eine Option [1-3] (Standard: 1): " choice || choice="1"
|
||||
choice="$(echo "$choice" | xargs)"
|
||||
[[ -z "$choice" ]] && choice="1"
|
||||
|
||||
case "$choice" in
|
||||
1)
|
||||
install_linuxbeginnings
|
||||
break
|
||||
;;
|
||||
2)
|
||||
clone_custom_repo
|
||||
break
|
||||
;;
|
||||
3)
|
||||
printf "\n"
|
||||
print_warn "Dotfiles-Einrichtung übersprungen. Die Basiskonfiguration bleibt aktiv."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
print_error "Ungültige Eingabe. Bitte 1, 2 oder 3 wählen."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Nur ausführen, wenn das Skript direkt gestartet wird (nicht bei source)
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
run_dotfiles_menu
|
||||
fi
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# /usr/local/lib/first-login-setup/setup-junie-cli.sh
|
||||
# Installiert die JetBrains Junie CLI.
|
||||
#
|
||||
# Kann eigenständig ausgeführt werden, unabhängig von first-login-setup.sh.
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=_lib.sh
|
||||
source "$SCRIPT_DIR/_lib.sh"
|
||||
|
||||
install_junie_cli() {
|
||||
print_header " JetBrains Junie CLI Installation "
|
||||
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
if curl -fsSL https://junie.jetbrains.com/install.sh | bash; then
|
||||
print_success "JetBrains Junie CLI erfolgreich installiert."
|
||||
else
|
||||
print_warn "Installation von JetBrains Junie CLI fehlgeschlagen oder unterbrochen."
|
||||
fi
|
||||
else
|
||||
print_error "'curl' ist nicht installiert. Junie CLI konnte nicht geladen werden."
|
||||
fi
|
||||
}
|
||||
|
||||
# Nur ausführen, wenn das Skript direkt gestartet wird (nicht bei source)
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
install_junie_cli
|
||||
fi
|
||||
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# /usr/local/lib/first-login-setup/setup-junie-skills.sh
|
||||
# Klont/aktualisiert AwesomeJunieSkills in ~/.junie/skills, verknüpft alle
|
||||
# gefundenen Skills und trägt das Repository in ~/.junie/config.json ein.
|
||||
#
|
||||
# Kann eigenständig ausgeführt werden, unabhängig von first-login-setup.sh.
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=_lib.sh
|
||||
source "$SCRIPT_DIR/_lib.sh"
|
||||
|
||||
install_junie_skills() {
|
||||
print_header " AwesomeJunieSkills Installation "
|
||||
|
||||
local skills_dir="$HOME/.junie/skills"
|
||||
local repo_dir="$skills_dir/awesome-junie-skills"
|
||||
mkdir -p "$skills_dir"
|
||||
|
||||
if ! command -v git >/dev/null 2>&1; then
|
||||
print_error "'git' ist nicht installiert. AwesomeJunieSkills konnte nicht eingerichtet werden."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -d "$repo_dir/.git" ]]; then
|
||||
print_info "Repository existiert bereits in $repo_dir. Führe 'git pull' aus..."
|
||||
if git -C "$repo_dir" pull --ff-only 2>/dev/null; then
|
||||
print_success "AwesomeJunieSkills erfolgreich aktualisiert."
|
||||
else
|
||||
print_warn "'git pull' in $repo_dir fehlgeschlagen."
|
||||
fi
|
||||
else
|
||||
print_info "Klone AwesomeJunieSkills nach $repo_dir..."
|
||||
rm -rf "$repo_dir" 2>/dev/null || true
|
||||
if git clone https://github.com/alebaffa/awesome-junie-skills.git "$repo_dir"; then
|
||||
print_success "AwesomeJunieSkills erfolgreich nach $repo_dir geklont."
|
||||
else
|
||||
print_warn "Klonen von AwesomeJunieSkills fehlgeschlagen."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Symlinks für alle Skills im Skill-Hauptordner erstellen
|
||||
if [[ -d "$repo_dir" ]]; then
|
||||
local count=0
|
||||
for skill_path in "$repo_dir"/*; do
|
||||
if [[ -d "$skill_path" && -f "$skill_path/SKILL.md" ]]; then
|
||||
local s_name
|
||||
s_name="$(basename "$skill_path")"
|
||||
ln -sfn "$skill_path" "$skills_dir/$s_name"
|
||||
((count++)) || true
|
||||
fi
|
||||
done
|
||||
print_success "$count Skills verknüpft in '$skills_dir' (kann via 'git pull' in '$repo_dir' aktualisiert werden)."
|
||||
fi
|
||||
|
||||
# Junie config.json konfigurieren (skill-locations)
|
||||
mkdir -p "$HOME/.junie"
|
||||
local config_file="$HOME/.junie/config.json"
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
python3 -c "
|
||||
import json, os
|
||||
cfg_path = os.path.expanduser('$config_file')
|
||||
repo_path = os.path.expanduser('$repo_dir')
|
||||
data = {}
|
||||
if os.path.exists(cfg_path):
|
||||
try:
|
||||
with open(cfg_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
except Exception:
|
||||
data = {}
|
||||
locs = data.get('skill-locations', [])
|
||||
if repo_path not in locs:
|
||||
locs.append(repo_path)
|
||||
data['skill-locations'] = locs
|
||||
with open(cfg_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Nur ausführen, wenn das Skript direkt gestartet wird (nicht bei source)
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
install_junie_skills
|
||||
fi
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# /usr/local/lib/first-login-setup/setup-shell.sh
|
||||
# Richtet Oh-My-Zsh samt nützlicher Plugins (autosuggestions, syntax-highlighting)
|
||||
# für den aktuellen Benutzer ein.
|
||||
#
|
||||
# Kann eigenständig ausgeführt werden, unabhängig von first-login-setup.sh.
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=_lib.sh
|
||||
source "$SCRIPT_DIR/_lib.sh"
|
||||
|
||||
install_oh_my_zsh() {
|
||||
local zsh_dir="$HOME/.oh-my-zsh"
|
||||
print_header " Oh-My-Zsh & Shell-Konfiguration "
|
||||
|
||||
if [[ ! -d "$zsh_dir" ]]; then
|
||||
print_info "Richte Oh-My-Zsh für $USER ein..."
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
if git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$zsh_dir"; then
|
||||
mkdir -p "$zsh_dir/custom/plugins"
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$zsh_dir/custom/plugins/zsh-autosuggestions" 2>/dev/null || true
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "$zsh_dir/custom/plugins/zsh-syntax-highlighting" 2>/dev/null || true
|
||||
print_success "Oh-My-Zsh erfolgreich eingerichtet."
|
||||
else
|
||||
print_warn "Oh-My-Zsh konnte nicht geklont werden."
|
||||
fi
|
||||
else
|
||||
print_error "'git' ist nicht installiert. Oh-My-Zsh konnte nicht eingerichtet werden."
|
||||
fi
|
||||
else
|
||||
# Plugins sicherstellen
|
||||
if [[ ! -d "$zsh_dir/custom/plugins/zsh-autosuggestions" ]] && command -v git >/dev/null 2>&1; then
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$zsh_dir/custom/plugins/zsh-autosuggestions" 2>/dev/null || true
|
||||
fi
|
||||
if [[ ! -d "$zsh_dir/custom/plugins/zsh-syntax-highlighting" ]] && command -v git >/dev/null 2>&1; then
|
||||
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "$zsh_dir/custom/plugins/zsh-syntax-highlighting" 2>/dev/null || true
|
||||
fi
|
||||
print_success "Oh-My-Zsh ist bereits vorhanden und konfiguriert."
|
||||
fi
|
||||
}
|
||||
|
||||
# Nur ausführen, wenn das Skript direkt gestartet wird (nicht bei source)
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
install_oh_my_zsh
|
||||
fi
|
||||
@@ -47,9 +47,6 @@ fi
|
||||
if [[ -d "$SCRIPT_DIR/data/skel/.config" ]]; then
|
||||
mkdir -p /etc/skel/.config
|
||||
cp -r "$SCRIPT_DIR"/data/skel/.config/* /etc/skel/.config/ 2>/dev/null || true
|
||||
if [[ -d /etc/skel/.config/hypr/scripts ]]; then
|
||||
chmod 0755 /etc/skel/.config/hypr/scripts/*.sh 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Provision Oh-My-Zsh template in /etc/skel so newly created users receive it automatically
|
||||
@@ -92,9 +89,6 @@ fi
|
||||
|
||||
if [[ -d "$SCRIPT_DIR/data/skel/.config" ]]; then
|
||||
cp -r "$SCRIPT_DIR"/data/skel/.config/* "$TARGET_HOME/.config/" 2>/dev/null || true
|
||||
if [[ -d "$TARGET_HOME/.config/hypr/scripts" ]]; then
|
||||
chmod 0755 "$TARGET_HOME"/.config/hypr/scripts/*.sh 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. Install Oh-My-Zsh for Target User (if not already installed)
|
||||
|
||||
+32
-13
@@ -41,21 +41,40 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Ensure rudimentary Hyprland config is deployed to /etc/skel
|
||||
# 2. Install first-login-setup system-wide (shared by all users, not copied
|
||||
# into individual home directories) and enable its systemd --user service
|
||||
# globally, exactly as 'systemctl --global enable' would apply to every user.
|
||||
log_substep "Installing first-login-setup system-wide to /usr/local/lib/first-login-setup..."
|
||||
if [[ -d "$SCRIPT_DIR/data/usr/local/lib/first-login-setup" ]]; then
|
||||
mkdir -p /usr/local/lib/first-login-setup
|
||||
cp "$SCRIPT_DIR"/data/usr/local/lib/first-login-setup/*.sh /usr/local/lib/first-login-setup/
|
||||
chmod 0755 /usr/local/lib/first-login-setup/*.sh
|
||||
chown -R root:root /usr/local/lib/first-login-setup
|
||||
fi
|
||||
|
||||
if [[ -f "$SCRIPT_DIR/data/etc/systemd/user/first-login-setup.service" ]]; then
|
||||
mkdir -p /etc/systemd/user
|
||||
cp "$SCRIPT_DIR/data/etc/systemd/user/first-login-setup.service" /etc/systemd/user/first-login-setup.service
|
||||
if command_exists systemctl; then
|
||||
systemctl --global enable first-login-setup.service 2>/dev/null || log_warn "Could not globally enable first-login-setup.service via systemctl."
|
||||
else
|
||||
# Fallback: replicate what 'systemctl --global enable' would do.
|
||||
mkdir -p /etc/systemd/user/default.target.wants
|
||||
ln -sfn "../first-login-setup.service" /etc/systemd/user/default.target.wants/first-login-setup.service
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3. Ensure rudimentary Hyprland config is deployed to /etc/skel
|
||||
log_substep "Deploying rudimentary Hyprland configuration to /etc/skel..."
|
||||
mkdir -p /etc/skel/.config/hypr/scripts
|
||||
mkdir -p /etc/skel/.config/hypr
|
||||
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" ]]; then
|
||||
cp "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" /etc/skel/.config/hypr/hyprland.conf
|
||||
fi
|
||||
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" ]]; then
|
||||
cp "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" /etc/skel/.config/hypr/scripts/install-dots-prompt.sh
|
||||
chmod 0755 /etc/skel/.config/hypr/scripts/install-dots-prompt.sh
|
||||
fi
|
||||
chown -R root:root /etc/skel/.config
|
||||
|
||||
# 3. Deploy rudimentary Hyprland config to target user
|
||||
# 4. Deploy rudimentary Hyprland config to target user
|
||||
log_substep "Deploying rudimentary Hyprland configuration to $TARGET_HOME/.config/hypr..."
|
||||
mkdir -p "$TARGET_HOME/.config/hypr/scripts"
|
||||
mkdir -p "$TARGET_HOME/.config/hypr"
|
||||
|
||||
if [[ -f "$TARGET_HOME/.config/hypr/hyprland.conf" ]]; then
|
||||
backup_file_or_dir "$TARGET_HOME/.config/hypr/hyprland.conf"
|
||||
@@ -64,17 +83,17 @@ fi
|
||||
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" ]]; then
|
||||
cp "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" "$TARGET_HOME/.config/hypr/hyprland.conf"
|
||||
fi
|
||||
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" ]]; then
|
||||
cp "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" "$TARGET_HOME/.config/hypr/scripts/install-dots-prompt.sh"
|
||||
chmod 0755 "$TARGET_HOME/.config/hypr/scripts/install-dots-prompt.sh"
|
||||
fi
|
||||
|
||||
chown -R "$TARGET_USER:$TARGET_USER" "$TARGET_HOME/.config/hypr"
|
||||
|
||||
log_success "Rudimentary Hyprland configuration deployed:"
|
||||
log_info " - SUPER+ENTER: Kitty Terminal"
|
||||
log_info " - SUPER+Q: Close Active Window"
|
||||
log_info " - Login Prompt: Asks user after login to choose Dotfiles setup & installs JetBrains Junie CLI + AwesomeJunieSkills"
|
||||
log_info " - Ersteinrichtung (Dotfiles, Oh-My-Zsh, Junie CLI & Skills) startet automatisch beim"
|
||||
log_info " nächsten Login jedes Benutzers über den systemweiten systemd --user Service"
|
||||
log_info " 'first-login-setup.service' (unabhängig vom gewählten Compositor, NICHT über"
|
||||
log_info " hyprland.conf). Läuft nur beim ersten Login bzw. nach 'Später' erneut."
|
||||
log_info " Manueller Aufruf jederzeit möglich mit: /usr/local/lib/first-login-setup/first-login-setup.sh --force"
|
||||
|
||||
create_timeshift_snapshot "Stage 10: Post-Hyprland desktop setup" "O"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user