]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Only parse each path included with Include= once
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 2 Oct 2023 11:08:30 +0000 (13:08 +0200)
committerJörg Behrmann <behrmann@physik.fu-berlin.de>
Mon, 2 Oct 2023 13:17:32 +0000 (15:17 +0200)
Even if a path is included multiple times using Include=, let's make
sure we only parse it once.

mkosi/config.py
mkosi/resources/mkosi.md
tests/test_config.py

index 03d3698da030555c76a8c1240286eda87a47ad86..336d94d39fdb8c042963a7b5e82d80e3967b5892 100644 (file)
@@ -1969,6 +1969,8 @@ def parse_config(argv: Sequence[str] = ()) -> tuple[MkosiArgs, tuple[MkosiConfig
     settings_lookup_by_name = {name: s for s in SETTINGS for name in [s.name, *s.compat_names]}
     settings_lookup_by_dest = {s.dest: s for s in SETTINGS}
     match_lookup = {m.name: m for m in MATCHES}
+    # Compare inodes instead of paths so we can't get tricked by bind mounts and such.
+    parsed_includes: set[tuple[int, int]] = set()
 
     @contextlib.contextmanager
     def parse_new_includes(
@@ -1982,7 +1984,13 @@ def parse_config(argv: Sequence[str] = ()) -> tuple[MkosiArgs, tuple[MkosiConfig
         finally:
             # Parse any includes that were added after yielding.
             for p in getattr(namespace, "include", [])[l:]:
+                st = p.stat()
+
+                if (st.st_dev, st.st_ino) in parsed_includes:
+                    continue
+
                 parse_config(p, namespace, defaults)
+                parsed_includes.add((st.st_dev, st.st_ino))
 
     class MkosiAction(argparse.Action):
         def __call__(
index 4f5d3d6e908ca2b3249c9c9c8ec29a41fd1a996e..259ff6b136695a1f2415e9901f9af419d3b59119 100644 (file)
@@ -366,6 +366,9 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
   configuration is included after parsing all the other configuration
   files.
 
+: Note that each path containing extra configuration is only parsed
+  once, even if included more than once with `Include=`.
+
 ### [Preset] Section
 
 `Presets=`, `--preset=`
index 89fa124d6f1a59cffebfc52a1ec0bdfdc5a157d9..acd1afb8e9189ebf8f82c453c1889893d173c3fd 100644 (file)
@@ -186,6 +186,7 @@ def test_parse_config(tmp_path: Path) -> None:
         """\
         [Content]
         Bootable=yes
+        BuildPackages=abc
         """
     )
     (tmp_path / "abc/mkosi.conf.d").mkdir()
@@ -202,9 +203,11 @@ def test_parse_config(tmp_path: Path) -> None:
         assert config.split_artifacts == False
 
         # Passing the directory should include both the main config file and the dropin.
-        _, [config] = parse_config(["--include", os.fspath(tmp_path / "abc")])
+        _, [config] = parse_config(["--include", os.fspath(tmp_path / "abc")] * 2)
         assert config.bootable == ConfigFeature.enabled
         assert config.split_artifacts == True
+        # The same extra config should not be parsed more than once.
+        assert config.build_packages == ["abc"]
 
         # Passing the main config file should not include the dropin.
         _, [config] = parse_config(["--include", os.fspath(tmp_path / "abc/mkosi.conf")])