| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- #!/bin/bash
- # --- НАСТРОЙКИ ---
- # Цвета для вывода
- GREEN="\033[1;32m"
- YELLOW="\033[1;33m"
- RED="\033[1;31m"
- NC="\033[0m" # No Color
- # Путь к этому скрипту и его папке
- SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
- # Имена файлов с пакетами
- PACMAN_PKGS="pkglist.txt"
- AUR_PKGS="aurlist.txt"
- # --- НАСТРОЙКИ СИМЛИНКОВ (Имена папок в репозитории) ---
- CONFIG_DIR_NAME="config"
- HOME_DIR_NAME="home"
- SYSTEM_DIR_NAME="system"
- # --- ХЕЛПЕРЫ ---
- msg() {
- echo -e "${GREEN}[INFO]${NC} $1"
- }
- warn() {
- echo -e "${YELLOW}[WARN]${NC} $1"
- }
- err() {
- echo -e "${RED}[ERROR]${NC} $1"
- }
- # --- ФУНКЦИИ ---
- # 1. Установка YAY (AUR Helper)
- install_yay() {
- if ! command -v yay &>/dev/null; then
- msg "YAY не найден. Установка YAY..."
- if ! pacman -Q git &>/dev/null || ! pacman -Q base-devel &>/dev/null; then
- sudo pacman -S --needed git base-devel
- fi
-
- rm -rf /tmp/yay
- git clone https://aur.archlinux.org/yay.git /tmp/yay
- (cd /tmp/yay && makepkg -si --noconfirm)
- rm -rf /tmp/yay
- msg "YAY установлен."
- else
- msg "YAY уже установлен."
- fi
- }
- # 2. Установка пакетов (Pacman и YAY)
- install_packages() {
- msg "Сбор пакетов для установки..."
- # Основные пакеты
- local pacman_args=$(sed 's/#.*//' "$SCRIPT_DIR/$PACMAN_PKGS" | grep -vE '^\s*$' | xargs)
- local aur_args=$(sed 's/#.*//' "$SCRIPT_DIR/$AUR_PKGS" | grep -vE '^\s*$' | xargs)
- # --- Поиск и выбор дополнительных пакетов ---
- local optional_pacman_lists=($(find "$SCRIPT_DIR" -maxdepth 1 -name "pkglist-*.txt" ! -name "$PACMAN_PKGS"))
- local optional_aur_lists=($(find "$SCRIPT_DIR" -maxdepth 1 -name "aurlist-*.txt" ! -name "$AUR_PKGS"))
- if [ ${#optional_pacman_lists[@]} -gt 0 ] || [ ${#optional_aur_lists[@]} -gt 0 ]; then
- warn "Найдены дополнительные списки пакетов:"
- for list in "${optional_pacman_lists[@]}"; do echo " -> $(basename "$list") (Pacman)"; done
- for list in "${optional_aur_lists[@]}"; do echo " -> $(basename "$list") (AUR)"; done
-
- read -p "Хотите выбрать пакеты из этих списков для установки? [y/N]: " choice < /dev/tty
- if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
- for list in "${optional_pacman_lists[@]}"; do
- read -p " -> Установить из '$(basename "$list")'? [y/N]: " list_choice < /dev/tty
- if [[ "$list_choice" == "y" || "$list_choice" == "Y" ]]; then
- pacman_args+=" $(sed 's/#.*//' "$list" | grep -vE '^\s*$' | xargs)"
- fi
- done
- for list in "${optional_aur_lists[@]}"; do
- read -p " -> Установить из '$(basename "$list")'? [y/N]: " list_choice < /dev/tty
- if [[ "$list_choice" == "y" || "$list_choice" == "Y" ]]; then
- aur_args+=" $(sed 's/#.*//' "$list" | grep -vE '^\s*$' | xargs)"
- fi
- done
- fi
- fi
- # --- Установка пакетов Pacman ---
- if [[ ! -z "$pacman_args" ]]; then
- msg "Установка пакетов из Pacman..."
- sudo pacman -S --needed $pacman_args
- else
- msg "Список Pacman для установки пуст."
- fi
-
- # --- Установка пакетов AUR ---
- if [[ ! -z "$aur_args" ]]; then
- msg "Проверка и установка YAY..."
- install_yay
- msg "Установка пакетов из AUR..."
- yay -S --needed $aur_args
- else
- msg "Список AUR для установки пуст."
- fi
-
- msg "Установка пакетов завершена."
- }
- # 3. (НОВАЯ) Рекурсивная функция линковки
- link_item() {
- local src="$1"
- local dest="$2"
-
- # Проверка источника
- if [ ! -e "$src" ]; then
- return
- fi
- # 1. Если цель существует и это директория (и не симлинк)
- # И источник тоже директория
- # -> РЕКУРСИЯ (MERGE)
- if [ -d "$dest" ] && [ ! -L "$dest" ] && [ -d "$src" ]; then
- # msg " [DIR] Вход в $dest"
- for child in "$src"/*; do
- [ -e "$child" ] || continue
- local child_name=$(basename "$child")
- link_item "$child" "$dest/$child_name"
- done
- return
- fi
- # 2. Если цель существует (файл или симлинк)
- if [ -e "$dest" ] || [ -L "$dest" ]; then
- # Если это уже правильный симлинк - пропускаем
- if [ -L "$dest" ]; then
- local current_target=$(readlink -f "$dest")
- local source_absolute=$(readlink -f "$src")
- if [ "$current_target" == "$source_absolute" ]; then
- # msg " [OK] $dest уже указывает на правильный файл"
- return
- fi
- fi
-
- # Если это файл или неправильный симлинк - бэкап
- warn " [BACKUP] $dest существует. Бэкап -> $dest.bak"
- mv "$dest" "$dest.bak"
- fi
- # 3. Создаем симлинк
- # Создаем родительскую папку, если её нет (например для ~/.config/foo/bar)
- mkdir -p "$(dirname "$dest")"
- ln -sfn "$src" "$dest"
- msg " [LINK] $dest -> $src"
- }
- # 4. Создание символических ссылок (Обновлено)
- link_dotfiles() {
- msg "Создание символических ссылок..."
- # ВАЖНО: Предварительно создаем критические системные папки.
- # Это заставит функцию link_item использовать режим MERGE (рекурсию) для них,
- # вместо создания симлинка на всю папку.
- msg " -> Подготовка структуры папок..."
- mkdir -p "$HOME/.config"
- mkdir -p "$HOME/.local/share"
- mkdir -p "$HOME/.local/state"
- mkdir -p "$HOME/.local/bin"
- # mkdir -p "$HOME/bin" # Если используется
- # --- 1. Линкуем файлы в $HOME (из папки 'home') ---
- msg " -> Обработка '$HOME_DIR_NAME'..."
- local source_dir="$SCRIPT_DIR/$HOME_DIR_NAME"
-
- if [ -d "$source_dir" ]; then
- for item_path in "$source_dir"/*; do
- [ -e "$item_path" ] || continue # Пропуск, если папка пуста
- local item_name=$(basename "$item_path")
- # Вызываем рекурсивную функцию
- link_item "$item_path" "$HOME/$item_name"
- done
- fi
- # --- 2. Линкуем файлы в $HOME/.config (из папки 'config') ---
- msg " -> Обработка '$CONFIG_DIR_NAME'..."
- source_dir="$SCRIPT_DIR/$CONFIG_DIR_NAME"
-
- if [ -d "$source_dir" ]; then
- for item_path in "$source_dir"/*; do
- [ -e "$item_path" ] || continue
- local item_name=$(basename "$item_path")
- link_item "$item_path" "$HOME/.config/$item_name"
- done
- fi
-
- msg "Симлинки обработаны."
- }
- # 5. Проверка текущей конфигурации
- check_config() {
- msg "Проверка установленных пакетов Pacman..."
- local missing_pacman=0
- # Ищем pkglist.txt и pkglist-*.txt
- for f in $(find "$SCRIPT_DIR" -maxdepth 1 -name "pkglist*.txt"); do
- while IFS= read -r line || [[ -n "$line" ]]; do
- local pkg=$(echo "$line" | sed 's/#.*//' | xargs)
- if [[ -z "$pkg" ]]; then continue; fi
- if [[ "$pkg" == "xorg" ]]; then continue; fi
- if ! pacman -Q "$pkg" &>/dev/null; then
- warn " -> Не найден (Pacman, из $(basename "$f")): $pkg"
- missing_pacman=1
- fi
- done < "$f"
- done
- if [ $missing_pacman -eq 0 ]; then msg "Все пакеты Pacman установлены."; fi
- msg "Проверка установленных пакетов AUR..."
- local missing_aur=0
- for f in $(find "$SCRIPT_DIR" -maxdepth 1 -name "aurlist*.txt"); do
- while IFS= read -r line || [[ -n "$line" ]]; do
- local pkg=$(echo "$line" | sed 's/#.*//' | xargs)
- if [[ -z "$pkg" ]]; then continue; fi
- if ! pacman -Q "$pkg" &>/dev/null; then
- warn " -> Не найден (AUR, из $(basename "$f")): $pkg"
- missing_aur=1
- fi
- done < "$f"
- done
- if [ $missing_aur -eq 0 ]; then msg "Все пакеты AUR установлены."; fi
-
- msg "Проверка симлинков (выборочная)..."
- # Просто проверим наличие ссылок для корневых элементов
- local source_dir="$SCRIPT_DIR/$HOME_DIR_NAME"
- if [ -d "$source_dir" ]; then
- for item_path in "$source_dir"/*; do
- [ -e "$item_path" ] || continue
- local item_name=$(basename "$item_path")
- # Если это папка .local, проверяем глубже
- if [ "$item_name" == ".local" ]; then
- if [ ! -d "$HOME/.local" ]; then warn " -> Папка $HOME/.local отсутствует!"; fi
- elif [ ! -e "$HOME/$item_name" ]; then
- warn " -> Элемент не найден: $HOME/$item_name"
- fi
- done
- fi
- msg "Проверка завершена."
- }
- # 6. Проверка драйверов
- check_drivers() {
- msg "Проверка оборудования и рекомендации по драйверам..."
-
- if ! command -v lspci &>/dev/null; then
- warn "Команда lspci не найдена. Установите пакет 'pciutils'."
- return
- fi
-
- local vga=$(lspci -k | grep -A 2 -E "(VGA|3D)")
-
- if echo "$vga" | grep -iq "NVIDIA"; then
- warn "Найдена карта NVIDIA. Рекомендуемые пакеты:"
- warn " -> nvidia (или nvidia-lts, nvidia-dkms)"
- warn " -> lib32-nvidia-utils"
- elif echo "$vga" | grep -iq "Intel"; then
- msg "Найдена карта Intel. Рекомендуемые пакеты:"
- msg " -> mesa, lib32-mesa, vulkan-intel"
- elif echo "$vga" | grep -iq "AMD"; then
- msg "Найдена карта AMD/ATI. Рекомендуемые пакеты:"
- msg " -> mesa, lib32-mesa, vulkan-radeon"
- fi
-
- if lspci -k | grep -iq "broadcom"; then
- warn "Найден чип Broadcom. Возможно нужен: broadcom-wl-dkms"
- fi
- }
- # 7. Применение системных конфигов
- apply_system_configs() {
- msg "--- РЕЖИМ: ПРИМЕНЕНИЕ СИСТЕМНЫХ КОНФИГОВ ---"
- local system_source_dir="$SCRIPT_DIR/$SYSTEM_DIR_NAME"
-
- if [ ! -d "$system_source_dir" ]; then
- err "Папка '$system_source_dir' не найдена."
- return 1
- fi
-
- find "$system_source_dir" -type f | while read -r source_file; do
- local rel_path=${source_file#$system_source_dir/}
- local target_file="/$rel_path"
-
- msg "Конфиг: $rel_path"
-
- if [ ! -f "$target_file" ]; then
- warn " Файл '$target_file' не существует в системе."
- read -p " Скопировать? [y/N]: " choice < /dev/tty
- if [[ "$choice" =~ ^[yY]$ ]]; then
- sudo mkdir -p "$(dirname "$target_file")"
- sudo cp "$source_file" "$target_file"
- msg " -> СКОПИРОВАНО."
- fi
- continue
- fi
-
- if command -v diff &>/dev/null; then
- if ! diff -q "$target_file" "$source_file" &>/dev/null; then
- msg " Найдены различия:"
- diff -u "$target_file" "$source_file" | head -n 20
-
- warn " Заменить системный файл?"
- read -p " [y/N/b] (Да / Нет / Бэкап): " choice < /dev/tty
- case "$choice" in
- y|Y)
- sudo cp "$source_file" "$target_file"
- msg " -> ЗАМЕНЕНО."
- ;;
- b|B)
- sudo mv "$target_file" "$target_file.bak"
- sudo cp "$source_file" "$target_file"
- msg " -> БЭКАП И ЗАМЕНА."
- ;;
- esac
- else
- msg " -> Идентичны."
- fi
- else
- warn " diff не установлен, сравнение невозможно."
- fi
- done
- }
- # 8. Создание папок пользователя
- create_user_dirs() {
- msg "Проверка стандартных папок пользователя..."
- # Если xdg-user-dirs установлен, лучше использовать его
- if command -v xdg-user-dirs-update &>/dev/null; then
- xdg-user-dirs-update
- msg " -> Выполнен xdg-user-dirs-update"
- else
- mkdir -p "$HOME/Documents" "$HOME/Downloads" "$HOME/Pictures"
- msg " -> Папки созданы (fallback)."
- fi
- }
- # --- ГЛАВНЫЙ БЛОК ---
- show_help() {
- echo "Dotfiles Manager"
- echo "Команды:"
- echo " install - Установить пакеты, создать ссылки."
- echo " check - Проверка статуса."
- echo " update - git pull + install."
- echo " drivers - Рекомендации по драйверам."
- echo " system - Системные конфиги (/etc)."
- }
- if [ "$EUID" -eq 0 ]; then
- err "Запускайте от пользователя, не от root!"
- exit 1
- fi
- if [ $# -eq 0 ]; then show_help; exit 0; fi
- case "$1" in
- install)
- msg "--- УСТАНОВКА ---"
- install_packages
- link_dotfiles
- create_user_dirs
- msg "Готово."
- ;;
- check)
- check_config
- ;;
- update)
- msg "--- ОБНОВЛЕНИЕ ---"
- if git pull; then
- install_packages
- link_dotfiles
- create_user_dirs
- msg "Обновлено."
- else
- err "Ошибка git pull."
- fi
- ;;
- drivers)
- check_drivers
- ;;
- system)
- apply_system_configs
- ;;
- help|*)
- show_help
- ;;
- esac
|