diff options
author | Richard Hughes <richard@hughsie.com> | 2016-06-07 16:28:32 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2016-06-08 18:02:57 +0100 |
commit | 25d942831dba7d44c4044e960da7bc04dce58f17 (patch) | |
tree | baa94e98d7cc7bbca06d18bc9d51dba65e7a9de0 | |
parent | 960a6d9d22d6f7756093ffdb5fa46c1b588991e3 (diff) | |
download | appstream-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.am | 2 | ||||
-rw-r--r-- | data/tests/appstream.xml | 5 | ||||
l--------- | data/tests/flatpak_remote-name.xml | 1 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 40 | ||||
-rw-r--r-- | libappstream-glib/as-store.c | 83 |
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); |