Fix updater interface: pass desktop_arch_path in args

This also adds a lot of type hints. I refrained from changing a lot
of 'str' variables to Path variables, but eventually I think they
will need to become Paths
This commit is contained in:
Dave Dalcino
2022-07-27 22:13:03 -07:00
parent 861a3d6b61
commit 94ff9f44f7
2 changed files with 30 additions and 17 deletions

View File

@@ -20,9 +20,9 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import logging
import os
import pathlib
import subprocess
from logging import getLogger
from pathlib import Path
from typing import Optional
import patch
@@ -41,13 +41,13 @@ def unpatched_path(os_name: str, final_component: str) -> str:
class Updater:
def __init__(self, prefix: pathlib.Path, logger):
def __init__(self, prefix: Path, logger):
self.logger = logger
self.prefix = prefix
self.qmake_path = None
self.qconfigs = {}
def _patch_binfile(self, file: pathlib.Path, key: bytes, newpath: bytes):
def _patch_binfile(self, file: Path, key: bytes, newpath: bytes):
"""Patch binary file with key/value"""
st = file.stat()
data = file.read_bytes()
@@ -62,7 +62,7 @@ class Updater:
file.write_bytes(data)
os.chmod(str(file), st.st_mode)
def _append_string(self, file: pathlib.Path, val: str):
def _append_string(self, file: Path, val: str):
"""Append string to file"""
st = file.stat()
data = file.read_text("UTF-8")
@@ -70,7 +70,7 @@ class Updater:
file.write_text(data, "UTF-8")
os.chmod(str(file), st.st_mode)
def _patch_textfile(self, file: pathlib.Path, old: str, new: str):
def _patch_textfile(self, file: Path, old: str, new: str):
st = file.stat()
data = file.read_text("UTF-8")
data = data.replace(old, new)
@@ -167,10 +167,9 @@ class Updater:
newpath=bytes(str(self.prefix), "UTF-8"),
)
def patch_qmake_script(self, base_dir, qt_version: str, os_name):
arch_dir = default_desktop_arch_dir(os_name, qt_version)
def patch_qmake_script(self, base_dir, qt_version: str, os_name: str, desktop_arch_dir: str):
sep = "\\" if os_name == "windows" else "/"
patched = sep.join([base_dir, qt_version, arch_dir, "bin"])
patched = sep.join([base_dir, qt_version, desktop_arch_dir, "bin"])
unpatched = unpatched_path(os_name, "bin")
qmake_path = self.prefix / "bin" / ("qmake.bat" if os_name == "windows" else "qmake")
self.logger.info(f"Patching {qmake_path}")
@@ -211,7 +210,7 @@ class Updater:
f.write("cd /D {}\n".format(os.path.join(base_dir, qt_version, arch_dir)))
f.write("echo Remember to call vcvarsall.bat to complete environment setup!\n")
def set_license(self, base_dir, qt_version, arch_dir):
def set_license(self, base_dir: str, qt_version: str, arch_dir: str):
"""Update qtconfig.pri as OpenSource"""
with open(os.path.join(base_dir, qt_version, arch_dir, "mkspecs", "qconfig.pri"), "r+") as f:
lines = f.readlines()
@@ -224,21 +223,27 @@ class Updater:
line = "QT_LICHECK =\n"
f.write(line)
def patch_target_qt_conf(self, base_dir, qt_version, arch_dir, os_name):
def patch_target_qt_conf(self, base_dir: str, qt_version: str, arch_dir: str, os_name: str, desktop_arch_dir: str):
target_qt_conf = self.prefix / "bin" / "target_qt.conf"
old_targetprefix = f'Prefix={unpatched_path(os_name, "target")}'
new_hostprefix = f"HostPrefix=../../{default_desktop_arch_dir(os_name, qt_version)}"
new_targetprefix = "Prefix={}".format(str(pathlib.Path(base_dir).joinpath(qt_version, arch_dir, "target")))
new_hostprefix = f"HostPrefix=../../{desktop_arch_dir}"
new_targetprefix = "Prefix={}".format(str(Path(base_dir).joinpath(qt_version, arch_dir, "target")))
new_hostdata = "HostData=../{}".format(arch_dir)
self._patch_textfile(target_qt_conf, old_targetprefix, new_targetprefix)
self._patch_textfile(target_qt_conf, "HostPrefix=../../", new_hostprefix)
self._patch_textfile(target_qt_conf, "HostData=target", new_hostdata)
@classmethod
def update(cls, target: TargetConfig, base_dir: str):
def update(cls, target: TargetConfig, base_path: Path, installed_desktop_arch_dir: Optional[str]):
"""
Make Qt configuration files, qt.conf and qtconfig.pri.
And update pkgconfig and patch Qt5Core and qmake
:param installed_desktop_arch_dir: This is the path to a desktop Qt installation, like `Qt/6.3.0/mingw_win64`.
This may or may not contain an actual desktop Qt installation.
If it does not, the Updater will patch files in a mobile Qt installation
that point to this directory, and this installation will be non-functional
until the user installs a desktop Qt in this directory.
"""
logger = getLogger("aqt.updater")
arch = target.arch
@@ -246,8 +251,9 @@ class Updater:
os_name = target.os_name
version_dir = dir_for_version(version)
arch_dir = QtRepoProperty.get_arch_dir_name(os_name, arch, version)
base_dir = str(base_path)
try:
prefix = pathlib.Path(base_dir) / version_dir / arch_dir
prefix = base_path / version_dir / arch_dir
updater = Updater(prefix, logger)
updater.set_license(base_dir, version_dir, arch_dir)
if target.arch not in [
@@ -274,8 +280,14 @@ class Updater:
elif version in SimpleSpec(">=5.0,<6.0"):
updater.patch_qmake()
else: # qt6 non-desktop
updater.patch_qmake_script(base_dir, version_dir, target.os_name)
updater.patch_target_qt_conf(base_dir, version_dir, arch_dir, target.os_name)
desktop_arch_dir = (
installed_desktop_arch_dir
if installed_desktop_arch_dir is not None
else default_desktop_arch_dir(os_name, version)
)
updater.patch_qmake_script(base_dir, version_dir, target.os_name, desktop_arch_dir)
updater.patch_target_qt_conf(base_dir, version_dir, arch_dir, target.os_name, desktop_arch_dir)
except IOError as e:
raise UpdaterError(f"Updater caused an IO error: {e}") from e

View File

@@ -1,4 +1,5 @@
import re
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
@@ -58,7 +59,7 @@ def test_updater_update_license_io_error(monkeypatch, target_config: TargetConfi
with pytest.raises(UpdaterError) as err:
with TemporaryDirectory() as empty_dir:
# Try to update a Qt installation that does not exist
Updater.update(target_config, base_dir=empty_dir)
Updater.update(target_config, base_path=Path(empty_dir), installed_desktop_arch_dir=None)
assert err.type == UpdaterError
err_msg = format(err.value)
assert expected_err_pattern.match(err_msg)