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 typing import TYPE_CHECKING, override
|
||||
|
||||
from .lib.ExecApp import ExecApp as Base
|
||||
from .lib.Distro import Distro
|
||||
from .lib.ExecApp import ExecApp as Base
|
||||
from .lib.log import DEBUG, ERR, log
|
||||
from .lib.ProjectConf import ProjectConf
|
||||
from .lib.version.Dependency import Dependency
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import argparse
|
||||
|
|
@ -435,7 +436,7 @@ class App(Base):
|
|||
return self.find_dir(name, ['/tmpl'], ['/opt/' + name + '/share/tmpl'])
|
||||
|
||||
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
|
||||
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 ...lib.version.base import Syntax
|
||||
from .Cmd import Cmd, Parent
|
||||
from .lib.pkg_relations import VersionSyntax
|
||||
from .lib.pkg_relations import pkg_relations as pkg_relations_list
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -30,7 +30,11 @@ class BaseCmdPkgRelations(Cmd):
|
|||
no_subpackages = args.no_subpackages,
|
||||
dont_strip_revision = args.dont_strip_revision,
|
||||
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,
|
||||
dont_expand_version_macros = args.dont_expand_version_macros,
|
||||
ignore = set(re.split(self.arg_sep, args.ignore)),
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ from enum import Enum, auto
|
|||
from typing import override
|
||||
|
||||
from ...lib.log import WARNING, log
|
||||
from ...lib.version.base import Syntax
|
||||
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
|
||||
|
||||
def key_value(s: str) -> tuple[str, str]:
|
||||
|
|
@ -36,7 +37,7 @@ class CmdCreateFile(Cmd): # export
|
|||
flavours = ['run'],
|
||||
subsections = ['jw'],
|
||||
seed_pkgs = [module],
|
||||
syntax = VersionSyntax.names_only,
|
||||
syntax = Syntax.NAMES_ONLY,
|
||||
no_subpackages = True,
|
||||
recursive = True,
|
||||
quote = False,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,7 @@
|
|||
import re
|
||||
|
||||
from enum import Enum, auto
|
||||
|
||||
from ....App import App, Scope
|
||||
from ....lib.log import DEBUG, log
|
||||
|
||||
class VersionSyntax(Enum):
|
||||
semver = auto()
|
||||
debian = auto()
|
||||
names_only = auto()
|
||||
from ....lib.version.base import Syntax
|
||||
from ....lib.version.Dependency import Dependency
|
||||
|
||||
def pkg_relations(
|
||||
app: App,
|
||||
|
|
@ -20,7 +13,7 @@ def pkg_relations(
|
|||
no_subpackages: bool = False,
|
||||
dont_strip_revision: bool = False,
|
||||
expand_semver_revision_range: bool = False,
|
||||
syntax: VersionSyntax = VersionSyntax.semver,
|
||||
syntax: Syntax = Syntax.SEM_VER,
|
||||
recursive: bool = False,
|
||||
dont_expand_version_macros: bool = False,
|
||||
ignore: set[str] = set(),
|
||||
|
|
@ -34,8 +27,7 @@ def pkg_relations(
|
|||
subsections = app.distro.os_cascade
|
||||
subsections.append('jw')
|
||||
|
||||
expand_semver_revision_range = expand_semver_revision_range
|
||||
if syntax == VersionSyntax.debian:
|
||||
if syntax == Syntax.DEBIAN:
|
||||
expand_semver_revision_range = True
|
||||
|
||||
if skip_excluded:
|
||||
|
|
@ -58,113 +50,48 @@ def pkg_relations(
|
|||
),
|
||||
)
|
||||
|
||||
version_pattern = re.compile('[0-9-.]*')
|
||||
ret: list[str] = []
|
||||
for flavour in flavours: # build / release / run / devel
|
||||
cur_pkgs = seed_pkgs.copy()
|
||||
visited = set()
|
||||
visited_pkgs: set[str] = set()
|
||||
while len(cur_pkgs):
|
||||
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
|
||||
for subsec in subsections:
|
||||
version: str | None = None
|
||||
section = 'pkg.' + rel_type + '.' + subsec
|
||||
visited.add(cur_pkg)
|
||||
value = app.get_value(cur_pkg, section, flavour)
|
||||
if not value:
|
||||
visited_pkgs.add(cur_pkg)
|
||||
deps_spec = app.get_value(cur_pkg, section, flavour)
|
||||
if not deps_spec:
|
||||
continue
|
||||
deps = value.split(',')
|
||||
for spec in deps:
|
||||
dep = re.split('([=><]+)', spec)
|
||||
if syntax == VersionSyntax.names_only:
|
||||
dep = dep[:1]
|
||||
dep = list(map(str.strip, dep))
|
||||
dep_name = re.sub('-dev$|-devel$|-run$', '', dep[0])
|
||||
if dep_name in ignore or dep[0] in ignore:
|
||||
for dep in Dependency.parse_deps_spec(
|
||||
deps_spec,
|
||||
lookup_version = app.get_version,
|
||||
):
|
||||
dep_name = dep.base_name
|
||||
if dep_name in ignore or dep.full_name in ignore:
|
||||
continue
|
||||
if no_subpackages:
|
||||
dep[0] = dep_name
|
||||
for i, item in enumerate(dep):
|
||||
dep[i] = item.strip()
|
||||
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):
|
||||
cur_pkgs.append(dep_name)
|
||||
if hide_jw_pkg:
|
||||
if hide_jw_pkg and dep_name == 'jw-pkg':
|
||||
continue
|
||||
if len(dep) == 3:
|
||||
if dont_expand_version_macros and dep_name in cur_pkgs:
|
||||
version = dep[2]
|
||||
else:
|
||||
version = app.get_version(dep_name)
|
||||
if dep[2] == 'VERSION':
|
||||
if dont_strip_revision:
|
||||
dep[2] = version
|
||||
else:
|
||||
dep[2] = version.split('-')[0]
|
||||
elif dep[2] == 'VERSION-REVISION':
|
||||
dep[2] = version
|
||||
elif version_pattern.match(dep[2]):
|
||||
# dep[2] = dep[2]
|
||||
pass
|
||||
else:
|
||||
raise Exception('Unknown version specifier in ' + spec)
|
||||
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)
|
||||
expand_version_macros = subsec == 'jw'
|
||||
if dont_expand_version_macros and dep_name in cur_pkgs:
|
||||
expand_version_macros = False
|
||||
if hide_self and dep_name in seed_pkgs:
|
||||
continue
|
||||
dep_str = dep.constraint_str(
|
||||
untemplated = expand_version_macros,
|
||||
include_revision = dont_strip_revision,
|
||||
as_range = expand_semver_revision_range,
|
||||
no_subpackages = no_subpackages,
|
||||
syntax = syntax,
|
||||
quote = '"' if quote else None,
|
||||
)
|
||||
if dep_str in ret:
|
||||
continue
|
||||
log(DEBUG, f'Appending dependency >{dep_str}<')
|
||||
ret.append(dep_str)
|
||||
return ret
|
||||
|
|
|
|||
Loading…
Reference in a new issue