Support AppStream merging
Add support for AppStream merging. That’s the feature in appstream where you have
<components>
<component merge="append">
<id>some-id.desktop</id>
<!-- content to merge into canonical copy of the component with this ID -->
</components>
It’s intended to be used (and is used) by distributions to allow them to append metadata to components. For example, to mark them as featured or set their carousel background colour.
gnome-software currently supports it kind of accidentally:
-
gs_plugin_appstream_check_silo()
adds all the AppStream files from the system to a singleXbBuilder
. That includes full AppStream files and ones which containmerge
s. -
xb_builder_compile()
callsxb_builder_compile_source()
for each of these AppStream sources, and compiles them all into one XML silo, adding all the<component>
s to a single root. This effectively concatenates all the XML files. - This silo is taken to use for all gnome-software appstream queries
- When (for example) querying for category apps, perhaps for the
AudioVideo::Featured
category, gnome-software runs the querycomponents/component/categories/category[text()='AudioVideo']/../category[text()='Featured']/../..
. This queries the entire silo, and selects allcomponent
s, in allcomponents
lists, which have two categories,AudioVideo
andFeatured
. So far so correct. - If one of the AppStream files contains
<component merge="append"><id>…</id><categories><category>Featured</category></categories></component>
, that won’t get selected by the query, since it only has one<category>
. But that category is supposed to have been merged in to the canonical list of categories for that app. That’s what the reference implementation, libappstream, does.
Overall, vendors can work around this bug by including a full list of categories in their overrides for apps. The underlying problem is that the way gnome-software handles AppStream is pretty fragile. There are going to be many, many other situations with merge="append"
(not to mention the other values of the merge
attribute) which will break with the current implementation.