Improve installation scripts with better platform detection, dependency management, and error handling (#29)
This commit is contained in:
+702
-79
@@ -78,27 +78,205 @@ if [ "$EUID" -eq 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check Ubuntu version
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
if [[ "$NAME" != *"Ubuntu"* ]]; then
|
||||
print_warning "This installer is designed for Ubuntu. Your system: $NAME"
|
||||
echo "The application may still work, but you might need to install dependencies manually."
|
||||
# Detect Linux distribution and version
|
||||
detect_distro() {
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
DISTRO_NAME="$NAME"
|
||||
DISTRO_ID="$ID"
|
||||
DISTRO_VERSION="$VERSION_ID"
|
||||
DISTRO_FAMILY="unknown"
|
||||
|
||||
# Determine distribution family
|
||||
if [[ "$ID" == "ubuntu" || "$ID_LIKE" == *"ubuntu"* || "$ID" == "pop" || "$ID" == "linuxmint" || "$ID" == "elementary" || "$ID" == "zorin" ]]; then
|
||||
DISTRO_FAMILY="ubuntu"
|
||||
elif [[ "$ID" == "debian" || "$ID_LIKE" == *"debian"* ]]; then
|
||||
DISTRO_FAMILY="debian"
|
||||
elif [[ "$ID" == "fedora" || "$ID_LIKE" == *"fedora"* || "$ID" == "rhel" || "$ID" == "centos" || "$ID" == "rocky" || "$ID" == "almalinux" ]]; then
|
||||
DISTRO_FAMILY="fedora"
|
||||
elif [[ "$ID" == "arch" || "$ID_LIKE" == *"arch"* || "$ID" == "manjaro" || "$ID" == "endeavouros" ]]; then
|
||||
DISTRO_FAMILY="arch"
|
||||
elif [[ "$ID" == "opensuse" || "$ID_LIKE" == *"suse"* ]]; then
|
||||
DISTRO_FAMILY="suse"
|
||||
fi
|
||||
|
||||
print_info "Detected: $DISTRO_NAME $DISTRO_VERSION ($DISTRO_FAMILY family)"
|
||||
return 0
|
||||
else
|
||||
print_error "Could not detect Linux distribution (missing /etc/os-release)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check minimum required version for Ubuntu-based systems
|
||||
check_ubuntu_version() {
|
||||
local MIN_VERSION="18.04"
|
||||
if [[ "$DISTRO_FAMILY" == "ubuntu" ]]; then
|
||||
if [[ $(echo -e "$DISTRO_VERSION\n$MIN_VERSION" | sort -V | head -n1) == "$MIN_VERSION" || "$DISTRO_VERSION" == "$MIN_VERSION" ]]; then
|
||||
return 0
|
||||
else
|
||||
print_error "This application requires Ubuntu $MIN_VERSION or newer. Detected: $DISTRO_VERSION"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Detect distribution
|
||||
detect_distro
|
||||
|
||||
# Check compatibility
|
||||
if [[ "$DISTRO_FAMILY" != "ubuntu" ]]; then
|
||||
print_warning "This installer is primarily designed for Ubuntu-based systems. Your system: $DISTRO_NAME"
|
||||
print_warning "The application may still work, but you might need to install dependencies manually."
|
||||
read -p "Do you want to continue anyway? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Check version for Ubuntu-based systems
|
||||
if ! check_ubuntu_version; then
|
||||
read -p "Do you want to continue anyway? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_info "Detected Ubuntu $VERSION_ID"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Function to check if a command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to check if a package is installed (for apt-based systems)
|
||||
apt_package_installed() {
|
||||
dpkg -s "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to check if a package is installed (for dnf-based systems)
|
||||
dnf_package_installed() {
|
||||
rpm -q "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to check if a package is installed (for pacman-based systems)
|
||||
pacman_package_installed() {
|
||||
pacman -Q "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to install system dependencies based on the detected distribution
|
||||
install_system_dependencies() {
|
||||
print_info "Installing system dependencies..."
|
||||
|
||||
# Define package names for different distributions
|
||||
local APT_PACKAGES="python3-pip python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-appindicator3-0.1 libgirepository1.0-dev python3-dev portaudio19-dev python3-venv"
|
||||
local DNF_PACKAGES="python3-pip python3-gobject gtk3 libappindicator-gtk3 gobject-introspection-devel python3-devel portaudio-devel python3-virtualenv"
|
||||
local PACMAN_PACKAGES="python-pip python-gobject gtk3 libappindicator-gtk3 gobject-introspection python-cairo portaudio python-virtualenv"
|
||||
local ZYPPER_PACKAGES="python3-pip python3-gobject python3-gobject-cairo gtk3 libappindicator-gtk3 gobject-introspection-devel python3-devel portaudio-devel python3-virtualenv"
|
||||
|
||||
local MISSING_PACKAGES=""
|
||||
local INSTALL_CMD=""
|
||||
local UPDATE_CMD=""
|
||||
|
||||
case "$DISTRO_FAMILY" in
|
||||
ubuntu|debian)
|
||||
# Check for missing packages
|
||||
for pkg in $APT_PACKAGES; do
|
||||
if ! apt_package_installed "$pkg"; then
|
||||
MISSING_PACKAGES="$MISSING_PACKAGES $pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$MISSING_PACKAGES" ]; then
|
||||
print_info "Installing missing packages:$MISSING_PACKAGES"
|
||||
sudo apt update || { print_error "Failed to update package lists"; exit 1; }
|
||||
sudo apt install -y $MISSING_PACKAGES || { print_error "Failed to install dependencies"; exit 1; }
|
||||
else
|
||||
print_info "All required packages are already installed."
|
||||
fi
|
||||
;;
|
||||
|
||||
fedora)
|
||||
# For Fedora/RHEL-based systems
|
||||
if command_exists dnf; then
|
||||
INSTALL_CMD="sudo dnf install -y"
|
||||
UPDATE_CMD="sudo dnf check-update"
|
||||
elif command_exists yum; then
|
||||
INSTALL_CMD="sudo yum install -y"
|
||||
UPDATE_CMD="sudo yum check-update"
|
||||
else
|
||||
print_error "No supported package manager found (dnf/yum)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for missing packages
|
||||
for pkg in $DNF_PACKAGES; do
|
||||
if ! dnf_package_installed "$pkg"; then
|
||||
MISSING_PACKAGES="$MISSING_PACKAGES $pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$MISSING_PACKAGES" ]; then
|
||||
print_info "Installing missing packages:$MISSING_PACKAGES"
|
||||
$UPDATE_CMD
|
||||
$INSTALL_CMD $MISSING_PACKAGES || { print_error "Failed to install dependencies"; exit 1; }
|
||||
else
|
||||
print_info "All required packages are already installed."
|
||||
fi
|
||||
;;
|
||||
|
||||
arch)
|
||||
# For Arch-based systems
|
||||
if ! command_exists pacman; then
|
||||
print_error "Pacman package manager not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for missing packages
|
||||
for pkg in $PACMAN_PACKAGES; do
|
||||
if ! pacman_package_installed "$pkg"; then
|
||||
MISSING_PACKAGES="$MISSING_PACKAGES $pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$MISSING_PACKAGES" ]; then
|
||||
print_info "Installing missing packages:$MISSING_PACKAGES"
|
||||
sudo pacman -Sy
|
||||
sudo pacman -S --noconfirm $MISSING_PACKAGES || { print_error "Failed to install dependencies"; exit 1; }
|
||||
else
|
||||
print_info "All required packages are already installed."
|
||||
fi
|
||||
;;
|
||||
|
||||
suse)
|
||||
# For openSUSE
|
||||
if ! command_exists zypper; then
|
||||
print_error "Zypper package manager not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_info "Updating package lists and installing dependencies..."
|
||||
sudo zypper refresh
|
||||
sudo zypper install -y $ZYPPER_PACKAGES || { print_error "Failed to install dependencies"; exit 1; }
|
||||
;;
|
||||
|
||||
*)
|
||||
print_error "Unsupported distribution family: $DISTRO_FAMILY"
|
||||
print_warning "Please install the following dependencies manually:"
|
||||
print_warning "- Python 3.8 or newer with pip"
|
||||
print_warning "- PyGObject (GTK3 bindings for Python)"
|
||||
print_warning "- GTK3 development libraries"
|
||||
print_warning "- AppIndicator3 support"
|
||||
print_warning "- PortAudio development libraries"
|
||||
print_warning "- Python virtual environment support"
|
||||
read -p "Press Enter to continue once dependencies are installed, or Ctrl+C to cancel..."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Install system dependencies
|
||||
print_info "Installing system dependencies..."
|
||||
sudo apt update
|
||||
sudo apt install -y python3-pip python3-gi python3-gi-cairo gir1.2-gtk-3.0 \
|
||||
gir1.2-appindicator3-0.1 libgirepository1.0-dev python3-dev portaudio19-dev python3-venv
|
||||
install_system_dependencies
|
||||
|
||||
# Define XDG directories
|
||||
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/vocalinux"
|
||||
@@ -106,14 +284,134 @@ DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux"
|
||||
DESKTOP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
|
||||
ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps"
|
||||
|
||||
# Detect desktop environment for text input tools
|
||||
if [ "$XDG_SESSION_TYPE" = "wayland" ]; then
|
||||
print_info "Detected Wayland session, installing wtype..."
|
||||
sudo apt install -y wtype
|
||||
else
|
||||
print_info "Detected X11 session, installing xdotool..."
|
||||
sudo apt install -y xdotool
|
||||
fi
|
||||
# Function to detect and install text input tools
|
||||
install_text_input_tools() {
|
||||
# Detect session type more robustly
|
||||
local SESSION_TYPE="unknown"
|
||||
|
||||
# Check XDG_SESSION_TYPE first
|
||||
if [ -n "$XDG_SESSION_TYPE" ]; then
|
||||
SESSION_TYPE="$XDG_SESSION_TYPE"
|
||||
# Check for Wayland-specific environment variables
|
||||
elif [ -n "$WAYLAND_DISPLAY" ]; then
|
||||
SESSION_TYPE="wayland"
|
||||
# Check if X server is running
|
||||
elif [ -n "$DISPLAY" ] && command_exists xset && xset q &>/dev/null; then
|
||||
SESSION_TYPE="x11"
|
||||
# Check loginctl if available
|
||||
elif command_exists loginctl; then
|
||||
SESSION_TYPE=$(loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Type | cut -d= -f2)
|
||||
fi
|
||||
|
||||
print_info "Detected session type: $SESSION_TYPE"
|
||||
|
||||
# Install appropriate tools based on session type and distribution
|
||||
case "$SESSION_TYPE" in
|
||||
wayland)
|
||||
print_info "Installing Wayland text input tools..."
|
||||
case "$DISTRO_FAMILY" in
|
||||
ubuntu|debian)
|
||||
if ! apt_package_installed "wtype"; then
|
||||
sudo apt install -y wtype || { print_warning "Failed to install wtype. Text injection may not work properly."; }
|
||||
else
|
||||
print_info "wtype is already installed."
|
||||
fi
|
||||
;;
|
||||
fedora)
|
||||
if command_exists dnf && ! dnf_package_installed "wtype"; then
|
||||
sudo dnf install -y wtype || { print_warning "Failed to install wtype. Text injection may not work properly."; }
|
||||
elif command_exists yum && ! rpm -q wtype &>/dev/null; then
|
||||
sudo yum install -y wtype || { print_warning "Failed to install wtype. Text injection may not work properly."; }
|
||||
else
|
||||
print_info "wtype is already installed."
|
||||
fi
|
||||
;;
|
||||
arch)
|
||||
if ! pacman_package_installed "wtype"; then
|
||||
sudo pacman -S --noconfirm wtype || { print_warning "Failed to install wtype. Text injection may not work properly."; }
|
||||
else
|
||||
print_info "wtype is already installed."
|
||||
fi
|
||||
;;
|
||||
suse)
|
||||
sudo zypper install -y wtype || { print_warning "Failed to install wtype. Text injection may not work properly."; }
|
||||
;;
|
||||
*)
|
||||
print_warning "Unsupported distribution for Wayland text input tools."
|
||||
print_warning "Please install 'wtype' manually for Wayland text input support."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
x11|"")
|
||||
print_info "Installing X11 text input tools..."
|
||||
case "$DISTRO_FAMILY" in
|
||||
ubuntu|debian)
|
||||
if ! apt_package_installed "xdotool"; then
|
||||
sudo apt install -y xdotool || { print_warning "Failed to install xdotool. Text injection may not work properly."; }
|
||||
else
|
||||
print_info "xdotool is already installed."
|
||||
fi
|
||||
;;
|
||||
fedora)
|
||||
if command_exists dnf && ! dnf_package_installed "xdotool"; then
|
||||
sudo dnf install -y xdotool || { print_warning "Failed to install xdotool. Text injection may not work properly."; }
|
||||
elif command_exists yum && ! rpm -q xdotool &>/dev/null; then
|
||||
sudo yum install -y xdotool || { print_warning "Failed to install xdotool. Text injection may not work properly."; }
|
||||
else
|
||||
print_info "xdotool is already installed."
|
||||
fi
|
||||
;;
|
||||
arch)
|
||||
if ! pacman_package_installed "xdotool"; then
|
||||
sudo pacman -S --noconfirm xdotool || { print_warning "Failed to install xdotool. Text injection may not work properly."; }
|
||||
else
|
||||
print_info "xdotool is already installed."
|
||||
fi
|
||||
;;
|
||||
suse)
|
||||
sudo zypper install -y xdotool || { print_warning "Failed to install xdotool. Text injection may not work properly."; }
|
||||
;;
|
||||
*)
|
||||
print_warning "Unsupported distribution for X11 text input tools."
|
||||
print_warning "Please install 'xdotool' manually for X11 text input support."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
print_warning "Unknown session type: $SESSION_TYPE"
|
||||
print_warning "Installing both Wayland and X11 text input tools for compatibility..."
|
||||
|
||||
# Install both tools based on distribution
|
||||
case "$DISTRO_FAMILY" in
|
||||
ubuntu|debian)
|
||||
sudo apt install -y xdotool wtype || { print_warning "Failed to install text input tools. Text injection may not work properly."; }
|
||||
;;
|
||||
fedora)
|
||||
if command_exists dnf; then
|
||||
sudo dnf install -y xdotool wtype || { print_warning "Failed to install text input tools. Text injection may not work properly."; }
|
||||
elif command_exists yum; then
|
||||
sudo yum install -y xdotool wtype || { print_warning "Failed to install text input tools. Text injection may not work properly."; }
|
||||
fi
|
||||
;;
|
||||
arch)
|
||||
sudo pacman -S --noconfirm xdotool wtype || { print_warning "Failed to install text input tools. Text injection may not work properly."; }
|
||||
;;
|
||||
suse)
|
||||
sudo zypper install -y xdotool wtype || { print_warning "Failed to install text input tools. Text injection may not work properly."; }
|
||||
;;
|
||||
*)
|
||||
print_warning "Unsupported distribution for text input tools."
|
||||
print_warning "Please install 'xdotool' and 'wtype' manually for text input support."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Install text input tools based on session type
|
||||
install_text_input_tools
|
||||
|
||||
# Create necessary directories
|
||||
print_info "Creating application directories..."
|
||||
@@ -122,17 +420,76 @@ mkdir -p "$DATA_DIR/models"
|
||||
mkdir -p "$DESKTOP_DIR"
|
||||
mkdir -p "$ICON_DIR"
|
||||
|
||||
# Set up virtual environment
|
||||
print_info "Setting up Python virtual environment..."
|
||||
python3 -m venv "$VENV_DIR" --system-site-packages
|
||||
# Check Python version
|
||||
check_python_version() {
|
||||
local MIN_VERSION="3.8"
|
||||
local PYTHON_CMD="python3"
|
||||
|
||||
# Check if python3 command exists
|
||||
if ! command_exists python3; then
|
||||
print_error "Python 3 is not installed or not in PATH"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get Python version
|
||||
local PY_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
|
||||
print_info "Detected Python version: $PY_VERSION"
|
||||
|
||||
# Compare versions
|
||||
if [[ $(echo -e "$PY_VERSION\n$MIN_VERSION" | sort -V | head -n1) == "$MIN_VERSION" || "$PY_VERSION" == "$MIN_VERSION" ]]; then
|
||||
return 0
|
||||
else
|
||||
print_error "This application requires Python $MIN_VERSION or newer. Detected: $PY_VERSION"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Activate virtual environment
|
||||
source "$VENV_DIR/bin/activate"
|
||||
# Set up virtual environment with error handling
|
||||
setup_virtual_environment() {
|
||||
print_info "Setting up Python virtual environment in $VENV_DIR..."
|
||||
|
||||
# Check if virtual environment already exists
|
||||
if [ -d "$VENV_DIR" ] && [ -f "$VENV_DIR/bin/activate" ]; then
|
||||
print_warning "Virtual environment already exists in $VENV_DIR"
|
||||
read -p "Do you want to recreate it? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_info "Removing existing virtual environment..."
|
||||
rm -rf "$VENV_DIR"
|
||||
else
|
||||
print_info "Using existing virtual environment."
|
||||
source "$VENV_DIR/bin/activate" || { print_error "Failed to activate virtual environment"; exit 1; }
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create virtual environment
|
||||
python3 -m venv "$VENV_DIR" --system-site-packages || {
|
||||
print_error "Failed to create virtual environment"
|
||||
print_info "Trying without --system-site-packages..."
|
||||
python3 -m venv "$VENV_DIR" || {
|
||||
print_error "Failed to create virtual environment. Please check your Python installation."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Activate virtual environment
|
||||
source "$VENV_DIR/bin/activate" || { print_error "Failed to activate virtual environment"; exit 1; }
|
||||
|
||||
# Update pip and setuptools
|
||||
print_info "Updating pip, setuptools, and wheel..."
|
||||
pip install --upgrade pip setuptools wheel || { print_error "Failed to update pip, setuptools, and wheel"; exit 1; }
|
||||
|
||||
print_info "Virtual environment activated successfully."
|
||||
}
|
||||
|
||||
# Update pip and setuptools
|
||||
pip install --upgrade pip setuptools wheel
|
||||
# Check Python version
|
||||
if ! check_python_version; then
|
||||
print_warning "Continuing with unsupported Python version. Some features may not work correctly."
|
||||
fi
|
||||
|
||||
print_info "Virtual environment activated."
|
||||
# Set up virtual environment
|
||||
setup_virtual_environment
|
||||
|
||||
# Create activation script for users
|
||||
cat > activate-vocalinux.sh << EOF
|
||||
@@ -145,70 +502,336 @@ EOF
|
||||
chmod +x activate-vocalinux.sh
|
||||
print_info "Created activation script: activate-vocalinux.sh"
|
||||
|
||||
# Install Python package
|
||||
if [[ "$DEV_MODE" == "yes" ]]; then
|
||||
print_info "Installing Vocalinux in development mode..."
|
||||
pip install -e .
|
||||
pip install pytest pytest-mock pytest-cov
|
||||
# Install all optional dependencies for development
|
||||
print_info "Installing all optional dependencies for development..."
|
||||
pip install ".[whisper,dev]"
|
||||
else
|
||||
print_info "Installing Vocalinux..."
|
||||
pip install .
|
||||
# Function to install Python package with error handling and verification
|
||||
install_python_package() {
|
||||
# Create a temporary directory for pip logs
|
||||
local PIP_LOG_DIR=$(mktemp -d)
|
||||
local PIP_LOG_FILE="$PIP_LOG_DIR/pip_log.txt"
|
||||
|
||||
# Prompt for Whisper installation
|
||||
read -p "Do you want to install Whisper AI support? This requires additional disk space. (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_info "Installing Whisper support (this might take a while)..."
|
||||
pip install ".[whisper]"
|
||||
# Function to verify package installation
|
||||
verify_package_installed() {
|
||||
local PKG_NAME="vocalinux"
|
||||
python -c "import $PKG_NAME" 2>/dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
if [[ "$DEV_MODE" == "yes" ]]; then
|
||||
print_info "Installing Vocalinux in development mode..."
|
||||
|
||||
# Install in development mode with logging
|
||||
pip install -e . --log "$PIP_LOG_FILE" || {
|
||||
print_error "Failed to install Vocalinux in development mode."
|
||||
print_error "Check the pip log for details: $PIP_LOG_FILE"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Install test dependencies
|
||||
print_info "Installing test dependencies..."
|
||||
pip install pytest pytest-mock pytest-cov --log "$PIP_LOG_FILE" || {
|
||||
print_warning "Failed to install some test dependencies. Tests may not run correctly."
|
||||
}
|
||||
|
||||
# Install all optional dependencies for development
|
||||
print_info "Installing all optional dependencies for development..."
|
||||
pip install ".[whisper,dev]" --log "$PIP_LOG_FILE" || {
|
||||
print_warning "Failed to install some optional dependencies."
|
||||
print_warning "Some features may not work correctly."
|
||||
}
|
||||
else
|
||||
print_info "Installing Vocalinux..."
|
||||
|
||||
# Install the package with logging
|
||||
pip install . --log "$PIP_LOG_FILE" || {
|
||||
print_error "Failed to install Vocalinux."
|
||||
print_error "Check the pip log for details: $PIP_LOG_FILE"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Prompt for Whisper installation
|
||||
read -p "Do you want to install Whisper AI support? This requires additional disk space. (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_info "Installing Whisper support (this might take a while)..."
|
||||
pip install ".[whisper]" --log "$PIP_LOG_FILE" || {
|
||||
print_warning "Failed to install Whisper support."
|
||||
print_warning "Voice recognition will fall back to VOSK."
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify installation
|
||||
if verify_package_installed; then
|
||||
print_success "Vocalinux package installed successfully!"
|
||||
# Clean up log file if installation was successful
|
||||
rm -rf "$PIP_LOG_DIR"
|
||||
return 0
|
||||
else
|
||||
print_error "Vocalinux package installation verification failed."
|
||||
print_error "Check the pip log for details: $PIP_LOG_FILE"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Install Python package
|
||||
if ! install_python_package; then
|
||||
print_error "Failed to install Vocalinux package. Installation cannot continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to install desktop entry with error handling
|
||||
install_desktop_entry() {
|
||||
print_info "Installing desktop entry..."
|
||||
|
||||
# Check if desktop entry file exists
|
||||
if [ ! -f "vocalinux.desktop" ]; then
|
||||
print_error "Desktop entry file not found: vocalinux.desktop"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create desktop directory if it doesn't exist
|
||||
mkdir -p "$DESKTOP_DIR" || {
|
||||
print_error "Failed to create desktop directory: $DESKTOP_DIR"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Copy desktop entry
|
||||
cp vocalinux.desktop "$DESKTOP_DIR/" || {
|
||||
print_error "Failed to copy desktop entry to $DESKTOP_DIR"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Update the desktop entry to use the venv
|
||||
VENV_SCRIPT_PATH="$(realpath $VENV_DIR/bin/vocalinux)"
|
||||
if [ ! -f "$VENV_SCRIPT_PATH" ]; then
|
||||
print_warning "Vocalinux script not found at $VENV_SCRIPT_PATH"
|
||||
print_warning "Desktop entry may not work correctly"
|
||||
else
|
||||
sed -i "s|^Exec=vocalinux|Exec=$VENV_SCRIPT_PATH|" "$DESKTOP_DIR/vocalinux.desktop" || {
|
||||
print_warning "Failed to update desktop entry path"
|
||||
}
|
||||
print_info "Updated desktop entry to use virtual environment"
|
||||
fi
|
||||
|
||||
# Make desktop entry executable
|
||||
chmod +x "$DESKTOP_DIR/vocalinux.desktop" || {
|
||||
print_warning "Failed to make desktop entry executable"
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to install icons with error handling
|
||||
install_icons() {
|
||||
print_info "Installing application icons..."
|
||||
|
||||
# Create icon directory if it doesn't exist
|
||||
mkdir -p "$ICON_DIR" || {
|
||||
print_error "Failed to create icon directory: $ICON_DIR"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if icons directory exists
|
||||
if [ ! -d "resources/icons/scalable" ]; then
|
||||
print_warning "Custom icons not found in resources/icons/scalable directory"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# List of icons to install
|
||||
local ICONS=(
|
||||
"vocalinux.svg"
|
||||
"vocalinux-microphone.svg"
|
||||
"vocalinux-microphone-off.svg"
|
||||
"vocalinux-microphone-process.svg"
|
||||
)
|
||||
|
||||
# Install each icon
|
||||
local INSTALLED_COUNT=0
|
||||
for icon in "${ICONS[@]}"; do
|
||||
if [ -f "resources/icons/scalable/$icon" ]; then
|
||||
cp "resources/icons/scalable/$icon" "$ICON_DIR/" || {
|
||||
print_warning "Failed to copy icon: $icon"
|
||||
continue
|
||||
}
|
||||
((INSTALLED_COUNT++))
|
||||
else
|
||||
print_warning "Icon not found: resources/icons/scalable/$icon"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$INSTALLED_COUNT" -eq "${#ICONS[@]}" ]; then
|
||||
print_success "Installed all custom Vocalinux icons"
|
||||
return 0
|
||||
elif [ "$INSTALLED_COUNT" -gt 0 ]; then
|
||||
print_warning "Installed $INSTALLED_COUNT/${#ICONS[@]} custom Vocalinux icons"
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to install any icons"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to update icon cache
|
||||
update_icon_cache() {
|
||||
print_info "Updating icon cache..."
|
||||
|
||||
# Check if gtk-update-icon-cache command exists
|
||||
if command_exists gtk-update-icon-cache; then
|
||||
gtk-update-icon-cache -f -t "${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor" 2>/dev/null || {
|
||||
print_warning "Failed to update icon cache"
|
||||
}
|
||||
else
|
||||
print_warning "gtk-update-icon-cache command not found, skipping icon cache update"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install desktop entry
|
||||
print_info "Installing desktop entry..."
|
||||
cp vocalinux.desktop "$DESKTOP_DIR/"
|
||||
|
||||
# Update the desktop entry to use the venv
|
||||
VENV_SCRIPT_PATH="$(realpath $VENV_DIR/bin/vocalinux)"
|
||||
sed -i "s|^Exec=vocalinux|Exec=$VENV_SCRIPT_PATH|" "$DESKTOP_DIR/vocalinux.desktop"
|
||||
print_info "Updated desktop entry to use virtual environment"
|
||||
install_desktop_entry || print_warning "Desktop entry installation failed"
|
||||
|
||||
# Install icons
|
||||
print_info "Installing application icons..."
|
||||
if [ -d "resources/icons/scalable" ]; then
|
||||
cp resources/icons/scalable/vocalinux.svg "$ICON_DIR/"
|
||||
cp resources/icons/scalable/vocalinux-microphone.svg "$ICON_DIR/"
|
||||
cp resources/icons/scalable/vocalinux-microphone-off.svg "$ICON_DIR/"
|
||||
cp resources/icons/scalable/vocalinux-microphone-process.svg "$ICON_DIR/"
|
||||
print_info "Installed custom Vocalinux icons"
|
||||
else
|
||||
print_warning "Custom icons not found in resources/icons/scalable directory"
|
||||
fi
|
||||
install_icons || print_warning "Icon installation failed"
|
||||
|
||||
# Update icon cache to make the icons available immediately
|
||||
gtk-update-icon-cache -f -t "${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor" 2>/dev/null || true
|
||||
# Update icon cache
|
||||
update_icon_cache
|
||||
|
||||
# Function to run tests with better error handling
|
||||
run_tests() {
|
||||
print_info "Running tests..."
|
||||
|
||||
# Check if pytest is installed
|
||||
if ! python -c "import pytest" &>/dev/null; then
|
||||
print_info "Installing pytest and related packages..."
|
||||
pip install pytest pytest-mock pytest-cov || {
|
||||
print_error "Failed to install pytest. Cannot run tests."
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
# Create a directory for test results
|
||||
local TEST_RESULTS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux/test_results"
|
||||
mkdir -p "$TEST_RESULTS_DIR"
|
||||
local TEST_RESULTS_FILE="$TEST_RESULTS_DIR/pytest_$(date +%Y%m%d_%H%M%S).xml"
|
||||
|
||||
print_info "Running tests with pytest..."
|
||||
print_info "This may take a few minutes..."
|
||||
|
||||
# Run the tests with pytest and capture output
|
||||
local TEST_OUTPUT_FILE=$(mktemp)
|
||||
if pytest -v --junitxml="$TEST_RESULTS_FILE" | tee "$TEST_OUTPUT_FILE"; then
|
||||
print_success "All tests passed!"
|
||||
print_info "Test results saved to: $TEST_RESULTS_FILE"
|
||||
rm -f "$TEST_OUTPUT_FILE"
|
||||
return 0
|
||||
else
|
||||
local FAILED_COUNT=$(grep -c "FAILED" "$TEST_OUTPUT_FILE")
|
||||
print_error "$FAILED_COUNT tests failed!"
|
||||
print_info "Test results saved to: $TEST_RESULTS_FILE"
|
||||
print_info "Check the test output for details."
|
||||
rm -f "$TEST_OUTPUT_FILE"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run tests if requested
|
||||
if [[ "$RUN_TESTS" == "yes" ]]; then
|
||||
print_info "Running tests..."
|
||||
# Install pytest if not already installed
|
||||
pip install pytest pytest-mock pytest-cov
|
||||
|
||||
# Run the tests with pytest
|
||||
pytest
|
||||
if [ $? -eq 0 ]; then
|
||||
print_success "All tests passed!"
|
||||
if run_tests; then
|
||||
print_success "Test suite completed successfully."
|
||||
else
|
||||
print_error "Some tests failed!"
|
||||
print_warning "Test suite completed with failures."
|
||||
print_warning "You can still use the application, but some features might not work as expected."
|
||||
fi
|
||||
fi
|
||||
|
||||
print_success "Installation complete!"
|
||||
print_info "To activate the virtual environment in the future, run:"
|
||||
print_info " source activate-vocalinux.sh"
|
||||
print_info "You can then launch Vocalinux by running 'vocalinux'"
|
||||
# Function to verify the installation
|
||||
verify_installation() {
|
||||
print_info "Verifying installation..."
|
||||
local ISSUES=0
|
||||
|
||||
# Check if virtual environment exists and is activated
|
||||
if [ ! -d "$VENV_DIR" ] || [ ! -f "$VENV_DIR/bin/activate" ]; then
|
||||
print_error "Virtual environment not found or incomplete."
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if vocalinux command is available
|
||||
if ! command -v vocalinux &>/dev/null && [ ! -f "$VENV_DIR/bin/vocalinux" ]; then
|
||||
print_error "Vocalinux command not found."
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if desktop entry is installed
|
||||
if [ ! -f "$DESKTOP_DIR/vocalinux.desktop" ]; then
|
||||
print_warning "Desktop entry not found. Application may not appear in application menu."
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if icons are installed
|
||||
local ICON_COUNT=0
|
||||
for icon in vocalinux.svg vocalinux-microphone.svg vocalinux-microphone-off.svg vocalinux-microphone-process.svg; do
|
||||
if [ -f "$ICON_DIR/$icon" ]; then
|
||||
((ICON_COUNT++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ICON_COUNT" -lt 4 ]; then
|
||||
print_warning "Some icons are missing. Application may not display correctly."
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if Python package is importable
|
||||
if ! python -c "import vocalinux" &>/dev/null; then
|
||||
print_error "Vocalinux Python package cannot be imported."
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Return the number of issues found
|
||||
return $ISSUES
|
||||
}
|
||||
|
||||
echo
|
||||
print_info "For more information, see the documentation in the docs/ directory."
|
||||
# Function to print installation summary
|
||||
print_installation_summary() {
|
||||
local ISSUES=$1
|
||||
|
||||
echo
|
||||
echo "=============================="
|
||||
echo " INSTALLATION SUMMARY"
|
||||
echo "=============================="
|
||||
echo
|
||||
|
||||
if [ "$ISSUES" -eq 0 ]; then
|
||||
print_success "Installation completed successfully with no issues!"
|
||||
else
|
||||
print_warning "Installation completed with $ISSUES potential issue(s)."
|
||||
print_warning "The application may still work, but some features might be limited."
|
||||
fi
|
||||
|
||||
echo
|
||||
print_info "Installation details:"
|
||||
print_info "- Virtual environment: $VENV_DIR"
|
||||
print_info "- Desktop entry: $DESKTOP_DIR/vocalinux.desktop"
|
||||
print_info "- Icons: $ICON_DIR"
|
||||
print_info "- Configuration: $CONFIG_DIR"
|
||||
print_info "- Data directory: $DATA_DIR"
|
||||
|
||||
echo
|
||||
print_info "To activate the virtual environment in the future, run:"
|
||||
print_info " source activate-vocalinux.sh"
|
||||
print_info "You can then launch Vocalinux by running 'vocalinux'"
|
||||
|
||||
echo
|
||||
print_info "For more information, see the documentation in the docs/ directory."
|
||||
|
||||
if [ "$ISSUES" -gt 0 ]; then
|
||||
echo
|
||||
print_warning "If you encounter any problems, please report them at:"
|
||||
print_warning "https://github.com/jatinkrmalik/vocalinux/issues"
|
||||
fi
|
||||
}
|
||||
|
||||
# Verify the installation
|
||||
verify_installation
|
||||
INSTALL_ISSUES=$?
|
||||
|
||||
# Print installation summary
|
||||
print_installation_summary $INSTALL_ISSUES
|
||||
|
||||
print_success "Installation process completed!"
|
||||
|
||||
@@ -1,46 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
"""
|
||||
Vocalinux - A seamless voice dictation system for Linux
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
# Check Python version
|
||||
MIN_PYTHON_VERSION = (3, 8)
|
||||
if sys.version_info < MIN_PYTHON_VERSION:
|
||||
sys.exit(f"Error: Vocalinux requires Python {MIN_PYTHON_VERSION[0]}.{MIN_PYTHON_VERSION[1]} or higher")
|
||||
|
||||
# This package requires several system dependencies that must be installed manually:
|
||||
# For PyAudio: portaudio19-dev (on Ubuntu/Debian)
|
||||
# For PyGObject: libgirepository1.0-dev, libcairo2-dev, pkg-config, python3-dev
|
||||
|
||||
# Get long description from README if available
|
||||
long_description = ""
|
||||
if os.path.exists("README.md"):
|
||||
with open("README.md", "r", encoding="utf-8") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
# Get version from version file or default to 0.1.0
|
||||
version = "0.1.0"
|
||||
if os.path.exists("src/vocalinux/version.py"):
|
||||
with open("src/vocalinux/version.py", "r", encoding="utf-8") as f:
|
||||
exec(f.read())
|
||||
version = locals().get("__version__", "0.1.0")
|
||||
|
||||
# Platform-specific dependencies
|
||||
platform_dependencies = []
|
||||
if platform.system() == "Linux":
|
||||
platform_dependencies.extend([
|
||||
"python-xlib", # For keyboard shortcut handling in X11
|
||||
"PyGObject", # For GTK UI
|
||||
])
|
||||
|
||||
setup(
|
||||
name="vocalinux",
|
||||
version="0.1.0",
|
||||
version=version,
|
||||
description="A seamless voice dictation system for Linux",
|
||||
author="@jatinkrmaik",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
author="Jatin K Malik",
|
||||
author_email="jatinkrmalik@gmail.com",
|
||||
url="https://github.com/jatinkrmalik/vocalinux",
|
||||
project_urls={
|
||||
"Bug Tracker": "https://github.com/jatinkrmalik/vocalinux/issues",
|
||||
"Documentation": "https://github.com/jatinkrmalik/vocalinux/tree/main/docs",
|
||||
"Source Code": "https://github.com/jatinkrmalik/vocalinux",
|
||||
},
|
||||
packages=find_packages(where="src"),
|
||||
package_dir={"": "src"},
|
||||
install_requires=[
|
||||
"vosk", # For VOSK API speech recognition
|
||||
"pydub", # For audio processing
|
||||
"python-xlib", # For keyboard shortcut handling in X11
|
||||
"pynput", # For keyboard/mouse events
|
||||
"PyGObject", # For GTK UI
|
||||
"requests", # For downloading models
|
||||
"tqdm", # For progress bars during downloads
|
||||
"numpy", # For numerical operations
|
||||
"pyaudio", # For audio input/output
|
||||
],
|
||||
"vosk>=0.3.45", # For VOSK API speech recognition
|
||||
"pydub>=0.25.1", # For audio processing
|
||||
"pynput>=1.7.6", # For keyboard/mouse events
|
||||
"requests>=2.28.0", # For downloading models
|
||||
"tqdm>=4.64.0", # For progress bars during downloads
|
||||
"numpy>=1.22.0", # For numerical operations
|
||||
"pyaudio>=0.2.13", # For audio input/output
|
||||
] + platform_dependencies,
|
||||
extras_require={
|
||||
"whisper": ["whisper", "torch"], # Optional Whisper AI support
|
||||
"whisper": [
|
||||
"whisper>=1.1.10",
|
||||
"torch>=2.0.0",
|
||||
], # Optional Whisper AI support
|
||||
"dev": [
|
||||
"pytest",
|
||||
"pytest-cov", # Add this for coverage testing
|
||||
"black",
|
||||
"isort",
|
||||
"flake8",
|
||||
"pre-commit", # For pre-commit hooks
|
||||
"pytest>=7.0.0",
|
||||
"pytest-cov>=4.0.0", # For coverage testing
|
||||
"pytest-mock>=3.10.0", # For mocking in tests
|
||||
"black>=23.0.0", # For code formatting
|
||||
"isort>=5.12.0", # For import sorting
|
||||
"flake8>=6.0.0", # For linting
|
||||
"pre-commit>=3.0.0", # For pre-commit hooks
|
||||
],
|
||||
"docs": [
|
||||
"sphinx>=6.0.0",
|
||||
"sphinx-rtd-theme>=1.2.0",
|
||||
],
|
||||
},
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"vocalinux=vocalinux.main:main",
|
||||
],
|
||||
"gui_scripts": [
|
||||
"vocalinux-gui=vocalinux.main:main",
|
||||
],
|
||||
},
|
||||
# Include custom application icons and sounds in the package
|
||||
data_files=[
|
||||
@@ -83,7 +131,15 @@ setup(
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Topic :: Desktop Environment :: Gnome",
|
||||
"Topic :: Multimedia :: Sound/Audio :: Speech",
|
||||
"Topic :: Text Processing",
|
||||
"Topic :: Utilities",
|
||||
],
|
||||
python_requires=">=3.8", # Updated minimum Python version
|
||||
python_requires=">=3.8", # Minimum Python version
|
||||
zip_safe=False, # Required for PyGObject applications
|
||||
)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
Version information for Vocalinux.
|
||||
"""
|
||||
|
||||
__version__ = "0.1.0"
|
||||
__author__ = "Jatin K Malik"
|
||||
__email__ = "jatinkrmalik@gmail.com"
|
||||
__license__ = "GPL-3.0"
|
||||
__copyright__ = "Copyright 2023-2024 Jatin K Malik"
|
||||
+255
-60
@@ -2,7 +2,8 @@
|
||||
# Vocalinux Uninstaller
|
||||
# This script removes Vocalinux and cleans up the environment
|
||||
|
||||
set -e # Exit on error
|
||||
# Don't exit on error to allow for more robust cleanup
|
||||
# set -e
|
||||
|
||||
# Function to display colored output
|
||||
print_info() {
|
||||
@@ -21,89 +22,283 @@ print_warning() {
|
||||
echo -e "\e[1;33m[WARNING]\e[0m $1"
|
||||
}
|
||||
|
||||
# Function to check if a command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to safely remove a file or directory
|
||||
safe_remove() {
|
||||
local path="$1"
|
||||
local description="$2"
|
||||
|
||||
if [ -e "$path" ]; then
|
||||
print_info "Removing $description: $path"
|
||||
rm -rf "$path" && {
|
||||
print_success "Successfully removed $description"
|
||||
return 0
|
||||
} || {
|
||||
print_error "Failed to remove $description: $path"
|
||||
return 1
|
||||
}
|
||||
else
|
||||
print_info "$description not found: $path"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
print_info "Vocalinux Uninstaller"
|
||||
print_info "=============================="
|
||||
echo ""
|
||||
|
||||
# Parse command line arguments
|
||||
KEEP_CONFIG="no"
|
||||
KEEP_DATA="no"
|
||||
VENV_DIR="venv"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--keep-config)
|
||||
KEEP_CONFIG="yes"
|
||||
shift
|
||||
;;
|
||||
--keep-data)
|
||||
KEEP_DATA="yes"
|
||||
shift
|
||||
;;
|
||||
--venv-dir=*)
|
||||
VENV_DIR="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
echo "Vocalinux Uninstaller"
|
||||
echo "Usage: $0 [options]"
|
||||
echo "Options:"
|
||||
echo " --keep-config Keep configuration files"
|
||||
echo " --keep-data Keep application data (models, etc.)"
|
||||
echo " --venv-dir=PATH Specify custom virtual environment directory (default: venv)"
|
||||
echo " --help Show this help message"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown option: $1"
|
||||
echo "Use --help to see available options"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Define XDG directories
|
||||
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/vocalinux"
|
||||
DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux"
|
||||
DESKTOP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
|
||||
ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps"
|
||||
|
||||
# Print uninstallation options
|
||||
echo "Uninstallation options:"
|
||||
echo "- Virtual environment directory: $VENV_DIR"
|
||||
[[ "$KEEP_CONFIG" == "yes" ]] && echo "- Keeping configuration files"
|
||||
[[ "$KEEP_DATA" == "yes" ]] && echo "- Keeping application data"
|
||||
echo
|
||||
|
||||
# Ask for confirmation
|
||||
read -p "This will completely remove Vocalinux and all its data. Continue? (y/n) " -n 1 -r
|
||||
read -p "This will remove Vocalinux from your system. Continue? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_info "Uninstallation cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Remove virtual environment (if exists)
|
||||
if [ -d "venv" ]; then
|
||||
print_info "Removing virtual environment..."
|
||||
# Deactivate the virtual environment if it's active
|
||||
if [[ "$VIRTUAL_ENV" == *"venv"* ]]; then
|
||||
print_warning "Virtual environment is active. Deactivating..."
|
||||
deactivate
|
||||
# Function to handle virtual environment removal
|
||||
remove_virtual_environment() {
|
||||
if [ -d "$VENV_DIR" ]; then
|
||||
print_info "Removing virtual environment..."
|
||||
|
||||
# Deactivate the virtual environment if it's active
|
||||
if [[ -n "$VIRTUAL_ENV" && "$VIRTUAL_ENV" == *"$VENV_DIR"* ]]; then
|
||||
print_warning "Virtual environment is active. Deactivating..."
|
||||
deactivate 2>/dev/null || {
|
||||
print_warning "Failed to deactivate virtual environment. This is not critical."
|
||||
}
|
||||
fi
|
||||
|
||||
# Remove the virtual environment directory
|
||||
safe_remove "$VENV_DIR" "virtual environment directory"
|
||||
else
|
||||
print_info "Virtual environment not found: $VENV_DIR"
|
||||
fi
|
||||
# Remove the virtual environment directory
|
||||
print_info "Deleting virtual environment directory..."
|
||||
rm -rf venv
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove activation script
|
||||
if [ -f "activate-vocalinux.sh" ]; then
|
||||
print_info "Removing activation script..."
|
||||
rm activate-vocalinux.sh
|
||||
fi
|
||||
# Function to remove application files
|
||||
remove_application_files() {
|
||||
# Remove activation script
|
||||
safe_remove "activate-vocalinux.sh" "activation script"
|
||||
|
||||
# Remove desktop entry
|
||||
safe_remove "$DESKTOP_DIR/vocalinux.desktop" "desktop entry"
|
||||
|
||||
# Remove icons
|
||||
print_info "Removing application icons..."
|
||||
local ICONS=(
|
||||
"vocalinux.svg"
|
||||
"vocalinux-microphone.svg"
|
||||
"vocalinux-microphone-off.svg"
|
||||
"vocalinux-microphone-process.svg"
|
||||
)
|
||||
|
||||
for icon in "${ICONS[@]}"; do
|
||||
safe_remove "$ICON_DIR/$icon" "icon"
|
||||
done
|
||||
|
||||
# Update icon cache
|
||||
if command_exists gtk-update-icon-cache; then
|
||||
print_info "Updating icon cache..."
|
||||
gtk-update-icon-cache -f -t "${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor" 2>/dev/null || {
|
||||
print_warning "Failed to update icon cache. This is not critical."
|
||||
}
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove application configuration and data
|
||||
if [ -d "$CONFIG_DIR" ]; then
|
||||
print_info "Removing configuration directory..."
|
||||
rm -rf "$CONFIG_DIR"
|
||||
fi
|
||||
# Function to remove configuration and data
|
||||
remove_config_and_data() {
|
||||
# Remove configuration if not keeping it
|
||||
if [[ "$KEEP_CONFIG" != "yes" ]]; then
|
||||
safe_remove "$CONFIG_DIR" "configuration directory"
|
||||
else
|
||||
print_info "Keeping configuration directory as requested: $CONFIG_DIR"
|
||||
fi
|
||||
|
||||
# Remove data if not keeping it
|
||||
if [[ "$KEEP_DATA" != "yes" ]]; then
|
||||
safe_remove "$DATA_DIR" "application data directory"
|
||||
else
|
||||
print_info "Keeping application data directory as requested: $DATA_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -d "$DATA_DIR" ]; then
|
||||
print_info "Removing application data directory..."
|
||||
rm -rf "$DATA_DIR"
|
||||
fi
|
||||
# Function to clean up build artifacts
|
||||
cleanup_build_artifacts() {
|
||||
print_info "Cleaning up build artifacts..."
|
||||
|
||||
# Remove Python package build directories
|
||||
safe_remove "build/" "build directory"
|
||||
safe_remove "dist/" "distribution directory"
|
||||
safe_remove "*.egg-info/" "egg-info directory"
|
||||
|
||||
# Find and remove egg-info directories in src
|
||||
find src -name "*.egg-info" -type d -exec rm -rf {} \; 2>/dev/null || {
|
||||
print_warning "Failed to remove some egg-info directories."
|
||||
}
|
||||
|
||||
# Find and remove __pycache__ directories
|
||||
find . -name "__pycache__" -type d -exec rm -rf {} \; 2>/dev/null || {
|
||||
print_warning "Failed to remove some __pycache__ directories."
|
||||
}
|
||||
|
||||
# Clean up any temporary or generated files
|
||||
print_info "Cleaning up temporary files..."
|
||||
find . -name "*.pyc" -delete 2>/dev/null
|
||||
find . -name "*.pyo" -delete 2>/dev/null
|
||||
find . -name ".pytest_cache" -type d -exec rm -rf {} \; 2>/dev/null
|
||||
find . -name ".coverage" -delete 2>/dev/null
|
||||
|
||||
# Remove wrapper script if it exists
|
||||
safe_remove "vocalinux-run.py" "wrapper script"
|
||||
}
|
||||
|
||||
# Remove desktop entry
|
||||
if [ -f "$DESKTOP_DIR/vocalinux.desktop" ]; then
|
||||
print_info "Removing desktop entry..."
|
||||
rm "$DESKTOP_DIR/vocalinux.desktop"
|
||||
fi
|
||||
# Function to verify uninstallation
|
||||
verify_uninstallation() {
|
||||
print_info "Verifying uninstallation..."
|
||||
local ISSUES=0
|
||||
|
||||
# Check if virtual environment still exists
|
||||
if [ -d "$VENV_DIR" ]; then
|
||||
print_warning "Virtual environment still exists: $VENV_DIR"
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if desktop entry still exists
|
||||
if [ -f "$DESKTOP_DIR/vocalinux.desktop" ]; then
|
||||
print_warning "Desktop entry still exists: $DESKTOP_DIR/vocalinux.desktop"
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if any icons still exist
|
||||
local ICON_COUNT=0
|
||||
for icon in vocalinux.svg vocalinux-microphone.svg vocalinux-microphone-off.svg vocalinux-microphone-process.svg; do
|
||||
if [ -f "$ICON_DIR/$icon" ]; then
|
||||
((ICON_COUNT++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ICON_COUNT" -gt 0 ]; then
|
||||
print_warning "$ICON_COUNT icons still exist in $ICON_DIR"
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if configuration still exists (only if not keeping it)
|
||||
if [[ "$KEEP_CONFIG" != "yes" && -d "$CONFIG_DIR" ]]; then
|
||||
print_warning "Configuration directory still exists: $CONFIG_DIR"
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Check if data still exists (only if not keeping it)
|
||||
if [[ "$KEEP_DATA" != "yes" && -d "$DATA_DIR" ]]; then
|
||||
print_warning "Application data directory still exists: $DATA_DIR"
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
# Return the number of issues found
|
||||
return $ISSUES
|
||||
}
|
||||
|
||||
# Remove icons
|
||||
print_info "Removing application icons..."
|
||||
rm -f "$ICON_DIR/vocalinux.svg"
|
||||
rm -f "$ICON_DIR/vocalinux-microphone.svg"
|
||||
rm -f "$ICON_DIR/vocalinux-microphone-off.svg"
|
||||
rm -f "$ICON_DIR/vocalinux-microphone-process.svg"
|
||||
# Function to print uninstallation summary
|
||||
print_uninstallation_summary() {
|
||||
local ISSUES=$1
|
||||
|
||||
echo
|
||||
echo "=============================="
|
||||
echo " UNINSTALLATION SUMMARY"
|
||||
echo "=============================="
|
||||
echo
|
||||
|
||||
if [ "$ISSUES" -eq 0 ]; then
|
||||
print_success "Uninstallation completed successfully with no issues!"
|
||||
else
|
||||
print_warning "Uninstallation completed with $ISSUES potential issue(s)."
|
||||
print_warning "Some files or directories may still exist."
|
||||
fi
|
||||
|
||||
echo
|
||||
if [[ "$KEEP_CONFIG" == "yes" ]]; then
|
||||
print_info "Configuration directory was kept: $CONFIG_DIR"
|
||||
fi
|
||||
|
||||
if [[ "$KEEP_DATA" == "yes" ]]; then
|
||||
print_info "Application data directory was kept: $DATA_DIR"
|
||||
fi
|
||||
|
||||
echo
|
||||
print_info "Your system has been cleaned up and is ready for a fresh installation."
|
||||
|
||||
if [ "$ISSUES" -gt 0 ]; then
|
||||
echo
|
||||
print_warning "If you encounter any problems, please report them at:"
|
||||
print_warning "https://github.com/jatinkrmalik/vocalinux/issues"
|
||||
fi
|
||||
}
|
||||
|
||||
# Update icon cache
|
||||
gtk-update-icon-cache -f -t "${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor" 2>/dev/null || true
|
||||
# Perform uninstallation steps
|
||||
remove_virtual_environment
|
||||
remove_application_files
|
||||
remove_config_and_data
|
||||
cleanup_build_artifacts
|
||||
|
||||
# Remove Python package build directories
|
||||
print_info "Removing build directories..."
|
||||
rm -rf build/ dist/ *.egg-info/
|
||||
find src -name "*.egg-info" -type d -exec rm -rf {} +
|
||||
find src -name "__pycache__" -type d -exec rm -rf {} +
|
||||
# Verify uninstallation
|
||||
verify_uninstallation
|
||||
UNINSTALL_ISSUES=$?
|
||||
|
||||
# Clean up any temporary or generated files
|
||||
print_info "Cleaning up temporary files..."
|
||||
find . -name "*.pyc" -delete
|
||||
find . -name "*.pyo" -delete
|
||||
find . -name "__pycache__" -type d -exec rm -rf {} +
|
||||
find . -name ".pytest_cache" -type d -exec rm -rf {} +
|
||||
find . -name ".coverage" -delete
|
||||
# Print uninstallation summary
|
||||
print_uninstallation_summary $UNINSTALL_ISSUES
|
||||
|
||||
# Remove wrapper script if it exists
|
||||
if [ -f "vocalinux-run.py" ]; then
|
||||
print_info "Removing wrapper script..."
|
||||
rm vocalinux-run.py
|
||||
fi
|
||||
|
||||
print_success "Uninstallation complete!"
|
||||
print_info "Your system has been cleaned up and is ready for a fresh installation."
|
||||
print_success "Uninstallation process completed!"
|
||||
|
||||
Reference in New Issue
Block a user