diff options
Diffstat (limited to 'debian/lib/python/debian_linux')
-rw-r--r-- | debian/lib/python/debian_linux/config_v2.py | 612 | ||||
-rw-r--r-- | debian/lib/python/debian_linux/dataclasses_extra.py | 113 | ||||
-rw-r--r-- | debian/lib/python/debian_linux/gencontrol.py | 289 |
3 files changed, 920 insertions, 94 deletions
diff --git a/debian/lib/python/debian_linux/config_v2.py b/debian/lib/python/debian_linux/config_v2.py new file mode 100644 index 0000000000..1c32bc8864 --- /dev/null +++ b/debian/lib/python/debian_linux/config_v2.py @@ -0,0 +1,612 @@ +from __future__ import annotations + +import dataclasses +import functools +import subprocess +import tomllib +from collections.abc import ( + Iterable, +) +from pathlib import Path +from typing import ( + Optional, + Self, + TypeVar, +) + +import dacite + +from . import dataclasses_extra +from .debian import PackageRelationGroup + + +_dacite_config = dacite.Config( + cast=[ + PackageRelationGroup, + Path, + ], + strict=True, +) + + +@dataclasses.dataclass +class ConfigBuild: + cflags: Optional[str] = None + compiler: Optional[str] = None + compiler_gnutype: Optional[str] = None + compiler_gnutype_compat: Optional[str] = None + config: list[Path] = dataclasses.field(default_factory=list) + config_default: list[Path] = dataclasses.field(default_factory=list, repr=False) + enable_signed: Optional[bool] = None + enable_vdso: Optional[bool] = None + kernel_file: Optional[str] = None + kernel_stem: Optional[str] = None + + +@dataclasses.dataclass +class ConfigDescription: + hardware: Optional[str] = None + hardware_long: Optional[str] = None + parts: list[str] = dataclasses.field(default_factory=list) + short: dict[str, str] = dataclasses.field(default_factory=dict) + long: dict[str, str] = dataclasses.field(default_factory=dict) + + +@dataclasses.dataclass +class ConfigPackages: + docs: Optional[bool] = dataclasses.field(default=None, metadata={'default': True}) + installer: Optional[bool] = dataclasses.field(default=None, metadata={'default': False}) + libc_dev: Optional[bool] = dataclasses.field(default=None, metadata={'default': True}) + meta: Optional[bool] = dataclasses.field(default=None, metadata={'default': True}) + source: Optional[bool] = dataclasses.field(default=None, metadata={'default': True}) + tools_unversioned: Optional[bool] = dataclasses.field(default=None, metadata={'default': True}) + tools_versioned: Optional[bool] = dataclasses.field(default=None, metadata={'default': True}) + + +@dataclasses.dataclass +class ConfigRelationsSingle: + depends: list[PackageRelationGroup] = dataclasses.field(default_factory=list) + recommends: list[PackageRelationGroup] = dataclasses.field(default_factory=list) + suggests: list[PackageRelationGroup] = dataclasses.field(default_factory=list) + breaks: list[PackageRelationGroup] = dataclasses.field(default_factory=list) + + +@dataclasses.dataclass +class ConfigRelations: + image: ConfigRelationsSingle = dataclasses.field(default_factory=ConfigRelationsSingle) + + +@dataclasses.dataclass +class ConfigDebianarchDefs: + __arch: Optional[str] = dataclasses.field(default=None, init=False) + + def __post_init_defs__(self, parent: ConfigDebianarch) -> None: + self.__arch = parent.name + + @staticmethod + @functools.cache + def __dpkg_architecture(arch: str, query: str) -> str: + return subprocess.check_output( + [ + 'dpkg-architecture', + '-f', + '-a', arch, + '-q', query, + ], + stderr=subprocess.DEVNULL, + encoding='ascii', + ).strip() + + @property + def gnutype(self) -> str: + assert self.__arch is not None + return self.__dpkg_architecture(self.__arch, 'DEB_HOST_GNU_TYPE') + + @property + def gnutype_package(self) -> str: + return self.gnutype.replace("_", "-") + + @property + def multiarch(self) -> str: + assert self.__arch is not None + return self.__dpkg_architecture(self.__arch, 'DEB_HOST_MULTIARCH') + + +@dataclasses.dataclass +class ConfigFlavourDefs: + is_default: bool = False + is_quick: bool = False + + +@dataclasses.dataclass +class ConfigBase: + name: str + enable: bool = True + path: Optional[Path] = None + + build: ConfigBuild = dataclasses.field(default_factory=ConfigBuild) + description: ConfigDescription = dataclasses.field(default_factory=ConfigDescription) + packages: ConfigPackages = dataclasses.field(default_factory=ConfigPackages) + relations: ConfigRelations = dataclasses.field(default_factory=ConfigRelations) + + def __post_init_hierarchy__(self, path: Path) -> None: + ''' + Setup path and default config in the complete hierarchy + ''' + self.path = path + self.build.config_default = [path / 'config'] + + def read_replace(self, bases: Iterable[Path], path: Path) -> Self: + ''' + Read defines.toml at specified path in all bases and merged them + ''' + config = self + + try: + for base in bases: + if (file := base / path / 'defines.toml').exists(): + with file.open('rb') as f: + data = dataclasses.asdict(self) | tomllib.load(f) + + config = dataclasses_extra.merge(config, dacite.from_dict( + data_class=self.__class__, + data=data, + config=_dacite_config, + )) + except tomllib.TOMLDecodeError as e: + raise RuntimeError(f'{file}: {e}') from None + + return config + + +ConfigT = TypeVar('ConfigT', bound=ConfigBase) + + +@dataclasses.dataclass +class Config(ConfigBase): + # Disable basic fields + name: str = dataclasses.field(init=False, repr=False, default='') + enable: bool = dataclasses.field(init=False, repr=False, default=True) + + featureset: list[ConfigFeatureset] = dataclasses.field( + default_factory=list, metadata={'merge': 'assoclist'}, + ) + kernelarch: list[ConfigKernelarch] = dataclasses.field( + default_factory=list, metadata={'merge': 'assoclist'}, + ) + + def __post_init_hierarchy__(self, path: Path) -> None: + super().__post_init_hierarchy__(path) + + for featureset in self.featureset: + featureset.__post_init_hierarchy_featureset__( + Path(f'featureset-{featureset.name}'), + None, + ) + for kernelarch in self.kernelarch: + kernelarch.__post_init_hierarchy__( + Path(f'kernelarch-{kernelarch.name}'), + ) + + @property + def merged(self) -> ConfigMerged: + return ConfigMerged(root=self) + + @classmethod + def read_orig(cls, bases: Iterable[Path]) -> Config: + ''' + Read defines.toml at the root in all bases and merge them + ''' + config = cls() + found = False + + try: + for base in bases: + if (file := base / 'defines.toml').exists(): + with file.open('rb') as f: + data = tomllib.load(f) + found = True + + config = dataclasses_extra.merge(config, dacite.from_dict( + data_class=cls, + data=data, + config=_dacite_config, + )) + except (tomllib.TOMLDecodeError, dacite.exceptions.UnexpectedDataError) as e: + raise RuntimeError(f'{file}: {e}') from None + if not found: + raise FileNotFoundError('Did not find defines.toml in any directory') + + config.__post_init_hierarchy__(Path()) + + config.featureset = list(cls._read_hierarchy(bases, config.featureset)) + config.kernelarch = list(cls._read_hierarchy(bases, config.kernelarch)) + for kernelarch in config.kernelarch: + kernelarch.debianarch = list(cls._read_hierarchy(bases, kernelarch.debianarch)) + + config.__post_init_hierarchy__(Path()) + + return config + + @classmethod + def _read_hierarchy( + cls, bases: Iterable[Path], orig: Iterable[ConfigT], + ) -> Iterable[ConfigT]: + for i in orig: + try: + assert i.path is not None + yield i.read_replace(bases, i.path) + except FileNotFoundError: + yield i + + +@dataclasses.dataclass +class ConfigKernelarch(ConfigBase): + debianarch: list[ConfigDebianarch] = dataclasses.field( + default_factory=list, metadata={'merge': 'assoclist'}, + ) + + def __post_init_hierarchy__(self, path: Path) -> None: + super().__post_init_hierarchy__(path) + + for debianarch in self.debianarch: + debianarch.__post_init_hierarchy__( + Path(debianarch.name), + ) + + +@dataclasses.dataclass +class ConfigDebianarch(ConfigBase): + defs: ConfigDebianarchDefs = dataclasses.field(default_factory=ConfigDebianarchDefs) + + featureset: list[ConfigFeatureset] = dataclasses.field( + default_factory=list, metadata={'merge': 'assoclist'}, + ) + flavour: list[ConfigFlavour] = dataclasses.field( + default_factory=list, metadata={'merge': 'assoclist'}, + ) + + def __post_init__(self) -> None: + self.defs.__post_init_defs__(self) + + def __post_init_hierarchy__(self, path: Path) -> None: + super().__post_init_hierarchy__(path) + + for featureset in self.featureset: + featureset.__post_init_hierarchy_featureset__( + Path(path / featureset.name), + self, + ) + + for flavour in self.flavour: + flavour.__post_init_hierarchy__(path) + + +@dataclasses.dataclass +class ConfigFeatureset(ConfigBase): + flavour: list[ConfigFlavour] = dataclasses.field(default_factory=list) + + def __post_init_hierarchy__(self, path: Path) -> None: + super().__post_init_hierarchy__(path) + + for flavour in self.flavour: + flavour.__post_init_hierarchy__(path) + + def __post_init_hierarchy_featureset__( + self, + path: Path, + debianarch: Optional[ConfigDebianarch], + ) -> None: + # If we have no flavours defined within a featureset, we copy it from debianarch + if not self.flavour and debianarch: + self.flavour = [ + ConfigFlavour(name=flavour.name, defs=flavour.defs) + for flavour in debianarch.flavour + ] + + self.__post_init_hierarchy__(path) + + +@dataclasses.dataclass +class ConfigFlavour(ConfigBase): + defs: ConfigFlavourDefs = dataclasses.field(default_factory=ConfigFlavourDefs) + + def __post_init_hierarchy__(self, path: Path) -> None: + self.path = path + self.build.config_default = [path / f'config.{self.name}'] + + +class ConfigMergedBase: + _entries: list[ConfigBase] + + def __init__(self) -> None: + self._entries = [] + + @property + def enable(self) -> bool: + for entry in self._entries: + if not entry.enable: + return False + return True + + @property + def build(self) -> ConfigBuild: + return dataclasses_extra.merge_default( + ConfigBuild, *(i.build for i in self._entries) + ) + + @property + def config(self) -> list[Path]: + ret: list[Path] = [] + for entry in self._entries: + ret += entry.build.config + entry.build.config_default + return ret + + @property + def description(self) -> ConfigDescription: + return dataclasses_extra.merge_default( + ConfigDescription, *(i.description for i in self._entries) + ) + + @property + def packages(self) -> ConfigPackages: + return dataclasses_extra.merge_default( + ConfigPackages, *(i.packages for i in self._entries) + ) + + @property + def relations(self) -> ConfigRelations: + return dataclasses_extra.merge_default( + ConfigRelations, *(i.relations for i in self._entries) + ) + + +class ConfigMerged(ConfigMergedBase): + _root: Config + + def __init__( + self, *, + root: Optional[ConfigBase], + **kw: Optional[ConfigBase], + ) -> None: + super().__init__(**kw) + + assert isinstance(root, Config) + self._root = root + self._entries.append(root) + + @property + def root_featuresets(self) -> Iterable[ConfigMergedFeatureset]: + for featureset in self._root.featureset: + yield ConfigMergedFeatureset( + root=self._root, + root_featureset=None, + kernelarch=None, + debianarch=None, + debianarch_flavour=None, + featureset=featureset, + ) + + @property + def kernelarchs(self) -> Iterable[ConfigMergedKernelarch]: + for kernelarch in self._root.kernelarch: + yield ConfigMergedKernelarch( + root=self._root, + kernelarch=kernelarch, + ) + + +class ConfigMergedKernelarch(ConfigMerged): + _kernelarch: ConfigKernelarch + + def __init__( + self, *, + kernelarch: Optional[ConfigBase], + **kw: Optional[ConfigBase], + ) -> None: + super().__init__(**kw) + + if kernelarch is not None: + assert isinstance(kernelarch, ConfigKernelarch) + self._kernelarch = kernelarch + self._entries.append(kernelarch) + + @property + def name(self) -> str: + return self._kernelarch.name + + @property + def name_kernelarch(self) -> str: + return self._kernelarch.name + + @property + def debianarchs(self) -> Iterable[ConfigMergedDebianarch]: + for debianarch in self._kernelarch.debianarch: + yield ConfigMergedDebianarch( + root=self._root, + kernelarch=self._kernelarch, + debianarch=debianarch, + ) + + +class ConfigMergedDebianarch(ConfigMergedKernelarch): + _debianarch: ConfigDebianarch + + def __init__( + self, *, + debianarch: Optional[ConfigBase], + **kw: Optional[ConfigBase], + ) -> None: + super().__init__(**kw) + + if debianarch is not None: + assert isinstance(debianarch, ConfigDebianarch) + self._debianarch = debianarch + self._entries.append(debianarch) + + @property + def name(self) -> str: + return self._debianarch.name + + @property + def name_debianarch(self) -> str: + return self._debianarch.name + + @property + def defs_debianarch(self) -> ConfigDebianarchDefs: + return self._debianarch.defs + + @property + def featuresets(self) -> Iterable[ConfigMergedFeatureset]: + root_featureset = { + i.name: i + for i in self._root.featureset + } + + for featureset in self._debianarch.featureset: + yield ConfigMergedFeatureset( + root=self._root, + root_featureset=root_featureset[featureset.name], + kernelarch=self._kernelarch, + debianarch=self._debianarch, + debianarch_flavour=None, + featureset=featureset, + ) + + +class ConfigMergedFeatureset(ConfigMergedDebianarch): + _featureset: ConfigFeatureset + _root_featureset: Optional[ConfigFeatureset] = None + _debianarch_flavour: Optional[ConfigFlavour] = None + + def __init__( + self, *, + featureset: Optional[ConfigBase], + root_featureset: Optional[ConfigBase], + debianarch_flavour: Optional[ConfigBase], + **kw: Optional[ConfigBase], + ) -> None: + super().__init__(**kw) + + if debianarch_flavour is not None: + assert isinstance(debianarch_flavour, ConfigFlavour) + self._debianarch_flavour = debianarch_flavour + self._entries.append(debianarch_flavour) + + if root_featureset is not None: + assert isinstance(root_featureset, ConfigFeatureset) + self._root_featureset = root_featureset + self._entries.append(root_featureset) + + if featureset is not None: + assert isinstance(featureset, ConfigFeatureset) + self._featureset = featureset + self._entries.append(featureset) + + @property + def name(self) -> str: + return self._featureset.name + + @property + def name_featureset(self) -> str: + return self._featureset.name + + @property + def flavours(self) -> Iterable[ConfigMergedFlavour]: + debianarch_flavour = { + i.name: i + for i in self._debianarch.flavour + } + + for flavour in self._featureset.flavour: + yield ConfigMergedFlavour( + root=self._root, + root_featureset=self._root_featureset, + kernelarch=self._kernelarch, + debianarch=self._debianarch, + debianarch_flavour=debianarch_flavour[flavour.name], + featureset=self._featureset, + flavour=flavour, + ) + + +class ConfigMergedFlavour(ConfigMergedFeatureset): + _flavour: ConfigFlavour + + def __init__( + self, *, + flavour: Optional[ConfigBase], + **kw: Optional[ConfigBase], + ) -> None: + super().__init__(**kw) + + if flavour is not None: + assert isinstance(flavour, ConfigFlavour) + self._flavour = flavour + self._entries.append(flavour) + + @property + def name(self) -> str: + return self._flavour.name + + @property + def name_flavour(self) -> str: + return self._flavour.name + + @property + def defs_flavour(self) -> ConfigFlavourDefs: + return self._flavour.defs + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument( + 'dir', + default=[Path('debian/config')], + nargs='+', + type=Path, + ) + args = parser.parse_args() + config = Config.read_orig(args.dir) + merged = config.merged + +# from pprint import pprint +# pprint(config) + + def print_indent(indent: int, s: str, *args: str) -> None: + print(' ' * indent * 4 + s, *args) + + for kernelarch in merged.kernelarchs: + print_indent( + 0, + f'Kernelarch: {kernelarch.name}', + f'enable={kernelarch.enable}', + ) + + for debianarch in kernelarch.debianarchs: + print_indent( + 1, + f'Debianarch: {debianarch.name}', + f'enable={debianarch.enable}', + ) + + for featureset in debianarch.featuresets: + print_indent( + 2, + f'Featureset: {featureset.name}', + f'enable={featureset.enable}', + ) + + for flavour in featureset.flavours: + print_indent( + 3, + f'Flavour: {flavour.name}', + f'enable={flavour.enable}', + f'is_default={flavour.defs_flavour.is_default}', + ) + print_indent(4, f'Config: {" ".join(str(i) for i in flavour.config)}') + + else: + print() diff --git a/debian/lib/python/debian_linux/dataclasses_extra.py b/debian/lib/python/debian_linux/dataclasses_extra.py new file mode 100644 index 0000000000..49f2410038 --- /dev/null +++ b/debian/lib/python/debian_linux/dataclasses_extra.py @@ -0,0 +1,113 @@ +from __future__ import annotations + +from dataclasses import ( + fields, + is_dataclass, + replace, +) +from typing import ( + Protocol, + TypeVar, + TYPE_CHECKING, +) + +if TYPE_CHECKING: + from _typeshed import DataclassInstance as _DataclassInstance + + class _HasName(Protocol, _DataclassInstance): + name: str + + _DataclassT = TypeVar('_DataclassT', bound=_DataclassInstance) + _HasNameT = TypeVar('_HasNameT', bound=_HasName) + + +def default( + cls: type[_DataclassT], + /, +) -> _DataclassT: + f = {} + + for field in fields(cls): + if 'default' in field.metadata: + f[field.name] = field.metadata['default'] + + return cls(**f) + + +def merge( + self: _DataclassT, + other: _DataclassT | None, /, +) -> _DataclassT: + if other is None: + return self + + f = {} + + for field in fields(self): + if not field.init: + continue + + field_default_type = object + if isinstance(field.default_factory, type): + field_default_type = field.default_factory + + self_field = getattr(self, field.name) + other_field = getattr(other, field.name) + + if field.name == 'name': + assert self_field == other_field + elif field.type == 'bool': + f[field.name] = other_field + elif field.metadata.get('merge') == 'assoclist': + f[field.name] = _merge_assoclist(self_field, other_field) + elif is_dataclass(field_default_type): + f[field.name] = merge(self_field, other_field) + elif issubclass(field_default_type, list): + f[field.name] = self_field + other_field + elif issubclass(field_default_type, dict): + f[field.name] = self_field | other_field + elif field.default is None: + if other_field is not None: + f[field.name] = other_field + else: + raise RuntimeError(f'Unable to merge for type {field.type}') + + return replace(self, **f) + + +def merge_default( + cls: type[_DataclassT], + /, + *others: _DataclassT, +) -> _DataclassT: + ret: _DataclassT = default(cls) + for o in others: + ret = merge(ret, o) + return ret + + +def _merge_assoclist( + self_list: list[_HasNameT], + other_list: list[_HasNameT], + /, +) -> list[_HasNameT]: + ''' + Merge lists where each item got a "name" attribute + ''' + if not self_list: + return other_list + if not other_list: + return self_list + + ret: list[_HasNameT] = [] + other_dict = { + i.name: i + for i in other_list + } + for i in self_list: + if i.name in other_dict: + ret.append(merge(i, other_dict.pop(i.name))) + else: + ret.append(i) + ret.extend(other_dict.values()) + return ret diff --git a/debian/lib/python/debian_linux/gencontrol.py b/debian/lib/python/debian_linux/gencontrol.py index 66769a0639..49f52e878b 100644 --- a/debian/lib/python/debian_linux/gencontrol.py +++ b/debian/lib/python/debian_linux/gencontrol.py @@ -1,6 +1,7 @@ from __future__ import annotations import contextlib +import itertools import pathlib import re from collections import OrderedDict @@ -14,6 +15,12 @@ from typing import ( IO, ) +from .config_v2 import ( + ConfigMerged, + ConfigMergedDebianarch, + ConfigMergedFeatureset, + ConfigMergedFlavour, +) from .debian import Changelog, PackageArchitecture, \ Version, _ControlFileDict from .utils import Templates @@ -365,31 +372,12 @@ class PackagesBundle: f.write('\n') -def iter_featuresets(config) -> Iterable[str]: - for featureset in config['base', ]['featuresets']: - if config.merge('base', None, featureset).get('enabled', True): - yield featureset - - -def iter_arches(config) -> Iterable[str]: - return iter(config['base', ]['arches']) - - -def iter_arch_featuresets(config, arch) -> Iterable[str]: - for featureset in config['base', arch].get('featuresets', []): - if config.merge('base', arch, featureset).get('enabled', True): - yield featureset - - -def iter_flavours(config, arch, featureset) -> Iterable[str]: - return iter(config['base', arch, featureset]['flavours']) - - class Gencontrol(object): + config: ConfigMerged vars: dict[str, str] bundles: dict[str, PackagesBundle] - def __init__(self, config, templates, version=Version) -> None: + def __init__(self, config: ConfigMerged, templates, version=Version) -> None: self.config, self.templates = config, templates self.changelog = Changelog(version=version) self.vars = {} @@ -417,27 +405,53 @@ class Gencontrol(object): makeflags = MakeFlags() - self.do_main_setup(vars, makeflags) - self.do_main_makefile(makeflags) - self.do_main_packages(vars, makeflags) - self.do_main_recurse(vars, makeflags) + self.do_main_setup(self.config, vars, makeflags) + self.do_main_makefile(self.config, vars, makeflags) + self.do_main_packages(self.config, vars, makeflags) + self.do_main_recurse(self.config, vars, makeflags) - def do_main_setup(self, vars, makeflags) -> None: + def do_main_setup( + self, + config: ConfigMerged, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_main_makefile(self, makeflags) -> None: + def do_main_makefile( + self, + config: ConfigMerged, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_main_packages(self, vars, makeflags) -> None: + def do_main_packages( + self, + config: ConfigMerged, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_main_recurse(self, vars, makeflags) -> None: - for featureset in iter_featuresets(self.config): - self.do_indep_featureset(featureset, - vars.copy(), makeflags.copy()) - for arch in iter_arches(self.config): - self.do_arch(arch, vars.copy(), - makeflags.copy()) + def do_main_recurse( + self, + config: ConfigMerged, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + for featureset in config.root_featuresets: + self.do_indep_featureset(featureset, vars.copy(), makeflags.copy()) + + # Sort the output the same way as before + for arch in sorted( + itertools.chain.from_iterable( + i.debianarchs for i in config.kernelarchs + ), + key=lambda i: i.name + ): + if arch.enable: + self.do_arch(arch, vars.copy(), makeflags.copy()) def do_extra(self) -> None: try: @@ -456,81 +470,158 @@ class Gencontrol(object): self.bundle.add_packages(packages_extra, (arch, ), MakeFlags(), check_packages=False) - def do_indep_featureset(self, featureset, vars, makeflags) -> None: + def do_indep_featureset( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: vars['localversion'] = '' - if featureset != 'none': - vars['localversion'] = '-' + featureset - - self.do_indep_featureset_setup(vars, makeflags, featureset) - self.do_indep_featureset_makefile(featureset, makeflags) - self.do_indep_featureset_packages(featureset, - vars, makeflags) - - def do_indep_featureset_setup(self, vars, makeflags, featureset) -> None: + if config.name_featureset != 'none': + vars['localversion'] = '-' + config.name_featureset + + self.do_indep_featureset_setup(config, vars, makeflags) + self.do_indep_featureset_makefile(config, vars, makeflags) + self.do_indep_featureset_packages(config, vars, makeflags) + + def do_indep_featureset_setup( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_indep_featureset_makefile(self, featureset, makeflags) -> None: - makeflags['FEATURESET'] = featureset + def do_indep_featureset_makefile( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + makeflags['FEATURESET'] = config.name - def do_indep_featureset_packages(self, featureset, vars, makeflags) -> None: + def do_indep_featureset_packages( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_arch(self, arch, vars, makeflags) -> None: - vars['arch'] = arch - - self.do_arch_setup(vars, makeflags, arch) - self.do_arch_makefile(arch, makeflags) - self.do_arch_packages(arch, vars, makeflags) - self.do_arch_recurse(arch, vars, makeflags) - - def do_arch_setup(self, vars, makeflags, arch) -> None: + def do_arch( + self, + config: ConfigMergedDebianarch, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + vars['arch'] = config.name + + self.do_arch_setup(config, vars, makeflags) + self.do_arch_makefile(config, vars, makeflags) + self.do_arch_packages(config, vars, makeflags) + self.do_arch_recurse(config, vars, makeflags) + + def do_arch_setup( + self, + config: ConfigMergedDebianarch, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_arch_makefile(self, arch, makeflags) -> None: - makeflags['ARCH'] = arch + def do_arch_makefile( + self, + config: ConfigMergedDebianarch, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + makeflags['ARCH'] = config.name - def do_arch_packages(self, arch, vars, makeflags) -> None: + def do_arch_packages( + self, + config: ConfigMergedDebianarch, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_arch_recurse(self, arch, vars, makeflags) -> None: - for featureset in iter_arch_featuresets(self.config, arch): - self.do_featureset(arch, featureset, - vars.copy(), makeflags.copy()) - - def do_featureset(self, arch, featureset, vars, makeflags) -> None: + def do_arch_recurse( + self, + config: ConfigMergedDebianarch, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + for featureset in config.featuresets: + if featureset.enable: + self.do_featureset(featureset, vars.copy(), makeflags.copy()) + + def do_featureset( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: vars['localversion'] = '' - if featureset != 'none': - vars['localversion'] = '-' + featureset - - self.do_featureset_setup(vars, makeflags, arch, featureset) - self.do_featureset_makefile(arch, featureset, makeflags) - self.do_featureset_packages(arch, featureset, vars, makeflags) - self.do_featureset_recurse(arch, featureset, vars, makeflags) - - def do_featureset_setup(self, vars, makeflags, arch, featureset) -> None: + if config.name_featureset != 'none': + vars['localversion'] = '-' + config.name_featureset + + self.do_featureset_setup(config, vars, makeflags) + self.do_featureset_makefile(config, vars, makeflags) + self.do_featureset_packages(config, vars, makeflags) + self.do_featureset_recurse(config, vars, makeflags) + + def do_featureset_setup( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_featureset_makefile(self, arch, featureset, makeflags) -> None: - makeflags['FEATURESET'] = featureset + def do_featureset_makefile( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + makeflags['FEATURESET'] = config.name - def do_featureset_packages(self, arch, featureset, vars, makeflags) -> None: + def do_featureset_packages( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass - def do_featureset_recurse(self, arch, featureset, vars, makeflags) -> None: - for flavour in iter_flavours(self.config, arch, featureset): - self.do_flavour(arch, featureset, flavour, - vars.copy(), makeflags.copy()) - - def do_flavour(self, arch, featureset, flavour, vars, - makeflags): - vars['localversion'] += '-' + flavour + def do_featureset_recurse( + self, + config: ConfigMergedFeatureset, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + for flavour in config.flavours: + if flavour.enable: + self.do_flavour(flavour, vars.copy(), makeflags.copy()) + + def do_flavour( + self, + config: ConfigMergedFlavour, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + vars['localversion'] += '-' + config.name_flavour - self.do_flavour_setup(vars, makeflags, arch, featureset, flavour) - self.do_flavour_makefile(arch, featureset, flavour, makeflags) - self.do_flavour_packages(arch, featureset, flavour, - vars, makeflags) + self.do_flavour_setup(config, vars, makeflags) + self.do_flavour_makefile(config, vars, makeflags) + self.do_flavour_packages(config, vars, makeflags) - def do_flavour_setup(self, vars, makeflags, arch, featureset, flavour) -> None: + def do_flavour_setup( + self, + config: ConfigMergedFlavour, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: for i in ( ('kernel-arch', 'KERNEL_ARCH'), ('localversion', 'LOCALVERSION'), @@ -538,10 +629,20 @@ class Gencontrol(object): if i[0] in vars: makeflags[i[1]] = vars[i[0]] - def do_flavour_makefile(self, arch, featureset, flavour, makeflags) -> None: - makeflags['FLAVOUR'] = flavour + def do_flavour_makefile( + self, + config: ConfigMergedFlavour, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: + makeflags['FLAVOUR'] = config.name - def do_flavour_packages(self, arch, featureset, flavour, vars, makeflags) -> None: + def do_flavour_packages( + self, + config: ConfigMergedFlavour, + vars: dict[str, str], + makeflags: MakeFlags, + ) -> None: pass def substitute(self, s: str | list | tuple, vars) -> str | list: |