diff --git a/data/etc/systemd/user/first-login-setup.service b/data/etc/systemd/user/first-login-setup.service new file mode 100644 index 0000000..bb88e8f --- /dev/null +++ b/data/etc/systemd/user/first-login-setup.service @@ -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 diff --git a/data/skel/.config/hypr/hyprland.conf b/data/skel/.config/hypr/hyprland.conf index 73c5f76..0e5780d 100644 --- a/data/skel/.config/hypr/hyprland.conf +++ b/data/skel/.config/hypr/hyprland.conf @@ -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 diff --git a/data/skel/.config/hypr/scripts/install-dots-prompt.sh b/data/skel/.config/hypr/scripts/install-dots-prompt.sh deleted file mode 100755 index 4bbe9e9..0000000 --- a/data/skel/.config/hypr/scripts/install-dots-prompt.sh +++ /dev/null @@ -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}" diff --git a/data/usr/local/lib/first-login-setup/_lib.sh b/data/usr/local/lib/first-login-setup/_lib.sh new file mode 100755 index 0000000..10e6f99 --- /dev/null +++ b/data/usr/local/lib/first-login-setup/_lib.sh @@ -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}" +} diff --git a/data/usr/local/lib/first-login-setup/first-login-setup.sh b/data/usr/local/lib/first-login-setup/first-login-setup.sh new file mode 100755 index 0000000..92081e6 --- /dev/null +++ b/data/usr/local/lib/first-login-setup/first-login-setup.sh @@ -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}" diff --git a/data/usr/local/lib/first-login-setup/setup-dotfiles.sh b/data/usr/local/lib/first-login-setup/setup-dotfiles.sh new file mode 100755 index 0000000..8388416 --- /dev/null +++ b/data/usr/local/lib/first-login-setup/setup-dotfiles.sh @@ -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 diff --git a/data/usr/local/lib/first-login-setup/setup-junie-cli.sh b/data/usr/local/lib/first-login-setup/setup-junie-cli.sh new file mode 100755 index 0000000..d88dc81 --- /dev/null +++ b/data/usr/local/lib/first-login-setup/setup-junie-cli.sh @@ -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 diff --git a/data/usr/local/lib/first-login-setup/setup-junie-skills.sh b/data/usr/local/lib/first-login-setup/setup-junie-skills.sh new file mode 100755 index 0000000..984f881 --- /dev/null +++ b/data/usr/local/lib/first-login-setup/setup-junie-skills.sh @@ -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 diff --git a/data/usr/local/lib/first-login-setup/setup-shell.sh b/data/usr/local/lib/first-login-setup/setup-shell.sh new file mode 100755 index 0000000..025c09b --- /dev/null +++ b/data/usr/local/lib/first-login-setup/setup-shell.sh @@ -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 diff --git a/stages/07-skel-and-user.sh b/stages/07-skel-and-user.sh index d470f8b..c9cc304 100755 --- a/stages/07-skel-and-user.sh +++ b/stages/07-skel-and-user.sh @@ -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) diff --git a/stages/10-hyprland.sh b/stages/10-hyprland.sh index a73b918..7f5bf07 100755 --- a/stages/10-hyprland.sh +++ b/stages/10-hyprland.sh @@ -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"