feat(identity): rename user-visible identity to voculinux with one-time legacy import
The fork takes its own name everywhere a user can see it: binaries (voculinux, voculinux-gui), desktop entry, autostart, tray, D-Bus namespace (com.voculinux.Voculinux, no alias for the old name), config/data/cache dirs, single-instance lock, IBus engine identity, tray icons, resource prefixes, VOCULINUX_* environment names, and the update-checker user agent. The internal Python module stays vocalinux and the distribution metadata keeps the upstream URLs as provenance. On first run a previous Vocalinux install's config.json, custom dictionary, and portal restore token are copied once into the new locations (new config always wins, no merge, no write-back); models re-resolve through the pinned-checksum download path. An offline naming-sweep test proves no old-name strings remain on user-visible surfaces outside the allowlist. Refs #18
This commit is contained in:
+70
-70
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
# Vocalinux Uninstaller
|
||||
# This script removes Vocalinux and cleans up the environment
|
||||
# Voculinux Uninstaller
|
||||
# This script removes Voculinux and cleans up the environment
|
||||
|
||||
# Don't exit on error to allow for more robust cleanup
|
||||
# set -e
|
||||
@@ -39,9 +39,9 @@ read_pid_file() {
|
||||
fi
|
||||
}
|
||||
|
||||
# True only for the Vocalinux app / IBus engine — not editors, shells, or tests
|
||||
# whose argv merely contains the string "vocalinux" (e.g. cwd under the repo).
|
||||
is_vocalinux_process() {
|
||||
# True only for the Voculinux app / IBus engine — not editors, shells, or tests
|
||||
# whose argv merely contains the string "voculinux" (e.g. cwd under the repo).
|
||||
is_voculinux_process() {
|
||||
local pid="$1"
|
||||
|
||||
if [ "$pid" = "$$" ] || [ "$pid" = "$PPID" ]; then
|
||||
@@ -69,18 +69,18 @@ is_vocalinux_process() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
# IBus engine: .../vocalinux/.../ibus_engine.py
|
||||
if [[ "$cmdline" == *"ibus_engine.py"* && "$cmdline" == *"vocalinux"* ]]; then
|
||||
# IBus engine: .../voculinux/.../ibus_engine.py
|
||||
if [[ "$cmdline" == *"ibus_engine.py"* && "$cmdline" == *"voculinux"* ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Console-script entrypoints. Setuptools scripts are executed as
|
||||
# `python …/bin/vocalinux`, so argv0 is python — scan every arg for the
|
||||
# script path (require …/bin/vocalinux to avoid matching a repo directory).
|
||||
# `python …/bin/voculinux`, so argv0 is python — scan every arg for the
|
||||
# script path (require …/bin/voculinux to avoid matching a repo directory).
|
||||
local arg
|
||||
while IFS= read -r -d '' arg; do
|
||||
case "$arg" in
|
||||
vocalinux|vocalinux-gui|*/bin/vocalinux|*/bin/vocalinux-gui)
|
||||
voculinux|voculinux-gui|*/bin/voculinux|*/bin/voculinux-gui)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
@@ -90,16 +90,16 @@ is_vocalinux_process() {
|
||||
}
|
||||
|
||||
# Prefer the PIDs the app writes; fall back to narrow entrypoint patterns only.
|
||||
# Deliberately does NOT use `pgrep -f vocalinux` (matches editors/shells/cwd paths).
|
||||
get_vocalinux_pids() {
|
||||
# Deliberately does NOT use `pgrep -f voculinux` (matches editors/shells/cwd paths).
|
||||
get_voculinux_pids() {
|
||||
local data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
local -A seen=()
|
||||
local pid candidate
|
||||
local -a candidates=()
|
||||
|
||||
for candidate in \
|
||||
"$(read_pid_file "$data_home/vocalinux/instance.lock")" \
|
||||
"$(read_pid_file "$data_home/vocalinux-ibus/engine.pid")"
|
||||
"$(read_pid_file "$data_home/voculinux/instance.lock")" \
|
||||
"$(read_pid_file "$data_home/voculinux-ibus/engine.pid")"
|
||||
do
|
||||
[ -n "$candidate" ] && candidates+=("$candidate")
|
||||
done
|
||||
@@ -108,16 +108,16 @@ get_vocalinux_pids() {
|
||||
while read -r candidate; do
|
||||
[ -n "$candidate" ] && candidates+=("$candidate")
|
||||
done < <(
|
||||
pgrep -u "$(id -u)" -x vocalinux 2>/dev/null || true
|
||||
pgrep -u "$(id -u)" -x vocalinux-gui 2>/dev/null || true
|
||||
pgrep -u "$(id -u)" -f -- '-m vocalinux\.main' 2>/dev/null || true
|
||||
pgrep -u "$(id -u)" -f -- 'vocalinux/.*/ibus_engine\.py' 2>/dev/null || true
|
||||
pgrep -u "$(id -u)" -x voculinux 2>/dev/null || true
|
||||
pgrep -u "$(id -u)" -x voculinux-gui 2>/dev/null || true
|
||||
pgrep -u "$(id -u)" -f -- '-m voculinux\.main' 2>/dev/null || true
|
||||
pgrep -u "$(id -u)" -f -- 'voculinux/.*/ibus_engine\.py' 2>/dev/null || true
|
||||
)
|
||||
|
||||
for pid in "${candidates[@]}"; do
|
||||
[ -n "${seen[$pid]:-}" ] && continue
|
||||
seen[$pid]=1
|
||||
if is_vocalinux_process "$pid"; then
|
||||
if is_voculinux_process "$pid"; then
|
||||
echo "$pid"
|
||||
fi
|
||||
done
|
||||
@@ -145,15 +145,15 @@ safe_remove() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to kill running Vocalinux processes
|
||||
kill_vocalinux_processes() {
|
||||
print_info "Checking for running Vocalinux processes..."
|
||||
# Function to kill running Voculinux processes
|
||||
kill_voculinux_processes() {
|
||||
print_info "Checking for running Voculinux processes..."
|
||||
|
||||
local PIDS
|
||||
PIDS=$(get_vocalinux_pids || true)
|
||||
PIDS=$(get_voculinux_pids || true)
|
||||
|
||||
if [ -n "$PIDS" ]; then
|
||||
print_warning "Found running Vocalinux process(es):"
|
||||
print_warning "Found running Voculinux process(es):"
|
||||
local pid
|
||||
for pid in $PIDS; do
|
||||
local cmd
|
||||
@@ -162,7 +162,7 @@ kill_vocalinux_processes() {
|
||||
done
|
||||
|
||||
if [[ "$NON_INTERACTIVE" != "yes" ]]; then
|
||||
read -p "Kill running Vocalinux process(es)? (Y/n) " -n 1 -r
|
||||
read -p "Kill running Voculinux process(es)? (Y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||
print_warning "Processes not killed. Uninstallation may be incomplete."
|
||||
@@ -170,13 +170,13 @@ kill_vocalinux_processes() {
|
||||
fi
|
||||
fi
|
||||
|
||||
print_info "Stopping Vocalinux..."
|
||||
print_info "Stopping Voculinux..."
|
||||
# shellcheck disable=SC2086
|
||||
echo $PIDS | xargs -r kill -TERM 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
local REMAINING_PIDS
|
||||
REMAINING_PIDS=$(get_vocalinux_pids || true)
|
||||
REMAINING_PIDS=$(get_voculinux_pids || true)
|
||||
|
||||
if [ -n "$REMAINING_PIDS" ]; then
|
||||
print_warning "Some processes still running, forcing termination..."
|
||||
@@ -186,19 +186,19 @@ kill_vocalinux_processes() {
|
||||
fi
|
||||
|
||||
local FINAL_PIDS
|
||||
FINAL_PIDS=$(get_vocalinux_pids || true)
|
||||
FINAL_PIDS=$(get_voculinux_pids || true)
|
||||
if [ -n "$FINAL_PIDS" ]; then
|
||||
print_error "Warning: Could not terminate all Vocalinux processes: $FINAL_PIDS"
|
||||
print_error "Warning: Could not terminate all Voculinux processes: $FINAL_PIDS"
|
||||
print_error "You may need to manually kill these processes before continuing."
|
||||
else
|
||||
print_success "All Vocalinux processes stopped"
|
||||
print_success "All Voculinux processes stopped"
|
||||
fi
|
||||
else
|
||||
print_info "No running Vocalinux processes found"
|
||||
print_info "No running Voculinux processes found"
|
||||
fi
|
||||
}
|
||||
|
||||
print_info "Vocalinux Uninstaller"
|
||||
print_info "Voculinux Uninstaller"
|
||||
print_info "=============================="
|
||||
echo ""
|
||||
|
||||
@@ -214,7 +214,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SOURCE_CHECKOUT=""
|
||||
VENV_DIR=""
|
||||
if [[ -f "$SCRIPT_DIR/pyproject.toml" && -d "$SCRIPT_DIR/src/vocalinux" ]] \
|
||||
&& grep -q 'name = "vocalinux"' "$SCRIPT_DIR/pyproject.toml" 2>/dev/null; then
|
||||
&& grep -q 'name = "voculinux"' "$SCRIPT_DIR/pyproject.toml" 2>/dev/null; then
|
||||
SOURCE_CHECKOUT="$SCRIPT_DIR"
|
||||
VENV_DIR="$SCRIPT_DIR/venv"
|
||||
fi
|
||||
@@ -243,15 +243,15 @@ while [[ $# -gt 0 ]]; do
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
echo "Vocalinux Uninstaller"
|
||||
echo "Voculinux 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 Virtual environment to remove. Absolute, or relative to a"
|
||||
echo " source checkout. Default: <checkout>/venv when this script"
|
||||
echo " lives in a Vocalinux tree; otherwise only the curl install"
|
||||
echo " at ~/.local/share/vocalinux/venv is removed."
|
||||
echo " lives in a Voculinux tree; otherwise only the curl install"
|
||||
echo " at ~/.local/share/voculinux/venv is removed."
|
||||
echo " -y, --yes Non-interactive mode (no confirmation prompts)"
|
||||
echo " --help Show this help message"
|
||||
exit 0
|
||||
@@ -271,22 +271,22 @@ if [[ -n "$VENV_DIR" && "$VENV_DIR" != /* ]]; then
|
||||
VENV_DIR="$SOURCE_CHECKOUT/$VENV_DIR"
|
||||
else
|
||||
print_error "Refusing relative --venv-dir outside a source checkout: $VENV_DIR"
|
||||
print_error "Pass an absolute path. A curl uninstall already removes ~/.local/share/vocalinux/venv."
|
||||
print_error "Pass an absolute path. A curl uninstall already removes ~/.local/share/voculinux/venv."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Define XDG directories
|
||||
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/vocalinux"
|
||||
DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux"
|
||||
IBUS_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux-ibus"
|
||||
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/voculinux"
|
||||
DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voculinux"
|
||||
IBUS_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voculinux-ibus"
|
||||
DESKTOP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
|
||||
AUTOSTART_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/autostart"
|
||||
ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps"
|
||||
|
||||
# Directories created by curl-based installation
|
||||
CURL_INSTALL_DIR="$HOME/.local/share/vocalinux-install"
|
||||
CURL_VENV_DIR="$HOME/.local/share/vocalinux/venv"
|
||||
CURL_INSTALL_DIR="$HOME/.local/share/voculinux-install"
|
||||
CURL_VENV_DIR="$HOME/.local/share/voculinux/venv"
|
||||
CURL_BIN_DIR="$HOME/.local/bin"
|
||||
|
||||
echo "Uninstallation options:"
|
||||
@@ -302,7 +302,7 @@ echo
|
||||
if [[ "$NON_INTERACTIVE" == "yes" ]]; then
|
||||
print_info "Non-interactive mode: proceeding with uninstallation..."
|
||||
else
|
||||
read -p "This will remove Vocalinux from your system. Continue? (y/n) " -n 1 -r
|
||||
read -p "This will remove Voculinux from your system. Continue? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_info "Uninstallation cancelled."
|
||||
@@ -346,10 +346,10 @@ remove_virtual_environment() {
|
||||
safe_remove "$CURL_VENV_DIR" "curl-installed virtual environment"
|
||||
fi
|
||||
|
||||
# Remove the vocalinux data directory if empty (contains venv)
|
||||
local VOCALINUX_DATA_DIR="$HOME/.local/share/vocalinux"
|
||||
if [ -d "$VOCALINUX_DATA_DIR" ] && [ -z "$(ls -A "$VOCALINUX_DATA_DIR" 2>/dev/null)" ]; then
|
||||
safe_remove "$VOCALINUX_DATA_DIR" "empty vocalinux data directory"
|
||||
# Remove the voculinux data directory if empty (contains venv)
|
||||
local VOCULINUX_DATA_DIR="$HOME/.local/share/voculinux"
|
||||
if [ -d "$VOCULINUX_DATA_DIR" ] && [ -z "$(ls -A "$VOCULINUX_DATA_DIR" 2>/dev/null)" ]; then
|
||||
safe_remove "$VOCULINUX_DATA_DIR" "empty voculinux data directory"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -364,35 +364,35 @@ remove_curl_install_files() {
|
||||
# remove_application_files() (they exist for both curl and repo installs).
|
||||
|
||||
# Remove activation script in ~/.local/bin
|
||||
safe_remove "$CURL_BIN_DIR/activate-vocalinux.sh" "activation script in ~/.local/bin"
|
||||
safe_remove "$CURL_BIN_DIR/activate-voculinux.sh" "activation script in ~/.local/bin"
|
||||
}
|
||||
|
||||
# Function to remove application files
|
||||
remove_application_files() {
|
||||
# Only the copy inside a source checkout. A relative path would delete
|
||||
# whatever activate-vocalinux.sh happens to sit in $PWD.
|
||||
# whatever activate-voculinux.sh happens to sit in $PWD.
|
||||
if [[ -n "$SOURCE_CHECKOUT" ]]; then
|
||||
safe_remove "$SOURCE_CHECKOUT/activate-vocalinux.sh" "local activation script"
|
||||
safe_remove "$SOURCE_CHECKOUT/activate-voculinux.sh" "local activation script"
|
||||
fi
|
||||
|
||||
# Remove launcher wrappers in ~/.local/bin created by install.sh. These are
|
||||
# regular files in a repo/dev install and may be symlinks in a curl install;
|
||||
# safe_remove handles both (and dangling symlinks).
|
||||
safe_remove "$CURL_BIN_DIR/vocalinux" "vocalinux launcher script"
|
||||
safe_remove "$CURL_BIN_DIR/vocalinux-gui" "vocalinux-gui launcher script"
|
||||
safe_remove "$CURL_BIN_DIR/voculinux" "voculinux launcher script"
|
||||
safe_remove "$CURL_BIN_DIR/voculinux-gui" "voculinux-gui launcher script"
|
||||
|
||||
# Remove desktop entry
|
||||
safe_remove "$DESKTOP_DIR/vocalinux.desktop" "desktop entry"
|
||||
safe_remove "$DESKTOP_DIR/voculinux.desktop" "desktop entry"
|
||||
|
||||
safe_remove "$AUTOSTART_DIR/vocalinux.desktop" "autostart desktop entry"
|
||||
safe_remove "$AUTOSTART_DIR/voculinux.desktop" "autostart desktop entry"
|
||||
|
||||
# Remove icons
|
||||
print_info "Removing application icons..."
|
||||
local ICONS=(
|
||||
"vocalinux.svg"
|
||||
"vocalinux-microphone.svg"
|
||||
"vocalinux-microphone-off.svg"
|
||||
"vocalinux-microphone-process.svg"
|
||||
"voculinux.svg"
|
||||
"voculinux-microphone.svg"
|
||||
"voculinux-microphone-off.svg"
|
||||
"voculinux-microphone-process.svg"
|
||||
)
|
||||
|
||||
for icon in "${ICONS[@]}"; do
|
||||
@@ -428,7 +428,7 @@ remove_config_and_data() {
|
||||
safe_remove "$IBUS_DATA_DIR" "IBus runtime data directory"
|
||||
}
|
||||
|
||||
# Clean build artifacts inside a Vocalinux source checkout.
|
||||
# Clean build artifacts inside a Voculinux source checkout.
|
||||
# $1 must be an absolute directory. A relative path would follow the caller's
|
||||
# working directory ($HOME, when the website command runs this script from
|
||||
# /tmp). -xdev stays on one filesystem. -prune removes a directory without
|
||||
@@ -453,7 +453,7 @@ cleanup_build_artifacts() {
|
||||
safe_remove "$root/build" "build directory"
|
||||
safe_remove "$root/dist" "distribution directory"
|
||||
|
||||
# vocalinux metadata lives in src/ (setuptools src layout) and sometimes as
|
||||
# voculinux metadata lives in src/ (setuptools src layout) and sometimes as
|
||||
# *.egg-info at the checkout root. Do not search the whole tree: .venv is
|
||||
# a separate dev environment and its egg-info has to stay.
|
||||
find "$root/src" -xdev -name "*.egg-info" -type d -prune -exec rm -rf {} + \
|
||||
@@ -482,7 +482,7 @@ cleanup_build_artifacts() {
|
||||
print_warning "Failed to remove some temporary files."
|
||||
}
|
||||
|
||||
safe_remove "$root/vocalinux-run.py" "wrapper script"
|
||||
safe_remove "$root/voculinux-run.py" "wrapper script"
|
||||
}
|
||||
|
||||
# Function to verify uninstallation
|
||||
@@ -509,7 +509,7 @@ verify_uninstallation() {
|
||||
fi
|
||||
|
||||
# Check if launcher wrappers (files or symlinks) still exist
|
||||
for launcher in vocalinux vocalinux-gui; do
|
||||
for launcher in voculinux voculinux-gui; do
|
||||
if [ -e "$CURL_BIN_DIR/$launcher" ] || [ -L "$CURL_BIN_DIR/$launcher" ]; then
|
||||
print_warning "Launcher script still exists: $CURL_BIN_DIR/$launcher"
|
||||
((ISSUES++))
|
||||
@@ -517,19 +517,19 @@ verify_uninstallation() {
|
||||
done
|
||||
|
||||
# Check if desktop entry still exists
|
||||
if [ -f "$DESKTOP_DIR/vocalinux.desktop" ]; then
|
||||
print_warning "Desktop entry still exists: $DESKTOP_DIR/vocalinux.desktop"
|
||||
if [ -f "$DESKTOP_DIR/voculinux.desktop" ]; then
|
||||
print_warning "Desktop entry still exists: $DESKTOP_DIR/voculinux.desktop"
|
||||
((ISSUES++))
|
||||
fi
|
||||
|
||||
if [ -f "$AUTOSTART_DIR/vocalinux.desktop" ]; then
|
||||
print_warning "Autostart desktop entry still exists: $AUTOSTART_DIR/vocalinux.desktop"
|
||||
if [ -f "$AUTOSTART_DIR/voculinux.desktop" ]; then
|
||||
print_warning "Autostart desktop entry still exists: $AUTOSTART_DIR/voculinux.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
|
||||
for icon in voculinux.svg voculinux-microphone.svg voculinux-microphone-off.svg voculinux-microphone-process.svg; do
|
||||
if [ -f "$ICON_DIR/$icon" ]; then
|
||||
((ICON_COUNT++))
|
||||
fi
|
||||
@@ -598,13 +598,13 @@ print_uninstallation_summary() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Kill any running Vocalinux processes first
|
||||
kill_vocalinux_processes
|
||||
# Kill any running Voculinux processes first
|
||||
kill_voculinux_processes
|
||||
|
||||
# Perform uninstallation steps
|
||||
remove_virtual_environment
|
||||
# Clean the checkout before remove_curl_install_files. A script that lives in
|
||||
# ~/.local/share/vocalinux-install is both the checkout and the curl clone, and
|
||||
# ~/.local/share/voculinux-install is both the checkout and the curl clone, and
|
||||
# that step deletes the directory.
|
||||
if [[ -n "$SOURCE_CHECKOUT" ]]; then
|
||||
cleanup_build_artifacts "$SOURCE_CHECKOUT"
|
||||
|
||||
Reference in New Issue
Block a user