cmds.projects.lib.pkg_relations: Integrate lib.version
- The pkg_relations() function is a horribly bad read. It contains a mind-bending amount of interwoven case distinctions that are not clearly reflected in the participating variable and function names. Much of it is version handling. That's intricate by nature, but much of it has now been implemented in the lib.version module, so moving the logic there makes the function a good deal more readable than before. That's most of what this commit does. - Use version syntax macros from lib.version instead of pkg_relations-defined macros, and fix the fallout in BaseCmdPkgRelations and CmdCreateFile. - Use lib.version also as a central place for dep string parsing from App. Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
c9cbef15bb
commit
0c808f9383
4 changed files with 46 additions and 113 deletions
|
|
@ -11,10 +11,11 @@ from enum import Enum, auto
|
||||||
from functools import cache
|
from functools import cache
|
||||||
from typing import TYPE_CHECKING, override
|
from typing import TYPE_CHECKING, override
|
||||||
|
|
||||||
from .lib.ExecApp import ExecApp as Base
|
|
||||||
from .lib.Distro import Distro
|
from .lib.Distro import Distro
|
||||||
|
from .lib.ExecApp import ExecApp as Base
|
||||||
from .lib.log import DEBUG, ERR, log
|
from .lib.log import DEBUG, ERR, log
|
||||||
from .lib.ProjectConf import ProjectConf
|
from .lib.ProjectConf import ProjectConf
|
||||||
|
from .lib.version.Dependency import Dependency
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import argparse
|
import argparse
|
||||||
|
|
@ -435,7 +436,7 @@ class App(Base):
|
||||||
return self.find_dir(name, ['/tmpl'], ['/opt/' + name + '/share/tmpl'])
|
return self.find_dir(name, ['/tmpl'], ['/opt/' + name + '/share/tmpl'])
|
||||||
|
|
||||||
def strip_module_from_spec(self, mod: str) -> str:
|
def strip_module_from_spec(self, mod: str) -> str:
|
||||||
return re.sub(r'-dev$|-devel$|-run$', '', re.split('([=><]+)', mod)[0].strip())
|
return Dependency(mod).base_name
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_value(self, project: str, section: str, key: str) -> str | None:
|
def get_value(self, project: str, section: str, key: str) -> str | None:
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import re
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, cast, override
|
from typing import TYPE_CHECKING, cast, override
|
||||||
|
|
||||||
|
from ...lib.version.base import Syntax
|
||||||
from .Cmd import Cmd, Parent
|
from .Cmd import Cmd, Parent
|
||||||
from .lib.pkg_relations import VersionSyntax
|
|
||||||
from .lib.pkg_relations import pkg_relations as pkg_relations_list
|
from .lib.pkg_relations import pkg_relations as pkg_relations_list
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
@ -30,7 +30,11 @@ class BaseCmdPkgRelations(Cmd):
|
||||||
no_subpackages = args.no_subpackages,
|
no_subpackages = args.no_subpackages,
|
||||||
dont_strip_revision = args.dont_strip_revision,
|
dont_strip_revision = args.dont_strip_revision,
|
||||||
expand_semver_revision_range = args.expand_semver_revision_range,
|
expand_semver_revision_range = args.expand_semver_revision_range,
|
||||||
syntax = VersionSyntax[args.syntax.replace('-', '_')],
|
syntax = {
|
||||||
|
'semver': Syntax.SEM_VER,
|
||||||
|
'debian': Syntax.DEBIAN,
|
||||||
|
'names-only': Syntax.NAMES_ONLY,
|
||||||
|
}[args.syntax],
|
||||||
recursive = args.recursive,
|
recursive = args.recursive,
|
||||||
dont_expand_version_macros = args.dont_expand_version_macros,
|
dont_expand_version_macros = args.dont_expand_version_macros,
|
||||||
ignore = set(re.split(self.arg_sep, args.ignore)),
|
ignore = set(re.split(self.arg_sep, args.ignore)),
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ from enum import Enum, auto
|
||||||
from typing import override
|
from typing import override
|
||||||
|
|
||||||
from ...lib.log import WARNING, log
|
from ...lib.log import WARNING, log
|
||||||
|
from ...lib.version.base import Syntax
|
||||||
from .Cmd import Cmd, Parent
|
from .Cmd import Cmd, Parent
|
||||||
from .lib.pkg_relations import VersionSyntax, pkg_relations
|
from .lib.pkg_relations import pkg_relations
|
||||||
from .lib.templates import ListDict, RenderValues, tmpl_render
|
from .lib.templates import ListDict, RenderValues, tmpl_render
|
||||||
|
|
||||||
def key_value(s: str) -> tuple[str, str]:
|
def key_value(s: str) -> tuple[str, str]:
|
||||||
|
|
@ -36,7 +37,7 @@ class CmdCreateFile(Cmd): # export
|
||||||
flavours = ['run'],
|
flavours = ['run'],
|
||||||
subsections = ['jw'],
|
subsections = ['jw'],
|
||||||
seed_pkgs = [module],
|
seed_pkgs = [module],
|
||||||
syntax = VersionSyntax.names_only,
|
syntax = Syntax.NAMES_ONLY,
|
||||||
no_subpackages = True,
|
no_subpackages = True,
|
||||||
recursive = True,
|
recursive = True,
|
||||||
quote = False,
|
quote = False,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
import re
|
|
||||||
|
|
||||||
from enum import Enum, auto
|
|
||||||
|
|
||||||
from ....App import App, Scope
|
from ....App import App, Scope
|
||||||
from ....lib.log import DEBUG, log
|
from ....lib.log import DEBUG, log
|
||||||
|
from ....lib.version.base import Syntax
|
||||||
class VersionSyntax(Enum):
|
from ....lib.version.Dependency import Dependency
|
||||||
semver = auto()
|
|
||||||
debian = auto()
|
|
||||||
names_only = auto()
|
|
||||||
|
|
||||||
def pkg_relations(
|
def pkg_relations(
|
||||||
app: App,
|
app: App,
|
||||||
|
|
@ -20,7 +13,7 @@ def pkg_relations(
|
||||||
no_subpackages: bool = False,
|
no_subpackages: bool = False,
|
||||||
dont_strip_revision: bool = False,
|
dont_strip_revision: bool = False,
|
||||||
expand_semver_revision_range: bool = False,
|
expand_semver_revision_range: bool = False,
|
||||||
syntax: VersionSyntax = VersionSyntax.semver,
|
syntax: Syntax = Syntax.SEM_VER,
|
||||||
recursive: bool = False,
|
recursive: bool = False,
|
||||||
dont_expand_version_macros: bool = False,
|
dont_expand_version_macros: bool = False,
|
||||||
ignore: set[str] = set(),
|
ignore: set[str] = set(),
|
||||||
|
|
@ -34,8 +27,7 @@ def pkg_relations(
|
||||||
subsections = app.distro.os_cascade
|
subsections = app.distro.os_cascade
|
||||||
subsections.append('jw')
|
subsections.append('jw')
|
||||||
|
|
||||||
expand_semver_revision_range = expand_semver_revision_range
|
if syntax == Syntax.DEBIAN:
|
||||||
if syntax == VersionSyntax.debian:
|
|
||||||
expand_semver_revision_range = True
|
expand_semver_revision_range = True
|
||||||
|
|
||||||
if skip_excluded:
|
if skip_excluded:
|
||||||
|
|
@ -58,113 +50,48 @@ def pkg_relations(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
version_pattern = re.compile('[0-9-.]*')
|
|
||||||
ret: list[str] = []
|
ret: list[str] = []
|
||||||
for flavour in flavours: # build / release / run / devel
|
for flavour in flavours: # build / release / run / devel
|
||||||
cur_pkgs = seed_pkgs.copy()
|
cur_pkgs = seed_pkgs.copy()
|
||||||
visited = set()
|
visited_pkgs: set[str] = set()
|
||||||
while len(cur_pkgs):
|
while len(cur_pkgs):
|
||||||
cur_pkg = cur_pkgs.pop(0)
|
cur_pkg = cur_pkgs.pop(0)
|
||||||
if cur_pkg in visited or cur_pkg in ignore:
|
if cur_pkg in visited_pkgs or cur_pkg in ignore:
|
||||||
continue
|
continue
|
||||||
for subsec in subsections:
|
for subsec in subsections:
|
||||||
version: str | None = None
|
|
||||||
section = 'pkg.' + rel_type + '.' + subsec
|
section = 'pkg.' + rel_type + '.' + subsec
|
||||||
visited.add(cur_pkg)
|
visited_pkgs.add(cur_pkg)
|
||||||
value = app.get_value(cur_pkg, section, flavour)
|
deps_spec = app.get_value(cur_pkg, section, flavour)
|
||||||
if not value:
|
if not deps_spec:
|
||||||
continue
|
continue
|
||||||
deps = value.split(',')
|
for dep in Dependency.parse_deps_spec(
|
||||||
for spec in deps:
|
deps_spec,
|
||||||
dep = re.split('([=><]+)', spec)
|
lookup_version = app.get_version,
|
||||||
if syntax == VersionSyntax.names_only:
|
):
|
||||||
dep = dep[:1]
|
dep_name = dep.base_name
|
||||||
dep = list(map(str.strip, dep))
|
if dep_name in ignore or dep.full_name in ignore:
|
||||||
dep_name = re.sub('-dev$|-devel$|-run$', '', dep[0])
|
|
||||||
if dep_name in ignore or dep[0] in ignore:
|
|
||||||
continue
|
continue
|
||||||
if no_subpackages:
|
|
||||||
dep[0] = dep_name
|
|
||||||
for i, item in enumerate(dep):
|
|
||||||
dep[i] = item.strip()
|
|
||||||
if subsec == 'jw':
|
if subsec == 'jw':
|
||||||
if (recursive and dep_name not in visited
|
if (recursive and dep_name not in visited_pkgs
|
||||||
and dep_name not in cur_pkgs):
|
and dep_name not in cur_pkgs):
|
||||||
cur_pkgs.append(dep_name)
|
cur_pkgs.append(dep_name)
|
||||||
if hide_jw_pkg:
|
if hide_jw_pkg and dep_name == 'jw-pkg':
|
||||||
continue
|
continue
|
||||||
if len(dep) == 3:
|
expand_version_macros = subsec == 'jw'
|
||||||
if dont_expand_version_macros and dep_name in cur_pkgs:
|
if dont_expand_version_macros and dep_name in cur_pkgs:
|
||||||
version = dep[2]
|
expand_version_macros = False
|
||||||
else:
|
if hide_self and dep_name in seed_pkgs:
|
||||||
version = app.get_version(dep_name)
|
continue
|
||||||
if dep[2] == 'VERSION':
|
dep_str = dep.constraint_str(
|
||||||
if dont_strip_revision:
|
untemplated = expand_version_macros,
|
||||||
dep[2] = version
|
include_revision = dont_strip_revision,
|
||||||
else:
|
as_range = expand_semver_revision_range,
|
||||||
dep[2] = version.split('-')[0]
|
no_subpackages = no_subpackages,
|
||||||
elif dep[2] == 'VERSION-REVISION':
|
syntax = syntax,
|
||||||
dep[2] = version
|
quote = '"' if quote else None,
|
||||||
elif version_pattern.match(dep[2]):
|
)
|
||||||
# dep[2] = dep[2]
|
if dep_str in ret:
|
||||||
pass
|
continue
|
||||||
else:
|
log(DEBUG, f'Appending dependency >{dep_str}<')
|
||||||
raise Exception('Unknown version specifier in ' + spec)
|
ret.append(dep_str)
|
||||||
if len(dep) != 3 or not expand_semver_revision_range:
|
|
||||||
expanded_deps = [dep]
|
|
||||||
else:
|
|
||||||
assert version is not None
|
|
||||||
expanded_deps = []
|
|
||||||
semver = re.split(r'[.-]', version)
|
|
||||||
if len(semver) != 4:
|
|
||||||
expanded_deps = [dep]
|
|
||||||
else:
|
|
||||||
release = int(semver[2])
|
|
||||||
major_minor = f'{semver[0]}.{semver[1]}'
|
|
||||||
match dep[1]:
|
|
||||||
case '>' | '>=':
|
|
||||||
expanded_deps.append([dep[0], dep[1], dep[2]])
|
|
||||||
expanded_deps.append(
|
|
||||||
[dep[0], '<', f'{major_minor}.{release + 1}']
|
|
||||||
)
|
|
||||||
case '<' | '<=':
|
|
||||||
expanded_deps.append([dep[0], dep[1], dep[2]])
|
|
||||||
case '=':
|
|
||||||
expanded_deps.append(
|
|
||||||
[dep[0], '>=', f'{major_minor}.{release}']
|
|
||||||
)
|
|
||||||
expanded_deps.append(
|
|
||||||
[dep[0], '<', f'{major_minor}.{release + 1}']
|
|
||||||
)
|
|
||||||
case _:
|
|
||||||
raise NotImplementedError(
|
|
||||||
(
|
|
||||||
'Expanding SemVer range '
|
|
||||||
f'"{dep[0]} {dep[1]} {dep[3]}" '
|
|
||||||
'is not yet implemented'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for expanded_dep in expanded_deps:
|
|
||||||
if hide_self and dep_name in seed_pkgs:
|
|
||||||
continue
|
|
||||||
match syntax:
|
|
||||||
case VersionSyntax.semver:
|
|
||||||
pass
|
|
||||||
case VersionSyntax.names_only:
|
|
||||||
pass
|
|
||||||
case VersionSyntax.debian:
|
|
||||||
if len(expanded_dep) == 3:
|
|
||||||
match expanded_dep[1]:
|
|
||||||
case '<':
|
|
||||||
expanded_dep[1] = '<<'
|
|
||||||
case '>':
|
|
||||||
expanded_dep[1] = '>>'
|
|
||||||
case _:
|
|
||||||
pass
|
|
||||||
dep_str = ' '.join(expanded_dep)
|
|
||||||
if quote:
|
|
||||||
dep_str = '"' + dep_str + '"'
|
|
||||||
if dep_str not in ret:
|
|
||||||
log(DEBUG, f'Appending dependency >{dep_str}<')
|
|
||||||
ret.append(dep_str)
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue