summaryrefslogtreecommitdiffstats
path: root/debian/lib/python/debian_linux
diff options
context:
space:
mode:
Diffstat (limited to 'debian/lib/python/debian_linux')
-rw-r--r--debian/lib/python/debian_linux/config_v2.py612
-rw-r--r--debian/lib/python/debian_linux/dataclasses_extra.py113
-rw-r--r--debian/lib/python/debian_linux/gencontrol.py289
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: