]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Make sure apt sources are installed when BaseTrees= is in the mix
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 16 Oct 2025 12:52:37 +0000 (14:52 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 17 Oct 2025 09:56:40 +0000 (11:56 +0200)
Let's make sure to install apt sources every time we install the apt
package, even if BaseTrees= or volatile packages or such are in the mix.

To make this work we unfortunately have to reintroduce install_packages().

While we're at it, make sure the installed apt sources don't use the
configured mirror or snapshot. We only install a default set of sources
and for anything custom users should install their own sources.

13 files changed:
mkosi/__init__.py
mkosi/distribution/__init__.py
mkosi/distribution/arch.py
mkosi/distribution/azure.py
mkosi/distribution/centos.py
mkosi/distribution/debian.py
mkosi/distribution/fedora.py
mkosi/distribution/kali.py
mkosi/distribution/mageia.py
mkosi/distribution/openmandriva.py
mkosi/distribution/opensuse.py
mkosi/distribution/postmarketos.py
mkosi/distribution/ubuntu.py

index 8e6203c7393c5636b3c5ef64f239e458d348637d..a77cdb84a0fce24fe33ed2656feb9e157c065f12 100644 (file)
@@ -268,7 +268,7 @@ def install_distribution(context: Context) -> None:
         with complete_step(
             f"Installing extra packages for {context.config.distribution.installer.pretty_name()}"
         ):
-            context.config.distribution.installer.package_manager(context.config).install(context, packages)
+            context.config.distribution.installer.install_packages(context, packages)
     else:
         if context.config.overlay or context.config.output_format.is_extension_image():
             if packages:
@@ -307,9 +307,7 @@ def install_distribution(context: Context) -> None:
                 (context.root / "boot/loader/entries.srel").write_text("type1\n")
 
             if packages:
-                context.config.distribution.installer.package_manager(context.config).install(
-                    context, packages
-                )
+                context.config.distribution.installer.install_packages(context, packages)
 
     for f in (
         "var/lib/systemd/random-seed",
@@ -333,9 +331,7 @@ def install_build_packages(context: Context) -> None:
         ),
         setup_build_overlay(context),
     ):
-        context.config.distribution.installer.package_manager(context.config).install(
-            context, context.config.build_packages
-        )
+        context.config.distribution.installer.install_packages(context, context.config.build_packages)
 
 
 def install_volatile_packages(context: Context) -> None:
@@ -345,7 +341,7 @@ def install_volatile_packages(context: Context) -> None:
     with complete_step(
         f"Installing volatile packages for {context.config.distribution.installer.pretty_name()}"
     ):
-        context.config.distribution.installer.package_manager(context.config).install(
+        context.config.distribution.installer.install_packages(
             context, context.config.volatile_packages, allow_downgrade=True
         )
 
index 65753f325cc6ec5d2b40801f52d1269cb389bd63..2b8b632bd1ea7b2912f68064b4f112fdd39622e9 100644 (file)
@@ -3,6 +3,7 @@
 import enum
 import importlib
 import urllib.parse
+from collections.abc import Sequence
 from pathlib import Path
 from typing import TYPE_CHECKING, Optional
 
@@ -101,6 +102,22 @@ class DistributionInstaller:
     def install(cls, context: "Context") -> None:
         raise NotImplementedError
 
+    @classmethod
+    def install_packages(
+        cls,
+        context: "Context",
+        packages: Sequence[str],
+        *,
+        apivfs: bool = True,
+        allow_downgrade: bool = False,
+    ) -> None:
+        return cls.package_manager(context.config).install(
+            context,
+            packages,
+            apivfs=apivfs,
+            allow_downgrade=allow_downgrade,
+        )
+
     @classmethod
     def filesystem(cls) -> str:
         return "ext4"
index a01ea6636f5d7b08fb666c3a6cb5eeeca7245e72..1fc31014f5d07e1a1e07b956c7ae09f28ecef0f2 100644 (file)
@@ -62,7 +62,7 @@ class Installer(DistributionInstaller, distribution=Distribution.arch):
 
     @classmethod
     def install(cls, context: Context) -> None:
-        Pacman.install(context, ["filesystem"], apivfs=False)
+        cls.install_packages(context, ["filesystem"], apivfs=False)
 
     @classmethod
     def repositories(cls, context: Context) -> Iterable[PacmanRepository]:
index 4c036f14324f7ccedf0868f88f4a15bb95e16d87..a440cc347963f160dadb2e012a7fe4e4144df4be 100644 (file)
@@ -34,7 +34,7 @@ class Installer(fedora.Installer, distribution=Distribution.azure):
 
     @classmethod
     def install(cls, context: Context) -> None:
-        Dnf.install(context, ["filesystem", "azurelinux-release"], apivfs=False)
+        cls.install_packages(context, ["filesystem", "azurelinux-release"], apivfs=False)
 
     @classmethod
     def repositories(cls, context: Context) -> Iterable[RpmRepository]:
index 7c8e89652f4eccd83b5779def6ea42823bc6afed..57176a30a67926b2fe8888e60274e3198a64a2d7 100644 (file)
@@ -79,7 +79,7 @@ class Installer(DistributionInstaller, distribution=Distribution.centos):
 
     @classmethod
     def install(cls, context: Context) -> None:
-        Dnf.install(context, ["basesystem"], apivfs=False)
+        cls.install_packages(context, ["basesystem"], apivfs=False)
 
     @classmethod
     def architecture(cls, arch: Architecture) -> str:
index 9d1e1a5205e1bfb8c64f5c92cb97b2d6b4777df7..ca95dd42669b14bb590c62953fc9fe0c106976e4 100644 (file)
@@ -1,9 +1,8 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-import itertools
 import json
 import tempfile
-from collections.abc import Iterable
+from collections.abc import Iterable, Sequence
 from pathlib import Path
 from typing import cast
 
@@ -40,11 +39,13 @@ class Installer(DistributionInstaller, distribution=Distribution.debian):
         return Apt
 
     @classmethod
-    def repositories(cls, context: Context, local: bool = True) -> Iterable[AptRepository]:
+    def repositories(cls, context: Context, for_image: bool = False) -> Iterable[AptRepository]:
         types = ("deb", "deb-src")
         components = ("main", *context.config.repositories)
+        mirror = None if for_image else context.config.mirror
+        snapshot = None if for_image else context.config.snapshot
 
-        if context.config.local_mirror and local:
+        if context.config.local_mirror and not for_image:
             yield AptRepository(
                 types=("deb",),
                 url=context.config.local_mirror,
@@ -54,15 +55,15 @@ class Installer(DistributionInstaller, distribution=Distribution.debian):
             )
             return
 
-        if context.config.mirror:
-            mirror = context.config.mirror
-        elif context.config.snapshot:
+        if mirror:
+            pass
+        elif snapshot:
             mirror = "https://snapshot.debian.org"
         else:
             mirror = "http://deb.debian.org"
 
-        if context.config.snapshot:
-            url = join_mirror(mirror, f"archive/debian/{context.config.snapshot}")
+        if snapshot:
+            url = join_mirror(mirror, f"archive/debian/{snapshot}")
         else:
             url = join_mirror(mirror, "debian")
 
@@ -77,8 +78,8 @@ class Installer(DistributionInstaller, distribution=Distribution.debian):
         )
 
         # Debug repos are typically not mirrored.
-        if context.config.snapshot:
-            url = join_mirror(mirror, f"archive/debian-debug/{context.config.snapshot}")
+        if snapshot:
+            url = join_mirror(mirror, f"archive/debian-debug/{snapshot}")
         else:
             url = join_mirror(mirror, "debian-debug")
 
@@ -93,7 +94,7 @@ class Installer(DistributionInstaller, distribution=Distribution.debian):
         if context.config.release in ("unstable", "sid"):
             return
 
-        if not context.config.snapshot:
+        if not snapshot:
             yield AptRepository(
                 types=types,
                 url=join_mirror(mirror, "debian"),
@@ -103,8 +104,8 @@ class Installer(DistributionInstaller, distribution=Distribution.debian):
             )
 
         # Security updates repos are never mirrored.
-        if context.config.snapshot:
-            url = join_mirror(mirror, f"archive/debian-security/{context.config.snapshot}")
+        if snapshot:
+            url = join_mirror(mirror, f"archive/debian-security/{snapshot}")
         else:
             url = join_mirror(mirror, "debian-security")
 
@@ -210,15 +211,25 @@ class Installer(DistributionInstaller, distribution=Distribution.debian):
         # Finally, run apt to properly install packages in the chroot without having to worry that maintainer
         # scripts won't find basic tools that they depend on.
 
-        Apt.install(context, [Path(deb).name.partition("_")[0].removesuffix(".deb") for deb in essential])
+        cls.install_packages(
+            context, [Path(deb).name.partition("_")[0].removesuffix(".deb") for deb in essential]
+        )
 
         fixup_os_release(context)
 
-        if (
-            "apt" in itertools.chain(context.config.packages, context.config.volatile_packages)
-            or (context.root / "usr/bin/apt").exists()
-        ):
-            install_apt_sources(context, cls.repositories(context, local=False))
+    @classmethod
+    def install_packages(
+        cls,
+        context: Context,
+        packages: Sequence[str],
+        *,
+        apivfs: bool = True,
+        allow_downgrade: bool = False,
+    ) -> None:
+        super().install_packages(context, packages, apivfs=apivfs, allow_downgrade=allow_downgrade)
+
+        if "apt" in packages:
+            install_apt_sources(context, cls.repositories(context, for_image=True))
 
     @classmethod
     def architecture(cls, arch: Architecture) -> str:
index 3574fe8acb4f037d87140468d6a7022d81f4722a..8a8cc4fac5dfcdf09d897185895d133194dfe095 100644 (file)
@@ -137,7 +137,7 @@ class Installer(DistributionInstaller, distribution=Distribution.fedora):
 
     @classmethod
     def install(cls, context: Context) -> None:
-        Dnf.install(context, ["basesystem"], apivfs=False)
+        cls.install_packages(context, ["basesystem"], apivfs=False)
 
     @classmethod
     def repositories(cls, context: Context) -> Iterable[RpmRepository]:
index 9de806d15821b052d0730b8d6ebef3fc7ac2221c..d3dec56b7cffaefffe719850cb7acf7dab539de6 100644 (file)
@@ -24,11 +24,15 @@ class Installer(debian.Installer, distribution=Distribution.kali):
         return Distribution.kali
 
     @classmethod
-    def repositories(cls, context: Context, local: bool = True) -> Iterable[AptRepository]:
-        if context.config.snapshot:
+    def repositories(cls, context: Context, for_image: bool = False) -> Iterable[AptRepository]:
+        mirror = None if for_image else context.config.mirror
+        if not mirror:
+            mirror = "http://http.kali.org/kali"
+
+        if context.config.snapshot and not for_image:
             die(f"Snapshot= is not supported for {cls.pretty_name()}")
 
-        if context.config.local_mirror and local:
+        if context.config.local_mirror and not for_image:
             yield AptRepository(
                 types=("deb",),
                 url=context.config.local_mirror,
@@ -40,7 +44,7 @@ class Installer(debian.Installer, distribution=Distribution.kali):
 
         yield AptRepository(
             types=("deb", "deb-src"),
-            url=context.config.mirror or "http://http.kali.org/kali",
+            url=mirror,
             suite=context.config.release,
             components=("main", *context.config.repositories),
             signedby=Path("/usr/share/keyrings/kali-archive-keyring.gpg"),
index 43756bef73375b14c9eea2c6c8b693d3e697a677..657af17c64e753b5fe387eb2b36ac7bbbd1372e9 100644 (file)
@@ -5,7 +5,6 @@ from collections.abc import Iterable
 from mkosi.config import Architecture
 from mkosi.context import Context
 from mkosi.distribution import Distribution, fedora, join_mirror
-from mkosi.installer.dnf import Dnf
 from mkosi.installer.rpm import RpmRepository, find_rpm_gpgkey
 from mkosi.log import die
 
@@ -25,7 +24,7 @@ class Installer(fedora.Installer, distribution=Distribution.mageia):
 
     @classmethod
     def install(cls, context: Context) -> None:
-        Dnf.install(context, ["filesystem"], apivfs=False)
+        cls.install_packages(context, ["filesystem"], apivfs=False)
 
     @classmethod
     def repositories(cls, context: Context) -> Iterable[RpmRepository]:
index dd9661ed87340ecaeca58f13f55e22438e4b3ddf..424a04f249615d0812407d1f9d1e4f354d211a98 100644 (file)
@@ -5,7 +5,6 @@ from collections.abc import Iterable
 from mkosi.config import Architecture
 from mkosi.context import Context
 from mkosi.distribution import Distribution, fedora, join_mirror
-from mkosi.installer.dnf import Dnf
 from mkosi.installer.rpm import RpmRepository, find_rpm_gpgkey
 from mkosi.log import die
 
@@ -25,7 +24,7 @@ class Installer(fedora.Installer, distribution=Distribution.openmandriva):
 
     @classmethod
     def install(cls, context: Context) -> None:
-        Dnf.install(context, ["filesystem"], apivfs=False)
+        cls.install_packages(context, ["filesystem"], apivfs=False)
 
     @classmethod
     def repositories(cls, context: Context) -> Iterable[RpmRepository]:
index 58f96f9b14de4ad29da7bedf7388a7dcf83add55..44e4c3a68b18747e750391d6e42e5179ea41f1ca 100644 (file)
@@ -57,7 +57,7 @@ class Installer(DistributionInstaller, distribution=Distribution.opensuse):
         if not any(p.endswith("-release") for p in context.config.packages):
             packages += ["openSUSE-release"]
 
-        cls.package_manager(context.config).install(context, packages, apivfs=False)
+        cls.install_packages(context, packages, apivfs=False)
 
     @classmethod
     def repositories(cls, context: Context) -> Iterable[RpmRepository]:
index 267435dfc9f71fb9ca12ab1c66aa317921ca5843..7673e1aaaaf0976d6fa3d2302cc362c712e9da41 100644 (file)
@@ -71,7 +71,7 @@ class Installer(DistributionInstaller, distribution=Distribution.postmarketos):
             (context.root / "usr" / dir).mkdir(parents=True, exist_ok=True)
             (context.root / dir).symlink_to(f"usr/{dir}")
 
-        Apk.install(context, ["postmarketos-baselayout", "postmarketos-release"], apivfs=False)
+        cls.install_packages(context, ["postmarketos-baselayout", "postmarketos-release"], apivfs=False)
 
     @classmethod
     def repositories(cls, context: Context) -> Iterable[ApkRepository]:
index c84e5fd0434854f9c455f5808d5398b6ccec7bea..2112b4e8f9971cc922d4acdd962e802f2bda8e01 100644 (file)
@@ -28,15 +28,17 @@ class Installer(debian.Installer, distribution=Distribution.ubuntu):
         return Distribution.debian
 
     @classmethod
-    def repositories(cls, context: Context, local: bool = True) -> Iterable[AptRepository]:
+    def repositories(cls, context: Context, for_image: bool = False) -> Iterable[AptRepository]:
         types = ("deb", "deb-src")
+        mirror = None if for_image else context.config.mirror
+        snapshot = None if for_image else context.config.snapshot
 
         components = (
             "main",
             *context.config.repositories,
         )
 
-        if context.config.local_mirror and local:
+        if context.config.local_mirror and not for_image:
             yield AptRepository(
                 types=("deb",),
                 url=context.config.local_mirror,
@@ -46,10 +48,12 @@ class Installer(debian.Installer, distribution=Distribution.ubuntu):
             )
             return
 
-        if context.config.architecture.is_x86_variant():
-            mirror = context.config.mirror or "http://archive.ubuntu.com/ubuntu"
+        if mirror:
+            pass
+        elif context.config.architecture.is_x86_variant():
+            mirror = "http://archive.ubuntu.com/ubuntu"
         else:
-            mirror = context.config.mirror or "http://ports.ubuntu.com"
+            mirror = "http://ports.ubuntu.com"
 
         signedby = Path("/usr/share/keyrings/ubuntu-archive-keyring.gpg")
 
@@ -59,7 +63,7 @@ class Installer(debian.Installer, distribution=Distribution.ubuntu):
             suite=context.config.release,
             components=components,
             signedby=signedby,
-            snapshot=context.config.snapshot,
+            snapshot=snapshot,
         )
 
         yield AptRepository(
@@ -68,7 +72,7 @@ class Installer(debian.Installer, distribution=Distribution.ubuntu):
             suite=f"{context.config.release}-updates",
             components=components,
             signedby=signedby,
-            snapshot=context.config.snapshot,
+            snapshot=snapshot,
         )
 
         # Security updates repos are never mirrored. But !x86 are on the ports server.
@@ -83,7 +87,7 @@ class Installer(debian.Installer, distribution=Distribution.ubuntu):
             suite=f"{context.config.release}-security",
             components=components,
             signedby=signedby,
-            snapshot=context.config.snapshot,
+            snapshot=snapshot,
         )
 
     @classmethod