1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2023 Sandro Knauß <hefee@debian.org>
# SPDX-License-Identifier: LGPL-2.0-or-later
#INTROSPECTABLE: CONFIG-FILES pkgfile(qmlfiles) path(debian/qmldeps.overrides) path(debian/qmldeps.optional)
import logging
import os
import pathlib
import subprocess
import sys
import typing
from debian.debian_support import DpkgArchTable
PKGKDE_GETQMLDEPENDS = "pkgkde-getqmldepends"
sys.path.insert(0,'/usr/share/pkg-kde-tools')
parent_path = pathlib.Path(__file__).parent.absolute()
if parent_path not in ("/usr/bin", "/bin"):
sys.path.insert(0, str(parent_path))
PKGKDE_GETQMLDEPENDS = parent_path/"pkgkde-getqmldepends"
from pythonlib import qmldeps
logging.basicConfig(format='%(levelname).1s: %(module)s:%(lineno)d: %(message)s')
log = logging.getLogger()
log.setLevel(logging.INFO)
def qmlfiles_args(pkg_name: str) -> list[str | pathlib.Path]:
qmlfiles_path = pathlib.Path(f"debian/{pkg_name}.qmlfiles")
ret = []
multiarch = qmldeps.deb_host_multiarch()
replace_args = {
"${DEB_HOST_MULTIARCH}" : lambda x: multiarch,
"${QMLDEPS_AUTODETECT_MODULES}": autodetect_modules,
"${QMLDEPS_AUTODETECT_FILES}": autodetect_files,
"${QMLDEPS_AUTODETECT_SOURCE_FILES}": autodetect_source_files,
}
if qmlfiles_path.exists():
content = qmlfiles_path.read_text()
args = content.split()
for arg in args:
for test_arg,func in replace_args.items():
if test_arg == arg:
arg = func(pkg_name)
elif test_arg in arg:
arg = arg.replace(test_arg, func(pkg_name))
if "*" in arg:
ret.extend(pathlib.Path().glob(arg))
elif type(arg) == list:
ret.extend(arg)
else:
ret.append(arg)
return ret
def qt_version_from_files(files: list[str|pathlib.Path]) -> typing.Optional[str]:
qt_version = None
for path in files:
if qt_version:
break
if not isinstance(path, pathlib.Path):
continue
if not qt_version:
for p, ver in qt_versions.items():
if p in path.parts:
qt_version = ver
break
return qt_version
def autodetect_modules(pkg_name: str) -> list[pathlib.Path]:
"""returns a list of all qml module paths shipped within a binary package."""
return list(p.parent for p in pathlib.Path(f"debian/{pkg_name}").glob("**/qmldir"))
def autodetect_files(pkg_name: str) -> list[pathlib.Path]:
"""returns a list of all qml files shipped within a binnry package."""
return list(pathlib.Path(f"debian/{pkg_name}").glob("**/*.qml"))
def autodetect_source_files(pkg_name: str) -> list[pathlib.Path]:
"""returns a list of all qml modules that are shipped within the source package and all binary packages.
This function is mostly usefull for a single binary package mode.
pkg_name is not used. It needs the same arguments than the other autodetect functions."""
return list(pathlib.Path(".").glob("**/*.qml"))
qt_configs = qmldeps.get_config()
qt_versions = {i.qt_name: k for k,i in qt_configs.items()}
control = qmldeps.DebianControl(pathlib.Path("debian/control"))
single_pkg = control.isSinglePackage()
failed = False
getqmldepends_glob_args = sys.argv[1:]
arch_any = "-a" in getqmldepends_glob_args
arch_all = "-i" in getqmldepends_glob_args
try:
host_arch = os.environ["DEB_HOST_ARCH"]
except KeyError:
host_arch = subprocess.check_output(["dpkg-architecture", "-qDEB_HOST_ARCH"]).strip().decode()
archtable = DpkgArchTable.load_arch_table()
if not arch_any and not arch_all:
arch_any = True
arch_all = True
for pkg_name, pkg in control.packages.items():
archs = pkg.get("Architecture", "").split()
skip = True
if archs == []:
skip = False
elif arch_all and "all" in archs:
skip = False
elif arch_any and any(archtable.matches_architecture(host_arch, arch) for arch in archs):
skip = False
if skip:
continue
for qt_version, config_qt in qt_configs.items():
var_name = config_qt.substvar_name("Depends")
var = f"${{{var_name}}}"
for field in ("Depends", "Recommends", "Suggests"):
if var in pkg.get(field, ""):
break
else:
continue
break
else:
qt_version = None
extra_args = qmlfiles_args(pkg_name)
if not extra_args:
if root_path := autodetect_modules(pkg_name):
extra_args = ["-rootPath"] + root_path
if not extra_args:
files = autodetect_files(pkg_name)
if single_pkg and not files:
files = autodetect_source_files(pkg_name)
if files:
extra_args = ["-qmlFiles"] + files
if extra_args:
if not qt_version:
qt_version = qt_version_from_files(extra_args)
cmd = [PKGKDE_GETQMLDEPENDS]
cmd.extend(getqmldepends_glob_args)
cmd.extend(["-p", pkg_name])
if qt_version:
cmd.extend(["--qt", qt_version])
cmd.append("--")
cmd.extend(extra_args)
log.info(f"Execute {' '.join(str(i) for i in cmd)}")
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError as e:
log.error(f"{PKGKDE_GETQMLDEPENDS} failed with {e.returncode}.")
failed = True
elif qt_version or single_pkg:
log.error(f"{pkg_name}: No automatic qml files found for package you need to add the files by hand to debian/{pkg_name}.qmlfiles")
if failed:
sys.exit(1)
|