@@ -388,6 +388,64 @@ def configure_os_release(context: Context) -> None:
388388 if ArtifactOutput .os_release in context .config .split_artifacts :
389389 shutil .copy (osrelease , context .staging / context .config .output_split_os_release )
390390
391+ if ArtifactOutput .metainfo in context .config .split_artifacts :
392+ # https://www.freedesktop.org/software/appstream/docs/sect-Metadata-OS.html
393+ metainfo = '<?xml version="1.0" encoding="UTF-8"?>\n '
394+ metainfo += '<component type="operating-system">\n '
395+ id = name = home_url = pretty_name = None
396+ for line in osrelease .read_text ().splitlines ():
397+ if line .startswith ("ID=" ):
398+ id = line .split ("=" )[1 ].strip ('"' )
399+ elif line .startswith ("NAME=" ):
400+ name = line .split ("=" )[1 ].strip ('"' )
401+ elif line .startswith ("HOME_URL=" ):
402+ home_url = line .split ("=" )[1 ].strip ('"' )
403+ elif line .startswith ("PRETTY_NAME=" ):
404+ pretty_name = line .split ("=" )[1 ].strip ('"' )
405+
406+ # The <id> format is reverse DNS style with home_url + id
407+ if home_url :
408+ from urllib .parse import urlparse
409+
410+ url = urlparse (home_url )
411+ if url .netloc :
412+ netloc = url .netloc .split ("." )
413+ netloc .reverse ()
414+ netloc .remove ("www" )
415+ id_field = "." .join (netloc )
416+ if id :
417+ id_field += f".{ id } "
418+ metainfo += f" <id>{ id_field } </id>\n "
419+ else :
420+ metainfo += f" <id>{ id } </id>\n "
421+ if name :
422+ metainfo += f" <name>{ name } </name>\n "
423+ elif context .config .image_id :
424+ metainfo += f" <name>{ context .config .image_id } </name>\n "
425+ metainfo += f" <summary>{ id } image built with mkosi</summary>\n "
426+ if pretty_name :
427+ metainfo += f" <description><p>{ pretty_name } built with mkosi</p></description>\n "
428+ else :
429+ metainfo += " <description><p>Image built with mkosi</p></description>\n "
430+ if home_url :
431+ metainfo += f' <url type="homepage">{ home_url } </url>\n '
432+ metainfo += (
433+ ' <icon type="remote">https://brand.systemd.io/assets/svg/systemd-logomark.svg</icon>\n '
434+ )
435+ metainfo += " <metadata_license>FSFAP</metadata_license>\n "
436+ metainfo += " <releases>\n "
437+ timestamp = (
438+ datetime .datetime .fromtimestamp (context .config .source_date_epoch , tz = datetime .timezone .utc )
439+ if context .config .source_date_epoch is not None
440+ else datetime .datetime .now (tz = datetime .timezone .utc )
441+ ).isoformat ()
442+ metainfo += f' <release version="{ context .config .image_version } " date="{ timestamp } " type="development">\n ' # noqa E501
443+ metainfo += " <description></description>\n "
444+ metainfo += " </release>\n "
445+ metainfo += " </releases>\n "
446+ metainfo += "</component>\n "
447+ (context .staging / context .config .output_split_metainfo ).write_text (metainfo )
448+
391449
392450def configure_extension_release (context : Context ) -> None :
393451 if context .config .output_format not in (OutputFormat .sysext , OutputFormat .confext ):
0 commit comments