Repository: osbuild/osbuild
Pull request #247 (2020-02-29 11:01:31)

Improvements on `detect_os()`
Two minor improvements on the recently introduced `detect_os()` function. Details in each commit-message.


Patch:
diff --git a/osbuild/pipeline.py b/osbuild/pipeline.py
index 50b3c9f1..6fda954e 100644
--- a/osbuild/pipeline.py
+++ b/osbuild/pipeline.py
@@ -302,31 +302,36 @@ class Pipeline:
         return results
 
 
-def detect_os(*paths):
-    """Detect the os from an os-release file.
+def describe_os(*paths):
+    """Read the Operating System Description from `os-release`
 
-    The first file in 'paths' is used and interpreted like a os-release(5)
-    file.
+    This creates a string describing the running operating-system name and
+    version. It reads the information from the path array provided as `paths`.
+    The first available file takes precedence. It must be formatted according
+    to the rules in `os-release(5)`.
 
-    Returns ID + VERSION_ID (without dots), which is the same format that
-    runners are named as.
+    The returned string uses the format `${ID}${VERSION_ID}` with all dots
+    stripped.
     """
+    osrelease = {}
+
     path = next((p for p in paths if os.path.exists(p)), None)
-    if not path:
-        raise FileNotFoundError("none of the specified os-release files exist")
+    if path:
+        with open(path) as f:
+            for line in f:
+                line = line.strip()
+                if not line:
+                    continue
+                if line[0] == "#":
+                    continue
+                key, value = line.split("=", 1)
+                osrelease[key] = value.strip('"')
 
-    with open(path) as f:
-        osrelease = {}
-        for line in f:
-            line = line.strip()
-            if not line:
-                continue
-            if line[0] == "#":
-                continue
-            key, value = line.split("=", 1)
-            osrelease[key] = value.strip('"')
+    # Fetch `ID` and `VERSION_ID`. Defaults are defined in `os-release(5)`.
+    osrelease_id = osrelease.get("ID", "linux")
+    osrelease_version_id = osrelease.get("VERSION_ID", "")
 
-    return osrelease["ID"] + osrelease["VERSION_ID"].replace(".", "")
+    return osrelease_id + osrelease_version_id.replace(".", "")
 
 
 def load_build(description, sources_options):
@@ -344,7 +349,7 @@ def load(description, sources_options):
     if build:
         build_pipeline, runner = load_build(build, sources_options)
     else:
-        build_pipeline, runner = None, "org.osbuild." + detect_os("/etc/os-release", "/usr/lib/os-release")
+        build_pipeline, runner = None, "org.osbuild." + describe_os("/etc/os-release", "/usr/lib/os-release")
 
     pipeline = Pipeline(runner, build_pipeline)
 


Test patch:
diff --git a/test/os-release/arch b/test/os-release/arch
new file mode 100644
index 00000000..560b8ae4
--- /dev/null
+++ b/test/os-release/arch
@@ -0,0 +1,10 @@
+NAME="Arch Linux"
+PRETTY_NAME="Arch Linux"
+ID=arch
+BUILD_ID=rolling
+ANSI_COLOR="0;36"
+HOME_URL="https://www.archlinux.org/"
+DOCUMENTATION_URL="https://wiki.archlinux.org/"
+SUPPORT_URL="https://bbs.archlinux.org/"
+BUG_REPORT_URL="https://bugs.archlinux.org/"
+LOGO=archlinux
diff --git a/test/os-release/linux b/test/os-release/linux
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_osrelease.py b/test/test_osrelease.py
index 1c8578cd..5d687399 100644
--- a/test/test_osrelease.py
+++ b/test/test_osrelease.py
@@ -5,13 +5,14 @@ import osbuild
 
 class TestOSRelease(unittest.TestCase):
     def test_non_existant(self):
-        self.assertRaises(FileNotFoundError, osbuild.pipeline.detect_os, "💩")
+        """Verify default os-release value, if no files are given."""
+        self.assertEqual(osbuild.pipeline.describe_os(), "linux")
 
-    def test_detect_os(self):
+    def test_describe_os(self):
         """Test host os detection. test/os-release contains the os-release files
         for all supported runners.
         """
         for entry in os.scandir("test/os-release"):
             with self.subTest(entry.name):
-                self.assertEqual(osbuild.pipeline.detect_os(entry.path), entry.name)
+                self.assertEqual(osbuild.pipeline.describe_os(entry.path), entry.name)