[gnome-software] Add a plugin to create an object representing the local system



commit 3c4c79a83958a5e331deb79449282a9098952151
Author: Richard Hughes <richard hughsie com>
Date:   Fri May 12 12:13:29 2017 +0100

    Add a plugin to create an object representing the local system

 contrib/gnome-software.spec.in                     |    1 +
 lib/gs-app.c                                       |    1 +
 lib/gs-plugin-loader.c                             |   14 +++
 lib/gs-plugin-loader.h                             |    1 +
 plugins/core/gs-plugin-os-release.c                |  103 ++++++++++++++++++++
 plugins/core/gs-self-test.c                        |   63 ++++++++++++
 plugins/core/meson.build                           |   15 +++-
 plugins/core/tests/os-release                      |    1 +
 plugins/dummy/gs-plugin-dummy.c                    |    5 +
 .../gs-plugin-fedora-distro-upgrades.c             |    2 +-
 10 files changed, 204 insertions(+), 2 deletions(-)
---
diff --git a/contrib/gnome-software.spec.in b/contrib/gnome-software.spec.in
index dd7e43b..a45244d 100644
--- a/contrib/gnome-software.spec.in
+++ b/contrib/gnome-software.spec.in
@@ -175,6 +175,7 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
 %{_libdir}/gs-plugins-%{gs_plugin_version}/libgs_plugin_key-colors.so
 %{_libdir}/gs-plugins-%{gs_plugin_version}/libgs_plugin_modalias.so
 %{_libdir}/gs-plugins-%{gs_plugin_version}/libgs_plugin_odrs.so
+%{_libdir}/gs-plugins-%{gs_plugin_version}/libgs_plugin_os-release.so
 %{_libdir}/gs-plugins-%{gs_plugin_version}/libgs_plugin_ostree.so
 %if %{with packagekit}
 %{_libdir}/gs-plugins-%{gs_plugin_version}/libgs_plugin_packagekit-history.so
diff --git a/lib/gs-app.c b/lib/gs-app.c
index 4ae0705..2b3af9f 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -810,6 +810,7 @@ gs_app_set_state_internal (GsApp *app, AsAppState state)
                /* installed has to go into an action state */
                if (state == AS_APP_STATE_UNKNOWN ||
                    state == AS_APP_STATE_REMOVING ||
+                   state == AS_APP_STATE_UNAVAILABLE ||
                    state == AS_APP_STATE_UPDATABLE ||
                    state == AS_APP_STATE_UPDATABLE_LIVE)
                        state_change_ok = TRUE;
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index 99cb8e8..5e9d9db 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -5028,6 +5028,20 @@ gs_plugin_loader_app_create (GsPluginLoader *plugin_loader, const gchar *unique_
        return app;
 }
 
+/**
+ * gs_plugin_loader_get_system_app:
+ * @plugin_loader: a #GsPluginLoader
+ *
+ * Returns the application that represents the currently installed OS.
+ *
+ * Returns: (transfer full): a #GsApp
+ **/
+GsApp *
+gs_plugin_loader_get_system_app (GsPluginLoader *plugin_loader)
+{
+       return gs_plugin_loader_app_create (plugin_loader, "*/*/*/*/system/*");
+}
+
 /******************************************************************************/
 
 AsProfile *
diff --git a/lib/gs-plugin-loader.h b/lib/gs-plugin-loader.h
index 53d9335..745df87 100644
--- a/lib/gs-plugin-loader.h
+++ b/lib/gs-plugin-loader.h
@@ -281,6 +281,7 @@ void                 gs_plugin_loader_remove_events         (GsPluginLoader 
*plugin_loader);
 AsProfile      *gs_plugin_loader_get_profile           (GsPluginLoader *plugin_loader);
 GsApp          *gs_plugin_loader_app_create            (GsPluginLoader *plugin_loader,
                                                         const gchar    *unique_id);
+GsApp          *gs_plugin_loader_get_system_app        (GsPluginLoader *plugin_loader);
 
 /* only useful from the self tests */
 void            gs_plugin_loader_setup_again           (GsPluginLoader *plugin_loader);
diff --git a/plugins/core/gs-plugin-os-release.c b/plugins/core/gs-plugin-os-release.c
new file mode 100644
index 0000000..b2d1cfa
--- /dev/null
+++ b/plugins/core/gs-plugin-os-release.c
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <gnome-software.h>
+
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+       /* we might change the app-id */
+       gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_BEFORE, "appstream");
+       gs_plugin_add_flags (plugin, GS_PLUGIN_FLAGS_GLOBAL_CACHE);
+}
+
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+       const gchar *cpe_name;
+       const gchar *home_url;
+       const gchar *name;
+       const gchar *version;
+       g_autoptr(GsOsRelease) os_release = NULL;
+
+       /* match meta-id */
+       if (g_strcmp0 (gs_app_get_id (app), "system") != 0)
+               return TRUE;
+
+       /* avoid setting again */
+       if (gs_app_get_metadata_item (app, "GnomeSoftware::CpeName") != NULL)
+               return TRUE;
+
+       /* hardcoded */
+       gs_app_set_kind (app, AS_APP_KIND_OS_UPGRADE);
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+
+       /* get visible data */
+       os_release = gs_os_release_new (error);
+       if (os_release == NULL)
+               return FALSE;
+       cpe_name = gs_os_release_get_cpe_name (os_release);
+       if (cpe_name != NULL)
+               gs_app_set_metadata (app, "GnomeSoftware::CpeName", cpe_name);
+       name = gs_os_release_get_name (os_release);
+       if (name != NULL)
+               gs_app_set_name (app, GS_APP_QUALITY_LOWEST, name);
+       version = gs_os_release_get_version_id (os_release);
+       if (version != NULL)
+               gs_app_set_version (app, version);
+
+       /* use libsoup to convert a URL */
+       home_url = gs_os_release_get_home_url (os_release);
+       if (home_url != NULL) {
+               g_autoptr(SoupURI) uri = NULL;
+
+               /* homepage */
+               gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, home_url);
+
+               /* build ID from the reverse-DNS URL and the name version */
+               uri = soup_uri_new (home_url);
+               if (uri != NULL) {
+                       g_auto(GStrv) split = NULL;
+                       const gchar *home_host = soup_uri_get_host (uri);
+                       split = g_strsplit_set (home_host, ".", -1);
+                       if (g_strv_length (split) >= 2) {
+                               g_autofree gchar *id = NULL;
+                               id = g_strdup_printf ("%s.%s.%s-%s",
+                                                     split[1],
+                                                     split[0],
+                                                     name,
+                                                     version);
+                               /* set the new ID and update the cache */
+                               gs_app_set_id (app, id);
+                               gs_plugin_cache_add (plugin, NULL, app);
+                       }
+               }
+       }
+
+       /* success */
+       return TRUE;
+}
diff --git a/plugins/core/gs-self-test.c b/plugins/core/gs-self-test.c
index 04e18b2..f8b3a70 100644
--- a/plugins/core/gs-self-test.c
+++ b/plugins/core/gs-self-test.c
@@ -121,17 +121,69 @@ gs_plugins_core_search_repo_name_func (GsPluginLoader *plugin_loader)
        g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
 }
 
+static void
+gs_plugins_core_os_release_func (GsPluginLoader *plugin_loader)
+{
+       gboolean ret;
+       g_autoptr(GsApp) app = NULL;
+       g_autoptr(GsApp) app2 = NULL;
+       g_autoptr(GsApp) app3 = NULL;
+       g_autoptr(GError) error = NULL;
+
+       /* drop all caches */
+       gs_plugin_loader_setup_again (plugin_loader);
+
+       /* refine system application */
+       app = gs_plugin_loader_get_system_app (plugin_loader);
+       ret = gs_plugin_loader_app_refine (plugin_loader,
+                                          app,
+                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
+                                          GS_PLUGIN_FAILURE_FLAGS_FATAL_ANY,
+                                          NULL,
+                                          &error);
+       gs_test_flush_main_context ();
+       g_assert_no_error (error);
+       g_assert (ret);
+
+       /* make sure there is valid content */
+       g_assert_cmpstr (gs_app_get_id (app), ==, "org.fedoraproject.Fedora-25");
+       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_OS_UPGRADE);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+       g_assert_cmpstr (gs_app_get_name (app), ==, "Fedora");
+       g_assert_cmpstr (gs_app_get_version (app), ==, "25");
+       g_assert_cmpstr (gs_app_get_url (app, AS_URL_KIND_HOMEPAGE), ==,
+                        "https://fedoraproject.org/";);
+       g_assert_cmpstr (gs_app_get_metadata_item (app, "GnomeSoftware::CpeName"), ==,
+                        "cpe:/o:fedoraproject:fedora:25");
+
+       /* this comes from appstream */
+       g_assert_cmpstr (gs_app_get_summary (app), ==, "Fedora Workstation");
+
+       /* get using the new name */
+       app2 = gs_plugin_loader_app_create (plugin_loader,
+                                           "*/*/*/*/org.fedoraproject.Fedora-25/*");
+       g_assert (app2 != NULL);
+       g_assert (app2 == app);
+
+       /* check we can get this by the old name too */
+       app3 = gs_plugin_loader_get_system_app (plugin_loader);
+       g_assert (app3 != NULL);
+       g_assert (app3 == app);
+}
+
 int
 main (int argc, char **argv)
 {
        const gchar *tmp_root = "/var/tmp/self-test";
        gboolean ret;
+       g_autofree gchar *os_release_filename = NULL;
        g_autoptr(GError) error = NULL;
        g_autoptr(GsPluginLoader) plugin_loader = NULL;
        const gchar *xml;
        const gchar *whitelist[] = {
                "appstream",
                "icons",
+               "os-release",
                NULL
        };
 
@@ -139,6 +191,10 @@ main (int argc, char **argv)
        g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
        g_setenv ("GS_SELF_TEST_CORE_DATADIR", tmp_root, TRUE);
 
+       os_release_filename = gs_test_get_filename (TESTDATADIR, "os-release");
+       g_assert (os_release_filename != NULL);
+       g_setenv ("GS_SELF_TEST_OS_RELEASE_FILENAME", os_release_filename, TRUE);
+
        /* ensure test root does not exist */
        if (g_file_test (tmp_root, G_FILE_TEST_EXISTS)) {
                ret = gs_utils_rmtree (tmp_root, &error);
@@ -160,6 +216,10 @@ main (int argc, char **argv)
                "    <summary>Test</summary>\n"
                "    <icon type=\"stock\">system-file-manager</icon>\n"
                "  </component>\n"
+               "  <component type=\"os-upgrade\">\n"
+               "    <id>org.fedoraproject.Fedora-25</id>\n"
+               "    <summary>Fedora Workstation</summary>\n"
+               "  </component>\n"
                "</components>\n";
        g_setenv ("GS_SELF_TEST_APPSTREAM_XML", xml, TRUE);
        g_setenv ("GS_SELF_TEST_ALL_ORIGIN_KEYWORDS", "1", TRUE);
@@ -186,6 +246,9 @@ main (int argc, char **argv)
        g_test_add_data_func ("/gnome-software/plugins/core/app-creation",
                              plugin_loader,
                              (GTestDataFunc) gs_plugins_core_app_creation_func);
+       g_test_add_data_func ("/gnome-software/plugins/core/os-release",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugins_core_os_release_func);
        return g_test_run ();
 }
 
diff --git a/plugins/core/meson.build b/plugins/core/meson.build
index ef07d47..1002b14 100644
--- a/plugins/core/meson.build
+++ b/plugins/core/meson.build
@@ -167,9 +167,22 @@ shared_module(
   dependencies : plugin_libs
 )
 
+shared_module(
+  'gs_plugin_os-release',
+  sources : 'gs-plugin-os-release.c',
+  include_directories : [
+    include_directories('../..'),
+    include_directories('../../lib'),
+  ],
+  install : true,
+  install_dir: plugin_dir,
+  c_args : cargs,
+  dependencies : plugin_libs
+)
+
 if get_option('enable-tests')
   cargs += ['-DLOCALPLUGINDIR="' + meson.current_build_dir() + '"']
-  cargs += ['-DTESTDATADIR="' + join_paths(meson.current_build_dir(), 'tests') + '"']
+  cargs += ['-DTESTDATADIR="' + join_paths(meson.current_source_dir(), 'tests') + '"']
   e = executable('gs-self-test-core',
     sources : [
       'gs-self-test.c',
diff --git a/plugins/core/tests/os-release b/plugins/core/tests/os-release
new file mode 120000
index 0000000..1efe264
--- /dev/null
+++ b/plugins/core/tests/os-release
@@ -0,0 +1 @@
+../../../data/tests/os-release
\ No newline at end of file
diff --git a/plugins/dummy/gs-plugin-dummy.c b/plugins/dummy/gs-plugin-dummy.c
index 182e646..c86ffe2 100644
--- a/plugins/dummy/gs-plugin-dummy.c
+++ b/plugins/dummy/gs-plugin-dummy.c
@@ -105,6 +105,7 @@ gs_plugin_initialize (GsPlugin *plugin)
 
        /* need help from appstream */
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "appstream");
+       gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "os-release");
        gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_CONFLICTS, "odrs");
 }
 
@@ -538,6 +539,10 @@ gs_plugin_refine_app (GsPlugin *plugin,
 {
        GsPluginData *priv = gs_plugin_get_data (plugin);
 
+       /* make the local system EOL */
+       if (gs_app_get_metadata_item (app, "GnomeSoftware::CpeName") != NULL)
+               gs_app_set_state (app, AS_APP_STATE_UNAVAILABLE);
+
        /* state */
        if (gs_app_get_state (app) == AS_APP_STATE_UNKNOWN) {
                if (g_hash_table_lookup (priv->installed_apps,
diff --git a/plugins/fedora-distro-upgrades/gs-plugin-fedora-distro-upgrades.c 
b/plugins/fedora-distro-upgrades/gs-plugin-fedora-distro-upgrades.c
index 536861d..42b9a3a 100644
--- a/plugins/fedora-distro-upgrades/gs-plugin-fedora-distro-upgrades.c
+++ b/plugins/fedora-distro-upgrades/gs-plugin-fedora-distro-upgrades.c
@@ -357,7 +357,7 @@ gs_plugin_fedora_distro_upgrades_create_app (GsPlugin *plugin, DistroInfo *distr
                return app;
 
        /* create app */
-       app_id = g_strdup_printf ("org.fedoraproject.release-%u",
+       app_id = g_strdup_printf ("org.fedoraproject.Fedora-%u",
                                  distro_info->version);
        app_version = g_strdup_printf ("%u", distro_info->version);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]