diff --git a/.gitmodules b/.gitmodules index b83134d..f81b8b8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "src/dotfiles"] path = src/dotfiles url = https://github.com/garretpatten/dotfiles.git + branch = master diff --git a/src/dotfiles b/src/dotfiles index c75951e..3fbe20f 160000 --- a/src/dotfiles +++ b/src/dotfiles @@ -1 +1 @@ -Subproject commit c75951e4fdcddb4eea7a39ad07ba59b0aec24609 +Subproject commit 3fbe20fbadad55f4a13dea3eb6185dd965486da5 diff --git a/src/scripts/cli.sh b/src/scripts/cli.sh index d4ce376..d03b616 100644 --- a/src/scripts/cli.sh +++ b/src/scripts/cli.sh @@ -58,11 +58,22 @@ install_fastfetch() { log_info "Installing fastfetch system information tool..." if ! is_installed "fastfetch"; then - # Add PPA repository for fastfetch + # Try PPA first (Ubuntu) if ! grep -q "zhangsongcui3371/fastfetch" /etc/apt/sources.list.d/*.list 2>/dev/null; then log_info "Adding fastfetch PPA repository..." - sudo add-apt-repository -y ppa:zhangsongcui3371/fastfetch - update_apt_cache + if sudo add-apt-repository -y ppa:zhangsongcui3371/fastfetch; then + update_apt_cache + else + log_warning "Failed to add fastfetch PPA, trying alternative installation..." + # Try installing from standard repositories + if sudo apt-get install -y fastfetch; then + log_success "fastfetch installed from standard repositories" + return 0 + else + log_error "Failed to install fastfetch from any source" + return 1 + fi + fi fi # Install fastfetch @@ -79,12 +90,13 @@ main() { # Update package cache update_apt_cache - # Install components - install_package_managers - install_cli_tools - install_fastfetch + # Install components with error handling + execute_with_fallback install_package_managers + execute_with_fallback install_cli_tools + execute_with_fallback install_fastfetch log_success "CLI tools installation completed!" + log_info "Check $ERROR_LOG_FILE for any failed installations" } # Execute main function diff --git a/src/scripts/dev.sh b/src/scripts/dev.sh index 34b2e6a..6acbfee 100644 --- a/src/scripts/dev.sh +++ b/src/scripts/dev.sh @@ -127,11 +127,37 @@ install_neovim() { log_info "Installing Neovim with latest version..." if ! is_installed "nvim"; then - # Add Neovim PPA for latest stable version + # Try to add Neovim PPA for latest stable version if ! grep -q "neovim-ppa" /etc/apt/sources.list.d/*.list 2>/dev/null; then log_info "Adding Neovim PPA repository..." - sudo add-apt-repository -y ppa:neovim-ppa/stable - update_apt_cache + if sudo add-apt-repository -y ppa:neovim-ppa/stable; then + update_apt_cache + else + log_warning "Failed to add Neovim PPA, trying alternative installation method..." + # Fallback: try alternative installation methods + log_warning "Failed to add Neovim PPA, trying alternative installation methods..." + + # Try snap if available (Ubuntu) + if command -v snap >/dev/null 2>&1; then + log_info "Installing Neovim via Snap as fallback..." + if sudo snap install nvim --classic; then + log_success "Neovim installed via Snap" + return 0 + else + log_warning "Snap installation failed, trying other methods..." + fi + fi + + # Try installing from Ubuntu repositories (works on both Ubuntu and Mint) + log_info "Trying to install Neovim from standard repositories..." + if sudo apt-get install -y neovim; then + log_success "Neovim installed from standard repositories" + return 0 + else + log_error "All Neovim installation methods failed" + return 1 + fi + fi fi # Install Neovim and Python support @@ -141,27 +167,42 @@ install_neovim() { "python3-dev" "python3-pip" ) - install_apt_packages "${neovim_packages[@]}" + + # Try to install packages, with individual fallback + if ! install_apt_packages "${neovim_packages[@]}"; then + log_warning "Batch installation failed, trying individual packages..." + for package in "${neovim_packages[@]}"; do + if ! sudo apt-get install -y "$package"; then + log_error "Failed to install: $package" + fi + done + fi # Install pynvim for better Python integration if is_installed "pip3"; then log_info "Installing pynvim for Python integration..." - pip3 install --user pynvim || log_warning "Failed to install pynvim" + if ! pip3 install --user pynvim; then + log_warning "Failed to install pynvim" + fi fi # Install additional LSP servers via npm (if available) if is_installed "npm"; then log_info "Installing additional LSP servers..." - npm install -g typescript-language-server pyright vscode-langservers-extracted || log_warning "Failed to install some LSP servers" + if ! npm install -g typescript-language-server pyright vscode-langservers-extracted; then + log_warning "Failed to install some LSP servers" + fi fi # Install vsnip for snippet support (used in the dotfiles config) if is_installed "npm"; then log_info "Installing vsnip for snippet support..." - npm install -g vsnip || log_warning "Failed to install vsnip" + if ! npm install -g vsnip; then + log_warning "Failed to install vsnip" + fi fi - log_success "Neovim installed successfully" + log_success "Neovim installation process completed" else log_info "Neovim is already installed" fi @@ -218,21 +259,27 @@ install_cursor_ide() { log_info "Installing Cursor IDE..." if ! is_installed "cursor"; then - # Download Cursor IDE .deb package - local cursor_deb="$TEMP_DIR/cursor.deb" + # Download Cursor IDE AppImage + local cursor_appimage="$TEMP_DIR/cursor.AppImage" local cursor_url="https://downloader.cursor.sh/linux/appImage/x64" - # Try to get the latest .deb package URL - log_info "Downloading Cursor IDE..." + log_info "Downloading Cursor IDE AppImage..." # Download the AppImage version (more reliable for Linux) - local cursor_appimage="$TEMP_DIR/cursor.AppImage" if download_file_safe "$cursor_url" "$cursor_appimage"; then # Make it executable chmod +x "$cursor_appimage" + # Create a permanent location for the AppImage + local cursor_install_dir="$HOME/.local/bin" + ensure_directory "$cursor_install_dir" + local cursor_installed="$cursor_install_dir/cursor.AppImage" + + # Move AppImage to permanent location + mv "$cursor_appimage" "$cursor_installed" + # Create a symlink in /usr/local/bin for easy access - sudo ln -sf "$cursor_appimage" /usr/local/bin/cursor + sudo ln -sf "$cursor_installed" /usr/local/bin/cursor # Create desktop entry local desktop_entry="$HOME/.local/share/applications/cursor.desktop" @@ -242,7 +289,7 @@ install_cursor_ide() { [Desktop Entry] Name=Cursor Comment=The AI-first code editor -Exec=/usr/local/bin/cursor %U +Exec=$cursor_installed %U Icon=cursor Terminal=false Type=Application @@ -251,7 +298,18 @@ MimeType=text/plain;text/x-chdr;text/x-csrc;text/x-c++hdr;text/x-c++src;text/x-j StartupWMClass=Cursor EOF + # Create an icon (using a generic text editor icon as fallback) + local icon_dir="$HOME/.local/share/icons" + ensure_directory "$icon_dir" + + # Try to find a suitable icon or create a simple one + if command -v convert >/dev/null 2>&1; then + # Create a simple icon using ImageMagick if available + convert -size 64x64 xc:transparent -fill "#007ACC" -draw "circle 32,32 32,16" "$icon_dir/cursor.png" 2>/dev/null || true + fi + log_success "Cursor IDE installed successfully" + log_info "Cursor AppImage installed to: $cursor_installed" else log_error "Failed to download Cursor IDE" return 1 @@ -367,17 +425,18 @@ main() { # Update package cache update_apt_cache - # Install components - install_runtimes - install_frameworks - install_docker - install_dev_tools - install_cursor_ide - configure_dev_tools + # Install components with error handling + execute_with_fallback install_runtimes + execute_with_fallback install_frameworks + execute_with_fallback install_docker + execute_with_fallback install_dev_tools + execute_with_fallback install_cursor_ide + execute_with_fallback configure_dev_tools log_success "Development tools installation completed!" log_info "Note: You may need to log out and back in for Docker group permissions to take effect" log_info "Neovim setup: After installation, open neovim and run :PackerSync to install plugins from your dotfiles configuration" + log_info "Check $ERROR_LOG_FILE for any failed installations" } # Execute main function diff --git a/src/scripts/master.sh b/src/scripts/master.sh index d2d5de9..11bb755 100644 --- a/src/scripts/master.sh +++ b/src/scripts/master.sh @@ -18,6 +18,9 @@ main() { log_info "Project root: $PROJECT_ROOT" log_info "Script directory: $SCRIPT_DIR" + # Detect distribution for compatibility + detect_distribution + # Array of setup scripts to execute in order local setup_scripts=( "pre-install.sh" @@ -31,24 +34,24 @@ main() { "post-install.sh" ) - # Execute each setup script + # Execute each setup script with error handling for script in "${setup_scripts[@]}"; do local script_path="$SCRIPT_DIR/$script" if [[ -f "$script_path" ]]; then log_info "Executing setup script: $script" - # Execute script and capture exit code + # Execute script and continue even if it fails if bash "$script_path"; then log_success "Completed setup script: $script" else log_error "Failed to execute setup script: $script" + log_error "Continuing with remaining scripts..." log_error "Check $ERROR_LOG_FILE for details" - return 1 fi else log_error "Setup script not found: $script_path" - return 1 + log_error "Continuing with remaining scripts..." fi done diff --git a/src/scripts/media.sh b/src/scripts/media.sh index a354846..2a53650 100644 --- a/src/scripts/media.sh +++ b/src/scripts/media.sh @@ -61,24 +61,43 @@ install_media_applications() { log_info "VLC media player is already installed" fi - # Install Spotify via snap (more reliable than apt) + # Install Spotify with multiple fallback methods install_spotify() { if ! is_installed "spotify"; then log_info "Installing Spotify..." - # Check if snap is available - if is_installed "snap"; then - sudo snap install spotify - log_success "Spotify installed via snap" - else - # Fallback to apt if available - if is_package_installed "spotify-client"; then - log_info "Spotify is already installed via apt" + # Try snap first (Ubuntu) + if is_snap_available; then + if sudo snap install spotify; then + log_success "Spotify installed via snap" + return 0 else - log_warning "Neither snap nor apt package available for Spotify" - log_info "You may need to install Spotify manually from https://spotify.com" + log_warning "Snap installation failed, trying alternative methods..." fi fi + + # Try Flatpak (works on both Ubuntu and Mint) + if is_flatpak_available; then + if flatpak install -y flathub com.spotify.Client; then + log_success "Spotify installed via Flatpak" + return 0 + else + log_warning "Flatpak installation failed, trying apt..." + fi + fi + + # Try apt as fallback + if apt-cache show spotify-client >/dev/null 2>&1; then + if install_apt_packages "spotify-client"; then + log_success "Spotify installed via apt" + return 0 + else + log_warning "Apt installation failed" + fi + fi + + log_warning "No suitable installation method available for Spotify" + log_info "You may need to install Spotify manually from https://spotify.com" else log_info "Spotify is already installed" fi @@ -91,41 +110,56 @@ install_media_applications() { install_multimedia_codecs() { log_info "Installing multimedia codecs and tools..." - # Define multimedia packages + # Install distribution-agnostic multimedia packages first local multimedia_packages=( - "ubuntu-restricted-extras" # Codecs for proprietary formats "ffmpeg" # Video/audio processing tool "gstreamer1.0-plugins-bad" # Additional GStreamer plugins "gstreamer1.0-plugins-ugly" # More GStreamer plugins "gstreamer1.0-libav" # GStreamer libav plugin + "gstreamer1.0-plugins-good" # GStreamer good plugins ) - # Install multimedia packages - # Note: ubuntu-restricted-extras requires user interaction, so handle separately log_info "Installing essential multimedia codecs..." + install_apt_packages "${multimedia_packages[@]}" + + # Install distribution-specific restricted extras + install_restricted_extras() { + local distro_id + distro_id=$(lsb_release -si 2>/dev/null || echo "Unknown") + + case "$distro_id" in + "Ubuntu") + if ! is_package_installed "ubuntu-restricted-extras"; then + log_info "Installing ubuntu-restricted-extras (this may take a while)..." + # Pre-accept EULA for ttf-mscorefonts-installer + echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | \ + sudo debconf-set-selections + + # Install with non-interactive frontend + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ubuntu-restricted-extras || \ + log_warning "Failed to install ubuntu-restricted-extras" + else + log_info "ubuntu-restricted-extras is already installed" + fi + ;; + "LinuxMint") + # Linux Mint has its own multimedia codecs package + if ! is_package_installed "mint-meta-codecs"; then + log_info "Installing Linux Mint multimedia codecs..." + install_apt_packages "mint-meta-codecs" || \ + log_warning "Failed to install mint-meta-codecs" + else + log_info "Linux Mint multimedia codecs already installed" + fi + ;; + *) + log_info "Distribution-specific codecs not available for $distro_id" + log_info "Basic codecs have been installed" + ;; + esac + } - # Install non-interactive packages first - local non_interactive_packages=( - "ffmpeg" - "gstreamer1.0-plugins-bad" - "gstreamer1.0-plugins-ugly" - "gstreamer1.0-libav" - ) - install_apt_packages "${non_interactive_packages[@]}" - - # Install ubuntu-restricted-extras with automatic yes responses - if ! is_package_installed "ubuntu-restricted-extras"; then - log_info "Installing ubuntu-restricted-extras (this may take a while)..." - # Pre-accept EULA for ttf-mscorefonts-installer - echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | \ - sudo debconf-set-selections - - # Install with non-interactive frontend - sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ubuntu-restricted-extras || \ - log_warning "Failed to install ubuntu-restricted-extras" - else - log_info "ubuntu-restricted-extras is already installed" - fi + install_restricted_extras } # Main function @@ -135,13 +169,14 @@ main() { # Update package cache update_apt_cache - # Install components - install_browsers - install_media_applications - install_multimedia_codecs + # Install components with error handling + execute_with_fallback install_browsers + execute_with_fallback install_media_applications + execute_with_fallback install_multimedia_codecs log_success "Media applications installation completed!" log_info "You may need to restart your browser to use new codecs" + log_info "Check $ERROR_LOG_FILE for any failed installations" } # Execute main function diff --git a/src/scripts/organizeHome.sh b/src/scripts/organizeHome.sh index dfd1a7a..0b752ca 100644 --- a/src/scripts/organizeHome.sh +++ b/src/scripts/organizeHome.sh @@ -120,15 +120,16 @@ set_directory_permissions() { main() { log_info "Starting home directory organization..." - # Organize home directory - remove_unused_directories - create_project_directories - setup_development_workspace - create_useful_symlinks - set_directory_permissions + # Organize home directory with error handling + execute_with_fallback remove_unused_directories + execute_with_fallback create_project_directories + execute_with_fallback setup_development_workspace + execute_with_fallback create_useful_symlinks + execute_with_fallback set_directory_permissions log_success "Home directory organization completed!" log_info "Your home directory has been organized with useful project folders" + log_info "Check $ERROR_LOG_FILE for any failed operations" } # Execute main function diff --git a/src/scripts/post-install.sh b/src/scripts/post-install.sh index 92415e2..1c4d3d4 100644 --- a/src/scripts/post-install.sh +++ b/src/scripts/post-install.sh @@ -194,13 +194,14 @@ generate_setup_summary() { main() { log_info "Starting post-installation cleanup and configuration..." - # Perform final tasks - perform_final_system_update - configure_system_services - generate_setup_summary - display_completion_info + # Perform final tasks with error handling + execute_with_fallback perform_final_system_update + execute_with_fallback configure_system_services + execute_with_fallback generate_setup_summary + execute_with_fallback display_completion_info log_success "Post-installation setup completed successfully!" + log_info "Check $ERROR_LOG_FILE for any failed operations" } # Execute main function diff --git a/src/scripts/pre-install.sh b/src/scripts/pre-install.sh index 6833472..d58345a 100644 --- a/src/scripts/pre-install.sh +++ b/src/scripts/pre-install.sh @@ -137,13 +137,14 @@ main() { # Check system requirements check_system_requirements - # Perform system updates and configuration - perform_system_update - install_essential_tools - configure_system_settings + # Perform system updates and configuration with error handling + execute_with_fallback perform_system_update + execute_with_fallback install_essential_tools + execute_with_fallback configure_system_settings log_success "Pre-installation setup completed!" log_info "System is ready for application installation" + log_info "Check $ERROR_LOG_FILE for any failed operations" } # Execute main function diff --git a/src/scripts/productivity.sh b/src/scripts/productivity.sh index 27e97f1..207ed95 100644 --- a/src/scripts/productivity.sh +++ b/src/scripts/productivity.sh @@ -47,15 +47,43 @@ install_office_applications() { install_communication_tools() { log_info "Installing communication and collaboration tools..." - # Install Zoom via snap (more reliable than manual installation) + # Install Zoom with multiple fallback methods install_zoom() { if ! is_installed "zoom"; then log_info "Installing Zoom video conferencing..." - if is_installed "snap"; then - sudo snap install zoom-client - log_success "Zoom installed via snap" + + # Try snap first (Ubuntu) + if is_snap_available; then + if sudo snap install zoom-client; then + log_success "Zoom installed via snap" + return 0 + else + log_warning "Snap installation failed, trying alternative methods..." + fi + fi + + # Try Flatpak (works on both Ubuntu and Mint) + if is_flatpak_available; then + if flatpak install -y flathub us.zoom.Zoom; then + log_success "Zoom installed via Flatpak" + return 0 + else + log_warning "Flatpak installation failed, trying manual download..." + fi + fi + + # Manual download as last resort + log_info "Attempting manual Zoom installation..." + local zoom_deb="$TEMP_DIR/zoom.deb" + if download_file_safe "https://zoom.us/client/latest/zoom_amd64.deb" "$zoom_deb"; then + if sudo dpkg -i "$zoom_deb"; then + sudo apt-get install -f -y # Fix dependencies + log_success "Zoom installed via manual download" + else + log_error "Manual Zoom installation failed" + fi else - log_warning "Snap not available, skipping Zoom installation" + log_warning "Failed to download Zoom, skipping installation" log_info "You can install Zoom manually from https://zoom.us/download" fi else @@ -63,31 +91,63 @@ install_communication_tools() { fi } - # Install Discord via snap + # Install Discord with multiple fallback methods install_discord() { if ! is_installed "discord"; then log_info "Installing Discord communication platform..." - if is_installed "snap"; then - sudo snap install discord - log_success "Discord installed via snap" - else - log_warning "Snap not available, skipping Discord installation" + + # Try snap first (Ubuntu) + if is_snap_available; then + if sudo snap install discord; then + log_success "Discord installed via snap" + return 0 + else + log_warning "Snap installation failed, trying alternative methods..." + fi fi + + # Try Flatpak (works on both Ubuntu and Mint) + if is_flatpak_available; then + if flatpak install -y flathub com.discordapp.Discord; then + log_success "Discord installed via Flatpak" + return 0 + else + log_warning "Flatpak installation failed" + fi + fi + + log_warning "No suitable installation method available for Discord" else log_info "Discord is already installed" fi } - # Install Slack via snap + # Install Slack with multiple fallback methods install_slack() { if ! is_installed "slack"; then log_info "Installing Slack team communication..." - if is_installed "snap"; then - sudo snap install slack --classic - log_success "Slack installed via snap" - else - log_warning "Snap not available, skipping Slack installation" + + # Try snap first (Ubuntu) + if is_snap_available; then + if sudo snap install slack --classic; then + log_success "Slack installed via snap" + return 0 + else + log_warning "Snap installation failed, trying alternative methods..." + fi fi + + # Try Flatpak (works on both Ubuntu and Mint) + if is_flatpak_available; then + if flatpak install -y flathub com.slack.Slack; then + log_success "Slack installed via Flatpak" + return 0 + else + log_warning "Flatpak installation failed" + fi + fi + + log_warning "No suitable installation method available for Slack" else log_info "Slack is already installed" fi @@ -294,15 +354,16 @@ main() { # Update package cache update_apt_cache - # Install productivity components - install_office_applications - install_communication_tools - install_productivity_tools - install_system_utilities - configure_productivity_apps + # Install productivity components with error handling + execute_with_fallback install_office_applications + execute_with_fallback install_communication_tools + execute_with_fallback install_productivity_tools + execute_with_fallback install_system_utilities + execute_with_fallback configure_productivity_apps log_success "Productivity applications installation completed!" log_info "Note: Some applications may require additional configuration" + log_info "Check $ERROR_LOG_FILE for any failed installations" } # Execute main function diff --git a/src/scripts/security.sh b/src/scripts/security.sh index bd2ed7a..21d4c06 100644 --- a/src/scripts/security.sh +++ b/src/scripts/security.sh @@ -71,7 +71,6 @@ install_defense_tools() { "clamav-daemon" # ClamAV daemon "ufw" # Uncomplicated Firewall "openvpn" # OpenVPN client - "gnome-shell" # Required for some VPN integrations ) # Install defense tools in batch @@ -122,13 +121,20 @@ install_protonvpn() { sudo dpkg -i "$protonvpn_deb" update_apt_cache - # Install ProtonVPN packages + # Install ProtonVPN packages (with fallback for non-GNOME systems) local protonvpn_packages=( "proton-vpn-gnome-desktop" "libayatana-appindicator3-1" "gir1.2-ayatanaappindicator3-0.1" - "gnome-shell-extension-appindicator" ) + + # Try to install gnome-shell-extension-appindicator, but don't fail if it's not available + if apt-cache show gnome-shell-extension-appindicator >/dev/null 2>&1; then + protonvpn_packages+=("gnome-shell-extension-appindicator") + else + log_info "gnome-shell-extension-appindicator not available, skipping..." + fi + install_apt_packages "${protonvpn_packages[@]}" log_success "ProtonVPN installed successfully" @@ -250,10 +256,30 @@ install_signal() { fi # Add Signal repository - local signal_list_file="/etc/apt/sources.list.d/signal-xenial.list" + local signal_list_file="/etc/apt/sources.list.d/signal-desktop.list" if [[ ! -f "$signal_list_file" ]] || ! grep -q "updates.signal.org" "$signal_list_file" 2>/dev/null; then log_info "Adding Signal repository..." - echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.gpg] https://updates.signal.org/desktop/apt xenial main' | \ + # Use the current Ubuntu codename or fallback to jammy for newer systems + local ubuntu_codename + if command -v lsb_release >/dev/null 2>&1; then + ubuntu_codename=$(lsb_release -cs) + else + ubuntu_codename="jammy" # Fallback for newer systems + fi + + # For Linux Mint, map to appropriate Ubuntu codename + case "$ubuntu_codename" in + "una"|"vanessa"|"vera"|"victoria"|"wilma") + ubuntu_codename="jammy" # Map Mint versions to Ubuntu 22.04 + log_info "Mapped Linux Mint codename to Ubuntu $ubuntu_codename for Signal repository" + ;; + "ulyssa"|"uma"|"ulyana"|"tina"|"tricia") + ubuntu_codename="focal" # Map older Mint versions to Ubuntu 20.04 + log_info "Mapped Linux Mint codename to Ubuntu $ubuntu_codename for Signal repository" + ;; + esac + + echo "deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.gpg] https://updates.signal.org/desktop/apt $ubuntu_codename main" | \ sudo tee "$signal_list_file" > /dev/null # Update apt cache after adding repository @@ -268,6 +294,25 @@ install_signal() { # Install Signal install_apt_packages "signal-desktop" + + # Verify Signal installation + verify_signal_installation() { + if is_installed "signal-desktop"; then + log_success "Signal Desktop installed successfully" + else + log_error "Signal Desktop installation verification failed" + # Try alternative installation method + log_info "Attempting alternative Signal installation..." + if sudo apt-get install -y --fix-missing signal-desktop; then + log_success "Signal Desktop installed via alternative method" + else + log_error "Failed to install Signal Desktop via alternative method" + return 1 + fi + fi + } + + verify_signal_installation else log_info "Signal Messenger is already installed" fi @@ -286,23 +331,67 @@ install_offensive_security_tools() { # Install APT security tools in batch install_apt_packages "${apt_security_tools[@]}" - # Install OWASP ZAP via Snap (not available in apt) + # Verify nmap installation specifically + verify_nmap_installation() { + if is_installed "nmap"; then + local nmap_version + nmap_version=$(nmap --version 2>/dev/null | head -n1 || echo "unknown") + log_success "nmap installed successfully: $nmap_version" + else + log_error "nmap installation verification failed" + # Try alternative installation method + log_info "Attempting alternative nmap installation..." + if sudo apt-get install -y --fix-missing nmap; then + log_success "nmap installed via alternative method" + else + log_error "Failed to install nmap via alternative method" + return 1 + fi + fi + } + + verify_nmap_installation + + # Install OWASP ZAP with multiple fallback methods install_zaproxy_snap() { if ! is_installed "zaproxy"; then - log_info "Installing OWASP ZAP via Snap..." + log_info "Installing OWASP ZAP..." + + # Try snap first (Ubuntu) + if is_snap_available; then + if sudo snap install zaproxy --classic; then + log_success "OWASP ZAP installed via snap" + return 0 + else + log_warning "Snap installation failed, trying alternative methods..." + fi + else + log_info "Snap not available, trying alternative installation methods..." + fi - # Ensure snapd is installed - if ! is_installed "snap"; then - log_info "Installing snapd..." - install_apt_packages "snapd" + # Try Flatpak (works on both Ubuntu and Mint) + if is_flatpak_available; then + if flatpak install -y flathub org.zaproxy.ZAP; then + log_success "OWASP ZAP installed via Flatpak" + return 0 + else + log_warning "Flatpak installation failed, trying manual download..." + fi fi - # Install OWASP ZAP - if sudo snap install zaproxy --classic; then - log_success "OWASP ZAP installed successfully" + # Manual download as last resort + log_info "Attempting manual OWASP ZAP installation..." + local zap_jar="$TEMP_DIR/ZAP_2_14_0.jar" + if download_file_safe "https://github.com/zaproxy/zaproxy/releases/download/v2.14.0/ZAP_2_14_0_unix.sh" "$TEMP_DIR/zap_install.sh"; then + chmod +x "$TEMP_DIR/zap_install.sh" + if sudo "$TEMP_DIR/zap_install.sh" -q; then + log_success "OWASP ZAP installed via manual download" + else + log_error "Manual OWASP ZAP installation failed" + fi else - log_error "Failed to install OWASP ZAP via Snap" - return 1 + log_warning "Failed to download OWASP ZAP, skipping installation" + log_info "You can install OWASP ZAP manually from https://www.zaproxy.org/download/" fi else log_info "OWASP ZAP is already installed" @@ -359,18 +448,19 @@ main() { # Update package cache update_apt_cache - # Install components - install_authentication_tools - install_defense_tools - install_protonvpn - install_proton_suite - install_signal - install_offensive_security_tools - install_additional_security_tools + # Install components with error handling + execute_with_fallback install_authentication_tools + execute_with_fallback install_defense_tools + execute_with_fallback install_protonvpn + execute_with_fallback install_proton_suite + execute_with_fallback install_signal + execute_with_fallback install_offensive_security_tools + execute_with_fallback install_additional_security_tools log_success "Security tools installation completed!" log_info "Remember to configure your VPN and security tools after installation" log_info "UFW firewall has been enabled with default deny incoming policy" + log_info "Check $ERROR_LOG_FILE for any failed installations" } # Execute main function diff --git a/src/scripts/shell.sh b/src/scripts/shell.sh index 4e9a5cc..101cee2 100644 --- a/src/scripts/shell.sh +++ b/src/scripts/shell.sh @@ -110,16 +110,57 @@ install_shell_plugins() { if ! is_installed "oh-my-posh"; then log_info "Installing Oh My Posh prompt theme engine..." - # Download and install Oh My Posh - local omp_install_script="$TEMP_DIR/oh-my-posh-install.sh" - download_file_safe "https://ohmyposh.dev/install.sh" "$omp_install_script" - bash "$omp_install_script" -s -- --user - - log_success "Oh My Posh installed successfully" + # Get the latest version from GitHub API + local latest_version + latest_version=$(curl -s https://api.github.com/repos/JanDeDobbeleer/oh-my-posh/releases/latest | grep -o '"tag_name": "[^"]*' | grep -o '[^"]*$' || echo "v19.6.0") + log_info "Installing Oh My Posh version: $latest_version" + + # Determine architecture + local arch + case "$(uname -m)" in + x86_64) arch="amd64" ;; + aarch64) arch="arm64" ;; + armv7l) arch="arm" ;; + *) arch="amd64" ;; # fallback + esac + + # Download Oh My Posh binary directly + local omp_binary="$TEMP_DIR/oh-my-posh" + local download_url="https://github.com/JanDeDobbeleer/oh-my-posh/releases/download/${latest_version}/posh-linux-${arch}" + + if download_file_safe "$download_url" "$omp_binary"; then + # Make it executable + chmod +x "$omp_binary" + + # Install to /usr/local/bin (which is in PATH) + if sudo mv "$omp_binary" /usr/local/bin/oh-my-posh; then + log_success "Oh My Posh installed successfully to /usr/local/bin/oh-my-posh" + else + log_error "Failed to move Oh My Posh binary to /usr/local/bin/" + return 1 + fi + else + log_error "Failed to download Oh My Posh binary" + return 1 + fi else log_info "Oh My Posh is already installed" fi + # Verify Oh My Posh installation + verify_oh_my_posh_installation() { + if is_installed "oh-my-posh"; then + local omp_version + omp_version=$(oh-my-posh version 2>/dev/null | head -n1 || echo "unknown") + log_success "Oh My Posh installed successfully: $omp_version" + else + log_error "Oh My Posh installation verification failed" + return 1 + fi + } + + verify_oh_my_posh_installation + # Install Oh My Posh themes install_oh_my_posh_themes() { local themes_dir="/usr/share/oh-my-posh/themes" @@ -352,16 +393,17 @@ main() { # Update package cache update_apt_cache - # Install and configure components - install_shells_and_terminals - install_fonts - install_shell_plugins - configure_terminal_applications - change_default_shell + # Install and configure components with error handling + execute_with_fallback install_shells_and_terminals + execute_with_fallback install_fonts + execute_with_fallback install_shell_plugins + execute_with_fallback configure_terminal_applications + execute_with_fallback change_default_shell log_success "Shell and terminal setup completed!" log_info "Please log out and log back in for shell changes to take effect" log_info "You may need to restart your terminal to see font changes" + log_info "Check $ERROR_LOG_FILE for any failed installations" } # Execute main function diff --git a/src/scripts/utils.sh b/src/scripts/utils.sh index a6ff4cb..2c5144b 100644 --- a/src/scripts/utils.sh +++ b/src/scripts/utils.sh @@ -1,7 +1,7 @@ #!/bin/bash -# Bash strict mode for better error handling -set -euo pipefail +# Bash strict mode for better error handling (but allow partial failures) +set -uo pipefail # Global configuration readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -58,7 +58,79 @@ is_directory_populated() { [[ -d "$directory" && -n "$(ls -A "$directory" 2>/dev/null)" ]] } -# Install packages in batch to reduce apt calls +# Detect distribution and provide compatibility info +detect_distribution() { + local distro_id + local distro_codename + local distro_version + + distro_id=$(lsb_release -si 2>/dev/null || echo "Unknown") + distro_codename=$(lsb_release -cs 2>/dev/null || echo "unknown") + distro_version=$(lsb_release -rs 2>/dev/null || echo "unknown") + + log_info "Detected distribution: $distro_id $distro_version ($distro_codename)" + + # Export distribution info for use in other scripts + export DISTRO_ID="$distro_id" + export DISTRO_CODENAME="$distro_codename" + export DISTRO_VERSION="$distro_version" + + # Check for specific compatibility issues + case "$distro_id" in + "LinuxMint") + log_info "Linux Mint detected - some Ubuntu-specific features may not be available" + log_info "Snap support is limited, Flatpak will be preferred for applications" + ;; + "Ubuntu") + log_info "Ubuntu detected - full feature set available" + ;; + *) + log_info "Unknown distribution - using compatibility mode" + ;; + esac +} + +# Check if snap is available and working +is_snap_available() { + if command -v snap >/dev/null 2>&1; then + # Test if snap is actually working + if snap version >/dev/null 2>&1; then + return 0 + fi + fi + return 1 +} + +# Check if flatpak is available and working +is_flatpak_available() { + if command -v flatpak >/dev/null 2>&1; then + # Test if flatpak is actually working + if flatpak --version >/dev/null 2>&1; then + return 0 + fi + fi + return 1 +} + +# Execute function with error handling (continues on failure) +execute_with_fallback() { + local function_name="$1" + shift + local args=("$@") + + log_info "Executing: $function_name" + + if "$function_name" "${args[@]}"; then + log_success "Successfully completed: $function_name" + return 0 + else + log_error "Failed to execute: $function_name" + log_error "Continuing with remaining tasks..." + return 1 + fi +} + +# Install packages in batch to reduce apt calls (with fallback) install_apt_packages() { local packages=("$@") local packages_to_install=() @@ -77,11 +149,20 @@ install_apt_packages() { # Install packages in batch if any are needed if [[ ${#packages_to_install[@]} -gt 0 ]]; then log_info "Installing packages: ${packages_to_install[*]}" - sudo apt-get install -y "${packages_to_install[@]}" || { + if sudo apt-get install -y "${packages_to_install[@]}"; then + log_success "Successfully installed packages: ${packages_to_install[*]}" + else log_error "Failed to install packages: ${packages_to_install[*]}" - return 1 - } - log_success "Successfully installed packages: ${packages_to_install[*]}" + # Try installing packages individually as fallback + log_info "Attempting individual package installation as fallback..." + for package in "${packages_to_install[@]}"; do + if sudo apt-get install -y "$package"; then + log_success "Successfully installed: $package" + else + log_error "Failed to install: $package" + fi + done + fi else log_info "All packages are already installed" fi @@ -224,6 +305,7 @@ ensure_directory "$TEMP_DIR" export -f log_info log_success log_warning log_error export -f is_installed is_package_installed is_flatpak_installed is_directory_populated export -f install_apt_packages update_apt_cache ensure_directory remove_empty_directory -export -f copy_file_safe download_file_safe clone_repository_safe +export -f copy_file_safe download_file_safe clone_repository_safe execute_with_fallback +export -f detect_distribution is_snap_available is_flatpak_available export PROJECT_ROOT SCRIPT_DIR ERROR_LOG_FILE TEMP_DIR