From 8232420c220858fca9578bc14f3c5726fa495376 Mon Sep 17 00:00:00 2001 From: Jan Feil <11638228+jfeil@users.noreply.github.com> Date: Thu, 11 May 2023 22:48:48 +0200 Subject: [PATCH] Fix self updater --- RegeltestCreator.pyw | 53 ++++++++++++++++++++++++++++++++++++++++++- RegeltestCreator.spec | 2 +- requirements.txt | 3 ++- src/updater.py | 36 +++++++++-------------------- updater.sh | 17 -------------- 5 files changed, 66 insertions(+), 45 deletions(-) delete mode 100644 updater.sh diff --git a/RegeltestCreator.pyw b/RegeltestCreator.pyw index b827161..3c991d7 100644 --- a/RegeltestCreator.pyw +++ b/RegeltestCreator.pyw @@ -1,7 +1,13 @@ import logging +import os +import shutil import sys +import time -from PySide6.QtWidgets import QApplication +import psutil +from PySide6.QtCore import Signal, QThread +from PySide6.QtGui import Qt +from PySide6.QtWidgets import QApplication, QDialog, QVBoxLayout, QLabel from src.basic_config import log_level from src.database import db @@ -12,8 +18,53 @@ logging.getLogger('sqlalchemy.engine').setLevel(log_level) logging.getLogger().setLevel(log_level) +class UpdateWorker(QThread): + finished = Signal() + + def __init__(self, original_path: str, old_pid: int): + self.original_path = original_path + self.old_pid = old_pid + + super().__init__() + + def run(self): + while psutil.pid_exists(self.old_pid): + time.sleep(0.2) + os.remove(self.original_path) + shutil.copy(sys.executable, self.original_path) + self.finished.emit() + + +class UpdateFinishDialog(QDialog): + def __init__(self, original_path: str, old_pid: str): + super().__init__() + self.setWindowTitle("Update abschließen") + self.setModal(True) + self.setFixedSize(300, 100) + + layout = QVBoxLayout(self) + self.label = QLabel("Letzte Update-Schritte durchführen...", self) + self.label.setAlignment(Qt.AlignCenter) + layout.addWidget(self.label) + + self.worker = UpdateWorker(original_path, int(old_pid)) + self.worker.finished.connect(self.close) + self.worker.start() + + def closeEvent(self, event): + # Prevent closing the dialog while the background task is running + if self.worker.isRunning(): + event.ignore() + else: + event.accept() + + def run(): app = QApplication(sys.argv) + if len(sys.argv) == 3: + test = UpdateFinishDialog(sys.argv[1], sys.argv[2]) + test.exec() + pass main_window = MainWindow() main_window.initialize() main_window.show() diff --git a/RegeltestCreator.spec b/RegeltestCreator.spec index 1e01d12..56f76f2 100644 --- a/RegeltestCreator.spec +++ b/RegeltestCreator.spec @@ -7,7 +7,7 @@ block_cipher = None a = Analysis(['RegeltestCreator.pyw'], pathex=[], binaries=[], - datas=[('alembic', 'alembic'), ('alembic.ini', '.'), ('updater.sh', '.')], + datas=[('alembic', 'alembic'), ('alembic.ini', '.')], hiddenimports=['logging.config'], hookspath=[], runtime_hooks=[], diff --git a/requirements.txt b/requirements.txt index 6a2feb6..308bb21 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,4 +11,5 @@ markdown2==2.4.3 lxml==4.9.1 Jinja2==3.1.2 alembic==1.8.1 -aiohttp~=3.8.4 \ No newline at end of file +aiohttp~=3.8.4 +psutil~=5.9.5 \ No newline at end of file diff --git a/src/updater.py b/src/updater.py index fe0447a..a30c3ca 100644 --- a/src/updater.py +++ b/src/updater.py @@ -1,6 +1,5 @@ import os import shutil -import stat import subprocess import sys from typing import Optional @@ -10,7 +9,7 @@ from PySide6.QtCore import Signal, QThread, Qt from PySide6.QtWidgets import QDialog, QMessageBox -from src.basic_config import app_dirs, current_platform, base_path, is_bundled +from src.basic_config import app_dirs, current_platform, is_bundled from src.ui_update_checker import Ui_UpdateChecker @@ -65,27 +64,6 @@ def display(self): f'{release_notes}{download_link}') def update(self) -> None: - def install_update(): - updater_script_unix = "updater.sh" - os.rename(os.path.join(base_path, updater_script_unix), - os.path.join(app_dirs.user_cache_dir, updater_script_unix)) - if current_platform == 'Darwin' or current_platform == 'Linux': - os.chmod(os.path.join(app_dirs.user_cache_dir, updater_script_unix), - stat.S_IXUSR | stat.S_IRUSR) - os.chmod(os.path.join(app_dirs.user_cache_dir, executable_name), - stat.S_IXUSR | stat.S_IRUSR) - - if current_platform == 'Windows': - command = f'timeout 10 & ' \ - f'copy "{download_path}" "{sys.executable}" & ' \ - f'del "{download_path}" & ' \ - f'"{sys.executable}"' - subprocess.Popen(command, shell=True) - elif current_platform == 'Darwin' or current_platform == 'Linux': - subprocess.Popen(" ".join([os.path.join(app_dirs.user_cache_dir, updater_script_unix), - sys.executable, str(os.getpid()), download_path]), shell=True) - sys.exit(0) - def progressbar_tracking(value): self.ui.download_progress.setValue(value) if value != 100: @@ -97,7 +75,8 @@ def progressbar_tracking(value): info_box.setInformativeText("Dabei wird die Applikation beendet und nach " "erfolgreichem Update erneut gestartet.") info_box.exec() - install_update() + subprocess.Popen([download_path, sys.executable, str(os.getpid())]) + sys.exit(0) if not self.download_link: return @@ -109,12 +88,19 @@ def progressbar_tracking(value): if not os.path.isdir(app_dirs.user_cache_dir): os.makedirs(app_dirs.user_cache_dir) - path, executable_name = os.path.split(sys.executable) + executable_name = "RegeltestCreator" + + if current_platform == 'Darwin': + executable_name += ".app.zip" + elif current_platform == 'Windows': + executable_name += ".exe" download_path = os.path.join(app_dirs.user_cache_dir, executable_name) request = requests.get(self.download_link, stream=True) filesize = request.headers['Content-Length'] + if os.path.isfile(download_path): + os.remove(download_path) file_handle = open(download_path, 'wb+') downloadThread = DownloadThread(request, filesize, file_handle, buffer=10240) downloadThread.download_progress.connect(progressbar_tracking) diff --git a/updater.sh b/updater.sh deleted file mode 100644 index 05d2137..0000000 --- a/updater.sh +++ /dev/null @@ -1,17 +0,0 @@ -echo "Waiting 10 seconds to close the application..." -sleep 10s -# get Program process -echo "Checking if it is closed..." -if ps -p "$2" > /dev/null -then - echo "Force closing the programm..." - kill "$2" - sleep 5s - # Do something knowing the pid exists, i.e. the process with $PID is running -fi -echo "Deleting the old executable..." -rm "$1" -echo "Moving the new executable..." -mv "$3" "$1" -echo "Done! Starting the closed app!" -"$1" \ No newline at end of file