summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2016-06-07 16:28:32 +0100
committerRichard Hughes <richard@hughsie.com>2016-06-08 18:02:57 +0100
commit25d942831dba7d44c4044e960da7bc04dce58f17 (patch)
treebaa94e98d7cc7bbca06d18bc9d51dba65e7a9de0
parent960a6d9d22d6f7756093ffdb5fa46c1b588991e3 (diff)
downloadappstream-glib-25d942831dba7d44c4044e960da7bc04dce58f17.tar.gz
Allow setting the id prefix and origin using a symlink file name
The idea is to encode the scope and user-specified origin in the filename as flatpak remotes have metadata with the filename `appstream.xml.gz` that have origin harcoded to 'flatpak'. We can't set a custom origin when generating the metadata as the remote name is set client side and can be any string the user chooses. It's also expected that something like gnome-software will keep the symlink cache up to date. I'm using ~/.local/share/app-info/xmls at the moment, but if we decide that the data is actually gnome-software specific then it can move.
-rw-r--r--data/tests/Makefile.am2
-rw-r--r--data/tests/appstream.xml5
l---------data/tests/flatpak_remote-name.xml1
-rw-r--r--libappstream-glib/as-self-test.c40
-rw-r--r--libappstream-glib/as-store.c83
5 files changed, 120 insertions, 11 deletions
diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am
index cf8d5f5..6034e2b 100644
--- a/data/tests/Makefile.am
+++ b/data/tests/Makefile.am
@@ -8,6 +8,7 @@ test_files = \
app-1-1.fc21.x86_64.rpm \
app-console-1-1.fc21.noarch.rpm \
app-extra-1-1.fc21.noarch.rpm \
+ appstream.xml \
asb-self-test.xml.gz \
broken.appdata.xml \
broken.metainfo.xml \
@@ -26,6 +27,7 @@ test_files = \
firmware/2_0_2/firmware.bin \
firmware/2_0_2/firmware.inf \
firmware/2_0_2/firmware.metainfo.xml \
+ flatpak_remote-name.xml \
font-1-1.fc21.noarch.rpm \
font-serif-1-1.fc21.noarch.rpm \
intltool.appdata.xml.in \
diff --git a/data/tests/appstream.xml b/data/tests/appstream.xml
new file mode 100644
index 0000000..630583d
--- /dev/null
+++ b/data/tests/appstream.xml
@@ -0,0 +1,5 @@
+<components origin="flatpak">
+<component type="desktop">
+<id>test.desktop</id>
+</component>
+</components>
diff --git a/data/tests/flatpak_remote-name.xml b/data/tests/flatpak_remote-name.xml
new file mode 120000
index 0000000..ce18932
--- /dev/null
+++ b/data/tests/flatpak_remote-name.xml
@@ -0,0 +1 @@
+appstream.xml \ No newline at end of file
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c
index be52bb2..ee02369 100644
--- a/libappstream-glib/as-self-test.c
+++ b/libappstream-glib/as-self-test.c
@@ -2921,6 +2921,45 @@ as_test_store_prefix_func (void)
"flatpak-user:org.gnome.Software.desktop");
}
+/* load a store with a origin and scope encoded in the symlink name */
+static void
+as_test_store_flatpak_func (void)
+{
+ AsApp *app;
+ GError *error = NULL;
+ GPtrArray *apps;
+ gboolean ret;
+ g_autofree gchar *filename = NULL;
+ g_autofree gchar *filename_root = NULL;
+ g_autoptr(AsStore) store = NULL;
+ g_autoptr(GFile) file = NULL;
+
+ /* make throws us under a bus, yet again */
+ g_setenv ("AS_SELF_TEST_PREFIX_DELIM", "_", TRUE);
+
+ /* load a symlinked file to the store */
+ store = as_store_new ();
+ filename_root = as_test_get_filename (".");
+ filename = g_build_filename (filename_root, "flatpak_remote-name.xml", NULL);
+ file = g_file_new_for_path (filename);
+ ret = as_store_from_file (store, file, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+
+ /* test extraction of symlink data */
+ g_assert_cmpstr (as_store_get_origin (store), ==, "flatpak");
+ g_assert_cmpint (as_store_get_size (store), ==, 1);
+ apps = as_store_get_apps (store);
+ g_assert_cmpint (apps->len, ==, 1);
+ app = g_ptr_array_index (apps, 0);
+ g_assert_cmpstr (as_app_get_id (app), ==, "flatpak:test.desktop");
+ g_assert_cmpstr (as_app_get_origin (app), ==, "flatpak_remote-name");
+ g_assert_cmpstr (as_app_get_source_file (app), ==, filename);
+
+ /* back to normality */
+ g_unsetenv ("AS_SELF_TEST_PREFIX_DELIM");
+}
+
/* demote the .desktop "application" to an addon */
static void
as_test_store_demote_func (void)
@@ -4871,6 +4910,7 @@ main (int argc, char **argv)
g_test_add_func ("/AppStream/store{auto-reload-dir}", as_test_store_auto_reload_dir_func);
g_test_add_func ("/AppStream/store{auto-reload-file}", as_test_store_auto_reload_file_func);
}
+ g_test_add_func ("/AppStream/store{flatpak}", as_test_store_flatpak_func);
g_test_add_func ("/AppStream/store{prefix}", as_test_store_prefix_func);
g_test_add_func ("/AppStream/store{demote}", as_test_store_demote_func);
g_test_add_func ("/AppStream/store{cab}", as_test_store_cab_func);
diff --git a/libappstream-glib/as-store.c b/libappstream-glib/as-store.c
index 79b1fda..53e89bf 100644
--- a/libappstream-glib/as-store.c
+++ b/libappstream-glib/as-store.c
@@ -1030,14 +1030,22 @@ as_store_from_root (AsStore *store,
AsNode *apps;
AsNode *n;
const gchar *tmp;
+ const gchar *origin_delim = ":";
+ gchar *str;
g_autofree AsNodeContext *ctx = NULL;
g_autofree gchar *icon_path = NULL;
+ g_autofree gchar *id_prefix_app = NULL;
g_autofree gchar *origin_app = NULL;
_cleanup_uninhibit_ guint32 *tok = NULL;
g_autoptr(AsProfileTask) ptask = NULL;
g_return_val_if_fail (AS_IS_STORE (store), FALSE);
+ /* make throws us under a bus, yet again */
+ tmp = g_getenv ("AS_SELF_TEST_PREFIX_DELIM");
+ if (tmp != NULL)
+ origin_delim = tmp;
+
/* profile */
ptask = as_profile_start_literal (priv->profile, "AsStore:store-from-root");
@@ -1067,14 +1075,64 @@ as_store_from_root (AsStore *store,
if (tmp != NULL)
as_store_set_origin (store, tmp);
- /* special case flatpak */
- if (source_filename != NULL &&
- as_bundle_kind_from_string (priv->origin) == AS_BUNDLE_KIND_FLATPAK) {
+ /* origin has prefix already specified in the XML */
+ if (priv->origin != NULL) {
+ str = g_strstr_len (priv->origin, -1, origin_delim);
+ if (str != NULL) {
+ id_prefix_app = g_strdup (priv->origin);
+ str = g_strstr_len (id_prefix_app, -1, origin_delim);
+ if (str != NULL) {
+ str[0] = '\0';
+ origin_app = g_strdup (str + 1);
+ }
+ }
+ }
+
+ /* special case flatpak symlinks -- scope:name.xml.gz */
+ if (origin_app == NULL &&
+ g_strcmp0 (priv->origin, "flatpak") == 0 &&
+ source_filename != NULL &&
+ g_file_test (source_filename, G_FILE_TEST_IS_SYMLINK)) {
+ g_autofree gchar *source_basename = NULL;
+
+ /* get the origin */
+ source_basename = g_path_get_basename (source_filename);
+ str = g_strrstr (source_basename, ".xml");
+ if (str != NULL) {
+ str[0] = '\0';
+ origin_app = g_strdup (source_basename);
+ }
+
+ /* get the id-prefix */
+ str = g_strstr_len (source_basename, -1, origin_delim);
+ if (str != NULL) {
+ str[0] = '\0';
+ id_prefix_app = g_strdup (source_basename);
+ }
+ }
+
+ /* FIXME: we can remove this helper when nuking FLATPAK */
+ if (origin_app == NULL &&
+ source_filename != NULL &&
+ g_strcmp0 (priv->origin, "flatpak") == 0) {
+ id_prefix_app = g_strdup (id_prefix);
origin_app = as_store_get_origin_for_flatpak (source_filename);
+ }
+
+ /* fallback */
+ if (origin_app == NULL) {
+ id_prefix_app = g_strdup (id_prefix);
+ origin_app = g_strdup (priv->origin);
+ }
+
+ /* print what cleverness we did */
+ if (g_strcmp0 (origin_app, priv->origin) != 0) {
g_debug ("using app origin of '%s' rather than '%s'",
origin_app, priv->origin);
- } else {
- origin_app = g_strdup (priv->origin);
+ }
+ if (g_strcmp0 (id_prefix_app, id_prefix) != 0) {
+ g_debug ("using app prefix of '%s' rather than '%s'",
+ id_prefix_app, id_prefix);
}
/* guess the icon path after we've read the origin and then look for
@@ -1084,12 +1142,12 @@ as_store_from_root (AsStore *store,
topdir = g_path_get_basename (icon_prefix);
if ((g_strcmp0 (topdir, "xmls") == 0 ||
g_strcmp0 (topdir, "yaml") == 0)
- && priv->origin != NULL) {
+ && origin_app != NULL) {
g_autofree gchar *dirname = NULL;
dirname = g_path_get_dirname (icon_prefix);
icon_path = g_build_filename (dirname,
"icons",
- priv->origin,
+ origin_app,
NULL);
} else {
icon_path = g_build_filename (icon_prefix, "icons", NULL);
@@ -1136,7 +1194,7 @@ as_store_from_root (AsStore *store,
}
/* set the correct scope */
- as_store_fixup_id_prefix (app, id_prefix);
+ as_store_fixup_id_prefix (app, id_prefix_app);
if (origin_app != NULL)
as_app_set_origin (app, origin_app);
@@ -1519,7 +1577,9 @@ as_store_from_file (AsStore *store,
GCancellable *cancellable,
GError **error)
{
- return as_store_from_file_internal (store, file, NULL, NULL,
+ return as_store_from_file_internal (store, file,
+ NULL, /* id_prefix */
+ NULL, /* arch */
cancellable, error);
}
@@ -1604,7 +1664,6 @@ as_store_from_xml (AsStore *store,
{
g_autoptr(GError) error_local = NULL;
g_autoptr(AsNode) root = NULL;
- const gchar *id_prefix = NULL;
g_return_val_if_fail (AS_IS_STORE (store), FALSE);
g_return_val_if_fail (data != NULL, FALSE);
@@ -1624,7 +1683,9 @@ as_store_from_xml (AsStore *store,
error_local->message);
return FALSE;
}
- return as_store_from_root (store, root, id_prefix, icon_root,
+ return as_store_from_root (store, root,
+ NULL, /* id_prefix */
+ icon_root,
NULL, /* filename */
NULL, /* arch */
error);