From a9a394cf7dc4788451ed16b29b273c6915cdaf09 Mon Sep 17 00:00:00 2001 From: benya Date: Sun, 15 Feb 2026 20:38:24 +0300 Subject: [PATCH] fix(update): improve updater script reliability for 1.7.0 - quote env vars in cmd script for paths with spaces - add update_error.log diagnostics and timeout while waiting for app exit - bump APP_VERSION to 1.7.0 and update updater tests --- app_version.py | 2 +- services/auto_update_service.py | 34 ++++++++++++++++++++++--------- tests/test_auto_update_service.py | 9 ++++---- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/app_version.py b/app_version.py index 09dd4ed..ea1631a 100644 --- a/app_version.py +++ b/app_version.py @@ -1 +1 @@ -APP_VERSION = "1.6.4" +APP_VERSION = "1.7.0" diff --git a/services/auto_update_service.py b/services/auto_update_service.py index daaabaf..d6c08eb 100644 --- a/services/auto_update_service.py +++ b/services/auto_update_service.py @@ -86,39 +86,53 @@ class AutoUpdateService: script_path = os.path.join(tempfile.gettempdir(), "anabasis_apply_update.cmd") script_lines = [ "@echo off", - "setlocal", - f"set APP_DIR={app_dir}", - f"set SRC_DIR={source_dir}", - f"set EXE_NAME={exe_name}", - f"set TARGET_PID={target_pid}", - "set BACKUP_DIR=%TEMP%\\anabasis_backup_%RANDOM%%RANDOM%", + "setlocal EnableExtensions", + f"set \"APP_DIR={app_dir}\"", + f"set \"SRC_DIR={source_dir}\"", + f"set \"EXE_NAME={exe_name}\"", + f"set \"TARGET_PID={target_pid}\"", + "set \"BACKUP_DIR=%TEMP%\\anabasis_backup_%RANDOM%%RANDOM%\"", + "set \"UPDATE_LOG=%APP_DIR%\\update_error.log\"", + "echo [%DATE% %TIME%] Update start > \"%UPDATE_LOG%\"", + "if not exist \"%SRC_DIR%\\%EXE_NAME%\" (", + " echo Source executable not found: \"%SRC_DIR%\\%EXE_NAME%\" >> \"%UPDATE_LOG%\"", + " exit /b 3", + ")", + "set /a WAIT_LOOPS=0", ":wait_for_exit", "tasklist /FI \"PID eq %TARGET_PID%\" | find \"%TARGET_PID%\" >nul", "if %ERRORLEVEL% EQU 0 (", + " set /a WAIT_LOOPS+=1", + " if %WAIT_LOOPS% GEQ 180 (", + " echo Timeout waiting for process %TARGET_PID% to exit >> \"%UPDATE_LOG%\"", + " goto :backup", + " )", " timeout /t 1 /nobreak >nul", " goto :wait_for_exit", ")", + ":backup", "timeout /t 1 /nobreak >nul", "mkdir \"%BACKUP_DIR%\" >nul 2>&1", "robocopy \"%APP_DIR%\" \"%BACKUP_DIR%\" /E /NFL /NDL /NJH /NJS /NP /R:6 /W:2 >nul", - "set RC=%ERRORLEVEL%", + "set \"RC=%ERRORLEVEL%\"", "if %RC% GEQ 8 goto :backup_error", "robocopy \"%SRC_DIR%\" \"%APP_DIR%\" /E /NFL /NDL /NJH /NJS /NP /R:12 /W:2 >nul", - "set RC=%ERRORLEVEL%", + "set \"RC=%ERRORLEVEL%\"", "if %RC% GEQ 8 goto :rollback", "start \"\" \"%APP_DIR%\\%EXE_NAME%\"", "timeout /t 2 /nobreak >nul", "tasklist /FI \"IMAGENAME eq %EXE_NAME%\" | find /I \"%EXE_NAME%\" >nul", "if %ERRORLEVEL% NEQ 0 goto :rollback", + "echo Update success >> \"%UPDATE_LOG%\"", "rmdir /S /Q \"%BACKUP_DIR%\" >nul 2>&1", "exit /b 0", ":rollback", "robocopy \"%BACKUP_DIR%\" \"%APP_DIR%\" /E /NFL /NDL /NJH /NJS /NP /R:6 /W:2 >nul", "start \"\" \"%APP_DIR%\\%EXE_NAME%\"", - "echo Auto-update failed. Rollback executed. > \"%APP_DIR%\\update_error.log\"", + "echo Auto-update failed. Rollback executed. >> \"%UPDATE_LOG%\"", "exit /b 2", ":backup_error", - "echo Auto-update failed during backup. Code %RC% > \"%APP_DIR%\\update_error.log\"", + "echo Auto-update failed during backup. Code %RC% >> \"%UPDATE_LOG%\"", "exit /b %RC%", ] with open(script_path, "w", encoding="utf-8", newline="\r\n") as f: diff --git a/tests/test_auto_update_service.py b/tests/test_auto_update_service.py index 37fbbc9..8d2f0f7 100644 --- a/tests/test_auto_update_service.py +++ b/tests/test_auto_update_service.py @@ -39,11 +39,12 @@ class AutoUpdateServiceTests(unittest.TestCase): target_pid=1234, ) script_text = Path(script).read_text(encoding="utf-8") - self.assertIn("set APP_DIR=", script_text) - self.assertIn("set SRC_DIR=", script_text) - self.assertIn("set EXE_NAME=", script_text) - self.assertIn("set TARGET_PID=", script_text) + self.assertIn("set \"APP_DIR=", script_text) + self.assertIn("set \"SRC_DIR=", script_text) + self.assertIn("set \"EXE_NAME=", script_text) + self.assertIn("set \"TARGET_PID=", script_text) self.assertIn(":rollback", script_text) + self.assertIn("if not exist \"%SRC_DIR%\\%EXE_NAME%\"", script_text) if __name__ == "__main__":