Files
dotfiles/Scripts/install.sh
T

490 lines
16 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# --- Источники загрузки ------------------------------------------------------
# По умолчанию всё тянется с домашнего сервера. Любое значение можно
# переопределить переменной окружения, например:
# DOTFILES_REPO=https://github.com/retrilzzy/dotfiles.git ./install.sh
DOTFILES_REPO="${DOTFILES_REPO:-https://revaks-git.duckdns.org/revaks/dotfiles.git}"
YAY_REPO="${YAY_REPO:-https://revaks-git.duckdns.org/revaks/yay.git}"
OHMYZSH_INSTALLER="${OHMYZSH_INSTALLER:-https://revaks-git.duckdns.org/revaks/ohmyzsh/raw/branch/master/tools/install.sh}"
P10K_REPO="${P10K_REPO:-https://revaks-git.duckdns.org/revaks/powerlevel10k.git}"
ZSH_AS_REPO="${ZSH_AS_REPO:-https://revaks-git.duckdns.org/revaks/zsh-autosuggestions.git}"
ZSH_SH_REPO="${ZSH_SH_REPO:-https://revaks-git.duckdns.org/revaks/zsh-syntax-highlighting.git}"
BIBATA_URL="${BIBATA_URL:-https://revaks-git.duckdns.org/revaks/bibata-cursor/releases/download/v2.0.7/Bibata-Modern-Classic.tar.xz}"
WALLPAPERS_API="${WALLPAPERS_API:-https://revaks-git.duckdns.org/api/v1/repos/revaks/wallpapers/contents}"
WALLPAPERS_RAW="${WALLPAPERS_RAW:-https://revaks-git.duckdns.org/revaks/wallpapers/raw/branch/main}"
WALLPAPERS_PAGE="${WALLPAPERS_PAGE:-https://revaks-git.duckdns.org/revaks/wallpapers}"
# -----------------------------------------------------------------------------
# Directories
DOTFILES_DIR="${DOTFILES_DIR:-$HOME/dotfiles}"
BACKUP_DIR="${BACKUP_DIR:-$HOME/.config-backups}"
WALLPAPER_DIR="${WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"
# Colors
C_ACCENT="#5BA3FF"
C_ACCENT_BRIGHT="#5BC0FF"
C_SUCCESS="#00FF7F"
C_WARNING="#FFD700"
C_ERROR="#FF1744"
C_BORDER_HIGHLIGHT="#5BA3FF"
C_BG_DARK="#0A0A0F"
C_BG_MED="#2A2D3E"
export GUM_CHOOSE_CURSOR_FOREGROUND="$C_ACCENT_BRIGHT"
export GUM_CHOOSE_HEADER_FOREGROUND="$C_ACCENT"
export GUM_CHOOSE_SELECTED_FOREGROUND="$C_ACCENT"
export GUM_CONFIRM_PROMPT_FOREGROUND="$C_ACCENT"
export GUM_CONFIRM_SELECTED_BACKGROUND="$C_ACCENT"
export GUM_CONFIRM_SELECTED_FOREGROUND="$C_BG_DARK"
export GUM_CONFIRM_UNSELECTED_BACKGROUND="$C_BG_MED"
export GUM_SPIN_SPINNER_FOREGROUND="$C_ACCENT"
# Error handling
handle_error() {
local exit_code=$?
local line_number=$1
local command=$2
local error_message="Error on line $line_number: command '$command' exited with status $exit_code"
if command -v gum &>/dev/null; then
gum style --foreground "$C_ERROR" "$error_message"
else
echo -e "\033[1;31m$error_message\033[0m"
fi
exit $exit_code
}
trap 'handle_error $LINENO "$BASH_COMMAND"' ERR
# Output helpers
print_section() {
gum style --border normal --margin "1" --padding "1 2" --border-foreground "$C_BORDER_HIGHLIGHT" "$1"
}
print_info() {
echo -n "$(gum style --bold --foreground "$C_ACCENT_BRIGHT" 'Info: ')"
gum style --foreground "$C_ACCENT_BRIGHT" "$1"
}
print_warning() {
echo -n "$(gum style --bold --foreground "$C_WARNING" 'Warning: ')"
gum style --foreground "$C_WARNING" "$1"
}
print_error() {
echo -n "$(gum style --bold --foreground "$C_ERROR" 'Error: ')"
gum style --foreground "$C_ERROR" "$1"
}
print_success() {
echo -n "$(gum style --bold --foreground "$C_SUCCESS" 'Success: ')"
gum style --foreground "$C_SUCCESS" "$1"
}
print_action() {
echo -n "$(gum style --bold --foreground "$C_ACCENT" 'Action: ')"
gum style --foreground "$C_ACCENT" "$1"
}
confirm() {
gum confirm "$1" --affirmative="Yes" --negative="No"
}
# Installation functions
ensure_core_deps() {
if ! command -v pacman &>/dev/null; then
echo -e "\033[1;31mError: pacman is not available. This script is for Arch-based distributions.\033[0m"
exit 1
fi
if sudo pacman -S --noconfirm --needed git base-devel gum jq; then
echo -e "\033[1;32mCore dependencies ready.\033[0m"
else
echo -e "\033[1;31mFailed to install dependencies.\033[0m"
exit 1
fi
}
clone_repo() {
print_section "Cloning or Updating Dotfiles Repository"
if [ -d "$DOTFILES_DIR" ]; then
print_info "Dotfiles directory exists. Pulling latest changes."
pushd "$DOTFILES_DIR" >/dev/null
if git pull --rebase --autostash; then
print_success "Dotfiles updated."
if git diff --name-only 'HEAD@{1}' HEAD | grep -q "Scripts/install.sh"; then
print_info "Installation script updated. Restarting..."
exec "$DOTFILES_DIR/Scripts/install.sh"
fi
else
print_error "Failed to pull dotfiles."
popd >/dev/null
exit 1
fi
popd >/dev/null
else
print_info "Cloning dotfiles repository."
if git clone --depth=10 "$DOTFILES_REPO" "$DOTFILES_DIR"; then
print_success "Dotfiles cloned."
else
print_error "Failed to clone dotfiles."
exit 1
fi
fi
}
setup_pacman() {
print_section "Configuring Pacman"
if confirm "Overwrite /etc/pacman.conf?"; then
print_info "Backing up /etc/pacman.conf to /etc/pacman.conf.bak"
sudo cp /etc/pacman.conf /etc/pacman.conf.bak || true
sudo cp "$DOTFILES_DIR/Configs/etc/pacman.conf" /etc/pacman.conf
print_success "pacman.conf overwritten."
else
print_warning "Skipping pacman.conf overwrite."
fi
print_section "Updating System"
sudo pacman -Syu --noconfirm
print_success "System updated."
}
ensure_yay() {
if ! command -v yay &>/dev/null; then
print_section "Installing AUR Helper (yay)"
local tmp_dir
tmp_dir=$(mktemp -d)
git clone --depth=1 "$YAY_REPO" "$tmp_dir"
(
cd "$tmp_dir"
makepkg -si --noconfirm
)
rm -rf "$tmp_dir"
print_success "Yay installed."
else
print_warning "Yay is already installed."
fi
}
install_pacman() {
local to_install=()
for pkg in "$@"; do
if ! pacman -Qq "$pkg" &>/dev/null; then
to_install+=("$pkg")
fi
done
if [ ${#to_install[@]} -gt 0 ]; then
print_info "Installing Pacman packages: ${to_install[*]}"
sudo pacman -S --noconfirm --needed "${to_install[@]}"
print_success "Installed: ${to_install[*]}"
fi
}
install_yay() {
local to_install=()
for pkg in "$@"; do
if ! yay -Qq "$pkg" &>/dev/null; then
to_install+=("$pkg")
fi
done
if [ ${#to_install[@]} -gt 0 ]; then
print_info "Installing AUR packages: ${to_install[*]}"
yay -S --noconfirm "${to_install[@]}"
print_success "Installed: ${to_install[*]}"
else
print_warning "packages already installed. (yay)"
fi
}
run_service() {
local service_name="$1"
shift
local cmd=("$@")
print_info "Starting service: $service_name"
if pgrep -x "$service_name" >/dev/null; then
print_warning "Service $service_name is already running. Killing it first."
killall "$service_name" && sleep 1
fi
local launch_cmd
if command -v uwsm &>/dev/null && [ -n "${UWSM_SESSION_ID:-}" ]; then
launch_cmd=(uwsm app -- "${cmd[@]}")
else
launch_cmd=("${cmd[@]}")
fi
"${launch_cmd[@]}" >/dev/null 2>&1 &
disown
print_success "$service_name started."
}
install_bibata_cursor() {
print_section "Installing Bibata Cursor"
local tmp_dir
tmp_dir=$(mktemp -d)
if gum spin --spinner dot --title "Downloading Bibata cursor..." -- \
curl -L ""$BIBATA_URL"" -o "$tmp_dir/bibata.tar.xz"; then
tar -xf "$tmp_dir/bibata.tar.xz" -C "$tmp_dir"
sudo cp -r "$tmp_dir/Bibata-Modern-Classic" /usr/share/icons/
print_success "Bibata cursor installed."
else
print_error "Failed to download Bibata cursor."
fi
rm -rf "$tmp_dir"
}
setup_zsh() {
print_section "Setting up Zsh & Plugins"
install_pacman zsh
if [ ! -d "$HOME/.oh-my-zsh" ]; then
sh -c "$(curl -fsSL "$OHMYZSH_INSTALLER")" "" --unattended
fi
sudo chsh -s "$(which zsh)" "$USER"
git clone --depth=1 "$P10K_REPO" "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k" || true
git clone --depth=1 "$ZSH_SH_REPO" "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting" || true
git clone --depth=1 "$ZSH_AS_REPO" "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions" || true
print_success "Zsh setup complete."
}
backup_configs() {
print_section "Backing Up Current Configs"
local date_now
date_now=$(date +%Y-%m-%d_%H-%M-%S)
local backup_dir="$BACKUP_DIR/$date_now"
mkdir -p "$backup_dir/.config" "$backup_dir/etc" "$backup_dir/.local/share/nwg-look"
print_info "Backing up current configs to $backup_dir"
shopt -s nullglob
for dir in "$DOTFILES_DIR"/Configs/.config/*; do
local name
name=$(basename "$dir")
if [ "$name" = "discord" ]; then continue; fi
if [ -d "$HOME/.config/$name" ]; then
print_info "Moving $HOME/.config/$name to $backup_dir/.config/"
mv "$HOME/.config/$name" "$backup_dir/.config/"
fi
done
local home_files=(".zshrc" ".p10k.zsh" ".nanorc")
for file in "${home_files[@]}"; do
if [ -f "$HOME/$file" ]; then
print_info "Moving $HOME/$file to $backup_dir/"
mv "$HOME/$file" "$backup_dir/"
fi
done
cp "$HOME/.local/share/nwg-look/gsettings" "$backup_dir/.local/share/nwg-look/" || true
shopt -u nullglob
print_success "Backup complete."
}
apply_configs() {
print_section "Applying New Configs"
print_info "Applying new configurations..."
mkdir -p "$HOME/.config" "$HOME/.local/share/nwg-look"
cp -a "$DOTFILES_DIR/Configs/.config/." "$HOME/.config/"
cp "$DOTFILES_DIR/Configs/.zshrc" "$DOTFILES_DIR/Configs/.p10k.zsh" "$DOTFILES_DIR/Configs/.nanorc" "$HOME/"
print_success "New configurations applied."
}
run_initial_services() {
print_section "Running Essential Services"
if pgrep -x "dunst" >/dev/null; then
killall dunst && sleep 0.3
fi
if pgrep -x "mako" >/dev/null; then
killall mako && sleep 0.3
fi
run_service "swaync" swaync -c "$HOME/.config/swaync/config.json"
run_service "nm-applet" nm-applet
run_service "vicinae" vicinae server
run_service "awww-daemon" awww-daemon
run_service "waybar" waybar -c "$HOME/.config/waybar/config.jsonc" -s "$HOME/.config/waybar/styles.css"
}
setup_wallpapers() {
print_section "Setting Up Wallpapers"
mkdir -p "$WALLPAPER_DIR"
print_info "Downloading a few random wallpapers..."
print_info "Full collection: $WALLPAPERS_PAGE"
local names
names=$(curl -s "$WALLPAPERS_API" | jq -r '.[].name' | shuf -n 5)
if [ -z "$names" ]; then
print_error "Could not fetch wallpaper list. Is 'jq' installed and are you online?"
return 1
fi
local downloaded_count=0
set +e
while IFS= read -r name; do
[ -z "$name" ] && continue
local dest="$WALLPAPER_DIR/$name"
if [ -f "$dest" ]; then
print_info "Wallpaper '$name' already exists, skipping."
((downloaded_count++))
continue
fi
local url="$WALLPAPERS_RAW/$name"
if gum spin --spinner dot --title "Downloading $name" -- \
curl --fail -L -s --connect-timeout 10 --max-time 60 -o "$dest" "$url"; then
print_success "Downloaded: $url"
((downloaded_count++))
else
print_error "Failed to download $url."
rm -f "$dest"
fi
done <<<"$names"
set -e
if [ "$downloaded_count" -eq 0 ]; then
print_error "No wallpapers were downloaded. Cannot set theme."
return 1
fi
print_success "Downloaded $downloaded_count wallpapers to $WALLPAPER_DIR"
mkdir -p "$HOME/.local/share/color-schemes"
if "$HOME/.config/bin/change-wall.sh" "$WALLPAPER_DIR"; then
print_success "Wallpaper and theme set."
else
print_warning "Failed to set wallpaper. You can do it manually later."
fi
}
setup_theme() {
print_section "Applying GTK Theme"
cp "$DOTFILES_DIR/Configs/.local/share/nwg-look/gsettings" "$HOME/.local/share/nwg-look/gsettings"
gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3-dark'
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'
nwg-look -a || print_warning "Failed to apply theme via nwg-look. It might not be critical."
print_success "GTK theme applied."
}
reload_services() {
print_section "Reloading Services"
run_service "waybar" waybar -c "$HOME/.config/waybar/config.jsonc" -s "$HOME/.config/waybar/styles.css"
print_success "Services reloaded."
}
# Entrypoint
main() {
if [ "$EUID" -eq 0 ]; then
echo -e "\033[1;31mThis script must not be run as root.\033[0m"
exit 1
fi
if ! sudo -v; then
echo -e "\033[1;31mSudo privileges are required to run this script.\033[0m"
exit 1
fi
ensure_core_deps
clear
if ! [[ "${XDG_CURRENT_DESKTOP:-}" == "Hyprland" && -n "${UWSM_FINALIZE_VARNAMES:-}" ]]; then
print_warning "This script is optimized for Hyprland with UWSM."
if ! confirm "You don't seem to be in a UWSM-managed Hyprland session. Some features might not work as expected. Continue anyway?"; then
exit 0
fi
fi
gum style --border normal --margin "1" --padding "1 2" --border-foreground "$C_ACCENT" "Retrilz's Dotfiles Installer"
local CHOICES
CHOICES=$(gum choose --no-limit --height 15 --cursor " > " \
--header "Select components to install" \
"Clone/Update Dotfiles Repository" "Configure Pacman & Update System" "Install AUR Helper (yay)" \
"Install System Interface packages" "Install Utilities & Tools packages" \
"Install Networking & Audio packages" "Install Appearance & Theme packages" \
"Setup Zsh & Plugins" "Backup Current Configs" "Apply New Configs" "Run Essential Services" "Setup Wallpapers & GTK Theme" \
--selected "*")
if [[ "$CHOICES" == *"Clone/Update Dotfiles Repository"* ]]; then
clone_repo
fi
if [[ "$CHOICES" == *"Configure Pacman & Update System"* ]]; then
setup_pacman
fi
if [[ "$CHOICES" == *"Install AUR Helper (yay)"* ]]; then
ensure_yay
fi
if [[ "$CHOICES" == *"Install System Interface packages"* ]]; then
print_section "Installing System Interface packages"
install_pacman hyprlock hypridle kitty nwg-look swaync waybar awww hyprshot
install_yay waypaper wlogout vicinae-bin
fi
if [[ "$CHOICES" == *"Install Utilities & Tools packages"* ]]; then
print_section "Installing Utilities & Tools"
install_pacman brightnessctl imagemagick fastfetch grim gnome-keyring tar lsd pavucontrol playerctl satty trash-cli uwsm wl-clipboard wl-clip-persist jq
install_yay gpu-screen-recorder nautilus network-manager-applet
fi
if [[ "$CHOICES" == *"Install Networking & Audio packages"* ]]; then
print_section "Installing Networking & Audio packages"
install_pacman networkmanager bluez blueman pipewire pipewire-pulse pipewire-audio pipewire-alsa polkit-gnome xdg-utils xdg-desktop-portal xdg-desktop-portal-hyprland xdg-desktop-portal-gtk xdg-desktop-portal-wlr
fi
if [[ "$CHOICES" == *"Install Appearance & Theme packages"* ]]; then
print_section "Installing Appearance & Theme packages"
install_pacman adw-gtk-theme frameworkintegration inter-font noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra papirus-icon-theme ttf-jetbrains-mono-nerd
install_yay matugen-bin qt5ct-kde qt6ct-kde darkly-bin
install_bibata_cursor
fi
if [[ "$CHOICES" == *"Setup Zsh & Plugins"* ]]; then
setup_zsh
fi
if [[ "$CHOICES" == *"Backup Current Configs"* ]]; then
backup_configs
fi
if [[ "$CHOICES" == *"Apply New Configs"* ]]; then
apply_configs
fi
if [[ "$CHOICES" == *"Run Essential Services"* ]]; then
run_initial_services
fi
if [[ "$CHOICES" == *"Setup Wallpapers & GTK Theme"* ]]; then
sleep 2
setup_wallpapers
setup_theme
reload_services
fi
print_success "Installation complete!"
print_action "It is recommended to reboot your system to apply all changes."
if confirm "Switch to zsh now?"; then
exec zsh
fi
}
main "$@"