From d26b6a47b76750626098aad7290e6d31e7de52f5 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Tue, 17 Oct 2023 16:48:56 +0300 Subject: [PATCH 1/4] unload plugin and free library before upgrading --- Mergin/plugin.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Mergin/plugin.py b/Mergin/plugin.py index cd81f52b..6981c00b 100644 --- a/Mergin/plugin.py +++ b/Mergin/plugin.py @@ -67,9 +67,34 @@ from .processing.provider import MerginProvider import processing +from pyplugin_installer.qgsplugininstallerinstallingdialog import QgsPluginInstallerInstallingDialog + MERGIN_CLIENT_LOG = os.path.join(QgsApplication.qgisSettingsDirPath(), "mergin-client-log.txt") os.environ["MERGIN_CLIENT_LOG"] = MERGIN_CLIENT_LOG +# store method that will be monkeypatched +_original_method = QgsPluginInstallerInstallingDialog.requestFinished + + +def request_finished(self): + """ + On Windows we need to release lock on geodiff library and unload plugin before + performing an update. See https://github.com/MerginMaps/qgis-mergin-plugin/issues/504 + and https://github.com/MerginMaps/geodiff/issues/205 + """ + if self.plugin["id"] == "Mergin" and os.name == "nt": + from _ctypes import FreeLibrary + from .mergin.deps import pygeodiff + + geodiff = pygeodiff.GeoDiff() + FreeLibrary(geodiff.clib.lib._handle) + + from qgis.utils import unloadPlugin + + res = unloadPlugin(self.plugin["id"]) + + _original_method(self) + class MerginPlugin: def __init__(self, iface): @@ -185,6 +210,11 @@ def initGui(self): QgsProject.instance().layersAdded.connect(self.add_context_menu_actions) + # monkeypatch plugin installer to allow unlocking geodiff library and unloading plugin before installing + # see https://github.com/MerginMaps/qgis-mergin-plugin/issues/504, https://github.com/MerginMaps/geodiff/issues/205 + if os.name == "nt": + QgsPluginInstallerInstallingDialog.requestFinished = request_finished + def add_action( self, icon_name, @@ -547,6 +577,10 @@ def unload(self): QgsApplication.processingRegistry().removeProvider(self.provider) + # revert monkeypatching + if os.name == "nt": + QgsPluginInstallerInstallingDialog.requestFinished = _original_method + def view_local_changes(self): project_path = QgsProject.instance().homePath() if not project_path: From 059cb68273805539378cfa608bbf777f42fa7624 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Wed, 18 Oct 2023 16:25:40 +0300 Subject: [PATCH 2/4] patch another method --- Mergin/plugin.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Mergin/plugin.py b/Mergin/plugin.py index 6981c00b..c53ab1ab 100644 --- a/Mergin/plugin.py +++ b/Mergin/plugin.py @@ -67,33 +67,27 @@ from .processing.provider import MerginProvider import processing -from pyplugin_installer.qgsplugininstallerinstallingdialog import QgsPluginInstallerInstallingDialog +from pyplugin_installer.installer import QgsPluginInstaller MERGIN_CLIENT_LOG = os.path.join(QgsApplication.qgisSettingsDirPath(), "mergin-client-log.txt") os.environ["MERGIN_CLIENT_LOG"] = MERGIN_CLIENT_LOG # store method that will be monkeypatched -_original_method = QgsPluginInstallerInstallingDialog.requestFinished +_original_method = QgsPluginInstaller.installPlugin -def request_finished(self): +def install_plugin(self, key, quiet=False, stable=True): """ On Windows we need to release lock on geodiff library and unload plugin before performing an update. See https://github.com/MerginMaps/qgis-mergin-plugin/issues/504 and https://github.com/MerginMaps/geodiff/issues/205 """ - if self.plugin["id"] == "Mergin" and os.name == "nt": - from _ctypes import FreeLibrary - from .mergin.deps import pygeodiff - - geodiff = pygeodiff.GeoDiff() - FreeLibrary(geodiff.clib.lib._handle) - + if key == "Mergin" and os.name == "nt": from qgis.utils import unloadPlugin - res = unloadPlugin(self.plugin["id"]) + unloadPlugin(key) - _original_method(self) + _original_method(self, key, quiet, stable) class MerginPlugin: @@ -213,7 +207,7 @@ def initGui(self): # monkeypatch plugin installer to allow unlocking geodiff library and unloading plugin before installing # see https://github.com/MerginMaps/qgis-mergin-plugin/issues/504, https://github.com/MerginMaps/geodiff/issues/205 if os.name == "nt": - QgsPluginInstallerInstallingDialog.requestFinished = request_finished + QgsPluginInstaller.installPlugin = install_plugin def add_action( self, @@ -577,9 +571,15 @@ def unload(self): QgsApplication.processingRegistry().removeProvider(self.provider) - # revert monkeypatching + # unlock geodiff library and revert monkeypatching if os.name == "nt": - QgsPluginInstallerInstallingDialog.requestFinished = _original_method + from _ctypes import FreeLibrary + from .mergin.deps import pygeodiff + + geodiff = pygeodiff.GeoDiff() + FreeLibrary(geodiff.clib.lib._handle) + + QgsPluginInstaller.installPlugin = _original_method def view_local_changes(self): project_path = QgsProject.instance().homePath() From e8484d33724a17242e3704a4bca898ba708c3f36 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Thu, 19 Oct 2023 15:35:40 +0300 Subject: [PATCH 3/4] try to delete file first, if failed try to unload library --- Mergin/plugin.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Mergin/plugin.py b/Mergin/plugin.py index c53ab1ab..a22ab415 100644 --- a/Mergin/plugin.py +++ b/Mergin/plugin.py @@ -573,11 +573,17 @@ def unload(self): # unlock geodiff library and revert monkeypatching if os.name == "nt": - from _ctypes import FreeLibrary - from .mergin.deps import pygeodiff - - geodiff = pygeodiff.GeoDiff() - FreeLibrary(geodiff.clib.lib._handle) + try: + lib_path = os.path.join(os.path.dirname(__file__), "mergin", "deps", "pygeodiff") + for f in os.listdir(lib_path): + if f.lower().endswith(".pyd"): + os.remove(os.path.join(lib_path, f)) + except: + from _ctypes import FreeLibrary + from .mergin.deps import pygeodiff + + geodiff = pygeodiff.GeoDiff() + FreeLibrary(geodiff.clib.lib._handle) QgsPluginInstaller.installPlugin = _original_method From a73a62c155729e12d7b6fc8c6bf540d32c9b5ea7 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Thu, 19 Oct 2023 16:06:02 +0300 Subject: [PATCH 4/4] Revert "try to delete file first, if failed try to unload library" This reverts commit e8484d33724a17242e3704a4bca898ba708c3f36. --- Mergin/plugin.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Mergin/plugin.py b/Mergin/plugin.py index a22ab415..c53ab1ab 100644 --- a/Mergin/plugin.py +++ b/Mergin/plugin.py @@ -573,17 +573,11 @@ def unload(self): # unlock geodiff library and revert monkeypatching if os.name == "nt": - try: - lib_path = os.path.join(os.path.dirname(__file__), "mergin", "deps", "pygeodiff") - for f in os.listdir(lib_path): - if f.lower().endswith(".pyd"): - os.remove(os.path.join(lib_path, f)) - except: - from _ctypes import FreeLibrary - from .mergin.deps import pygeodiff - - geodiff = pygeodiff.GeoDiff() - FreeLibrary(geodiff.clib.lib._handle) + from _ctypes import FreeLibrary + from .mergin.deps import pygeodiff + + geodiff = pygeodiff.GeoDiff() + FreeLibrary(geodiff.clib.lib._handle) QgsPluginInstaller.installPlugin = _original_method