import shutil
import tempfile
-from collections.abc import Sequence
+from collections.abc import Iterable, Sequence
from pathlib import Path
from mkosi.archive import extract_tar
from mkosi.config import Architecture
from mkosi.context import Context
from mkosi.distributions import Distribution, DistributionInstaller, PackageType
-from mkosi.installer.apt import createrepo_apt, invoke_apt, setup_apt
+from mkosi.installer.apt import AptRepository, createrepo_apt, invoke_apt, setup_apt
from mkosi.log import die
from mkosi.run import run
from mkosi.sandbox import finalize_passwd_mounts
return Distribution.debian
@staticmethod
- def repositories(context: Context, local: bool = True) -> list[str]:
- archives = ("deb", "deb-src")
- components = ' '.join(("main", *context.config.repositories))
+ def repositories(context: Context, local: bool = True) -> Iterable[AptRepository]:
+ types = ("deb", "deb-src")
+ components = ("main", *context.config.repositories)
if context.config.local_mirror and local:
- return [f"deb [trusted=yes] {context.config.local_mirror} {context.config.release} {components}"]
+ yield AptRepository(
+ types=("deb",),
+ url=context.config.local_mirror,
+ suite=context.config.release,
+ components=("main",),
+ signedby=None,
+ )
+ return
mirror = context.config.mirror or "http://deb.debian.org/debian"
- signedby = "[signed-by=/usr/share/keyrings/debian-archive-keyring.gpg]"
+ signedby = "/usr/share/keyrings/debian-archive-keyring.gpg"
- repos = [
- f"{archive} {signedby} {mirror} {context.config.release} {components}"
- for archive in archives
- ]
+ yield AptRepository(
+ types=types,
+ url=mirror,
+ suite=context.config.release,
+ components=components,
+ signedby=signedby,
+ )
# Debug repos are typically not mirrored.
url = "http://deb.debian.org/debian-debug"
- repos += [f"deb {signedby} {url} {context.config.release}-debug {components}"]
-
- if context.config.release in ("unstable", "sid"):
- return repos
- repos += [
- f"{archive} {signedby} {mirror} {context.config.release}-updates {components}"
- for archive in archives
- ]
+ yield AptRepository(
+ types=types,
+ url=url,
+ suite=f"{context.config.release}-debug",
+ components=components,
+ signedby=signedby,
+ )
- # Security updates repos are never mirrored.
- url = "http://security.debian.org/debian-security "
- repos += [
- f"{archive} {signedby} {url} {context.config.release}-security {components}"
- for archive in archives
- ]
-
- return repos
+ if context.config.release in ("unstable", "sid"):
+ return
+
+ yield AptRepository(
+ types=types,
+ url=mirror,
+ suite=f"{context.config.release}-updates",
+ components=components,
+ signedby=signedby,
+ )
+
+ yield AptRepository(
+ types=types,
+ # Security updates repos are never mirrored.
+ url="http://security.debian.org/debian-security",
+ suite=f"{context.config.release}-security",
+ components=components,
+ signedby=signedby,
+ )
@classmethod
def setup(cls, context: Context) -> None:
return a
-def install_apt_sources(context: Context, repos: Sequence[str]) -> None:
+def install_apt_sources(context: Context, repos: Iterable[AptRepository]) -> None:
if not (context.root / "usr/bin/apt").exists():
return
- sources = context.root / "etc/apt/sources.list"
+ sources = context.root / f"etc/apt/sources.list.d/{context.config.release}.sources"
if not sources.exists():
with sources.open("w") as f:
for repo in repos:
- f.write(f"{repo}\n")
+ f.write(str(repo))
# SPDX-License-Identifier: LGPL-2.1+
+from collections.abc import Iterable
+
from mkosi.config import Architecture
from mkosi.context import Context
from mkosi.distributions import debian
+from mkosi.installer.apt import AptRepository
class Installer(debian.Installer):
return "lunar"
@staticmethod
- def repositories(context: Context, local: bool = True) -> list[str]:
- if context.config.local_mirror and local:
- return [f"deb [trusted=yes] {context.config.local_mirror} {context.config.release} main"]
+ def repositories(context: Context, local: bool = True) -> Iterable[AptRepository]:
+ types = ("deb", "deb-src")
- archives = ("deb", "deb-src")
+ # From kinetic onwards, the usr-is-merged package is available in universe and is required by
+ # mkosi to set up a proper usr-merged system so we add the universe repository unconditionally.
+ components = ["main"] + (["universe"] if context.config.release not in ("focal", "jammy") else [])
+ components = (*components, *context.config.repositories)
+
+ if context.config.local_mirror and local:
+ yield AptRepository(
+ types=("deb",),
+ url=context.config.local_mirror,
+ suite=context.config.release,
+ components=("main",),
+ signedby=None,
+ )
+ return
if context.config.architecture in (Architecture.x86, Architecture.x86_64):
mirror = context.config.mirror or "http://archive.ubuntu.com/ubuntu"
else:
mirror = context.config.mirror or "http://ports.ubuntu.com"
- signedby = "[signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg]"
-
- # From kinetic onwards, the usr-is-merged package is available in universe and is required by
- # mkosi to set up a proper usr-merged system so we add the universe repository unconditionally.
- components = ["main"] + (["universe"] if context.config.release not in ("focal", "jammy") else [])
- components = ' '.join((*components, *context.config.repositories))
+ signedby = "/usr/share/keyrings/ubuntu-archive-keyring.gpg"
- repos = [
- f"{archive} {signedby} {mirror} {context.config.release} {components}"
- for archive in archives
- ]
+ yield AptRepository(
+ types=types,
+ url=mirror,
+ suite=context.config.release,
+ components=components,
+ signedby=signedby,
+ )
- repos += [
- f"{archive} {signedby} {mirror} {context.config.release}-updates {components}"
- for archive in archives
- ]
+ yield AptRepository(
+ types=types,
+ url=mirror,
+ suite=f"{context.config.release}-updates",
+ components=components,
+ signedby=signedby,
+ )
# Security updates repos are never mirrored. But !x86 are on the ports server.
if context.config.architecture in [Architecture.x86, Architecture.x86_64]:
else:
mirror = "http://ports.ubuntu.com/"
- repos += [
- f"{archive} {signedby} {mirror} {context.config.release}-security {components}"
- for archive in archives
- ]
+ yield AptRepository(
+ types=types,
+ url=mirror,
+ suite=f"{context.config.release}-security",
+ components=components,
+ signedby=signedby,
+ )
- return repos
# SPDX-License-Identifier: LGPL-2.1+
import textwrap
-from collections.abc import Sequence
+from collections.abc import Iterable, Sequence
+from typing import NamedTuple, Optional
from mkosi.context import Context
from mkosi.installer import finalize_package_manager_mounts
from mkosi.util import sort_packages, umask
-def setup_apt(context: Context, repos: Sequence[str]) -> None:
+class AptRepository(NamedTuple):
+ types: tuple[str, ...]
+ url: str
+ suite: str
+ components: tuple[str, ...]
+ signedby: Optional[str]
+
+ def __str__(self) -> str:
+ return textwrap.dedent(
+ f"""\
+ Types: {" ".join(self.types)}
+ URIs: {self.url}
+ Suites: {self.suite}
+ Components: {" ".join(self.components)}
+ {"Signed-By" if self.signedby else "Trusted"}: {self.signedby or "yes"}
+
+ """
+ )
+
+
+def setup_apt(context: Context, repos: Iterable[AptRepository]) -> None:
(context.pkgmngr / "etc/apt").mkdir(exist_ok=True, parents=True)
(context.pkgmngr / "etc/apt/apt.conf.d").mkdir(exist_ok=True, parents=True)
(context.pkgmngr / "etc/apt/preferences.d").mkdir(exist_ok=True, parents=True)
)
)
- sources = context.pkgmngr / "etc/apt/sources.list"
+ sources = context.pkgmngr / "etc/apt/sources.list.d/mkosi.sources"
if not sources.exists():
with sources.open("w") as f:
for repo in repos:
- f.write(f"{repo}\n")
+ f.write(str(repo))
def apt_cmd(context: Context, command: str) -> list[PathString]: