Created
February 13, 2025 09:13
-
-
Save BradKML/b84675c356007c8029ce927c484f4cc6 to your computer and use it in GitHub Desktop.
Draft of an alternative Cursor WSL fixer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# ================================================================= | |
# Cursor WSL Fix Installation Script v1.2 | |
# Combines solutions from @ddwang and @swayducky | |
# With additional process management and safety features | |
# ================================================================= | |
# Color codes for output | |
RED='\033[0;31m' | |
GREEN='\033[0;32m' | |
YELLOW='\033[1;33m' | |
BLUE='\033[0;34m' | |
NC='\033[0m' | |
# Print functions | |
print_status() { echo -e "${GREEN}[+]${NC} $1"; } | |
print_error() { echo -e "${RED}[!]${NC} $1"; } | |
print_warning() { echo -e "${YELLOW}[*]${NC} $1"; } | |
print_info() { echo -e "${BLUE}[i]${NC} $1"; } | |
# Define common paths and variables | |
POWERSHELL="/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" | |
if [ ! -x "$POWERSHELL" ]; then | |
POWERSHELL="/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe" # Alternative path | |
fi | |
# Script version for tracking | |
SCRIPT_VERSION="1.2" | |
SCRIPT_DATE="2024-02-13" | |
# Check if we're in a devcontainer with improved detection | |
IN_DEVCONTAINER=false | |
if [ -f /.dockerenv ] || [ -f /run/.containerenv ] || [ -d /home/devcontainers ] || \ | |
[ -n "$REMOTE_CONTAINERS" ] || [ -n "$CODESPACES" ] || [ -n "$DEVCONTAINER" ]; then | |
IN_DEVCONTAINER=true | |
fi | |
# Verify WSL environment | |
verify_wsl() { | |
if ! grep -qi microsoft /proc/version && ! grep -qi wsl /proc/version; then | |
print_error "This script must be run in WSL" | |
return 1 | |
fi | |
return 0 | |
} | |
# Verify root privileges | |
verify_root() { | |
if [ "$EUID" -ne 0 ]; then | |
print_error "Please run this script with sudo" | |
return 1 | |
fi | |
return 0 | |
} | |
# Function to run PowerShell commands safely with improved error handling | |
run_powershell() { | |
local cmd="$1" | |
local error_msg="${2:-PowerShell command failed}" | |
if [ ! -x "$POWERSHELL" ]; then | |
print_error "PowerShell not found at expected locations" | |
return 1 | |
fi | |
local output | |
if ! output=$("$POWERSHELL" -Command "$cmd" 2>&1); then | |
print_error "$error_msg: $output" | |
return 1 | |
fi | |
echo "$output" | |
return 0 | |
} | |
# Get current non-root user with validation | |
get_real_user() { | |
local real_user | |
if [ -n "$SUDO_USER" ]; then | |
real_user="$SUDO_USER" | |
else | |
real_user=$(whoami) | |
fi | |
# Verify user exists and is not root | |
if ! id "$real_user" >/dev/null 2>&1 || [ "$real_user" = "root" ]; then | |
print_error "Could not determine valid non-root user" | |
return 1 | |
fi | |
echo "$real_user" | |
return 0 | |
} | |
# Get Windows username with improved detection and validation | |
get_windows_user() { | |
local win_user | |
local system_dirs=("All Users" "Default" "Default User" "Public" "desktop.ini" "Administrator") | |
local cursor_found=false | |
print_info "Detecting Windows username..." | |
# Method 1: Direct CMD query with verification | |
win_user=$(cmd.exe /c "echo %USERNAME%" 2>/dev/null | tr -d '\r\n') | |
if [ -n "$win_user" ] && [ -d "/mnt/c/Users/${win_user}" ] && \ | |
[ -d "/mnt/c/Users/${win_user}/AppData/Local/Programs/cursor" ]; then | |
print_info "Found Cursor installation for user: $win_user (Method 1)" | |
echo "$win_user" | |
return 0 | |
fi | |
# Method 2: Search Users directory for Cursor installation | |
print_info "Searching for Cursor installation in user directories..." | |
for user_dir in /mnt/c/Users/*; do | |
local dirname=$(basename "$user_dir") | |
# Skip system directories | |
local is_system_dir=false | |
for sys_dir in "${system_dirs[@]}"; do | |
if [ "$dirname" = "$sys_dir" ]; then | |
is_system_dir=true | |
break | |
fi | |
done | |
if [ "$is_system_dir" = true ]; then | |
continue | |
fi | |
# Check for Cursor installation | |
if [ -d "$user_dir/AppData/Local/Programs/cursor" ]; then | |
print_info "Found Cursor installation for user: $dirname (Method 2)" | |
cursor_found=true | |
win_user="$dirname" | |
break | |
fi | |
done | |
if [ "$cursor_found" = true ]; then | |
echo "$win_user" | |
return 0 | |
fi | |
# If we get here, we couldn't find the installation | |
print_error "Could not find Cursor installation in any user directory" | |
print_info "Checked directories in /mnt/c/Users/:" | |
for user_dir in /mnt/c/Users/*; do | |
local dirname=$(basename "$user_dir") | |
local is_system_dir=false | |
for sys_dir in "${system_dirs[@]}"; do | |
if [ "$dirname" = "$sys_dir" ]; then | |
is_system_dir=true | |
break | |
fi | |
done | |
if [ "$is_system_dir" = false ]; then | |
print_info " - $dirname" | |
fi | |
done | |
return 1 | |
} | |
# Check dependencies with improved validation | |
check_dependencies() { | |
local deps=("wget" "curl") | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
deps+=("cron") | |
else | |
deps+=("systemctl") | |
fi | |
local missing_deps=() | |
local installed_deps=() | |
print_info "Checking dependencies..." | |
# Check PowerShell separately | |
if ! command -v "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" >/dev/null 2>&1 && \ | |
! command -v "/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe" >/dev/null 2>&1; then | |
print_error "PowerShell not found in expected Windows locations" | |
return 1 | |
fi | |
# Check other dependencies | |
for dep in "${deps[@]}"; do | |
if ! command -v "$dep" >/dev/null 2>&1; then | |
missing_deps+=("$dep") | |
else | |
installed_deps+=("$dep") | |
fi | |
done | |
# Report status | |
if [ ${#installed_deps[@]} -gt 0 ]; then | |
print_status "Found dependencies: ${installed_deps[*]}" | |
fi | |
if [ ${#missing_deps[@]} -ne 0 ]; then | |
print_warning "Missing dependencies: ${missing_deps[*]}" | |
print_info "Installing missing dependencies..." | |
# Update package list if it's older than 1 hour | |
if [ ! -f "/var/cache/apt/pkgcache.bin" ] || \ | |
[ "$(stat -c %Y /var/cache/apt/pkgcache.bin)" -lt "$(( $(date +%s) - 3600 ))" ]; then | |
print_info "Updating package list..." | |
if ! apt-get update; then | |
print_error "Failed to update package list" | |
return 1 | |
fi | |
fi | |
if ! apt-get install -y "${missing_deps[@]}"; then | |
print_error "Failed to install dependencies" | |
return 1 | |
fi | |
print_status "Successfully installed missing dependencies" | |
fi | |
# Verify cron service in devcontainer | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
print_info "Checking cron service..." | |
if ! service cron status >/dev/null 2>&1; then | |
print_warning "Cron service is not running" | |
if ! service cron start; then | |
print_error "Failed to start cron service" | |
return 1 | |
fi | |
print_status "Successfully started cron service" | |
fi | |
fi | |
return 0 | |
} | |
# Check and handle running Cursor instances with improved process management | |
check_cursor_process() { | |
print_info "Checking for running Cursor instances..." | |
# Try to find Cursor process in Windows | |
local cursor_running | |
local check_attempts=0 | |
local max_attempts=3 | |
while [ $check_attempts -lt $max_attempts ]; do | |
if ! cursor_running=$(run_powershell "Get-Process cursor -ErrorAction SilentlyContinue"); then | |
((check_attempts++)) | |
if [ $check_attempts -eq $max_attempts ]; then | |
print_warning "Could not check Cursor process status after $max_attempts attempts. Proceeding anyway..." | |
return 0 | |
fi | |
sleep 1 | |
continue | |
fi | |
break | |
done | |
if [ -n "$cursor_running" ]; then | |
print_warning "Cursor is currently running in Windows" | |
print_info "Process details:" | |
run_powershell "Get-Process cursor | Select-Object Id, ProcessName, StartTime, CPU | Format-Table -AutoSize" | |
# Ask user for action | |
while true; do | |
echo -e "${YELLOW}Choose an action:${NC}" | |
echo "1) Automatically close Cursor" | |
echo "2) I'll close it manually (wait)" | |
echo "3) Abort installation" | |
read -p "Enter choice [1-3]: " choice | |
case $choice in | |
1) | |
print_info "Attempting to close Cursor..." | |
if run_powershell "Stop-Process -Name cursor -Force -ErrorAction SilentlyContinue"; then | |
print_status "Successfully closed Cursor" | |
# Wait a moment to ensure process is fully terminated | |
sleep 2 | |
# Double-check if it's really closed | |
if [ -n "$(run_powershell "Get-Process cursor -ErrorAction SilentlyContinue")" ]; then | |
print_error "Failed to close Cursor completely. Please close it manually" | |
continue | |
fi | |
else | |
print_error "Failed to close Cursor automatically" | |
continue | |
fi | |
break | |
;; | |
2) | |
print_info "Waiting for you to close Cursor..." | |
local wait_dots=0 | |
while [ -n "$(run_powershell "Get-Process cursor -ErrorAction SilentlyContinue")" ]; do | |
echo -n "." | |
((wait_dots++)) | |
if [ $wait_dots -eq 60 ]; then | |
echo "" | |
print_warning "Still waiting for Cursor to close..." | |
wait_dots=0 | |
fi | |
sleep 1 | |
done | |
echo "" | |
print_status "Cursor has been closed" | |
break | |
;; | |
3) | |
print_error "Installation aborted by user" | |
exit 1 | |
;; | |
*) | |
print_error "Invalid choice. Please enter 1, 2, or 3" | |
;; | |
esac | |
done | |
else | |
print_status "No running Cursor instances found" | |
fi | |
} | |
# Verify Cursor is closed with improved checking | |
verify_cursor_closed() { | |
local max_attempts=5 | |
local attempt=1 | |
local check_interval=2 | |
print_info "Verifying Cursor is fully closed..." | |
while [ $attempt -le $max_attempts ]; do | |
local process_check | |
if ! process_check=$(run_powershell "Get-Process cursor -ErrorAction SilentlyContinue"); then | |
print_warning "Process check failed on attempt $attempt" | |
sleep $check_interval | |
((attempt++)) | |
continue | |
fi | |
if [ -z "$process_check" ]; then | |
print_status "Verified Cursor is not running" | |
return 0 | |
fi | |
print_warning "Attempt $attempt of $max_attempts: Cursor is still running..." | |
if [ $attempt -eq $max_attempts ]; then | |
print_error "Could not verify Cursor is closed after $max_attempts attempts" | |
return 1 | |
fi | |
sleep $check_interval | |
((attempt++)) | |
done | |
return 1 | |
} | |
# Verify Cursor installation with improved checks | |
verify_cursor_installation() { | |
local win_user=$1 | |
local cursor_path="/mnt/c/Users/${win_user}/AppData/Local/Programs/cursor" | |
local bin_path="${cursor_path}/resources/app/bin" | |
print_info "Verifying Cursor installation..." | |
# Check main installation directory | |
if [ ! -d "$cursor_path" ]; then | |
print_error "Cursor installation not found at $cursor_path" | |
print_info "Please ensure Cursor is installed in Windows first" | |
return 1 | |
fi | |
# Check bin directory | |
if [ ! -d "$bin_path" ]; then | |
print_error "Cursor bin directory not found at $bin_path" | |
print_info "Your Cursor installation might be corrupted" | |
return 1 | |
} | |
# Check for existing cursor script | |
if [ -f "${bin_path}/cursor" ]; then | |
print_status "Found existing cursor script" | |
# Verify file permissions | |
if [ ! -x "${bin_path}/cursor" ]; then | |
print_warning "Existing cursor script is not executable" | |
fi | |
else | |
print_info "No existing cursor script found - will create new one" | |
fi | |
print_status "Cursor installation verified successfully" | |
return 0 | |
} | |
# Create the fix-cursor script with improved error handling and logging | |
create_fix_script() { | |
local win_user=$1 | |
local script_path="/usr/local/sbin/fix-cursor" | |
local temp_script="${script_path}.tmp" | |
print_info "Creating fix-cursor script..." | |
# Create script in a temporary file first | |
cat > "$temp_script" << EOF | |
#!/bin/bash | |
# Configuration | |
CURSOR_BIN_PATH="/mnt/c/Users/${win_user}/AppData/Local/Programs/cursor/resources/app/bin" | |
SCRIPT_URL="https://gist.githubusercontent.com/swayducky/8ba8f2db156c7f445d562cdc12c0ddb4/raw/cursor" | |
BACKUP_SUFFIX=\$(date +%Y%m%d_%H%M%S) | |
BACKUP_DIR="\${HOME}/.cursor-backups" | |
LOG_DIR="\${HOME}/.cursor-fix/logs" | |
LAST_RUN_FILE="\${HOME}/.cursor-fix/last_run" | |
SCRIPT_VERSION="$SCRIPT_VERSION" | |
# Create necessary directories | |
mkdir -p "\${BACKUP_DIR}" "\${LOG_DIR}" "\$(dirname \${LAST_RUN_FILE})" | |
# Logging function with timestamps and log rotation | |
log() { | |
local max_log_size=5242880 # 5MB | |
local log_file="\${LOG_DIR}/cursor-fix.log" | |
local message="\$(date '+%Y-%m-%d %H:%M:%S') \$1" | |
# Rotate log if needed | |
if [ -f "\$log_file" ] && [ \$(stat -f%z "\$log_file" 2>/dev/null || stat -c%s "\$log_file") -gt \$max_log_size ]; then | |
mv "\$log_file" "\${log_file}.\${BACKUP_SUFFIX}" | |
gzip "\${log_file}.\${BACKUP_SUFFIX}" | |
fi | |
echo "\$message" >> "\$log_file" | |
echo "\$1" | |
} | |
# Error handling function with cleanup | |
handle_error() { | |
log "ERROR: \$1" | |
# Attempt to restore from backup if available | |
if [ -n "\$CURRENT_BACKUP" ] && [ -f "\$CURRENT_BACKUP" ]; then | |
log "Attempting to restore from backup \$CURRENT_BACKUP" | |
if cp "\$CURRENT_BACKUP" "\${CURSOR_BIN_PATH}/cursor"; then | |
log "Successfully restored from backup" | |
else | |
log "Failed to restore from backup" | |
fi | |
fi | |
exit 1 | |
} | |
# Check if we're in a devcontainer | |
IN_DEVCONTAINER=false | |
if [ -f /.dockerenv ] || [ -f /run/.containerenv ] || [ -d /home/devcontainers ] || \ | |
[ -n "\$REMOTE_CONTAINERS" ] || [ -n "\$CODESPACES" ] || [ -n "\$DEVCONTAINER" ]; then | |
IN_DEVCONTAINER=true | |
fi | |
# Check if Cursor is running (with devcontainer handling) | |
check_cursor_running() { | |
if [ "\$IN_DEVCONTAINER" = true ]; then | |
log "Running in devcontainer - skipping process check" | |
return 0 | |
fi | |
POWERSHELL="/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" | |
if [ ! -x "\$POWERSHELL" ]; then | |
POWERSHELL="/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe" | |
fi | |
if [ ! -x "\$POWERSHELL" ]; then | |
log "WARNING: PowerShell not accessible - skipping process check" | |
return 0 | |
fi | |
local max_attempts=3 | |
local attempt=1 | |
while [ \$attempt -le \$max_attempts ]; do | |
if [ -n "\$(\$POWERSHELL -Command "Get-Process cursor -ErrorAction SilentlyContinue")" ]; then | |
log "ERROR: Cursor is currently running. Please close it before running the fix" | |
return 1 | |
fi | |
((attempt++)) | |
sleep 1 | |
done | |
return 0 | |
} | |
# Process check with devcontainer handling | |
if [ "\$IN_DEVCONTAINER" = false ]; then | |
if ! check_cursor_running; then | |
handle_error "Please close Cursor before running the fix" | |
fi | |
fi | |
# Check if cursor binary directory exists | |
if [ ! -d "\${CURSOR_BIN_PATH}" ]; then | |
handle_error "Cursor installation not found at \${CURSOR_BIN_PATH}" | |
fi | |
# Backup existing cursor script | |
CURRENT_BACKUP="" | |
if [ -f "\${CURSOR_BIN_PATH}/cursor" ]; then | |
CURRENT_BACKUP="\${BACKUP_DIR}/cursor_\${BACKUP_SUFFIX}" | |
if ! cp "\${CURSOR_BIN_PATH}/cursor" "\$CURRENT_BACKUP"; then | |
handle_error "Failed to create backup" | |
fi | |
log "Created backup at \$CURRENT_BACKUP" | |
fi | |
# Download and install new script with verification | |
log "Downloading new cursor script..." | |
TEMP_SCRIPT="\${CURSOR_BIN_PATH}/cursor.tmp" | |
DOWNLOAD_SUCCESS=false | |
# Try wget first | |
if wget -q --spider "\$SCRIPT_URL" 2>/dev/null; then | |
if wget -O "\$TEMP_SCRIPT" "\$SCRIPT_URL" 2>/dev/null; then | |
DOWNLOAD_SUCCESS=true | |
fi | |
fi | |
# Try curl if wget fails | |
if [ "\$DOWNLOAD_SUCCESS" = false ]; then | |
if curl -s -f -I "\$SCRIPT_URL" >/dev/null; then | |
if curl -s "\$SCRIPT_URL" -o "\$TEMP_SCRIPT"; then | |
DOWNLOAD_SUCCESS=true | |
fi | |
fi | |
fi | |
if [ "\$DOWNLOAD_SUCCESS" = false ]; then | |
handle_error "Failed to download new cursor script" | |
fi | |
# Verify downloaded script | |
if [ ! -s "\$TEMP_SCRIPT" ]; then | |
handle_error "Downloaded script is empty" | |
fi | |
# Install new script | |
mv "\$TEMP_SCRIPT" "\${CURSOR_BIN_PATH}/cursor" || handle_error "Failed to install new script" | |
chmod +x "\${CURSOR_BIN_PATH}/cursor" || handle_error "Failed to set permissions" | |
# Clean up old server installations with backup | |
if [ -d "\${HOME}/.cursor-server" ]; then | |
local server_backup="\${HOME}/.cursor-server_\${BACKUP_SUFFIX}" | |
if ! mv "\${HOME}/.cursor-server" "\$server_backup"; then | |
log "Warning: Failed to backup old server installation" | |
else | |
log "Backed up old server installation to \$server_backup" | |
# Optional: Compress the backup | |
if command -v tar >/dev/null 2>&1; then | |
tar czf "\${server_backup}.tar.gz" "\$server_backup" && rm -rf "\$server_backup" | |
log "Compressed server backup to \${server_backup}.tar.gz" | |
fi | |
fi | |
fi | |
# Update last run timestamp and version | |
echo "\$(date '+%Y-%m-%d %H:%M:%S')" > "\$LAST_RUN_FILE" | |
echo "\$SCRIPT_VERSION" >> "\$LAST_RUN_FILE" | |
log "Successfully updated cursor script (version \$SCRIPT_VERSION)" | |
EOF | |
# Make the temporary script executable | |
chmod +x "$temp_script" || return 1 | |
# Move the temporary script to the final location | |
mv "$temp_script" "$script_path" || return 1 | |
print_status "Successfully created fix-cursor script" | |
return 0 | |
} | |
# Setup cron job with improved error handling and verification | |
setup_cron_job() { | |
local real_user=$1 | |
print_info "Setting up cron job for daily fixes..." | |
# Check if cron service is running | |
if ! service cron status >/dev/null 2>&1; then | |
print_warning "Cron service is not running" | |
if ! service cron start; then | |
print_error "Failed to start cron service" | |
return 1 | |
fi | |
print_status "Started cron service" | |
fi | |
# Create a temporary file for the new crontab | |
local temp_cron=$(mktemp) | |
# Get existing crontab | |
su - "$real_user" -c "crontab -l" > "$temp_cron" 2>/dev/null || echo "" > "$temp_cron" | |
# Remove any existing cursor fix entries | |
sed -i '/fix-cursor/d' "$temp_cron" | |
# Add new job with random minute to avoid system load spikes | |
local random_minute=$((RANDOM % 60)) | |
echo "$random_minute 4 * * * /usr/local/sbin/fix-cursor" >> "$temp_cron" | |
# Install new crontab | |
if ! su - "$real_user" -c "crontab $temp_cron"; then | |
rm -f "$temp_cron" | |
print_error "Failed to install crontab" | |
return 1 | |
fi | |
# Cleanup | |
rm -f "$temp_cron" | |
# Verify installation | |
if ! su - "$real_user" -c "crontab -l" | grep -q "fix-cursor"; then | |
print_error "Failed to verify cron job installation" | |
return 1 | |
fi | |
print_status "Cron job successfully configured to run daily at 4:$random_minute AM" | |
return 0 | |
} | |
# Create systemd service files with improved configuration and validation | |
create_systemd_services() { | |
local real_user=$1 | |
local user_home=$(eval echo ~${real_user}) | |
local systemd_dir="${user_home}/.config/systemd/user" | |
print_info "Creating systemd service files..." | |
# Create systemd directory with proper permissions | |
mkdir -p "$systemd_dir" | |
chmod 700 "$systemd_dir" | |
# Create service file with improved configuration | |
cat > "${systemd_dir}/cursor-fix.service" << 'EOFSERVICE' | |
[Unit] | |
Description=Cursor WSL Fix Monitor | |
After=network-online.target | |
Wants=network-online.target | |
StartLimitIntervalSec=300 | |
StartLimitBurst=3 | |
[Service] | |
Type=oneshot | |
ExecStart=/usr/local/sbin/fix-cursor | |
StandardOutput=append:/home/%u/.cursor-fix/logs/service.log | |
StandardError=append:/home/%u/.cursor-fix/logs/service.log | |
Restart=on-failure | |
RestartSec=30s | |
Environment="DISPLAY=:0" | |
# Security hardening | |
NoNewPrivileges=yes | |
ProtectSystem=full | |
ProtectHome=read-only | |
PrivateTmp=yes | |
[Install] | |
WantedBy=default.target | |
EOFSERVICE | |
# Create timer file with randomized start time | |
cat > "${systemd_dir}/cursor-fix.timer" << 'EOFTIMER' | |
[Unit] | |
Description=Check Cursor WSL Fix Daily | |
After=network-online.target | |
Wants=network-online.target | |
[Timer] | |
OnBootSec=5min | |
OnUnitActiveSec=1d | |
RandomizedDelaySec=1800 | |
Persistent=true | |
AccuracySec=1s | |
[Install] | |
WantedBy=timers.target | |
EOFTIMER | |
# Fix permissions | |
chown -R ${real_user}:${real_user} "${user_home}/.config/systemd" | |
# Verify service files | |
if [ ! -f "${systemd_dir}/cursor-fix.service" ] || [ ! -f "${systemd_dir}/cursor-fix.timer" ]; then | |
print_error "Failed to create systemd service files" | |
return 1 | |
fi | |
print_status "Successfully created systemd service files" | |
return 0 | |
} | |
# Add alias and environment setup to shell configuration with improved handling | |
add_shell_alias() { | |
local real_user=$1 | |
local user_home=$(eval echo ~${real_user}) | |
local shell_rc | |
local config_block=" | |
# Cursor WSL Fix Configuration | |
alias fix-cursor='/usr/local/sbin/fix-cursor' | |
export DONT_PROMPT_WSL_INSTALL=1 | |
# Cursor WSL Fix Path | |
if [ -d /usr/local/sbin ]; then | |
export PATH=\$PATH:/usr/local/sbin | |
fi | |
# Cursor WSL Fix Version | |
export CURSOR_FIX_VERSION=\"$SCRIPT_VERSION\" | |
" | |
print_info "Setting up shell configuration..." | |
# Determine shell configuration file | |
if [ -f "${user_home}/.zshrc" ]; then | |
shell_rc="${user_home}/.zshrc" | |
print_info "Using ZSH configuration" | |
else | |
shell_rc="${user_home}/.bashrc" | |
print_info "Using Bash configuration" | |
fi | |
# Create backup of shell configuration | |
if [ -f "$shell_rc" ]; then | |
cp "$shell_rc" "${shell_rc}.backup-$(date +%Y%m%d_%H%M%S)" | |
print_info "Created backup of shell configuration" | |
fi | |
# Remove any existing Cursor WSL Fix configuration | |
if grep -q "Cursor WSL Fix Configuration" "$shell_rc"; then | |
print_info "Removing existing Cursor configuration..." | |
sed -i '/# Cursor WSL Fix Configuration/,/# End Cursor WSL Fix Configuration/d' "$shell_rc" | |
fi | |
# Add new configuration block | |
echo -e "$config_block" >> "$shell_rc" | |
# Fix permissions | |
chown ${real_user}:${real_user} "$shell_rc" | |
chmod 644 "$shell_rc" | |
print_status "Successfully updated shell configuration" | |
return 0 | |
} | |
# Enable systemd service for user with improved error handling and verification | |
enable_systemd_service() { | |
local real_user=$1 | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
print_warning "Running in devcontainer environment - skipping systemd service setup" | |
return 0 | |
fi | |
print_info "Enabling systemd services..." | |
# Reload systemd daemon | |
if ! su - ${real_user} -c "systemctl --user daemon-reload"; then | |
print_warning "Failed to reload systemd daemon - attempting to continue" | |
fi | |
# Enable and start timer | |
local systemd_commands=( | |
"systemctl --user enable cursor-fix.timer" | |
"systemctl --user start cursor-fix.timer" | |
"systemctl --user enable cursor-fix.service" | |
) | |
for cmd in "${systemd_commands[@]}"; do | |
print_info "Running: $cmd" | |
if ! su - ${real_user} -c "$cmd"; then | |
print_error "Failed to execute: $cmd" | |
return 1 | |
fi | |
done | |
# Verify service status | |
if ! su - ${real_user} -c "systemctl --user status cursor-fix.timer" >/dev/null 2>&1; then | |
print_error "Failed to verify timer status" | |
return 1 | |
fi | |
print_status "Successfully enabled systemd services" | |
return 0 | |
} | |
# Main installation process with improved flow and error handling | |
main() { | |
trap cleanup ERR | |
local start_time=$(date +%s) | |
print_status "Starting Cursor WSL Fix installation (version $SCRIPT_VERSION)..." | |
# Get real user first | |
local real_user | |
if ! real_user=$(get_real_user); then | |
print_error "Failed to determine real user" | |
exit 1 | |
fi | |
# Initial environment checks | |
if ! verify_wsl || ! verify_root; then | |
exit 1 | |
fi | |
# Check for devcontainer environment | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
print_warning "======================================================" | |
print_warning "Running in a devcontainer environment" | |
print_warning "Some features will be limited:" | |
print_warning "- Systemd services will not be available" | |
print_warning "- Using cron job for automated fixes" | |
print_warning "- Some Windows process checks might be restricted" | |
print_warning "======================================================" | |
sleep 2 | |
fi | |
# Check dependencies | |
if ! check_dependencies; then | |
print_error "Failed to verify dependencies" | |
exit 1 | |
fi | |
# Get Windows username | |
local win_user | |
if ! win_user=$(get_windows_user); then | |
print_error "Failed to detect Windows username" | |
exit 1 | |
fi | |
print_status "Detected Windows username: $win_user" | |
# Verify Cursor installation | |
if ! verify_cursor_installation "$win_user"; then | |
exit 1 | |
fi | |
# Process checking | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
print_warning "Process checking might be limited in devcontainer environment" | |
print_info "Please ensure Cursor is closed manually before proceeding" | |
read -p "Press Enter to continue after closing Cursor..." | |
else | |
check_cursor_process | |
if ! verify_cursor_closed; then | |
print_error "Could not ensure Cursor is closed. Please close it manually and try again" | |
exit 1 | |
fi | |
fi | |
print_status "Proceeding with installation..." | |
# Create directories | |
local user_home=$(eval echo ~${real_user}) | |
mkdir -p "${user_home}/.cursor-fix/logs" "${user_home}/.cursor-fix/backup" | |
chown -R ${real_user}:${real_user} "${user_home}/.cursor-fix" | |
# Backup current cursor script | |
if [ -f "/usr/local/sbin/fix-cursor" ]; then | |
cp "/usr/local/sbin/fix-cursor" "${user_home}/.cursor-fix/backup/cursor.backup-$(date +%Y%m%d_%H%M%S)" | |
fi | |
# Installation steps | |
print_status "Creating fix-cursor script..." | |
if ! create_fix_script "$win_user"; then | |
print_error "Failed to create fix-cursor script" | |
exit 1 | |
fi | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
print_info "Setting up cron job for automated fixes..." | |
if ! setup_cron_job "$real_user"; then | |
print_warning "Failed to set up cron job - manual runs will be required" | |
fi | |
else | |
print_status "Creating systemd service files..." | |
if ! create_systemd_services "$real_user"; then | |
print_error "Failed to create systemd services" | |
exit 1 | |
fi | |
fi | |
print_status "Adding shell configuration..." | |
if ! add_shell_alias "$real_user"; then | |
print_error "Failed to update shell configuration" | |
exit 1 | |
fi | |
if [ "$IN_DEVCONTAINER" = false ]; then | |
print_status "Enabling systemd service..." | |
if ! enable_systemd_service "$real_user"; then | |
print_error "Failed to enable systemd service" | |
exit 1 | |
fi | |
fi | |
# Final process check before applying fix | |
print_status "Running initial fix..." | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
print_warning "Running fix in devcontainer environment - some features might be limited" | |
su - "$real_user" -c "/usr/local/sbin/fix-cursor" | |
else | |
if ! cursor_status=$(run_powershell "Get-Process cursor -ErrorAction SilentlyContinue"); then | |
print_warning "Could not check Cursor process status. Proceeding anyway..." | |
elif [ -n "$cursor_status" ]; then | |
print_error "Cursor was reopened during installation. Please close it and run 'fix-cursor' manually" | |
print_warning "Other components have been installed successfully" | |
exit 1 | |
else | |
su - "$real_user" -c "/usr/local/sbin/fix-cursor" | |
fi | |
fi | |
# Calculate installation time | |
local end_time=$(date +%s) | |
local duration=$((end_time - start_time)) | |
print_status "Installation complete! (Duration: ${duration}s)" | |
print_info "Logs are available in ~/.cursor-fix/logs/" | |
if [ "$IN_DEVCONTAINER" = true ]; then | |
print_warning "================================================================" | |
print_warning "Devcontainer Installation Notes:" | |
print_warning "1. The fix-cursor command is available but must be run manually" | |
print_warning "2. A cron job has been set up for daily fixes" | |
print_warning "3. Some Windows process checks may be limited" | |
print_warning "4. Please test the fix manually by running: fix-cursor" | |
print_warning "================================================================" | |
else | |
print_warning "Please restart your terminal or run: source ~/.bashrc (or ~/.zshrc)" | |
print_warning "The fix will be automatically applied daily and after system boot" | |
# Display service status | |
print_info "Checking service status..." | |
su - "$real_user" -c "systemctl --user status cursor-fix.timer" | |
fi | |
} | |
# Run main installation | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment