New update script
This commit is contained in:
parent
9fa71efe70
commit
d6e16d1155
10
bashrc_arch
10
bashrc_arch
@ -6,14 +6,18 @@ esac
|
||||
|
||||
# don't put duplicate lines or lines starting with space in the history.
|
||||
# See bash(1) for more options
|
||||
HISTCONTROL=ignoreboth
|
||||
HISTCONTROL=ignoreboth:erasedups
|
||||
|
||||
# append to the history file, don't overwrite it
|
||||
shopt -s histappend
|
||||
# Save multi-line commands as single entry
|
||||
shopt -s cmdhist
|
||||
# Save history immediately after each command
|
||||
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
|
||||
|
||||
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
|
||||
HISTSIZE=1000
|
||||
HISTFILESIZE=2000
|
||||
HISTSIZE=10000
|
||||
HISTFILESIZE=20000
|
||||
|
||||
# check the window size after each command and, if necessary,
|
||||
# update the values of LINES and COLUMNS.
|
||||
|
||||
@ -135,10 +135,6 @@ cursor {
|
||||
hide_on_key_press = true
|
||||
}
|
||||
|
||||
gestures {
|
||||
workspace_swipe = false
|
||||
}
|
||||
|
||||
device {
|
||||
name = elecom-trackball-mouse-deft-pro-trackball-1
|
||||
sensitivity = 0.7
|
||||
|
||||
46
update/arch/arch.sh
Normal file
46
update/arch/arch.sh
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux Master Module
|
||||
# Loads all Arch-specific modules and orchestrates installation
|
||||
|
||||
# Source all Arch modules
|
||||
source "$SCRIPT_DIR/arch/system.sh"
|
||||
source "$SCRIPT_DIR/arch/development.sh"
|
||||
source "$SCRIPT_DIR/arch/terminal.sh"
|
||||
source "$SCRIPT_DIR/arch/desktop.sh"
|
||||
source "$SCRIPT_DIR/arch/gaming.sh"
|
||||
source "$SCRIPT_DIR/arch/music.sh"
|
||||
source "$SCRIPT_DIR/arch/lab.sh"
|
||||
|
||||
# Main Arch installation function
|
||||
arch_install_all() {
|
||||
log SECTION "Starting Arch Linux installation"
|
||||
|
||||
# System setup (drivers, core system, Hyprland)
|
||||
arch_setup_system
|
||||
|
||||
# Terminal environment (CLI tools, modern replacements)
|
||||
arch_setup_terminal
|
||||
|
||||
# Development environment (languages, LSPs, tools)
|
||||
arch_setup_development
|
||||
|
||||
# Desktop applications (GUI apps, work tools)
|
||||
arch_setup_desktop
|
||||
|
||||
# Gaming setup (Steam, Wine, VR)
|
||||
arch_setup_gaming
|
||||
|
||||
# Music production
|
||||
arch_setup_music_production
|
||||
|
||||
# Lab equipment
|
||||
arch_setup_lab
|
||||
|
||||
log SUCCESS "Arch Linux installation completed"
|
||||
}
|
||||
|
||||
# Source guard
|
||||
if [ -z "$ARCH_MASTER_LOADED" ]; then
|
||||
ARCH_MASTER_LOADED=true
|
||||
fi
|
||||
287
update/arch/desktop.sh
Normal file
287
update/arch/desktop.sh
Normal file
@ -0,0 +1,287 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux Desktop Applications Module
|
||||
# Handles desktop applications, fonts, and user applications
|
||||
|
||||
arch_install_desktop_base() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing desktop base applications"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install base desktop applications?"; then
|
||||
local desktop_packages=(
|
||||
cameractrls feh
|
||||
)
|
||||
|
||||
install_packages "${desktop_packages[@]}"
|
||||
|
||||
# Essential Flatpak applications
|
||||
local flatpak_apps=(
|
||||
"com.discordapp.Discord"
|
||||
"com.behringer.XAirEdit"
|
||||
"com.github.vikdevelop.timer"
|
||||
"io.github.efogdev.mpris-timer"
|
||||
"org.remmina.Remmina"
|
||||
)
|
||||
|
||||
for app in "${flatpak_apps[@]}"; do
|
||||
install_flatpak_apps "$app"
|
||||
done
|
||||
|
||||
# Brave browser from AUR
|
||||
install_aur_packages brave-bin
|
||||
|
||||
log SUCCESS "Desktop base applications installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_fonts() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing fonts"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install additional fonts?"; then
|
||||
local font_packages=(
|
||||
noto-fonts poppler-data adobe-source-code-pro-fonts
|
||||
ttf-liberation ttf-dejavu
|
||||
)
|
||||
|
||||
install_packages "${font_packages[@]}"
|
||||
|
||||
log SUCCESS "Fonts installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_desktop_work() {
|
||||
if ! role_enabled "DESKTOP_WORK"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing desktop work applications"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install work applications (KiCad, FreeCad, etc.)?"; then
|
||||
# Applications from official repos
|
||||
local work_packages=(
|
||||
kicad freecad
|
||||
)
|
||||
|
||||
install_packages "${work_packages[@]}"
|
||||
|
||||
# Work applications from Flatpak
|
||||
local work_flatpaks=(
|
||||
"org.kde.krita"
|
||||
"com.prusa3d.PrusaSlicer"
|
||||
"com.jgraph.drawio.desktop"
|
||||
"org.gimp.GIMP"
|
||||
)
|
||||
|
||||
for app in "${work_flatpaks[@]}"; do
|
||||
install_flatpak_apps "$app"
|
||||
done
|
||||
|
||||
log SUCCESS "Desktop work applications installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_media_apps() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing media applications"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install media applications (video, image viewers, etc.)?"; then
|
||||
local media_packages=(
|
||||
mpv vlc imv imagemagick
|
||||
)
|
||||
|
||||
install_packages "${media_packages[@]}"
|
||||
|
||||
# Media Flatpak applications
|
||||
local media_flatpaks=(
|
||||
"org.videolan.VLC"
|
||||
"org.kde.kdenlive"
|
||||
)
|
||||
|
||||
for app in "${media_flatpaks[@]}"; do
|
||||
if confirm "Install $(basename $app)?"; then
|
||||
install_flatpak_apps "$app"
|
||||
fi
|
||||
done
|
||||
|
||||
log SUCCESS "Media applications installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_office_apps() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing office applications"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install office applications?"; then
|
||||
local office_flatpaks=(
|
||||
"org.libreoffice.LibreOffice"
|
||||
"com.github.jeromerobert.pdfarranger"
|
||||
)
|
||||
|
||||
for app in "${office_flatpaks[@]}"; do
|
||||
if confirm "Install $(basename $app)?"; then
|
||||
install_flatpak_apps "$app"
|
||||
fi
|
||||
done
|
||||
|
||||
log SUCCESS "Office applications installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_system_utilities() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing system utilities"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install system utilities (file managers, etc.)?"; then
|
||||
local utility_packages=(
|
||||
thunar thunar-archive-plugin thunar-media-tags-plugin
|
||||
file-roller gparted
|
||||
)
|
||||
|
||||
install_packages "${utility_packages[@]}"
|
||||
|
||||
log SUCCESS "System utilities installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_communication() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing communication applications"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install communication apps (beyond Discord)?"; then
|
||||
local comm_flatpaks=(
|
||||
"com.slack.Slack"
|
||||
"org.signal.Signal"
|
||||
"us.zoom.Zoom"
|
||||
)
|
||||
|
||||
for app in "${comm_flatpaks[@]}"; do
|
||||
if confirm "Install $(basename $app)?"; then
|
||||
install_flatpak_apps "$app"
|
||||
fi
|
||||
done
|
||||
|
||||
log SUCCESS "Communication applications installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_development_gui() {
|
||||
if ! role_enabled "DESKTOP_BASE" || (! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"); then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing GUI development tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install GUI development tools?"; then
|
||||
local dev_gui_flatpaks=(
|
||||
"com.visualstudio.code"
|
||||
"com.jetbrains.IntelliJ-IDEA-Community"
|
||||
)
|
||||
|
||||
for app in "${dev_gui_flatpaks[@]}"; do
|
||||
if confirm "Install $(basename $app)?"; then
|
||||
install_flatpak_apps "$app"
|
||||
fi
|
||||
done
|
||||
|
||||
log SUCCESS "GUI development tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_desktop_environment() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Setting up desktop environment"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
# Setup XDG directories
|
||||
mkdir -p ~/Desktop ~/Documents ~/Downloads ~/Music ~/Pictures ~/Videos
|
||||
|
||||
# Set up mime types and default applications
|
||||
if command_exists xdg-settings; then
|
||||
# Set default browser if Brave is installed
|
||||
if command_exists brave; then
|
||||
xdg-settings set default-web-browser brave-browser.desktop
|
||||
fi
|
||||
fi
|
||||
|
||||
log SUCCESS "Desktop environment configured $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
# Special applications for specific hostnames
|
||||
arch_install_hostname_specific() {
|
||||
local hostname="${SYSTEM_INFO[HOSTNAME]}"
|
||||
|
||||
case "$hostname" in
|
||||
"CMBOX")
|
||||
log SECTION "Installing CMBOX-specific applications"
|
||||
if confirm "Install CMBOX-specific apps?"; then
|
||||
# CMBOX might need specific tools for work
|
||||
local cmbox_flatpaks=("com.obsproject.Studio")
|
||||
for app in "${cmbox_flatpaks[@]}"; do
|
||||
install_flatpak_apps "$app"
|
||||
done
|
||||
fi
|
||||
;;
|
||||
"LABBOX")
|
||||
log SECTION "Installing LABBOX-specific applications"
|
||||
if confirm "Install LABBOX-specific apps?"; then
|
||||
# Lab-specific GUI tools
|
||||
local lab_packages=("wireshark-qt")
|
||||
install_packages "${lab_packages[@]}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Main function to run all desktop setup
|
||||
arch_setup_desktop() {
|
||||
if ! role_enabled "DESKTOP_BASE"; then
|
||||
log INFO "Desktop roles not enabled - skipping desktop setup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
arch_install_desktop_base
|
||||
arch_install_fonts
|
||||
arch_install_desktop_work
|
||||
arch_install_media_apps
|
||||
arch_install_office_apps
|
||||
arch_install_system_utilities
|
||||
arch_install_communication
|
||||
arch_install_development_gui
|
||||
arch_setup_desktop_environment
|
||||
arch_install_hostname_specific
|
||||
}
|
||||
|
||||
# Source guard
|
||||
if [ -z "$ARCH_DESKTOP_LOADED" ]; then
|
||||
ARCH_DESKTOP_LOADED=true
|
||||
fi
|
||||
283
update/arch/development.sh
Normal file
283
update/arch/development.sh
Normal file
@ -0,0 +1,283 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux Development Environment Module
|
||||
# Handles programming languages, tools, and development setup
|
||||
|
||||
arch_install_development_languages() {
|
||||
log SECTION "Installing development languages and runtimes"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install development languages (Node.js, Go, PHP, Ruby, Julia, Java)?"; then
|
||||
local dev_packages=(
|
||||
nodejs npm go php luarocks composer jdk-openjdk julia ruby
|
||||
)
|
||||
|
||||
install_packages "${dev_packages[@]}"
|
||||
|
||||
# Configure npm prefix
|
||||
npm config set prefix "${HOME}/.npm"
|
||||
|
||||
log SUCCESS "Development languages installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_neovim() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT" && ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing Neovim"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Neovim (git version)?"; then
|
||||
# Install git version of neovim from AUR
|
||||
install_aur_packages neovim-git-bin
|
||||
|
||||
# Install Node.js integration
|
||||
if command_exists npm; then
|
||||
sudo npm install -g neovim
|
||||
fi
|
||||
|
||||
# Setup Neovim configuration
|
||||
mkdir -p ~/.config/nvim
|
||||
ln -sf ~/linuxbox/config/nvim/init.lua ~/.config/nvim/init.lua
|
||||
|
||||
# Sync plugins if lazy directory exists
|
||||
if [ -d ~/.local/share/nvim/lazy ]; then
|
||||
nvim --headless "+Lazy! sync" +qa || true
|
||||
fi
|
||||
|
||||
log SUCCESS "Neovim installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_rust_tools() {
|
||||
log SECTION "Installing Rust development tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Rust tools (cargo packages)?"; then
|
||||
# Essential Rust tools
|
||||
local rust_tools=(
|
||||
"tree-sitter-cli"
|
||||
"ripgrep"
|
||||
"eza"
|
||||
"zoxide --locked"
|
||||
"starship --locked"
|
||||
)
|
||||
|
||||
for tool in "${rust_tools[@]}"; do
|
||||
log INFO "Installing $tool..."
|
||||
cargo install $tool
|
||||
done
|
||||
|
||||
# Setup starship configuration
|
||||
mkdir -p ~/.config
|
||||
ln -sf ~/linuxbox/config/starship.toml ~/.config/starship.toml
|
||||
|
||||
log SUCCESS "Rust tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_embedded_tools() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "LAB"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing embedded development tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install embedded development tools (RP2040, etc.)?"; then
|
||||
# Add embedded target for Rust
|
||||
rustup target add thumbv6m-none-eabi
|
||||
|
||||
# Install embedded-specific cargo tools
|
||||
local embedded_tools=(
|
||||
"elf2uf2-rs --locked"
|
||||
"probe-run"
|
||||
"flip-link"
|
||||
)
|
||||
|
||||
for tool in "${embedded_tools[@]}"; do
|
||||
log INFO "Installing $tool..."
|
||||
cargo install $tool
|
||||
done
|
||||
|
||||
# Link pico-load script
|
||||
mkdir -p ~/.local/bin
|
||||
ln -sf ~/linuxbox/pico-load.sh ~/.local/bin/pico-load
|
||||
|
||||
log SUCCESS "Embedded tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_lsp_servers() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing LSP servers"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Language Server Protocol servers?"; then
|
||||
# LSP servers from official repos
|
||||
local lsp_packages=(
|
||||
prettier stylua python-black shfmt lua-language-server
|
||||
bash-language-server ccls vscode-html-languageserver
|
||||
vscode-json-languageserver marksman pyright yaml-language-server
|
||||
vscode-css-languageserver clang
|
||||
)
|
||||
|
||||
install_packages "${lsp_packages[@]}"
|
||||
|
||||
# LSP servers from AUR
|
||||
install_aur_packages dockerfile-language-server
|
||||
|
||||
# Rust components
|
||||
rustup component add rust-analyzer clippy rustfmt
|
||||
|
||||
# Lua configuration
|
||||
ln -sf ~/linuxbox/luacheckrc ~/.luacheckrc
|
||||
|
||||
log SUCCESS "LSP servers installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_virtualhere() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "LAB"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing VirtualHere USB client"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install VirtualHere USB over IP client?"; then
|
||||
cd ~
|
||||
|
||||
# Download VirtualHere client files
|
||||
local vh_files=(
|
||||
"virtualhereclient.service"
|
||||
"vhclientx86_64"
|
||||
"vhuit64"
|
||||
)
|
||||
|
||||
local vh_base_url="https://www.virtualhere.com/sites/default/files/usbclient"
|
||||
|
||||
for file in "${vh_files[@]}"; do
|
||||
if [ "$file" == "virtualhereclient.service" ]; then
|
||||
wget "${vh_base_url}/scripts/$file"
|
||||
else
|
||||
wget "${vh_base_url}/$file"
|
||||
fi
|
||||
done
|
||||
|
||||
# Make executables and install
|
||||
chmod +x ./vhclientx86_64 ./vhuit64
|
||||
sudo mv ./vhclientx86_64 /usr/sbin
|
||||
sudo mv ./vhuit64 /usr/sbin
|
||||
|
||||
# Setup sudo permissions
|
||||
echo "$USER ALL=(ALL:ALL) NOPASSWD: /usr/sbin/vhclientx86_64" | \
|
||||
sudo tee /etc/sudoers.d/$USER+vhclientx86_64
|
||||
echo "$USER ALL=(ALL:ALL) NOPASSWD: /usr/sbin/vhuit64" | \
|
||||
sudo tee /etc/sudoers.d/$USER+vhuit64
|
||||
|
||||
# Install and enable service
|
||||
sudo mv virtualhereclient.service /etc/systemd/system/virtualhereclient.service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable virtualhereclient.service
|
||||
sudo systemctl start virtualhereclient.service
|
||||
|
||||
log SUCCESS "VirtualHere client installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_git() {
|
||||
log SECTION "Setting up Git configuration"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
# Install git-lfs if not present
|
||||
if ! command_exists git-lfs; then
|
||||
install_packages git-lfs
|
||||
fi
|
||||
|
||||
# Link git configuration
|
||||
ln -sf ~/linuxbox/gitconfig ~/.gitconfig
|
||||
|
||||
log SUCCESS "Git configuration setup $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
arch_install_lazygit() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing Lazygit"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Lazygit Git TUI?"; then
|
||||
install_packages lazygit
|
||||
|
||||
# Setup lazygit configuration
|
||||
mkdir -p ~/.config/lazygit
|
||||
ln -sf ~/linuxbox/config/lazygit/config.yml ~/.config/lazygit/config.yml
|
||||
|
||||
log SUCCESS "Lazygit installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_containers() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing container tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install container tools (Docker, Podman)?"; then
|
||||
# Install from official repositories or AUR
|
||||
local container_packages=()
|
||||
|
||||
if confirm "Install Docker?"; then
|
||||
container_packages+=(docker docker-compose)
|
||||
fi
|
||||
|
||||
if confirm "Install Podman?"; then
|
||||
container_packages+=(podman podman-compose)
|
||||
fi
|
||||
|
||||
if [ ${#container_packages[@]} -gt 0 ]; then
|
||||
install_packages "${container_packages[@]}"
|
||||
|
||||
# Add user to docker group if docker was installed
|
||||
if [[ " ${container_packages[@]} " =~ " docker " ]]; then
|
||||
sudo usermod -aG docker $USER
|
||||
log INFO "Added $USER to docker group - logout/login required"
|
||||
fi
|
||||
fi
|
||||
|
||||
log SUCCESS "Container tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function to run all development setup
|
||||
arch_setup_development() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"; then
|
||||
log INFO "Development roles not enabled - skipping development setup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
arch_setup_git
|
||||
arch_install_development_languages
|
||||
arch_install_neovim
|
||||
arch_install_rust_tools
|
||||
arch_install_embedded_tools
|
||||
arch_install_lsp_servers
|
||||
arch_install_virtualhere
|
||||
arch_install_lazygit
|
||||
arch_install_containers
|
||||
}
|
||||
|
||||
# Source guard
|
||||
if [ -z "$ARCH_DEVELOPMENT_LOADED" ]; then
|
||||
ARCH_DEVELOPMENT_LOADED=true
|
||||
fi
|
||||
147
update/arch/gaming.sh
Normal file
147
update/arch/gaming.sh
Normal file
@ -0,0 +1,147 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux Gaming Module
|
||||
# Handles gaming, VR, and entertainment software
|
||||
|
||||
arch_install_gaming_base() {
|
||||
if ! role_enabled "GAME"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing gaming base packages"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install gaming base (Wine, Steam, etc.)?"; then
|
||||
local gaming_packages=(
|
||||
wine wine-mono wine-gecko qt5-tools steam winetricks
|
||||
onnxruntime mangohud lib32-mangohud gamemode
|
||||
)
|
||||
|
||||
install_packages "${gaming_packages[@]}"
|
||||
|
||||
# Gaming tools from AUR
|
||||
local gaming_aur=(
|
||||
protonup-qt protontricks lug-helper openmpi jstest-gtk-git
|
||||
)
|
||||
|
||||
install_aur_packages "${gaming_aur[@]}"
|
||||
|
||||
log SUCCESS "Gaming base installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_opentrack() {
|
||||
if ! role_enabled "GAME"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing OpenTrack head tracking"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Build and install OpenTrack?"; then
|
||||
if [ ! -d ~/Games/opentrack ]; then
|
||||
mkdir -p ~/Games
|
||||
cd ~/Games
|
||||
|
||||
(
|
||||
git clone https://github.com/opentrack/opentrack
|
||||
cd opentrack/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
ccmake .
|
||||
make
|
||||
make install
|
||||
) 2>&1 | tee -a "$LOG_FILE" &
|
||||
|
||||
spinner $! "Building OpenTrack (this will take a while)..."
|
||||
wait
|
||||
|
||||
# Create desktop entry
|
||||
cat > /tmp/opentrack.desktop << EOF
|
||||
[Desktop Entry]
|
||||
Version=3.1.0
|
||||
Type=Application
|
||||
Name=Opentrack
|
||||
Exec=$HOME/Games/opentrack/build/install/bin/opentrack -platform xcb
|
||||
Icon=$HOME/Games/opentrack/contrib/cute-octopus-vector-material_15-1831.jpg
|
||||
Terminal=false
|
||||
StartupNotify=true
|
||||
EOF
|
||||
sudo mv /tmp/opentrack.desktop /usr/share/applications/opentrack.desktop
|
||||
sudo update-desktop-database /usr/share/applications
|
||||
fi
|
||||
|
||||
log SUCCESS "OpenTrack installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_simonbox_gaming() {
|
||||
if [ "${SYSTEM_INFO[HOSTNAME]}" != "SIMONBOX" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing SIMONBOX-specific gaming tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install SIMONBOX gaming packages?"; then
|
||||
# SIMONBOX specific packages
|
||||
local simonbox_packages=(
|
||||
fluidsynth gamemode gvfs libayatana-appindicator innoextract
|
||||
lib32-gamemode lib32-vkd3d python-pefile python-protobuf
|
||||
vulkan-icd-loader vkd3d lib32-vulkan-icd-loader vulkan-tools
|
||||
xorg-xgamma umu-launcher lutris
|
||||
)
|
||||
|
||||
install_packages "${simonbox_packages[@]}"
|
||||
|
||||
# Sober for Roblox
|
||||
install_flatpak_apps org.vinegarhq.Sober
|
||||
|
||||
log SUCCESS "SIMONBOX gaming setup completed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_vr() {
|
||||
if ! role_enabled "VR"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing VR support"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install VR tools (Monado, overlays)?"; then
|
||||
# VR development packages
|
||||
local vr_packages=(
|
||||
cli11 glib2-devel nlohmann-json glew
|
||||
)
|
||||
|
||||
install_packages "${vr_packages[@]}"
|
||||
|
||||
# VR tools from AUR
|
||||
local vr_aur=(
|
||||
monado-vulkan-layers-git wlx-overlay-s-git xrgears envision-xr-git
|
||||
)
|
||||
|
||||
install_aur_packages "${vr_aur[@]}"
|
||||
|
||||
log SUCCESS "VR support installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
arch_setup_gaming() {
|
||||
if ! role_enabled "GAME"; then
|
||||
log INFO "Gaming role not enabled - skipping gaming setup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
arch_install_gaming_base
|
||||
arch_install_opentrack
|
||||
arch_install_simonbox_gaming
|
||||
arch_install_vr
|
||||
}
|
||||
|
||||
if [ -z "$ARCH_GAMING_LOADED" ]; then
|
||||
ARCH_GAMING_LOADED=true
|
||||
fi
|
||||
41
update/arch/lab.sh
Normal file
41
update/arch/lab.sh
Normal file
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux Lab Equipment Module
|
||||
|
||||
arch_install_lab_tools() {
|
||||
if ! role_enabled "LAB"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing lab and measurement tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install lab equipment software?"; then
|
||||
# PicoScope and related tools from AUR
|
||||
local lab_aur=(
|
||||
ps7_libpicoipp ps7_libpicocv picoscope7
|
||||
ps7_libps2000a ps7_libps3000a
|
||||
nrf-udev nrfconnect-appimage
|
||||
)
|
||||
|
||||
install_aur_packages "${lab_aur[@]}"
|
||||
|
||||
# System packages for lab work
|
||||
local lab_packages=(tk python-pyserial)
|
||||
install_packages "${lab_packages[@]}"
|
||||
|
||||
# Download SPM6103 viewer
|
||||
cd ~ && wget -O spm6103_viewer.py \
|
||||
"https://git.cmtec.se/cm/spm6103_viewer/-/raw/main/spm6103_viewer.py?ref_type=heads&inline=false"
|
||||
|
||||
log SUCCESS "Lab tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_lab() {
|
||||
arch_install_lab_tools
|
||||
}
|
||||
|
||||
if [ -z "$ARCH_LAB_LOADED" ]; then
|
||||
ARCH_LAB_LOADED=true
|
||||
fi
|
||||
25
update/arch/music.sh
Normal file
25
update/arch/music.sh
Normal file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux Music Production Module
|
||||
|
||||
arch_setup_music_production() {
|
||||
if ! role_enabled "MUSIC"; then
|
||||
log INFO "Music role not enabled - skipping music production setup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing music production tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install music production software?"; then
|
||||
# Music production packages (already handled in system.sh for audio)
|
||||
# Install Bitwig Studio
|
||||
install_flatpak_apps com.bitwig.BitwigStudio
|
||||
|
||||
log SUCCESS "Music production tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -z "$ARCH_MUSIC_LOADED" ]; then
|
||||
ARCH_MUSIC_LOADED=true
|
||||
fi
|
||||
301
update/arch/system.sh
Normal file
301
update/arch/system.sh
Normal file
@ -0,0 +1,301 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux System Setup Module
|
||||
# Handles system packages, drivers, and core system configuration
|
||||
|
||||
arch_install_system_base() {
|
||||
log SECTION "Installing Arch system base packages"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install essential system packages?"; then
|
||||
local packages=(
|
||||
base-devel linux-headers git bc cmake gawk wget gettext unzip curl
|
||||
inetutils python python-pip python-pipx python-pynvim rustup timeshift
|
||||
)
|
||||
|
||||
install_packages "${packages[@]}"
|
||||
|
||||
# Setup Rust
|
||||
rustup update stable
|
||||
rustup default stable
|
||||
|
||||
log SUCCESS "System base packages installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_drivers() {
|
||||
log SECTION "Installing graphics drivers"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if role_enabled "NVIDIA_GPU" || role_enabled "NVIDIA_1080_GPU"; then
|
||||
if confirm "Install NVIDIA drivers?"; then
|
||||
log INFO "Installing NVIDIA drivers..."
|
||||
|
||||
# Check if we already have nvidia drivers
|
||||
local new_kernel="no"
|
||||
if ! package_installed nvidia-open-dkms && ! package_installed nvidia-dkms; then
|
||||
new_kernel="yes"
|
||||
fi
|
||||
|
||||
local nvidia_packages=(nvidia-dkms nvidia-utils nvidia-settings opencl-nvidia)
|
||||
|
||||
# Add CUDA for high-end GPUs
|
||||
if role_enabled "NVIDIA_1080_GPU"; then
|
||||
nvidia_packages+=(cuda)
|
||||
fi
|
||||
|
||||
# Add 32-bit libs for gaming
|
||||
if role_enabled "GAME"; then
|
||||
nvidia_packages+=(lib32-nvidia-utils)
|
||||
fi
|
||||
|
||||
install_packages "${nvidia_packages[@]}"
|
||||
|
||||
if [ "$new_kernel" == "yes" ]; then
|
||||
log WARNING "NVIDIA driver updated - kernel rebuild required"
|
||||
log WARNING "Please reboot and run the script again after reboot"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log SUCCESS "NVIDIA drivers installed $(show_timer $section_start)"
|
||||
fi
|
||||
else
|
||||
if confirm "Install Intel graphics drivers?"; then
|
||||
log INFO "Installing Intel graphics drivers..."
|
||||
install_packages mesa intel-media-driver
|
||||
log SUCCESS "Intel drivers installed $(show_timer $section_start)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_multilib() {
|
||||
if role_enabled "GAME"; then
|
||||
log SECTION "Enabling multilib repository"
|
||||
if ! grep -q "^\[multilib\]" /etc/pacman.conf; then
|
||||
if confirm "Enable multilib repository for gaming?"; then
|
||||
log INFO "Adding multilib repository..."
|
||||
sudo tee -a /etc/pacman.conf >/dev/null <<EOT
|
||||
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
EOT
|
||||
log SUCCESS "Multilib repository enabled"
|
||||
# Refresh databases after adding multilib
|
||||
update_package_databases
|
||||
fi
|
||||
else
|
||||
log INFO "Multilib repository already enabled"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_hyprland() {
|
||||
if ! role_enabled "HYPERLAND"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing Hyprland desktop environment"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Hyprland desktop environment?"; then
|
||||
# Core Hyprland packages
|
||||
local hypr_packages=(
|
||||
wayvnc nm-connection-editor usbutils plymouth dracut dunst hyprpaper
|
||||
hypridle hyprland hyprlock xdg-desktop-portal-hyprland polkit-gnome
|
||||
xorg-xhost gnome-keyring qt6ct gnome-themes-extra qt5-wayland qt6-wayland
|
||||
lxappearance qt5-tools adwaita-fonts gnome-disk-utility tk
|
||||
)
|
||||
|
||||
install_packages "${hypr_packages[@]}"
|
||||
|
||||
# AUR packages for Hyprland
|
||||
local hypr_aur_packages=(
|
||||
adwaita-qt5-git adwaita-qt6-git hyprshot walker-bin
|
||||
)
|
||||
|
||||
install_aur_packages "${hypr_aur_packages[@]}"
|
||||
|
||||
# Create configuration directories
|
||||
mkdir -p ~/.config/hypr ~/.local/bin
|
||||
|
||||
# Link Hyprland configurations
|
||||
local hostname="${SYSTEM_INFO[HOSTNAME]}"
|
||||
if [ -f ~/linuxbox/config/hypr/hyprland_$hostname.conf ]; then
|
||||
ln -sf ~/linuxbox/config/hypr/hyprland_$hostname.conf ~/.config/hypr/hyprland_extra.conf
|
||||
else
|
||||
touch ~/.config/hypr/hyprland_extra.conf
|
||||
fi
|
||||
|
||||
if [ -f ~/linuxbox/config/hypr/hypridle_$hostname.conf ]; then
|
||||
ln -sf ~/linuxbox/config/hypr/hypridle_$hostname.conf ~/.config/hypr/hypridle.conf
|
||||
else
|
||||
ln -sf ~/linuxbox/config/hypr/hypridle.conf ~/.config/hypr/hypridle.conf
|
||||
fi
|
||||
|
||||
# Link main configurations
|
||||
ln -sf ~/linuxbox/config/hypr/hyprland.conf ~/.config/hypr/hyprland.conf
|
||||
ln -sf ~/linuxbox/wrappedhl ~/.local/bin/wrappedhl
|
||||
ln -sf ~/linuxbox/config/hypr/hyprpaper.conf ~/.config/hypr/hyprpaper.conf
|
||||
|
||||
# Link theme configurations
|
||||
ln -sf ~/linuxbox/config/gtk-3.0 ~/.config
|
||||
ln -sf ~/linuxbox/config/qt5ct ~/.config
|
||||
ln -sf ~/linuxbox/config/qt6ct ~/.config
|
||||
ln -sf ~/linuxbox/config/dunst ~/.config
|
||||
ln -sf ~/linuxbox/config/walker ~/.config
|
||||
|
||||
log SUCCESS "Hyprland desktop environment installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_waybar() {
|
||||
if ! role_enabled "HYPERLAND"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing Waybar"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Waybar status bar?"; then
|
||||
install_packages waybar
|
||||
|
||||
mkdir -p ~/.config/waybar
|
||||
ln -sf ~/linuxbox/config/waybar/config ~/.config/waybar/config
|
||||
ln -sf ~/linuxbox/config/waybar/style.css ~/.config/waybar/style.css
|
||||
|
||||
log SUCCESS "Waybar installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_autologin() {
|
||||
if ! role_enabled "HYPERLAND"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Setting up autologin"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Setup automatic login?"; then
|
||||
install_aur_packages pam_autologin
|
||||
|
||||
sudo /bin/cp -rf ~/linuxbox/login /etc/pam.d/login
|
||||
sudo /bin/cp -rf ~/linuxbox/getty@.service /usr/lib/systemd/system/getty@.service
|
||||
sudo touch /etc/security/autologin.conf
|
||||
|
||||
log SUCCESS "Autologin configured $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_storage() {
|
||||
log SECTION "Setting up storage and mounting"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Setup udisks2 for automatic mounting?"; then
|
||||
install_packages udisks2 udiskie
|
||||
|
||||
echo 'ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{UDISKS_FILESYSTEM_SHARED}="1"' | \
|
||||
sudo tee /lib/udev/rules.d/99-udisks2.rules
|
||||
echo 'D /media 0755 root root 0 -' | sudo tee /etc/tmpfiles.d/media.conf
|
||||
|
||||
# Special configuration for STEAMBOX
|
||||
if [ "${SYSTEM_INFO[HOSTNAME]}" == "STEAMBOX" ]; then
|
||||
echo "$USER ALL=(ALL:ALL) NOPASSWD: /usr/sbin/udisksctl mount -b /dev/sda1" | \
|
||||
sudo tee /etc/sudoers.d/udisksctl
|
||||
fi
|
||||
|
||||
log SUCCESS "Storage setup completed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_audio() {
|
||||
log SECTION "Setting up audio system"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Setup PipeWire audio system?"; then
|
||||
local audio_packages=(pipewire pipewire-pulse pipewire-alsa pavucontrol helvum)
|
||||
|
||||
# Add JACK support for music production
|
||||
if role_enabled "MUSIC"; then
|
||||
audio_packages+=(pipewire-jack qpwgraph realtime-privileges gamemode)
|
||||
fi
|
||||
|
||||
install_packages "${audio_packages[@]}"
|
||||
|
||||
# Setup PipeWire configuration
|
||||
mkdir -p ~/.config/pipewire
|
||||
if [ -f ~/linuxbox/config/pipewire/pipewire.conf ]; then
|
||||
ln -sf ~/linuxbox/config/pipewire/pipewire.conf ~/.config/pipewire/pipewire.conf
|
||||
fi
|
||||
|
||||
# Music production setup
|
||||
if role_enabled "MUSIC"; then
|
||||
# Add user to audio groups
|
||||
sudo usermod -a -G realtime,audio,gamemode $USER
|
||||
|
||||
# Setup realtime privileges
|
||||
sudo tee /etc/security/limits.d/99-pipewire.conf <<'EOF'
|
||||
@audio soft rtprio 95
|
||||
@audio soft memlock unlimited
|
||||
@audio hard rtprio 95
|
||||
@audio hard memlock unlimited
|
||||
EOF
|
||||
|
||||
# Enable and configure PipeWire services
|
||||
systemctl --user --now enable pipewire{,-pulse}.{socket,service} filter-chain.service || true
|
||||
pw-metadata -n settings 0 clock.min-quantum 128 || true
|
||||
fi
|
||||
|
||||
log SUCCESS "Audio system configured $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_caffeine() {
|
||||
if ! role_enabled "HYPERLAND" && ! role_enabled "DESKTOP_BASE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing Caffeine"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Caffeine to prevent screen lock?"; then
|
||||
install_aur_packages caffeine-ng
|
||||
log SUCCESS "Caffeine installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_bluetooth() {
|
||||
if ! role_enabled "BT"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Setting up Bluetooth"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Setup Bluetooth support?"; then
|
||||
install_packages bluez bluez-utils blueman
|
||||
|
||||
sudo systemctl enable bluetooth.service
|
||||
sudo systemctl start bluetooth.service
|
||||
|
||||
log SUCCESS "Bluetooth configured $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function to run all system setup
|
||||
arch_setup_system() {
|
||||
arch_install_system_base
|
||||
arch_setup_multilib
|
||||
arch_install_drivers
|
||||
arch_install_hyprland
|
||||
arch_install_waybar
|
||||
arch_setup_autologin
|
||||
arch_setup_storage
|
||||
arch_setup_audio
|
||||
arch_install_caffeine
|
||||
arch_setup_bluetooth
|
||||
}
|
||||
|
||||
# Source guard
|
||||
if [ -z "$ARCH_SYSTEM_LOADED" ]; then
|
||||
ARCH_SYSTEM_LOADED=true
|
||||
fi
|
||||
245
update/arch/terminal.sh
Normal file
245
update/arch/terminal.sh
Normal file
@ -0,0 +1,245 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Arch Linux Terminal Utilities Module
|
||||
# Handles modern CLI tools, terminal applications, and replacements
|
||||
|
||||
arch_install_terminal_base() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing terminal base applications"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install terminal applications (alacritty, tmux, etc.)?"; then
|
||||
# Remove conflicting fonts
|
||||
if package_installed gnu-free-fonts; then
|
||||
sudo pacman --noconfirm -R gnu-free-fonts
|
||||
fi
|
||||
|
||||
local terminal_packages=(
|
||||
alacritty btop ranger tmux fd ttf-nerd-fonts-symbols
|
||||
ttf-roboto-mono-nerd gdu bottom dysk
|
||||
)
|
||||
|
||||
install_packages "${terminal_packages[@]}"
|
||||
|
||||
log SUCCESS "Terminal base applications installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_modern_replacements() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing modern CLI replacements"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install modern CLI tools (already installed via cargo)?"; then
|
||||
# These are installed via cargo in development.sh
|
||||
# Just verify they're available and set up aliases
|
||||
|
||||
local tools_to_check=("eza" "ripgrep" "fd" "zoxide" "starship")
|
||||
local missing_tools=()
|
||||
|
||||
for tool in "${tools_to_check[@]}"; do
|
||||
if ! command_exists "$tool"; then
|
||||
missing_tools+=("$tool")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing_tools[@]} -gt 0 ]; then
|
||||
log WARNING "Some modern CLI tools are missing: ${missing_tools[*]}"
|
||||
log INFO "These will be installed via cargo in development setup"
|
||||
else
|
||||
log SUCCESS "All modern CLI tools are available"
|
||||
fi
|
||||
|
||||
log SUCCESS "Modern CLI replacements verified $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_fzf() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing fzf fuzzy finder"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install fzf fuzzy finder?"; then
|
||||
# Clean up any existing installation
|
||||
rm -rf ~/.fzf
|
||||
|
||||
# Clone and install fzf
|
||||
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
|
||||
~/.fzf/install --all
|
||||
|
||||
# Source fzf for current session if possible
|
||||
if [ -f ~/.fzf.bash ]; then
|
||||
source ~/.fzf.bash
|
||||
fi
|
||||
|
||||
log SUCCESS "fzf installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_tmux() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Setting up tmux"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
# tmux is already installed via terminal_packages
|
||||
# Just link the configuration
|
||||
ln -sf ~/linuxbox/tmux.conf ~/.tmux.conf
|
||||
|
||||
log SUCCESS "tmux configuration linked $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
arch_setup_alacritty() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Setting up Alacritty terminal"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
# Create config directory and link configuration
|
||||
mkdir -p ~/.config/alacritty
|
||||
ln -sf ~/linuxbox/config/alacritty/alacritty.toml ~/.config/alacritty/alacritty.toml
|
||||
|
||||
log SUCCESS "Alacritty configuration linked $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
arch_setup_shell_config() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Setting up shell configuration"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
# Link bash configuration
|
||||
ln -sf ~/linuxbox/bashrc_arch ~/.bashrc
|
||||
|
||||
# Create local bin directory
|
||||
mkdir -p ~/.local/bin
|
||||
|
||||
# Link utility scripts
|
||||
ln -sf ~/linuxbox/start_nvim.sh ~/.local/bin/start_nvim
|
||||
|
||||
log SUCCESS "Shell configuration setup $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
arch_install_system_monitors() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing system monitoring tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install system monitoring tools (htop, iotop, etc.)?"; then
|
||||
local monitor_packages=(
|
||||
htop iotop nethogs bandwhich dust ncdu
|
||||
)
|
||||
|
||||
# Only install packages that aren't already covered by modern replacements
|
||||
local packages_to_install=()
|
||||
for pkg in "${monitor_packages[@]}"; do
|
||||
case "$pkg" in
|
||||
"dust"|"ncdu")
|
||||
# These might conflict with modern versions, check first
|
||||
if ! command_exists "$pkg"; then
|
||||
packages_to_install+=("$pkg")
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
packages_to_install+=("$pkg")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ${#packages_to_install[@]} -gt 0 ]; then
|
||||
install_packages "${packages_to_install[@]}"
|
||||
fi
|
||||
|
||||
log SUCCESS "System monitoring tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_network_tools() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing network utilities"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install network tools (wget, curl, etc.)?"; then
|
||||
local network_packages=(
|
||||
wget curl rsync openssh bind-tools whois nmap
|
||||
)
|
||||
|
||||
install_packages "${network_packages[@]}"
|
||||
|
||||
log SUCCESS "Network tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_install_archive_tools() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing archive and compression tools"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install archive tools (zip, 7zip, etc.)?"; then
|
||||
local archive_packages=(
|
||||
zip unzip p7zip tar gzip bzip2 xz
|
||||
)
|
||||
|
||||
install_packages "${archive_packages[@]}"
|
||||
|
||||
log SUCCESS "Archive tools installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
arch_setup_locale() {
|
||||
log SECTION "Setting up system locale"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
# Set locale
|
||||
sudo localectl set-locale LANG=en_US.UTF-8
|
||||
|
||||
log SUCCESS "System locale configured $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
# Main function to run all terminal setup
|
||||
arch_setup_terminal() {
|
||||
if ! role_enabled "TERMINAL"; then
|
||||
log INFO "Terminal role not enabled - skipping terminal setup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
arch_setup_locale
|
||||
arch_install_terminal_base
|
||||
arch_install_modern_replacements
|
||||
arch_install_fzf
|
||||
arch_setup_tmux
|
||||
arch_setup_alacritty
|
||||
arch_setup_shell_config
|
||||
arch_install_system_monitors
|
||||
arch_install_network_tools
|
||||
arch_install_archive_tools
|
||||
}
|
||||
|
||||
# Source guard
|
||||
if [ -z "$ARCH_TERMINAL_LOADED" ]; then
|
||||
ARCH_TERMINAL_LOADED=true
|
||||
fi
|
||||
55
update/config/arch-roles.conf
Normal file
55
update/config/arch-roles.conf
Normal file
@ -0,0 +1,55 @@
|
||||
# Arch Linux Role Configuration
|
||||
# This file defines role assignments for Arch Linux systems
|
||||
|
||||
# Default roles for all Arch systems
|
||||
DEFAULT_ROLES=(
|
||||
"TERMINAL"
|
||||
)
|
||||
|
||||
# Hostname-specific role assignments
|
||||
configure_roles_for_hostname() {
|
||||
local hostname="$1"
|
||||
|
||||
case "$hostname" in
|
||||
"CMBOX")
|
||||
ROLES[DESKTOP_BASE]="yes"
|
||||
ROLES[DESKTOP_WORK]="yes"
|
||||
ROLES[CODE]="yes"
|
||||
ROLES[TERMINAL]="yes"
|
||||
ROLES[HYPERLAND]="yes"
|
||||
ROLES[MUSIC]="yes"
|
||||
;;
|
||||
"STEAMBOX")
|
||||
ROLES[GAME]="yes"
|
||||
ROLES[VR]="yes"
|
||||
ROLES[DESKTOP_BASE]="yes"
|
||||
ROLES[NVIDIA_GPU]="yes"
|
||||
ROLES[TERMINAL]="yes"
|
||||
ROLES[HYPERLAND]="yes"
|
||||
;;
|
||||
"LABBOX")
|
||||
ROLES[DESKTOP_BASE]="yes"
|
||||
ROLES[CODE]="yes"
|
||||
ROLES[TERMINAL]="yes"
|
||||
ROLES[HYPERLAND]="yes"
|
||||
ROLES[LAB]="yes"
|
||||
ROLES[BT]="yes"
|
||||
;;
|
||||
"SIMONBOX")
|
||||
ROLES[GAME]="yes"
|
||||
ROLES[VR]="yes"
|
||||
ROLES[DESKTOP_BASE]="yes"
|
||||
ROLES[NVIDIA_1080_GPU]="yes"
|
||||
ROLES[TERMINAL]="yes"
|
||||
ROLES[HYPERLAND]="yes"
|
||||
ROLES[BT]="yes"
|
||||
;;
|
||||
*)
|
||||
# Default configuration for unknown hostnames
|
||||
ROLES[TERMINAL]="yes"
|
||||
if supports_feature "desktop"; then
|
||||
ROLES[DESKTOP_BASE]="yes"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
44
update/config/ubuntu-roles.conf
Normal file
44
update/config/ubuntu-roles.conf
Normal file
@ -0,0 +1,44 @@
|
||||
# Ubuntu Linux Role Configuration
|
||||
# This file defines role assignments for Ubuntu Linux systems
|
||||
|
||||
# Default roles for all Ubuntu systems
|
||||
DEFAULT_ROLES=(
|
||||
"DEVELOPMENT"
|
||||
"TERMINAL"
|
||||
)
|
||||
|
||||
# Hostname-specific role assignments
|
||||
configure_roles_for_hostname() {
|
||||
local hostname="$1"
|
||||
|
||||
case "$hostname" in
|
||||
"CMBOX"|"LABBOX"|"STEAMBOX"|"SIMONBOX")
|
||||
# These are primarily Arch systems, but provide fallback Ubuntu config
|
||||
ROLES[DEVELOPMENT]="yes"
|
||||
ROLES[TERMINAL]="yes"
|
||||
if [ "${SYSTEM_INFO[WSL]}" != "yes" ] && supports_feature "desktop"; then
|
||||
ROLES[DESKTOP_BASE]="yes"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Default configuration for Ubuntu systems
|
||||
ROLES[DEVELOPMENT]="yes"
|
||||
ROLES[TERMINAL]="yes"
|
||||
|
||||
# Enable desktop roles if not in WSL and desktop is available
|
||||
if [ "${SYSTEM_INFO[WSL]}" != "yes" ] && supports_feature "desktop"; then
|
||||
ROLES[DESKTOP_BASE]="yes"
|
||||
fi
|
||||
|
||||
# Enable WSL-specific roles if in WSL
|
||||
if [ "${SYSTEM_INFO[WSL]}" == "yes" ]; then
|
||||
ROLES[WSL]="yes"
|
||||
fi
|
||||
|
||||
# Enable Bluetooth if available
|
||||
if supports_feature "bluetooth"; then
|
||||
ROLES[BT]="yes"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
419
update/lib/core.sh
Normal file
419
update/lib/core.sh
Normal file
@ -0,0 +1,419 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CMtec Enhanced Update System - Core Library
|
||||
# Shared functions for logging, UI, health checks, and utilities
|
||||
|
||||
VERSION="3.0.0"
|
||||
LOG_FILE="/tmp/update_$(date +%Y%m%d_%H%M%S).log"
|
||||
START_TIME=$(date +%s)
|
||||
INTERACTIVE=false
|
||||
|
||||
# Color definitions and Unicode symbols
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
BLUE='\033[0;34m'
|
||||
MAGENTA='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
GRAY='\033[0;37m'
|
||||
BOLD='\033[1m'
|
||||
RESET='\033[0m'
|
||||
|
||||
# Unicode symbols
|
||||
CHECK="✓"
|
||||
CROSS="✗"
|
||||
WARNING="⚠"
|
||||
INFO="ℹ"
|
||||
ROCKET="🚀"
|
||||
GEAR="⚙"
|
||||
TIMER="⏱"
|
||||
PACKAGE="📦"
|
||||
|
||||
# Initialize core variables
|
||||
declare -A ROLES
|
||||
declare -A SYSTEM_INFO
|
||||
|
||||
# Logging function with colored output
|
||||
log() {
|
||||
local level=$1
|
||||
shift
|
||||
local message="$*"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
|
||||
|
||||
case $level in
|
||||
ERROR) echo -e "${RED}${CROSS}${RESET} $message" ;;
|
||||
SUCCESS) echo -e "${GREEN}${CHECK}${RESET} $message" ;;
|
||||
WARNING) echo -e "${YELLOW}${WARNING}${RESET} $message" ;;
|
||||
INFO) echo -e "${BLUE}${INFO}${RESET} $message" ;;
|
||||
SECTION) echo -e "\n${CYAN}${GEAR} $message${RESET}" ;;
|
||||
*) echo -e "${GRAY}$message${RESET}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Fancy spinner function for long operations
|
||||
spinner() {
|
||||
local pid=$1
|
||||
local message="$2"
|
||||
local delay=0.08
|
||||
local spinstr='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
||||
|
||||
echo -e "${CYAN}${GEAR} $message${RESET}"
|
||||
printf " "
|
||||
|
||||
while kill -0 $pid 2>/dev/null; do
|
||||
local temp=${spinstr#?}
|
||||
printf "${BLUE}%c${RESET}" "$spinstr"
|
||||
spinstr=$temp${spinstr%"$temp"}
|
||||
sleep $delay
|
||||
printf "\b"
|
||||
done
|
||||
|
||||
printf "${GREEN}${CHECK}${RESET}\n"
|
||||
}
|
||||
|
||||
# Progress bar function
|
||||
progress_bar() {
|
||||
local current=$1
|
||||
local total=$2
|
||||
local message="$3"
|
||||
local width=40
|
||||
local percentage=$((current * 100 / total))
|
||||
local filled=$((current * width / total))
|
||||
local empty=$((width - filled))
|
||||
|
||||
printf "\r${message} ${BLUE}["
|
||||
printf "%*s" $filled | tr ' ' '█'
|
||||
printf "%*s" $empty | tr ' ' '░'
|
||||
printf "] %d%% (%d/%d)${RESET}" $percentage $current $total
|
||||
if [ $current -eq $total ]; then
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
# Timer function
|
||||
show_timer() {
|
||||
local start_time=$1
|
||||
local end_time=$(date +%s)
|
||||
local elapsed=$((end_time - start_time))
|
||||
local hours=$((elapsed / 3600))
|
||||
local minutes=$(((elapsed % 3600) / 60))
|
||||
local seconds=$((elapsed % 60))
|
||||
|
||||
if [ $hours -gt 0 ]; then
|
||||
printf "${CYAN}${TIMER} %02d:%02d:%02d${RESET}" $hours $minutes $seconds
|
||||
else
|
||||
printf "${CYAN}${TIMER} %02dm %02ds${RESET}" $minutes $seconds
|
||||
fi
|
||||
}
|
||||
|
||||
# Confirmation function for interactive mode
|
||||
confirm() {
|
||||
if [ "$INTERACTIVE" == "true" ]; then
|
||||
local prompt="$1"
|
||||
local default="${2:-n}"
|
||||
echo -ne "${YELLOW}${WARNING} $prompt [y/N]: ${RESET}"
|
||||
read -r response
|
||||
response=${response:-$default}
|
||||
case $response in
|
||||
[yY][eE][sS]|[yY]) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# System health check function
|
||||
system_health_check() {
|
||||
local section_start=$(date +%s)
|
||||
log SECTION "Running system health check"
|
||||
local issues=0
|
||||
|
||||
# Check disk space
|
||||
local root_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||
if [ "$root_usage" -gt 85 ]; then
|
||||
log WARNING "Root filesystem is ${root_usage}% full"
|
||||
((issues++))
|
||||
else
|
||||
log SUCCESS "Root filesystem usage: ${root_usage}%"
|
||||
fi
|
||||
|
||||
# Check available memory
|
||||
local mem_available=$(free -m | awk 'NR==2{printf "%d", $7}')
|
||||
if [ "$mem_available" -lt 512 ]; then
|
||||
log WARNING "Low memory available: ${mem_available}MB"
|
||||
((issues++))
|
||||
else
|
||||
log SUCCESS "Available memory: ${mem_available}MB"
|
||||
fi
|
||||
|
||||
# Check for failed systemd services
|
||||
local failed_services=$(systemctl --failed --quiet --no-legend 2>/dev/null | wc -l)
|
||||
if [ "$failed_services" -gt 0 ]; then
|
||||
log WARNING "$failed_services failed systemd services detected"
|
||||
((issues++))
|
||||
else
|
||||
log SUCCESS "All systemd services running normally"
|
||||
fi
|
||||
|
||||
# Check package manager locks (distro-specific)
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
if [ -f /var/lib/pacman/db.lck ]; then
|
||||
log WARNING "Pacman database is locked"
|
||||
((issues++))
|
||||
fi
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
if sudo fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; then
|
||||
log WARNING "APT database is locked"
|
||||
((issues++))
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $issues -eq 0 ]; then
|
||||
log SUCCESS "System health check passed $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "System health check found $issues issues $(show_timer $section_start)"
|
||||
if [ "$INTERACTIVE" == "true" ]; then
|
||||
if ! confirm "Continue despite health issues?"; then
|
||||
log INFO "Update cancelled by user due to health issues"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
return $issues
|
||||
}
|
||||
|
||||
# Error handler function
|
||||
error_handler() {
|
||||
local line_number=$1
|
||||
local error_code=$2
|
||||
local command="$3"
|
||||
log ERROR "Script failed at line $line_number with exit code $error_code"
|
||||
log ERROR "Failed command: $command"
|
||||
log ERROR "Check log file: $LOG_FILE"
|
||||
|
||||
echo -e "\n${RED}╔══════════════════════════════════════════════════════════════════════════╗${RESET}"
|
||||
echo -e "${RED}║${RESET} ${BOLD}SCRIPT FAILED${RESET} ${RED}║${RESET}"
|
||||
echo -e "${RED}╠══════════════════════════════════════════════════════════════════════════╣${RESET}"
|
||||
echo -e "${RED}║${RESET} Line: $line_number ${RED}║${RESET}"
|
||||
echo -e "${RED}║${RESET} Exit Code: $error_code ${RED}║${RESET}"
|
||||
echo -e "${RED}║${RESET} Log File: $LOG_FILE ${RED}║${RESET}"
|
||||
echo -e "${RED}╚══════════════════════════════════════════════════════════════════════════╝${RESET}\n"
|
||||
exit $error_code
|
||||
}
|
||||
|
||||
# Fancy header display with original ASCII art
|
||||
show_header() {
|
||||
local hostname=$1
|
||||
local distro=$2
|
||||
clear
|
||||
echo -e "\n${BLUE}╔══════════════════════════════════════════════════════════════════════════╗${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}.${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ \\${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ \\${RESET} ${WHITE} # ${BLUE}| *${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/^. \\${RESET} ${WHITE} a##e #%\" a#\"e 6##% ${BLUE}| | |-^-. | | \\ /${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ .-. \\${RESET} ${WHITE}.oOo# # # # # ${BLUE}| | | | | | X${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ ( ) _\\${RESET} ${WHITE}%OoO# # %#e\" # # ${BLUE}| | | | ^._.| / \\${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ _.~ ~._^\\${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/.^ ^\\ ${GRAY}™${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${GREEN}${ROCKET} CMtec Universal Update System v$VERSION${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${GRAY}$hostname | $distro | $(date '+%Y-%m-%d %H:%M:%S')${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════════════════╝${RESET}\n"
|
||||
}
|
||||
|
||||
# Alternative fancy header with original Arch-style ASCII art
|
||||
show_arch_header() {
|
||||
local hostname=$1
|
||||
clear
|
||||
echo -e "\n${BLUE}╔══════════════════════════════════════════════════════════════════════════╗${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}.${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ \\${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ \\${RESET} ${WHITE} # ${BLUE}| *${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/^. \\${RESET} ${WHITE} a##e #%\" a#\"e 6##% ${BLUE}| | |-^-. | | \\ /${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ .-. \\${RESET} ${WHITE}.oOo# # # # # ${BLUE}| | | | | | X${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ ( ) _\\${RESET} ${WHITE}%OoO# # %#e\" # # ${BLUE}| | | | ^._.| / \\${RESET} ${GRAY}™${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/ _.~ ~._^\\${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}/.^ ^\\ ${GRAY}™${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${GREEN}${ROCKET} CMtec '$hostname' Enhanced Update Script${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}║${RESET} ${GRAY}$(date '+%Y-%m-%d %H:%M:%S')${RESET} ${BLUE}║${RESET}"
|
||||
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════════════════╝${RESET}\n"
|
||||
}
|
||||
|
||||
# Ubuntu-style header with Ubuntu ASCII art
|
||||
show_ubuntu_header() {
|
||||
local hostname=$1
|
||||
clear
|
||||
echo -e "\n${YELLOW}╔══════════════════════════════════════════════════════════════════════════╗${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} .--.${RESET} ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} .-\"''\`(|||)${RESET} ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} ,\`\\ \\ \`-\`.${RESET} 88 88 ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} / \\ \"\`\`-. \`${RESET} 88 88 ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} .-. , \`___:${RESET} 88 88 88,888, 88 88 ,88888, 88888 ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} (:::) : ___ ${RESET} 88 88 88 88 88 88 88 88 88 ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} \`-\` \` , :${RESET} 88 88 88 88 88 88 88 88 88 ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} \\ / ,..-\` ,${RESET} 88 88 88 88 88 88 88 88 88 ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} \`.\/ / .-.\`${RESET} \"88888\" \"88888\" \"88888\" 88 88 \"8888${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} \`-..-( )${RESET} ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${RED} \`-\`${RESET} ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${GREEN}${ROCKET} CMtec Ubuntu Install/Update Script${RESET} ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}║${RESET} ${GRAY}$hostname | $(date '+%Y-%m-%d %H:%M:%S')${RESET} ${YELLOW}║${RESET}"
|
||||
echo -e "${YELLOW}╚══════════════════════════════════════════════════════════════════════════╝${RESET}\n"
|
||||
}
|
||||
|
||||
# Display enabled roles with fancy formatting
|
||||
show_roles() {
|
||||
local role_count=0
|
||||
for role in "${!ROLES[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ]; then
|
||||
((role_count++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $role_count -eq 0 ]; then
|
||||
log WARNING "No roles enabled"
|
||||
return
|
||||
fi
|
||||
|
||||
log SECTION "System Configuration"
|
||||
echo -e "${BOLD}${PACKAGE} Enabled Roles ($role_count total):${RESET}"
|
||||
|
||||
for role in "${!ROLES[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ]; then
|
||||
case $role in
|
||||
desktop*|DESKTOP*) icon="🖥️" ;;
|
||||
game*|GAME*) icon="🎮" ;;
|
||||
music*|MUSIC*) icon="🎵" ;;
|
||||
dev*|code*|DEV*|CODE*) icon="💻" ;;
|
||||
terminal*|TERMINAL*) icon="📟" ;;
|
||||
nvidia*|NVIDIA*) icon="🎯" ;;
|
||||
vr*|VR*) icon="🥽" ;;
|
||||
lab*|LAB*) icon="🔬" ;;
|
||||
bt*|BT*|bluetooth*) icon="📶" ;;
|
||||
hypr*|HYPERLAND*) icon="🌊" ;;
|
||||
wsl*|WSL*) icon="🐧" ;;
|
||||
*) icon="⚙️" ;;
|
||||
esac
|
||||
echo -e " ${CYAN}$icon $role${RESET}"
|
||||
fi
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
# Final summary with statistics
|
||||
show_final_summary() {
|
||||
local end_time=$(date +%s)
|
||||
local total_time=$((end_time - START_TIME))
|
||||
local total_hours=$((total_time / 3600))
|
||||
local total_minutes=$(((total_time % 3600) / 60))
|
||||
local total_seconds=$((total_time % 60))
|
||||
|
||||
# Collect system info for summary
|
||||
local kernel_version=$(uname -r)
|
||||
local role_count=0
|
||||
for role in "${!ROLES[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ]; then
|
||||
((role_count++))
|
||||
fi
|
||||
done
|
||||
|
||||
log SECTION "Update Summary"
|
||||
|
||||
echo -e "\n${GREEN}╔══════════════════════════════════════════════════════════════════════════╗${RESET}"
|
||||
echo -e "${GREEN}║${RESET} ${BOLD}🎉 UPDATE COMPLETE! 🎉${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}╠══════════════════════════════════════════════════════════════════════════╣${RESET}"
|
||||
echo -e "${GREEN}║${RESET} ${CYAN}📊 Statistics:${RESET} ${GREEN}║${RESET}"
|
||||
|
||||
if [ $total_hours -gt 0 ]; then
|
||||
echo -e "${GREEN}║${RESET} • Total time: ${CYAN}${TIMER} ${total_hours}h ${total_minutes}m ${total_seconds}s${RESET} ${GREEN}║${RESET}"
|
||||
else
|
||||
echo -e "${GREEN}║${RESET} • Total time: ${CYAN}${TIMER} ${total_minutes}m ${total_seconds}s${RESET} ${GREEN}║${RESET}"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}║${RESET} • Hostname: ${CYAN}${SYSTEM_INFO[HOSTNAME]}${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}║${RESET} • Distro: ${CYAN}${SYSTEM_INFO[DISTRO]} ${SYSTEM_INFO[VERSION]}${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}║${RESET} • Kernel: ${CYAN}$kernel_version${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}║${RESET} • Active roles: ${CYAN}$role_count enabled${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}║${RESET} • Log file: ${GRAY}$LOG_FILE${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}╠══════════════════════════════════════════════════════════════════════════╣${RESET}"
|
||||
echo -e "${GREEN}║${RESET} ${YELLOW}⚠️ SYSTEM REBOOT RECOMMENDED ⚠️${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}║${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}║${RESET} ${WHITE}Some updates may require a reboot to take effect${RESET} ${GREEN}║${RESET}"
|
||||
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════════════════╝${RESET}\n"
|
||||
|
||||
log SUCCESS "Update script completed successfully"
|
||||
log INFO "Total execution time: $(show_timer $START_TIME)"
|
||||
log INFO "System: ${SYSTEM_INFO[DISTRO]} ${SYSTEM_INFO[VERSION]} on ${SYSTEM_INFO[HOSTNAME]}"
|
||||
log INFO "Active roles: $role_count"
|
||||
|
||||
# Interactive reboot prompt
|
||||
if [ "$INTERACTIVE" == "true" ]; then
|
||||
echo -ne "${YELLOW}${WARNING} Reboot system now? [y/N]: ${RESET}"
|
||||
read -r -t 10 response || response="n"
|
||||
case $response in
|
||||
[yY][eE][sS]|[yY])
|
||||
log INFO "Rebooting system as requested by user"
|
||||
echo -e "${GREEN}${CHECK} Rebooting in 3 seconds...${RESET}"
|
||||
sleep 1
|
||||
echo -e "${GREEN}${CHECK} Rebooting in 2 seconds...${RESET}"
|
||||
sleep 1
|
||||
echo -e "${GREEN}${CHECK} Rebooting in 1 second...${RESET}"
|
||||
sleep 1
|
||||
sudo reboot
|
||||
;;
|
||||
*)
|
||||
log INFO "Reboot cancelled by user"
|
||||
echo -e "${BLUE}${INFO} Remember to reboot when convenient!${RESET}"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo -e "${BLUE}${INFO} Please reboot your system when convenient${RESET}"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}${CHECK} Thank you for using CMtec Universal Update System!${RESET}\n"
|
||||
}
|
||||
|
||||
# Utility function to check if command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Utility function to check if package is installed (distro-agnostic)
|
||||
package_installed() {
|
||||
local package="$1"
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
pacman -Qs "$package" >/dev/null 2>&1
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
dpkg -l "$package" >/dev/null 2>&1
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Initialize logging
|
||||
init_core() {
|
||||
# Set error trap
|
||||
trap 'error_handler ${LINENO} $? "$BASH_COMMAND"' ERR
|
||||
|
||||
# Initialize log
|
||||
log INFO "Starting CMtec Universal Update System v$VERSION"
|
||||
log INFO "Log file: $LOG_FILE"
|
||||
log INFO "Interactive mode: $INTERACTIVE"
|
||||
}
|
||||
|
||||
# Source guard to prevent double-sourcing
|
||||
if [ -z "$CORE_LIB_LOADED" ]; then
|
||||
CORE_LIB_LOADED=true
|
||||
fi
|
||||
266
update/lib/detect.sh
Normal file
266
update/lib/detect.sh
Normal file
@ -0,0 +1,266 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CMtec Update System - OS Detection Library
|
||||
# Detects operating system, distribution, version, and environment
|
||||
|
||||
# Initialize system info array
|
||||
declare -A SYSTEM_INFO
|
||||
|
||||
# Detect operating system and distribution
|
||||
detect_system() {
|
||||
log INFO "Detecting system information..."
|
||||
|
||||
# Basic OS detection
|
||||
SYSTEM_INFO[OS]=$(uname -s)
|
||||
SYSTEM_INFO[ARCH]=$(uname -m)
|
||||
SYSTEM_INFO[HOSTNAME]=$(hostname | tr '[:lower:]' '[:upper:]')
|
||||
SYSTEM_INFO[KERNEL]=$(uname -r)
|
||||
|
||||
# Detect distribution
|
||||
if [ -f /etc/os-release ]; then
|
||||
source /etc/os-release
|
||||
SYSTEM_INFO[DISTRO]=$(echo "$ID" | tr '[:upper:]' '[:lower:]')
|
||||
SYSTEM_INFO[VERSION]="$VERSION_ID"
|
||||
SYSTEM_INFO[PRETTY_NAME]="$PRETTY_NAME"
|
||||
elif [ -f /etc/arch-release ]; then
|
||||
SYSTEM_INFO[DISTRO]="arch"
|
||||
SYSTEM_INFO[VERSION]="rolling"
|
||||
SYSTEM_INFO[PRETTY_NAME]="Arch Linux"
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
SYSTEM_INFO[DISTRO]="debian"
|
||||
SYSTEM_INFO[VERSION]=$(cat /etc/debian_version)
|
||||
SYSTEM_INFO[PRETTY_NAME]="Debian GNU/Linux"
|
||||
else
|
||||
log ERROR "Unable to detect Linux distribution"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Detect environment specifics
|
||||
detect_environment
|
||||
|
||||
# Log system information
|
||||
log SUCCESS "System detected: ${SYSTEM_INFO[PRETTY_NAME]} (${SYSTEM_INFO[DISTRO]})"
|
||||
log INFO "Hostname: ${SYSTEM_INFO[HOSTNAME]}"
|
||||
log INFO "Architecture: ${SYSTEM_INFO[ARCH]}"
|
||||
log INFO "Environment: ${SYSTEM_INFO[ENVIRONMENT]}"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Detect specific environment (WSL, Desktop, Container, etc.)
|
||||
detect_environment() {
|
||||
local env_flags=()
|
||||
|
||||
# Check for WSL
|
||||
if [[ "$(systemd-detect-virt 2>/dev/null)" == *"wsl"* ]] || \
|
||||
[ -f /proc/sys/fs/binfmt_misc/WSLInterop ] || \
|
||||
grep -qi "microsoft" /proc/version 2>/dev/null; then
|
||||
env_flags+=("wsl")
|
||||
SYSTEM_INFO[WSL]="yes"
|
||||
else
|
||||
SYSTEM_INFO[WSL]="no"
|
||||
fi
|
||||
|
||||
# Check for container environment
|
||||
if [ -f /.dockerenv ] || \
|
||||
[[ "$(systemd-detect-virt 2>/dev/null)" == "docker" ]] || \
|
||||
[[ "$(systemd-detect-virt 2>/dev/null)" == "podman" ]]; then
|
||||
env_flags+=("container")
|
||||
SYSTEM_INFO[CONTAINER]="yes"
|
||||
else
|
||||
SYSTEM_INFO[CONTAINER]="no"
|
||||
fi
|
||||
|
||||
# Check for desktop environment
|
||||
detect_desktop_environment
|
||||
|
||||
# Check for virtualization
|
||||
local virt=$(systemd-detect-virt 2>/dev/null)
|
||||
if [ "$virt" != "none" ] && [ -n "$virt" ]; then
|
||||
env_flags+=("vm")
|
||||
SYSTEM_INFO[VIRTUALIZATION]="$virt"
|
||||
else
|
||||
SYSTEM_INFO[VIRTUALIZATION]="none"
|
||||
fi
|
||||
|
||||
# Set environment string
|
||||
if [ ${#env_flags[@]} -gt 0 ]; then
|
||||
SYSTEM_INFO[ENVIRONMENT]=$(IFS=,; echo "${env_flags[*]}")
|
||||
else
|
||||
SYSTEM_INFO[ENVIRONMENT]="native"
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect desktop environment
|
||||
detect_desktop_environment() {
|
||||
local desktop_env=""
|
||||
|
||||
# Check for various desktop environments
|
||||
if [ -n "$XDG_CURRENT_DESKTOP" ]; then
|
||||
desktop_env="$XDG_CURRENT_DESKTOP"
|
||||
elif [ -n "$DESKTOP_SESSION" ]; then
|
||||
desktop_env="$DESKTOP_SESSION"
|
||||
elif [ -n "$GDMSESSION" ]; then
|
||||
desktop_env="$GDMSESSION"
|
||||
elif pgrep -x "gnome-session" >/dev/null; then
|
||||
desktop_env="GNOME"
|
||||
elif pgrep -x "kded5" >/dev/null || pgrep -x "kded6" >/dev/null; then
|
||||
desktop_env="KDE"
|
||||
elif pgrep -x "xfce4-session" >/dev/null; then
|
||||
desktop_env="XFCE"
|
||||
elif pgrep -x "hyprland" >/dev/null; then
|
||||
desktop_env="Hyprland"
|
||||
fi
|
||||
|
||||
# Special checks for distribution-specific detection
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"ubuntu")
|
||||
if dpkg -l | grep -q "ubuntu-desktop"; then
|
||||
SYSTEM_INFO[DESKTOP]="yes"
|
||||
SYSTEM_INFO[DESKTOP_ENV]="${desktop_env:-GNOME}"
|
||||
else
|
||||
SYSTEM_INFO[DESKTOP]="no"
|
||||
fi
|
||||
;;
|
||||
"arch")
|
||||
if pacman -Qs | grep -E "(gnome|kde|xfce|hyprland)" >/dev/null; then
|
||||
SYSTEM_INFO[DESKTOP]="yes"
|
||||
SYSTEM_INFO[DESKTOP_ENV]="$desktop_env"
|
||||
else
|
||||
SYSTEM_INFO[DESKTOP]="no"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [ -n "$desktop_env" ]; then
|
||||
SYSTEM_INFO[DESKTOP]="yes"
|
||||
SYSTEM_INFO[DESKTOP_ENV]="$desktop_env"
|
||||
else
|
||||
SYSTEM_INFO[DESKTOP]="no"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Detect hardware capabilities
|
||||
detect_hardware() {
|
||||
log INFO "Detecting hardware capabilities..."
|
||||
|
||||
# GPU Detection
|
||||
detect_gpu
|
||||
|
||||
# Audio system detection
|
||||
detect_audio_system
|
||||
|
||||
# Network capabilities
|
||||
detect_network_capabilities
|
||||
|
||||
log SUCCESS "Hardware detection completed"
|
||||
}
|
||||
|
||||
# Detect GPU type and capabilities
|
||||
detect_gpu() {
|
||||
local gpu_info=$(lspci | grep -i vga 2>/dev/null)
|
||||
|
||||
SYSTEM_INFO[NVIDIA_GPU]="no"
|
||||
SYSTEM_INFO[NVIDIA_1080_GPU]="no"
|
||||
SYSTEM_INFO[AMD_GPU]="no"
|
||||
SYSTEM_INFO[INTEL_GPU]="no"
|
||||
|
||||
if echo "$gpu_info" | grep -qi nvidia; then
|
||||
SYSTEM_INFO[NVIDIA_GPU]="yes"
|
||||
if echo "$gpu_info" | grep -qi "GTX 1080\\|RTX"; then
|
||||
SYSTEM_INFO[NVIDIA_1080_GPU]="yes"
|
||||
fi
|
||||
log INFO "NVIDIA GPU detected"
|
||||
fi
|
||||
|
||||
if echo "$gpu_info" | grep -qi "amd\\|radeon"; then
|
||||
SYSTEM_INFO[AMD_GPU]="yes"
|
||||
log INFO "AMD GPU detected"
|
||||
fi
|
||||
|
||||
if echo "$gpu_info" | grep -qi intel; then
|
||||
SYSTEM_INFO[INTEL_GPU]="yes"
|
||||
log INFO "Intel GPU detected"
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect audio system
|
||||
detect_audio_system() {
|
||||
if command_exists pulseaudio; then
|
||||
SYSTEM_INFO[AUDIO_SYSTEM]="pulseaudio"
|
||||
elif command_exists pipewire; then
|
||||
SYSTEM_INFO[AUDIO_SYSTEM]="pipewire"
|
||||
elif command_exists alsa; then
|
||||
SYSTEM_INFO[AUDIO_SYSTEM]="alsa"
|
||||
else
|
||||
SYSTEM_INFO[AUDIO_SYSTEM]="unknown"
|
||||
fi
|
||||
|
||||
log INFO "Audio system: ${SYSTEM_INFO[AUDIO_SYSTEM]}"
|
||||
}
|
||||
|
||||
# Detect network capabilities
|
||||
detect_network_capabilities() {
|
||||
SYSTEM_INFO[BLUETOOTH]="no"
|
||||
SYSTEM_INFO[WIFI]="no"
|
||||
|
||||
if command_exists bluetoothctl || [ -d /sys/class/bluetooth ]; then
|
||||
SYSTEM_INFO[BLUETOOTH]="yes"
|
||||
fi
|
||||
|
||||
if ip link show | grep -q "wlan\\|wifi\\|wireless" || \
|
||||
nmcli dev status 2>/dev/null | grep -q wifi; then
|
||||
SYSTEM_INFO[WIFI]="yes"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get system capabilities summary
|
||||
get_capabilities() {
|
||||
local capabilities=()
|
||||
|
||||
[ "${SYSTEM_INFO[DESKTOP]}" == "yes" ] && capabilities+=("desktop")
|
||||
[ "${SYSTEM_INFO[NVIDIA_GPU]}" == "yes" ] && capabilities+=("nvidia")
|
||||
[ "${SYSTEM_INFO[AMD_GPU]}" == "yes" ] && capabilities+=("amd")
|
||||
[ "${SYSTEM_INFO[BLUETOOTH]}" == "yes" ] && capabilities+=("bluetooth")
|
||||
[ "${SYSTEM_INFO[WIFI]}" == "yes" ] && capabilities+=("wifi")
|
||||
[ "${SYSTEM_INFO[WSL]}" == "yes" ] && capabilities+=("wsl")
|
||||
[ "${SYSTEM_INFO[CONTAINER]}" == "yes" ] && capabilities+=("container")
|
||||
|
||||
echo "${capabilities[@]}"
|
||||
}
|
||||
|
||||
# Check if current system supports a specific feature
|
||||
supports_feature() {
|
||||
local feature="$1"
|
||||
|
||||
case "$feature" in
|
||||
"desktop")
|
||||
[ "${SYSTEM_INFO[DESKTOP]}" == "yes" ]
|
||||
;;
|
||||
"gpu")
|
||||
[ "${SYSTEM_INFO[NVIDIA_GPU]}" == "yes" ] || \
|
||||
[ "${SYSTEM_INFO[AMD_GPU]}" == "yes" ]
|
||||
;;
|
||||
"nvidia")
|
||||
[ "${SYSTEM_INFO[NVIDIA_GPU]}" == "yes" ]
|
||||
;;
|
||||
"bluetooth")
|
||||
[ "${SYSTEM_INFO[BLUETOOTH]}" == "yes" ]
|
||||
;;
|
||||
"wsl")
|
||||
[ "${SYSTEM_INFO[WSL]}" == "yes" ]
|
||||
;;
|
||||
"container")
|
||||
[ "${SYSTEM_INFO[CONTAINER]}" == "yes" ]
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Source guard to prevent double-sourcing
|
||||
if [ -z "$DETECT_LIB_LOADED" ]; then
|
||||
DETECT_LIB_LOADED=true
|
||||
fi
|
||||
406
update/lib/packages.sh
Normal file
406
update/lib/packages.sh
Normal file
@ -0,0 +1,406 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CMtec Update System - Package Management Abstraction Layer
|
||||
# Provides unified interface for different package managers
|
||||
|
||||
# Package manager detection and initialization
|
||||
init_package_managers() {
|
||||
log INFO "Initializing package managers for ${SYSTEM_INFO[DISTRO]}..."
|
||||
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
PACKAGE_MANAGER="pacman"
|
||||
AUR_HELPER=""
|
||||
detect_aur_helper
|
||||
FLATPAK_AVAILABLE=$(command_exists flatpak && echo "yes" || echo "no")
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
PACKAGE_MANAGER="apt"
|
||||
SNAP_AVAILABLE=$(command_exists snap && echo "yes" || echo "no")
|
||||
FLATPAK_AVAILABLE=$(command_exists flatpak && echo "yes" || echo "no")
|
||||
;;
|
||||
*)
|
||||
log ERROR "Unsupported distribution: ${SYSTEM_INFO[DISTRO]}"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log SUCCESS "Package managers initialized"
|
||||
log INFO "Primary: $PACKAGE_MANAGER"
|
||||
[ -n "$AUR_HELPER" ] && log INFO "AUR helper: $AUR_HELPER"
|
||||
[ "$FLATPAK_AVAILABLE" == "yes" ] && log INFO "Flatpak: available"
|
||||
[ "$SNAP_AVAILABLE" == "yes" ] && log INFO "Snap: available"
|
||||
}
|
||||
|
||||
# Detect AUR helper for Arch systems
|
||||
detect_aur_helper() {
|
||||
local helpers=("yay" "paru" "pikaur" "trizen")
|
||||
|
||||
for helper in "${helpers[@]}"; do
|
||||
if command_exists "$helper"; then
|
||||
AUR_HELPER="$helper"
|
||||
log INFO "Found AUR helper: $helper"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
log WARNING "No AUR helper found - will install yay if needed"
|
||||
AUR_HELPER=""
|
||||
}
|
||||
|
||||
# Install AUR helper (yay) if not present
|
||||
install_aur_helper() {
|
||||
if [ -n "$AUR_HELPER" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "Installing yay AUR helper..."
|
||||
local section_start=$(date +%s)
|
||||
|
||||
# Clean up any existing build directory
|
||||
[ -d ~/yay-bin ] && rm -rf ~/yay-bin
|
||||
|
||||
cd ~
|
||||
(
|
||||
git clone https://aur.archlinux.org/yay-bin.git 2>&1 | tee -a "$LOG_FILE"
|
||||
cd yay-bin
|
||||
makepkg --noconfirm -si 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Installing yay AUR helper..."
|
||||
wait
|
||||
|
||||
# Clean up build directory
|
||||
[ -d ~/yay-bin ] && rm -rf ~/yay-bin
|
||||
|
||||
AUR_HELPER="yay"
|
||||
log SUCCESS "Yay AUR helper installed $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
# Update package databases
|
||||
update_package_databases() {
|
||||
local section_start=$(date +%s)
|
||||
log SECTION "Updating package databases"
|
||||
|
||||
case "$PACKAGE_MANAGER" in
|
||||
"pacman")
|
||||
if confirm "Refresh pacman package databases?"; then
|
||||
(
|
||||
sudo pacman -Syy --noconfirm 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Refreshing pacman databases..."
|
||||
wait
|
||||
log SUCCESS "Pacman databases updated $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "Package database refresh skipped"
|
||||
fi
|
||||
;;
|
||||
"apt")
|
||||
if confirm "Update APT package databases?"; then
|
||||
(
|
||||
sudo apt update 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Updating APT databases..."
|
||||
wait
|
||||
log SUCCESS "APT databases updated $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "Package database update skipped"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# System upgrade
|
||||
system_upgrade() {
|
||||
local section_start=$(date +%s)
|
||||
log SECTION "Upgrading system packages"
|
||||
|
||||
case "$PACKAGE_MANAGER" in
|
||||
"pacman")
|
||||
if confirm "Upgrade all system packages?"; then
|
||||
(
|
||||
sudo pacman -Su --noconfirm 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Upgrading system packages (may take a while)..."
|
||||
wait
|
||||
log SUCCESS "System packages upgraded $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "System upgrade skipped"
|
||||
fi
|
||||
;;
|
||||
"apt")
|
||||
if confirm "Upgrade all system packages?"; then
|
||||
(
|
||||
sudo apt upgrade -y 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Upgrading system packages (may take a while)..."
|
||||
wait
|
||||
log SUCCESS "System packages upgraded $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "System upgrade skipped"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Install packages using primary package manager
|
||||
install_packages() {
|
||||
local packages=("$@")
|
||||
if [ ${#packages[@]} -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "Installing packages: ${packages[*]}"
|
||||
|
||||
case "$PACKAGE_MANAGER" in
|
||||
"pacman")
|
||||
(
|
||||
sudo pacman --noconfirm --needed -S "${packages[@]}" 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Installing ${#packages[@]} packages..."
|
||||
wait
|
||||
;;
|
||||
"apt")
|
||||
(
|
||||
sudo apt install -y "${packages[@]}" 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Installing ${#packages[@]} packages..."
|
||||
wait
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Install AUR packages (Arch only)
|
||||
install_aur_packages() {
|
||||
local packages=("$@")
|
||||
if [ ${#packages[@]} -eq 0 ] || [ "$PACKAGE_MANAGER" != "pacman" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Ensure AUR helper is available
|
||||
if [ -z "$AUR_HELPER" ]; then
|
||||
install_aur_helper
|
||||
fi
|
||||
|
||||
log INFO "Installing AUR packages: ${packages[*]}"
|
||||
|
||||
(
|
||||
"$AUR_HELPER" --noconfirm -S --needed --aur "${packages[@]}" 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Installing ${#packages[@]} AUR packages..."
|
||||
wait
|
||||
}
|
||||
|
||||
# Update AUR packages
|
||||
update_aur_packages() {
|
||||
if [ "$PACKAGE_MANAGER" != "pacman" ] || [ -z "$AUR_HELPER" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local section_start=$(date +%s)
|
||||
log SECTION "Updating AUR packages"
|
||||
|
||||
if confirm "Update AUR packages?"; then
|
||||
(
|
||||
"$AUR_HELPER" --noconfirm --aur 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Updating AUR packages..."
|
||||
wait
|
||||
log SUCCESS "AUR packages updated $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "AUR update skipped"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install Flatpak applications
|
||||
install_flatpak_apps() {
|
||||
local apps=("$@")
|
||||
if [ ${#apps[@]} -eq 0 ] || [ "$FLATPAK_AVAILABLE" != "yes" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "Installing Flatpak apps: ${apps[*]}"
|
||||
|
||||
for app in "${apps[@]}"; do
|
||||
(
|
||||
flatpak install -y flathub "$app" 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Installing Flatpak app: $app..."
|
||||
wait
|
||||
done
|
||||
}
|
||||
|
||||
# Update Flatpak applications
|
||||
update_flatpak_apps() {
|
||||
if [ "$FLATPAK_AVAILABLE" != "yes" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local section_start=$(date +%s)
|
||||
log SECTION "Updating Flatpak applications"
|
||||
|
||||
if confirm "Update Flatpak applications?"; then
|
||||
(
|
||||
flatpak update -y 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Updating Flatpak applications..."
|
||||
wait
|
||||
log SUCCESS "Flatpak applications updated $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "Flatpak update skipped"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install Snap packages (Ubuntu/Debian)
|
||||
install_snap_packages() {
|
||||
local packages=("$@")
|
||||
if [ ${#packages[@]} -eq 0 ] || [ "$SNAP_AVAILABLE" != "yes" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log INFO "Installing Snap packages: ${packages[*]}"
|
||||
|
||||
for package in "${packages[@]}"; do
|
||||
local snap_args=""
|
||||
# Handle special snap flags
|
||||
case "$package" in
|
||||
*"--classic")
|
||||
snap_args="--classic"
|
||||
package=${package//" --classic"/}
|
||||
;;
|
||||
esac
|
||||
|
||||
(
|
||||
sudo snap install $snap_args "$package" 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Installing Snap package: $package..."
|
||||
wait
|
||||
done
|
||||
}
|
||||
|
||||
# Update Snap packages
|
||||
update_snap_packages() {
|
||||
if [ "$SNAP_AVAILABLE" != "yes" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local section_start=$(date +%s)
|
||||
log SECTION "Updating Snap packages"
|
||||
|
||||
if confirm "Update Snap packages?"; then
|
||||
(
|
||||
sudo snap refresh 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Updating Snap packages..."
|
||||
wait
|
||||
log SUCCESS "Snap packages updated $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "Snap update skipped"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install packages from various sources (unified interface)
|
||||
install_package_set() {
|
||||
local pkg_type="$1"
|
||||
shift
|
||||
local packages=("$@")
|
||||
|
||||
if [ ${#packages[@]} -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$pkg_type" in
|
||||
"system"|"main")
|
||||
install_packages "${packages[@]}"
|
||||
;;
|
||||
"aur")
|
||||
install_aur_packages "${packages[@]}"
|
||||
;;
|
||||
"flatpak")
|
||||
install_flatpak_apps "${packages[@]}"
|
||||
;;
|
||||
"snap")
|
||||
install_snap_packages "${packages[@]}"
|
||||
;;
|
||||
*)
|
||||
log ERROR "Unknown package type: $pkg_type"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Setup package managers (install if needed)
|
||||
setup_package_managers() {
|
||||
log SECTION "Setting up package managers"
|
||||
|
||||
# Setup Flatpak if not available but potentially useful
|
||||
if [ "$FLATPAK_AVAILABLE" != "yes" ] && [ "${SYSTEM_INFO[WSL]}" != "yes" ]; then
|
||||
setup_flatpak
|
||||
fi
|
||||
|
||||
# Setup Snap for Ubuntu systems if not available
|
||||
if [ "$PACKAGE_MANAGER" == "apt" ] && [ "$SNAP_AVAILABLE" != "yes" ]; then
|
||||
setup_snap
|
||||
fi
|
||||
|
||||
# Install AUR helper for Arch if needed
|
||||
if [ "$PACKAGE_MANAGER" == "pacman" ] && [ -z "$AUR_HELPER" ]; then
|
||||
install_aur_helper
|
||||
fi
|
||||
}
|
||||
|
||||
# Setup Flatpak
|
||||
setup_flatpak() {
|
||||
log INFO "Setting up Flatpak..."
|
||||
local section_start=$(date +%s)
|
||||
|
||||
(
|
||||
case "$PACKAGE_MANAGER" in
|
||||
"pacman")
|
||||
sudo pacman --noconfirm --needed -S flatpak
|
||||
;;
|
||||
"apt")
|
||||
sudo apt install -y flatpak
|
||||
;;
|
||||
esac
|
||||
|
||||
# Add Flathub repository
|
||||
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
|
||||
# Install Flatseal for permission management
|
||||
flatpak install -y flathub com.github.tchx84.Flatseal
|
||||
) 2>&1 | tee -a "$LOG_FILE" &
|
||||
|
||||
spinner $! "Setting up Flatpak and Flathub repository..."
|
||||
wait
|
||||
|
||||
FLATPAK_AVAILABLE="yes"
|
||||
log SUCCESS "Flatpak setup completed $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
# Setup Snap
|
||||
setup_snap() {
|
||||
log INFO "Setting up Snap..."
|
||||
local section_start=$(date +%s)
|
||||
|
||||
(
|
||||
sudo apt install -y snap 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Installing Snap package manager..."
|
||||
wait
|
||||
|
||||
SNAP_AVAILABLE="yes"
|
||||
log SUCCESS "Snap setup completed $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
# Get package manager status
|
||||
get_package_manager_status() {
|
||||
echo "Primary: $PACKAGE_MANAGER"
|
||||
[ -n "$AUR_HELPER" ] && echo "AUR: $AUR_HELPER"
|
||||
[ "$FLATPAK_AVAILABLE" == "yes" ] && echo "Flatpak: available"
|
||||
[ "$SNAP_AVAILABLE" == "yes" ] && echo "Snap: available"
|
||||
}
|
||||
|
||||
# Source guard to prevent double-sourcing
|
||||
if [ -z "$PACKAGES_LIB_LOADED" ]; then
|
||||
PACKAGES_LIB_LOADED=true
|
||||
fi
|
||||
332
update/lib/roles.sh
Normal file
332
update/lib/roles.sh
Normal file
@ -0,0 +1,332 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CMtec Update System - Role Management Library
|
||||
# Handles role-based installation system
|
||||
|
||||
# Load roles from configuration
|
||||
load_roles() {
|
||||
local hostname="${SYSTEM_INFO[HOSTNAME]}"
|
||||
local distro="${SYSTEM_INFO[DISTRO]}"
|
||||
|
||||
log INFO "Loading role configuration for $hostname ($distro)..."
|
||||
|
||||
# Initialize all roles to "no"
|
||||
declare -gA ROLES
|
||||
local all_roles=(
|
||||
"DESKTOP_BASE" "DESKTOP_WORK" "CODE" "TERMINAL" "HYPERLAND"
|
||||
"MUSIC" "GAME" "VR" "LAB" "BT" "NVIDIA_GPU" "NVIDIA_1080_GPU"
|
||||
"WSL" "DEVELOPMENT" "AUDIO_PRODUCTION"
|
||||
)
|
||||
|
||||
for role in "${all_roles[@]}"; do
|
||||
ROLES["$role"]="no"
|
||||
done
|
||||
|
||||
# Load distro-specific role configuration
|
||||
local role_config_file="$SCRIPT_DIR/config/${distro}-roles.conf"
|
||||
if [ -f "$role_config_file" ]; then
|
||||
source "$role_config_file"
|
||||
log SUCCESS "Loaded role configuration from $role_config_file"
|
||||
else
|
||||
log WARNING "Role configuration file not found: $role_config_file"
|
||||
# Fall back to hardcoded assignments
|
||||
assign_default_roles
|
||||
fi
|
||||
|
||||
# Apply hostname-specific role assignments
|
||||
assign_hostname_roles "$hostname"
|
||||
|
||||
# Apply auto-detected roles based on system capabilities
|
||||
assign_auto_detected_roles
|
||||
|
||||
# Validate role dependencies
|
||||
validate_role_dependencies
|
||||
|
||||
log SUCCESS "Role configuration completed"
|
||||
}
|
||||
|
||||
# Assign default roles based on system capabilities
|
||||
assign_default_roles() {
|
||||
log INFO "Assigning default roles based on system detection..."
|
||||
|
||||
# Basic roles based on system type
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
ROLES["TERMINAL"]="yes"
|
||||
if supports_feature "desktop"; then
|
||||
ROLES["DESKTOP_BASE"]="yes"
|
||||
ROLES["HYPERLAND"]="yes"
|
||||
fi
|
||||
;;
|
||||
"ubuntu")
|
||||
ROLES["TERMINAL"]="yes"
|
||||
if supports_feature "desktop"; then
|
||||
ROLES["DESKTOP_BASE"]="yes"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# WSL-specific roles
|
||||
if [ "${SYSTEM_INFO[WSL]}" == "yes" ]; then
|
||||
ROLES["WSL"]="yes"
|
||||
ROLES["DEVELOPMENT"]="yes"
|
||||
# Disable desktop-specific roles in WSL
|
||||
ROLES["DESKTOP_BASE"]="no"
|
||||
ROLES["HYPERLAND"]="no"
|
||||
ROLES["GAME"]="no"
|
||||
ROLES["VR"]="no"
|
||||
fi
|
||||
|
||||
# GPU-based roles
|
||||
if [ "${SYSTEM_INFO[NVIDIA_GPU]}" == "yes" ]; then
|
||||
ROLES["NVIDIA_GPU"]="yes"
|
||||
if echo "${SYSTEM_INFO[GPU_INFO]:-}" | grep -qi "GTX 1080"; then
|
||||
ROLES["NVIDIA_1080_GPU"]="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Bluetooth support
|
||||
if [ "${SYSTEM_INFO[BLUETOOTH]}" == "yes" ]; then
|
||||
ROLES["BT"]="yes"
|
||||
fi
|
||||
}
|
||||
|
||||
# Assign hostname-specific roles
|
||||
assign_hostname_roles() {
|
||||
local hostname="$1"
|
||||
|
||||
case "$hostname" in
|
||||
"CMBOX")
|
||||
ROLES["DESKTOP_BASE"]="yes"
|
||||
ROLES["DESKTOP_WORK"]="yes"
|
||||
ROLES["CODE"]="yes"
|
||||
ROLES["TERMINAL"]="yes"
|
||||
ROLES["HYPERLAND"]="yes"
|
||||
ROLES["MUSIC"]="yes"
|
||||
;;
|
||||
"STEAMBOX")
|
||||
ROLES["GAME"]="yes"
|
||||
ROLES["VR"]="yes"
|
||||
ROLES["DESKTOP_BASE"]="yes"
|
||||
ROLES["NVIDIA_GPU"]="yes"
|
||||
ROLES["TERMINAL"]="yes"
|
||||
ROLES["HYPERLAND"]="yes"
|
||||
;;
|
||||
"LABBOX")
|
||||
ROLES["DESKTOP_BASE"]="yes"
|
||||
ROLES["CODE"]="yes"
|
||||
ROLES["TERMINAL"]="yes"
|
||||
ROLES["HYPERLAND"]="yes"
|
||||
ROLES["LAB"]="yes"
|
||||
ROLES["BT"]="yes"
|
||||
;;
|
||||
"SIMONBOX")
|
||||
ROLES["GAME"]="yes"
|
||||
ROLES["VR"]="yes"
|
||||
ROLES["DESKTOP_BASE"]="yes"
|
||||
ROLES["NVIDIA_1080_GPU"]="yes"
|
||||
ROLES["TERMINAL"]="yes"
|
||||
ROLES["HYPERLAND"]="yes"
|
||||
ROLES["BT"]="yes"
|
||||
;;
|
||||
*)
|
||||
log INFO "No specific role configuration for hostname: $hostname"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Assign roles based on auto-detected system capabilities
|
||||
assign_auto_detected_roles() {
|
||||
log INFO "Auto-detecting additional roles based on system capabilities..."
|
||||
|
||||
# Development environment detection
|
||||
if command_exists git && (command_exists nvim || command_exists vim); then
|
||||
ROLES["DEVELOPMENT"]="yes"
|
||||
fi
|
||||
|
||||
# Audio production detection
|
||||
if [ "${SYSTEM_INFO[AUDIO_SYSTEM]}" == "pipewire" ] && supports_feature "desktop"; then
|
||||
# Only enable if desktop is available and pipewire is present
|
||||
if [ "${ROLES[DESKTOP_BASE]}" == "yes" ]; then
|
||||
# Don't auto-enable audio production, leave it to specific hostname configs
|
||||
log INFO "Pipewire detected - audio production capabilities available"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Gaming detection based on GPU
|
||||
if [ "${SYSTEM_INFO[NVIDIA_GPU]}" == "yes" ] && supports_feature "desktop"; then
|
||||
if [ "${ROLES[GAME]}" == "no" ]; then
|
||||
log INFO "Gaming-capable GPU detected but gaming role not enabled"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Validate role dependencies and conflicts
|
||||
validate_role_dependencies() {
|
||||
log INFO "Validating role dependencies..."
|
||||
|
||||
# Desktop dependencies
|
||||
local desktop_roles=("DESKTOP_WORK" "GAME" "VR" "MUSIC" "HYPERLAND")
|
||||
for role in "${desktop_roles[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ] && [ "${ROLES[DESKTOP_BASE]}" == "no" ]; then
|
||||
log WARNING "$role requires DESKTOP_BASE - enabling it"
|
||||
ROLES["DESKTOP_BASE"]="yes"
|
||||
fi
|
||||
done
|
||||
|
||||
# VR requires Gaming
|
||||
if [ "${ROLES[VR]}" == "yes" ] && [ "${ROLES[GAME]}" == "no" ]; then
|
||||
log WARNING "VR role requires GAME role - enabling it"
|
||||
ROLES["GAME"]="yes"
|
||||
fi
|
||||
|
||||
# NVIDIA GPU roles
|
||||
if [ "${ROLES[NVIDIA_1080_GPU]}" == "yes" ] && [ "${ROLES[NVIDIA_GPU]}" == "no" ]; then
|
||||
log WARNING "NVIDIA_1080_GPU requires NVIDIA_GPU - enabling it"
|
||||
ROLES["NVIDIA_GPU"]="yes"
|
||||
fi
|
||||
|
||||
# WSL conflicts
|
||||
if [ "${ROLES[WSL]}" == "yes" ]; then
|
||||
local wsl_conflicts=("HYPERLAND" "VR")
|
||||
for role in "${wsl_conflicts[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ]; then
|
||||
log WARNING "$role is not compatible with WSL - disabling it"
|
||||
ROLES["$role"]="no"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Container conflicts
|
||||
if [ "${SYSTEM_INFO[CONTAINER]}" == "yes" ]; then
|
||||
local container_conflicts=("HYPERLAND" "VR" "GAME" "NVIDIA_GPU")
|
||||
for role in "${container_conflicts[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ]; then
|
||||
log WARNING "$role is not compatible with containers - disabling it"
|
||||
ROLES["$role"]="no"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Get enabled roles
|
||||
get_enabled_roles() {
|
||||
local enabled_roles=()
|
||||
for role in "${!ROLES[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ]; then
|
||||
enabled_roles+=("$role")
|
||||
fi
|
||||
done
|
||||
echo "${enabled_roles[@]}"
|
||||
}
|
||||
|
||||
# Check if a specific role is enabled
|
||||
role_enabled() {
|
||||
local role="$1"
|
||||
[ "${ROLES[$role]}" == "yes" ]
|
||||
}
|
||||
|
||||
# Get role count
|
||||
get_role_count() {
|
||||
local count=0
|
||||
for role in "${!ROLES[@]}"; do
|
||||
if [ "${ROLES[$role]}" == "yes" ]; then
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
echo $count
|
||||
}
|
||||
|
||||
# Interactive role selection (if interactive mode is enabled)
|
||||
interactive_role_selection() {
|
||||
if [ "$INTERACTIVE" != "true" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log SECTION "Interactive Role Selection"
|
||||
echo -e "${YELLOW}Current role configuration:${RESET}"
|
||||
|
||||
local all_roles=($(printf '%s\n' "${!ROLES[@]}" | sort))
|
||||
for role in "${all_roles[@]}"; do
|
||||
local status="${ROLES[$role]}"
|
||||
local status_icon="${GREEN}${CHECK}${RESET}"
|
||||
[ "$status" == "no" ] && status_icon="${RED}${CROSS}${RESET}"
|
||||
echo -e " $status_icon $role"
|
||||
done
|
||||
|
||||
echo
|
||||
if confirm "Modify role configuration?"; then
|
||||
modify_roles_interactively
|
||||
fi
|
||||
}
|
||||
|
||||
# Interactive role modification
|
||||
modify_roles_interactively() {
|
||||
local all_roles=($(printf '%s\n' "${!ROLES[@]}" | sort))
|
||||
|
||||
for role in "${all_roles[@]}"; do
|
||||
local current_status="${ROLES[$role]}"
|
||||
local opposite_status="yes"
|
||||
[ "$current_status" == "yes" ] && opposite_status="no"
|
||||
|
||||
if confirm "Toggle $role (currently: $current_status) to $opposite_status?"; then
|
||||
ROLES["$role"]="$opposite_status"
|
||||
log INFO "$role toggled to $opposite_status"
|
||||
fi
|
||||
done
|
||||
|
||||
# Re-validate after interactive changes
|
||||
validate_role_dependencies
|
||||
}
|
||||
|
||||
# Export roles for use in other scripts
|
||||
export_roles() {
|
||||
for role in "${!ROLES[@]}"; do
|
||||
export "ROLE_${role}=${ROLES[$role]}"
|
||||
done
|
||||
}
|
||||
|
||||
# Get roles that should be installed by category
|
||||
get_roles_by_category() {
|
||||
local category="$1"
|
||||
local matching_roles=()
|
||||
|
||||
case "$category" in
|
||||
"desktop")
|
||||
for role in DESKTOP_BASE DESKTOP_WORK HYPERLAND; do
|
||||
[ "${ROLES[$role]}" == "yes" ] && matching_roles+=("$role")
|
||||
done
|
||||
;;
|
||||
"development")
|
||||
for role in CODE DEVELOPMENT TERMINAL; do
|
||||
[ "${ROLES[$role]}" == "yes" ] && matching_roles+=("$role")
|
||||
done
|
||||
;;
|
||||
"gaming")
|
||||
for role in GAME VR NVIDIA_GPU NVIDIA_1080_GPU; do
|
||||
[ "${ROLES[$role]}" == "yes" ] && matching_roles+=("$role")
|
||||
done
|
||||
;;
|
||||
"media")
|
||||
for role in MUSIC; do
|
||||
[ "${ROLES[$role]}" == "yes" ] && matching_roles+=("$role")
|
||||
done
|
||||
;;
|
||||
"hardware")
|
||||
for role in BT LAB; do
|
||||
[ "${ROLES[$role]}" == "yes" ] && matching_roles+=("$role")
|
||||
done
|
||||
;;
|
||||
*)
|
||||
log WARNING "Unknown role category: $category"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "${matching_roles[@]}"
|
||||
}
|
||||
|
||||
# Source guard to prevent double-sourcing
|
||||
if [ -z "$ROLES_LIB_LOADED" ]; then
|
||||
ROLES_LIB_LOADED=true
|
||||
fi
|
||||
146
update/ubuntu/development.sh
Normal file
146
update/ubuntu/development.sh
Normal file
@ -0,0 +1,146 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Ubuntu Development Environment Module
|
||||
|
||||
ubuntu_install_rust() {
|
||||
log SECTION "Installing Rust toolchain"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Rust via rustup?"; then
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --no-modify-path -y
|
||||
|
||||
if [ "${SYSTEM_INFO[WSL]}" == "yes" ]; then
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
|
||||
rustup self update
|
||||
rustup update stable
|
||||
rustup default stable
|
||||
|
||||
log SUCCESS "Rust installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
ubuntu_install_node() {
|
||||
log SECTION "Installing Node.js"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Node.js?"; then
|
||||
curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||
install_packages nodejs
|
||||
npm config set prefix "${HOME}/.npm"
|
||||
|
||||
log SUCCESS "Node.js installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
ubuntu_install_python() {
|
||||
log SECTION "Setting up Python development"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
local version="${SYSTEM_INFO[VERSION]}"
|
||||
if [ "$version" == "22.04" ]; then
|
||||
pip3 install pynvim
|
||||
else
|
||||
install_packages python3-pynvim
|
||||
fi
|
||||
|
||||
log SUCCESS "Python development setup $(show_timer $section_start)"
|
||||
}
|
||||
|
||||
ubuntu_build_neovim() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Building Neovim from source"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Build Neovim from source?"; then
|
||||
# Remove system neovim if in WSL
|
||||
if [ "${SYSTEM_INFO[WSL]}" == "yes" ]; then
|
||||
sudo apt -y purge --auto-remove neovim
|
||||
fi
|
||||
|
||||
install_packages bat fd-find
|
||||
|
||||
cd ~
|
||||
if [ -d ~/neovim ]; then rm -rf ~/neovim; fi
|
||||
|
||||
(
|
||||
git clone https://github.com/neovim/neovim
|
||||
cd neovim && git checkout stable
|
||||
make CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
cd build && cpack -G DEB && sudo dpkg -i nvim*.deb
|
||||
) 2>&1 | tee -a "$LOG_FILE" &
|
||||
|
||||
spinner $! "Building Neovim (this will take a while)..."
|
||||
wait
|
||||
|
||||
if [ -d ~/neovim ]; then rm -rf ~/neovim; fi
|
||||
|
||||
mkdir -p ~/.config/nvim
|
||||
ln -sf ~/linuxbox/config/nvim/init.lua ~/.config/nvim/init.lua
|
||||
|
||||
log SUCCESS "Neovim built and installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
ubuntu_install_languages() {
|
||||
log SECTION "Installing programming languages"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install additional languages (Go, PHP, Ruby, etc.)?"; then
|
||||
local packages=(golang ruby ruby-dev php php-curl php-xml php-mbstring luarocks composer)
|
||||
install_packages "${packages[@]}"
|
||||
|
||||
# Java installation
|
||||
if [ "${SYSTEM_INFO[WSL]}" == "yes" ]; then
|
||||
sudo add-apt-repository -y ppa:linuxuprising/java
|
||||
sudo apt update
|
||||
install_packages oracle-java17-installer
|
||||
else
|
||||
install_packages default-jdk
|
||||
fi
|
||||
|
||||
log SUCCESS "Programming languages installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
ubuntu_install_julia() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log SECTION "Installing Julia"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Julia programming language?"; then
|
||||
cd ~
|
||||
wget https://julialang-s3.julialang.org/bin/linux/x64/1.9/julia-1.9.0-linux-x86_64.tar.gz
|
||||
tar -xvzf julia-1.9.0-linux-x86_64.tar.gz
|
||||
sudo cp -r julia-1.9.0 /opt/
|
||||
sudo ln -sf /opt/julia-1.9.0/bin/julia /usr/local/bin/julia
|
||||
rm julia-1.9.0-linux-x86_64.tar.gz*
|
||||
rm -rf julia-1.9.0
|
||||
|
||||
log SUCCESS "Julia installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
ubuntu_setup_development() {
|
||||
if ! role_enabled "CODE" && ! role_enabled "DEVELOPMENT"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
ubuntu_install_rust
|
||||
ubuntu_install_node
|
||||
ubuntu_install_python
|
||||
ubuntu_build_neovim
|
||||
ubuntu_install_languages
|
||||
ubuntu_install_julia
|
||||
}
|
||||
|
||||
if [ -z "$UBUNTU_DEVELOPMENT_LOADED" ]; then
|
||||
UBUNTU_DEVELOPMENT_LOADED=true
|
||||
fi
|
||||
75
update/ubuntu/system.sh
Normal file
75
update/ubuntu/system.sh
Normal file
@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Ubuntu Linux System Setup Module
|
||||
|
||||
ubuntu_install_system_base() {
|
||||
log SECTION "Installing Ubuntu system base packages"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install essential system packages?"; then
|
||||
local packages=(
|
||||
build-essential gawk imagemagick gpg ninja-build gettext cmake unzip curl
|
||||
libssl-dev libffi-dev file libudev-dev pkg-config locales btop ncdu
|
||||
ranger timeshift python3 python3-pip python3-venv python3-dev pipx
|
||||
)
|
||||
|
||||
install_packages "${packages[@]}"
|
||||
log SUCCESS "System base packages installed $(show_timer $section_start)"
|
||||
fi
|
||||
}
|
||||
|
||||
ubuntu_install_homebrew() {
|
||||
log SECTION "Installing Homebrew"
|
||||
local section_start=$(date +%s)
|
||||
|
||||
if confirm "Install Homebrew package manager?"; then
|
||||
export NONINTERACTIVE=1
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
BREW_PREFIX="/home/linuxbrew/.linuxbrew"
|
||||
if [ -d "$BREW_PREFIX" ]; then
|
||||
eval "$("$BREW_PREFIX"/bin/brew shellenv)"
|
||||
log SUCCESS "Homebrew installed $(show_timer $section_start)"
|
||||
else
|
||||
log ERROR "Homebrew installation failed"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ubuntu_setup_locale() {
|
||||
log SECTION "Setting up locale"
|
||||
sudo locale-gen "en_US.UTF-8"
|
||||
sudo update-locale LANG=en_US.UTF-8
|
||||
}
|
||||
|
||||
ubuntu_setup_shell_config() {
|
||||
log SECTION "Setting up shell configuration"
|
||||
|
||||
if [ "${SYSTEM_INFO[WSL]}" == "yes" ]; then
|
||||
ln -sf ~/linuxbox/bashrc_ubuntu ~/.bashrc
|
||||
ln -sf ~/linuxbox/gitconfig.work ~/.gitconfig
|
||||
else
|
||||
ln -sf ~/linuxbox/bashrc_ubuntu ~/.bashrc
|
||||
ln -sf ~/linuxbox/gitconfig ~/.gitconfig
|
||||
|
||||
mkdir -p ~/.config/alacritty
|
||||
ln -sf ~/linuxbox/config/alacritty/alacritty.toml ~/.config/alacritty/alacritty.toml
|
||||
fi
|
||||
|
||||
mkdir -p ~/.local/bin
|
||||
ln -sf ~/linuxbox/update_wrapper.sh ~/.local/bin/update
|
||||
ln -sf ~/linuxbox/start_nvim.sh ~/.local/bin/start_nvim
|
||||
ln -sf ~/linuxbox/start_toolbox.sh ~/.local/bin/start_toolbox
|
||||
}
|
||||
|
||||
ubuntu_setup_system() {
|
||||
ubuntu_setup_locale
|
||||
ubuntu_install_system_base
|
||||
ubuntu_install_homebrew
|
||||
ubuntu_setup_shell_config
|
||||
}
|
||||
|
||||
if [ -z "$UBUNTU_SYSTEM_LOADED" ]; then
|
||||
UBUNTU_SYSTEM_LOADED=true
|
||||
fi
|
||||
29
update/ubuntu/ubuntu.sh
Normal file
29
update/ubuntu/ubuntu.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Ubuntu Linux Master Module
|
||||
# Loads all Ubuntu-specific modules and orchestrates installation
|
||||
|
||||
# Source all Ubuntu modules
|
||||
source "$SCRIPT_DIR/ubuntu/system.sh"
|
||||
source "$SCRIPT_DIR/ubuntu/development.sh"
|
||||
|
||||
# Main Ubuntu installation function
|
||||
ubuntu_install_all() {
|
||||
log SECTION "Starting Ubuntu Linux installation"
|
||||
|
||||
# System setup (homebrew, base packages)
|
||||
ubuntu_setup_system
|
||||
|
||||
# Development environment (custom builds, languages)
|
||||
ubuntu_setup_development
|
||||
|
||||
# Note: Terminal, desktop, etc. would be added here
|
||||
# For now, focusing on the core differences
|
||||
|
||||
log SUCCESS "Ubuntu Linux installation completed"
|
||||
}
|
||||
|
||||
# Source guard
|
||||
if [ -z "$UBUNTU_MASTER_LOADED" ]; then
|
||||
UBUNTU_MASTER_LOADED=true
|
||||
fi
|
||||
193
update/update.sh
Executable file
193
update/update.sh
Executable file
@ -0,0 +1,193 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CMtec Universal Update System v3.0.0
|
||||
# Main entry point for cross-platform system updates
|
||||
|
||||
set -e
|
||||
|
||||
# Get script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Parse command line arguments
|
||||
INTERACTIVE=false
|
||||
HELP=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-i|--interactive)
|
||||
INTERACTIVE=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
HELP=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Usage: $0 [-i|--interactive] [-h|--help]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$HELP" == "true" ]; then
|
||||
echo "CMtec Universal Update System v3.0.0"
|
||||
echo ""
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "OPTIONS:"
|
||||
echo " -i, --interactive Enable interactive mode with confirmations"
|
||||
echo " -h, --help Show this help message"
|
||||
echo ""
|
||||
echo "This script automatically detects your Linux distribution and applies"
|
||||
echo "appropriate updates and software installations based on system roles."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Source all library files
|
||||
source "$SCRIPT_DIR/lib/core.sh"
|
||||
source "$SCRIPT_DIR/lib/detect.sh"
|
||||
source "$SCRIPT_DIR/lib/roles.sh"
|
||||
source "$SCRIPT_DIR/lib/packages.sh"
|
||||
|
||||
# Initialize core system
|
||||
init_core
|
||||
|
||||
# Ensure sudo access
|
||||
sudo -v
|
||||
|
||||
# Detect system and hardware
|
||||
detect_system
|
||||
detect_hardware
|
||||
|
||||
# Show fancy distro-specific header
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
show_arch_header "${SYSTEM_INFO[HOSTNAME]}"
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
show_ubuntu_header "${SYSTEM_INFO[HOSTNAME]}"
|
||||
;;
|
||||
*)
|
||||
show_header "${SYSTEM_INFO[HOSTNAME]}" "${SYSTEM_INFO[PRETTY_NAME]}"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Load and configure roles
|
||||
load_roles
|
||||
|
||||
# Show system configuration
|
||||
show_roles
|
||||
|
||||
# Run system health check
|
||||
system_health_check
|
||||
|
||||
# Interactive confirmation
|
||||
if [ "$INTERACTIVE" == "true" ]; then
|
||||
if ! confirm "Proceed with system update?"; then
|
||||
log INFO "Update cancelled by user"
|
||||
exit 0
|
||||
fi
|
||||
interactive_role_selection
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}${CHECK} Starting update process...${RESET}\n"
|
||||
|
||||
# Initialize package managers
|
||||
init_package_managers
|
||||
setup_package_managers
|
||||
|
||||
# Create backup if timeshift is available
|
||||
if package_installed timeshift; then
|
||||
section_start=$(date +%s)
|
||||
log SECTION "Creating system snapshot"
|
||||
if confirm "Create Timeshift snapshot before update?"; then
|
||||
(
|
||||
sudo timeshift --create --comments "Universal update script $(date '+%Y-%m-%d %H:%M:%S')" 2>&1 | tee -a "$LOG_FILE"
|
||||
) &
|
||||
spinner $! "Creating system snapshot..."
|
||||
wait
|
||||
log SUCCESS "System snapshot created $(show_timer $section_start)"
|
||||
else
|
||||
log WARNING "System snapshot skipped"
|
||||
fi
|
||||
else
|
||||
log WARNING "Timeshift not installed - no system snapshot created"
|
||||
fi
|
||||
|
||||
# Update package databases and perform system upgrade
|
||||
update_package_databases
|
||||
system_upgrade
|
||||
|
||||
# Update AUR packages (Arch only)
|
||||
if [ "$PACKAGE_MANAGER" == "pacman" ]; then
|
||||
update_aur_packages
|
||||
fi
|
||||
|
||||
# Update Flatpak and Snap packages
|
||||
update_flatpak_apps
|
||||
[ "$PACKAGE_MANAGER" == "apt" ] && update_snap_packages
|
||||
|
||||
# Install basic system packages
|
||||
log SECTION "Installing essential system packages"
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
install_packages base-devel linux-headers git bc cmake gawk wget gettext unzip curl inetutils python python-pip python-pipx rustup
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
install_packages build-essential git gawk imagemagick gpg ninja-build gettext cmake unzip curl libssl-dev libffi-dev file libudev-dev pkg-config locales btop ncdu ranger timeshift
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create symbolic links for configuration files
|
||||
log SECTION "Setting up configuration links"
|
||||
mkdir -p ~/.local/bin ~/.config
|
||||
|
||||
# Link bash configuration
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
ln -sf ~/linuxbox/bashrc_arch ~/.bashrc
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
if [ "${SYSTEM_INFO[WSL]}" == "yes" ]; then
|
||||
ln -sf ~/linuxbox/bashrc_ubuntu ~/.bashrc
|
||||
ln -sf ~/linuxbox/gitconfig.work ~/.gitconfig
|
||||
else
|
||||
ln -sf ~/linuxbox/bashrc_ubuntu ~/.bashrc
|
||||
ln -sf ~/linuxbox/gitconfig ~/.gitconfig
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Link common configuration files
|
||||
ln -sf ~/linuxbox/update_wrapper.sh ~/.local/bin/update
|
||||
|
||||
# Set locale
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
sudo localectl set-locale LANG=en_US.UTF-8
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
sudo locale-gen "en_US.UTF-8" || true
|
||||
sudo update-locale LANG=en_US.UTF-8 || true
|
||||
;;
|
||||
esac
|
||||
|
||||
# Load and run distro-specific installation
|
||||
case "${SYSTEM_INFO[DISTRO]}" in
|
||||
"arch")
|
||||
source "$SCRIPT_DIR/arch/arch.sh"
|
||||
arch_install_all
|
||||
;;
|
||||
"ubuntu"|"debian")
|
||||
source "$SCRIPT_DIR/ubuntu/ubuntu.sh"
|
||||
ubuntu_install_all
|
||||
;;
|
||||
*)
|
||||
log ERROR "Unsupported distribution: ${SYSTEM_INFO[DISTRO]}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Final summary and reboot prompt
|
||||
show_final_summary
|
||||
Loading…
x
Reference in New Issue
Block a user