]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Sort packages during parsing
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 5 Mar 2025 14:15:07 +0000 (15:15 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 6 Mar 2025 10:08:32 +0000 (11:08 +0100)
mkosi/config.py
mkosi/distributions/arch.py
mkosi/distributions/opensuse.py
mkosi/util.py
tests/test_config.py

index 112f5edfc4ddd97a53740492b27dee658a7da3a9..152b757153a4ab889fbdb3ebff474fe0ceb3aca4 100644 (file)
@@ -1060,12 +1060,23 @@ def config_make_enum_matcher(type: type[SE]) -> ConfigMatchCallback[SE]:
     return config_match_enum
 
 
+def package_sort_key(package: str) -> tuple[int, str]:
+    """Sorts packages: normal first, paths second, conditional third"""
+
+    if package.startswith("("):
+        return 2, package
+    elif package.startswith("/"):
+        return 1, package
+    return 0, package
+
+
 def config_make_list_parser(
     *,
     delimiter: Optional[str] = None,
     parse: Callable[[str], T] = str,  # type: ignore # see mypy#3737
     unescape: bool = False,
     reset: bool = True,
+    key: Optional[Callable[[T], Any]] = None,
 ) -> ConfigParseCallback[list[T]]:
     def config_parse_list(value: Optional[str], old: Optional[list[T]]) -> Optional[list[T]]:
         new = old.copy() if old else []
@@ -1090,7 +1101,12 @@ def config_make_list_parser(
             if reset and len(values) == 1 and values[0] == "":
                 return None
 
-        return new + [parse(v) for v in values if v]
+        new += [parse(v) for v in values if v]
+
+        if key:
+            new.sort(key=key)
+
+        return new
 
     return config_parse_list
 
@@ -2719,7 +2735,7 @@ SETTINGS: list[ConfigSetting[Any]] = [
         long="--package",
         metavar="PACKAGE",
         section="Content",
-        parse=config_make_list_parser(delimiter=","),
+        parse=config_make_list_parser(delimiter=",", key=package_sort_key),
         help="Add an additional package to the OS image",
     ),
     ConfigSetting(
@@ -2727,7 +2743,7 @@ SETTINGS: list[ConfigSetting[Any]] = [
         long="--build-package",
         metavar="PACKAGE",
         section="Content",
-        parse=config_make_list_parser(delimiter=","),
+        parse=config_make_list_parser(delimiter=",", key=package_sort_key),
         help="Additional packages needed for build scripts",
     ),
     ConfigSetting(
@@ -2735,7 +2751,7 @@ SETTINGS: list[ConfigSetting[Any]] = [
         long="--volatile-package",
         metavar="PACKAGE",
         section="Content",
-        parse=config_make_list_parser(delimiter=","),
+        parse=config_make_list_parser(delimiter=",", key=package_sort_key),
         help="Packages to install after executing build scripts",
     ),
     ConfigSetting(
index cd9a81f50a14b734fad5e6fae9f67045d49ba094..382742c2571e5f6de8626fb763bae4f01f2d9671 100644 (file)
@@ -12,7 +12,6 @@ from mkosi.distributions import DistributionInstaller, PackageType
 from mkosi.installer import PackageManager
 from mkosi.installer.pacman import Pacman, PacmanRepository
 from mkosi.log import complete_step, die
-from mkosi.util import sort_packages
 
 
 class Installer(DistributionInstaller):
@@ -70,7 +69,7 @@ class Installer(DistributionInstaller):
         Pacman.invoke(
             context,
             "--sync",
-            ["--needed", "--assume-installed", "initramfs", *sort_packages(packages)],
+            ["--needed", "--assume-installed", "initramfs", *packages],
             apivfs=apivfs,
         )
 
index 17c6c253ba9b9ddf59514c19a797f6f9e97420b0..7ecc380209925ee0b0e04468475057d017e5104d 100644 (file)
@@ -16,7 +16,6 @@ from mkosi.installer.zypper import Zypper
 from mkosi.log import die
 from mkosi.mounts import finalize_certificate_mounts
 from mkosi.run import run
-from mkosi.util import sort_packages
 
 
 class Installer(DistributionInstaller):
@@ -70,17 +69,17 @@ class Installer(DistributionInstaller):
                 [
                     "--download", "in-advance",
                     "--recommends" if context.config.with_recommends else "--no-recommends",
-                    *sort_packages(packages),
+                    *packages,
                 ],
                 apivfs=apivfs,
             )  # fmt: skip
         else:
-            Dnf.invoke(context, "install", sort_packages(packages), apivfs=apivfs)
+            Dnf.invoke(context, "install", packages, apivfs=apivfs)
 
     @classmethod
     def remove_packages(cls, context: Context, packages: Sequence[str]) -> None:
         if context.config.find_binary("zypper"):
-            Zypper.invoke(context, "remove", ["--clean-deps", *sort_packages(packages)], apivfs=True)
+            Zypper.invoke(context, "remove", ["--clean-deps", *packages], apivfs=True)
         else:
             Dnf.invoke(context, "remove", packages, apivfs=True)
 
index b21ed689efa4d617e87d1ce3e37c697032cde41b..fe8c8006ef62b797a4e52c28cb8e9a3c81f0da48 100644 (file)
@@ -99,13 +99,6 @@ def format_rlimit(rlimit: int) -> str:
     return f"{soft}:{hard}"
 
 
-def sort_packages(packages: Iterable[str]) -> list[str]:
-    """Sorts packages: normal first, paths second, conditional third"""
-
-    m = {"(": 2, "/": 1}
-    return sorted(packages, key=lambda name: (m.get(name[0], 0), name))
-
-
 def flatten(lists: Iterable[Iterable[T]]) -> list[T]:
     """Flatten a sequence of sequences into a single list."""
     return list(itertools.chain.from_iterable(lists))
index 46c32c12e1b9a3cd6641e9dc8edcdfa1b6c17620..d822da9fc4717599120844b4378ac1a96597b4b5 100644 (file)
@@ -100,8 +100,8 @@ def test_parse_config(tmp_path: Path) -> None:
         Architecture=arm64
         Repositories=epel,epel-next
 
-        [Content]
-        Packages=abc
+        [Config]
+        Profiles=abc
 
         [Build]
         Environment=MY_KEY=MY_VALUE
@@ -120,7 +120,7 @@ def test_parse_config(tmp_path: Path) -> None:
 
     assert config.distribution == Distribution.ubuntu
     assert config.architecture == Architecture.arm64
-    assert config.packages == ["abc"]
+    assert config.profiles == ["abc"]
     assert config.output_format == OutputFormat.cpio
     assert config.image_id == "base"
 
@@ -163,8 +163,8 @@ def test_parse_config(tmp_path: Path) -> None:
         [Distribution]
         Distribution=debian
 
-        [Content]
-        Packages=qed
+        [Config]
+        Profiles=qed
                  def
 
         [Output]
@@ -175,13 +175,13 @@ def test_parse_config(tmp_path: Path) -> None:
     )
 
     with chdir(d):
-        _, [config] = parse_config(["--package", "last"])
+        _, [config] = parse_config(["--profile", "last"])
 
     # Setting a value explicitly in a dropin should override the default from mkosi.conf.
     assert config.distribution == Distribution.debian
     # Lists should be merged by appending the new values to the existing values. Any values from the CLI
     # should be appended to the values from the configuration files.
-    assert config.packages == ["abc", "qed", "def", "last"]
+    assert config.profiles == ["abc", "qed", "def", "last"]
     assert config.output_format == OutputFormat.cpio
     assert config.image_id == "00-dropin"
     assert config.image_version == "0"
@@ -329,7 +329,7 @@ def test_parse_includes_once(tmp_path: Path) -> None:
 
     with chdir(d):
         _, [config] = parse_config(["--include", "abc.conf", "--include", "abc.conf"])
-        assert config.build_packages == ["def", "abc"]
+        assert config.build_packages == ["abc", "def"]
 
     (d / "mkosi.images").mkdir()