From b4c0ae77456df60c327a198186a088aeca0c40e4 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Feb 05 2024 15:59:19 +0000 Subject: [PATCH 1/2] Add a new "build-extension" key and initial support for extensions This adds a new "build-extension" boolean key to container yaml, matching how it's named in flatpak-builder, making it possible to build flatpak extensions. --- diff --git a/flatpak_module_tools/container_spec.py b/flatpak_module_tools/container_spec.py index a818dd8..20f56f5 100644 --- a/flatpak_module_tools/container_spec.py +++ b/flatpak_module_tools/container_spec.py @@ -159,6 +159,7 @@ class FlatpakSpec(BaseSpec): self.base_image = self._get_str('base_image', None) self.branch = self._get_str('branch', 'stable') self.build_runtime = self._get_bool('build-runtime', False) + self.build_extension = self._get_bool('build-extension', False) self.cleanup_commands = self._get_str('cleanup-commands', None) self.command = self._get_str('command', None) self.component = self._get_str('component', None) diff --git a/flatpak_module_tools/flatpak_builder.py b/flatpak_module_tools/flatpak_builder.py index fe6c650..6c9769b 100644 --- a/flatpak_module_tools/flatpak_builder.py +++ b/flatpak_module_tools/flatpak_builder.py @@ -293,6 +293,7 @@ class FileTreeProcessor: class BaseFlatpakSourceInfo(ABC): runtime: bool + extension: bool spec: FlatpakSpec @abstractmethod @@ -335,6 +336,8 @@ class ModuleFlatpakSourceInfo(BaseFlatpakSourceInfo): # A runtime module must have a 'runtime' profile, but can have other # profiles for SDKs, minimal runtimes, etc. self.runtime = 'runtime' in base_module.mmd.get_profile_names() + # Extension support not implemented for module backend + self.extension = False if profile is None: profile = 'runtime' if self.runtime else 'default' @@ -507,6 +510,7 @@ class PackageFlatpakSourceInfo(BaseFlatpakSourceInfo): self.spec = spec self.runtime = spec.build_runtime self.runtime_info = runtime_info + self.extension = spec.build_extension def precheck(self): pass @@ -767,7 +771,7 @@ class FlatpakBuilder: if spec.finish_args: # shlex.split(None) reads from standard input, so avoid that finish_args = shlex.split(spec.finish_args, comments=True) - if spec.command and not self.source.runtime: + if spec.command and not self.source.runtime and not self.source.extension: finish_args = ['--command', spec.command] + finish_args subprocess.check_call(['flatpak', 'build-finish'] + finish_args + [builddir]) @@ -1051,7 +1055,7 @@ class FlatpakBuilder: def build_container(self, tarred_filesystem: str, tar_outfile: bool = True): outfile = os.path.join(self.workdir, 'flatpak-oci-image') - if self.source.runtime: + if self.source.runtime or self.source.extension: ref_name = self._create_runtime_oci(tarred_filesystem, outfile) else: ref_name = self._create_app_oci(tarred_filesystem, outfile) From e97b633c314f97fe641d9d5a772f6d57cd414922 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Feb 05 2024 15:59:19 +0000 Subject: [PATCH 2/2] Implement missing --extra-data finish arg This can be useful for extensions that want to download extra data during install time. --- diff --git a/flatpak_module_tools/flatpak_builder.py b/flatpak_module_tools/flatpak_builder.py index 6c9769b..337952f 100644 --- a/flatpak_module_tools/flatpak_builder.py +++ b/flatpak_module_tools/flatpak_builder.py @@ -27,6 +27,7 @@ import subprocess import tarfile from textwrap import dedent from xml.etree import ElementTree +from gi.repository import GLib from .container_spec import FlatpakSpec from .utils import Arch, RuntimeInfo @@ -787,6 +788,44 @@ class FlatpakBuilder: return repo + def _get_extra_data(self, metadata_file): + metadata_config = RawConfigParser() + metadata_config.optionxform = str # type: ignore + with open(metadata_file, 'r') as f: + metadata_config.read_file(f) + + if 'Extra Data' in metadata_config: + extra_data = metadata_config['Extra Data'] + + extra_data_uri = None + extra_data_checksum = None + extra_data_name = None + extra_data_size = 0 + extra_data_installed_size = 0 + + if 'uri' in extra_data: + extra_data_uri = extra_data.get('uri') + + if 'name' in extra_data: + extra_data_name = extra_data.get('name') + else: + extra_data_name = os.path.basename(extra_data_uri) + + if 'checksum' in extra_data: + extra_data_checksum = extra_data.get('checksum') + if 'size' in extra_data: + extra_data_size = extra_data.getint('size') + if 'installed-size' in extra_data: + extra_data_installed_size = extra_data.getint('installed-size') + + extra_data_variant = GLib.Variant("a(ayttays)", + [(extra_data_name.encode("UTF-8") + b'\x00', + int.from_bytes(extra_data_size.to_bytes(8, byteorder="little"), byteorder="big"), + int.from_bytes(extra_data_installed_size.to_bytes(8, byteorder="little"), byteorder="big"), + bytes.fromhex(extra_data_checksum), + extra_data_uri)]) + return extra_data_variant.print_(True) + def _create_runtime_oci(self, tarred_filesystem, outfile): spec = self.source.spec @@ -845,6 +884,11 @@ class FlatpakBuilder: commit_args += ['--add-metadata-string', 'ostree.endoflife-rebase=' + spec.end_of_life_rebase] + extra_data = self._get_extra_data(os.path.join(builddir, 'metadata')) + if extra_data is not None: + commit_args += ['--add-metadata', + "xa.extra-data-sources=" + extra_data] + subprocess.check_call(['ostree', 'commit'] + commit_args) subprocess.check_call(['ostree', 'summary', '-u', '--repo', repo])