[gnome-software] Add a plugin to set the origin-hostname for packages



commit 476d03eccfb9643a394f3a32064aaa37e5bda622
Author: Richard Hughes <richard hughsie com>
Date:   Thu Jul 7 09:27:48 2016 +0100

    Add a plugin to set the origin-hostname for packages

 data/tests/Makefile.am             |    3 +-
 data/tests/yum.repos.d/utopia.repo |    5 +
 src/gs-self-test.c                 |   29 ++++++
 src/plugins/Makefile.am            |    6 +
 src/plugins/gs-plugin-repos.c      |  184 ++++++++++++++++++++++++++++++++++++
 5 files changed, 226 insertions(+), 1 deletions(-)
---
diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am
index 019558b..29feb92 100644
--- a/data/tests/Makefile.am
+++ b/data/tests/Makefile.am
@@ -2,6 +2,7 @@ EXTRA_DIST =                                            \
        os-release                                      \
        chiron-0.2.cab                                  \
        chiron-1.1-1.deb                                \
-       chiron-1.1-1.fc24.x86_64.rpm
+       chiron-1.1-1.fc24.x86_64.rpm                    \
+       yum.repos.d/utopia.repo
 
 -include $(top_srcdir)/git.mk
diff --git a/data/tests/yum.repos.d/utopia.repo b/data/tests/yum.repos.d/utopia.repo
new file mode 100644
index 0000000..e912ec4
--- /dev/null
+++ b/data/tests/yum.repos.d/utopia.repo
@@ -0,0 +1,5 @@
+[utopia]
+name=utopia for Fedora $releasever
+baseurl=http://people.freedesktop.org/~hughsient/fedora/$releasever/x86_64/
+enabled=1
+gpgcheck=0
diff --git a/src/gs-self-test.c b/src/gs-self-test.c
index ccdd89f..30b7fd9 100644
--- a/src/gs-self-test.c
+++ b/src/gs-self-test.c
@@ -644,6 +644,25 @@ gs_plugin_loader_fwupd_func (GsPluginLoader *plugin_loader)
 }
 
 static void
+gs_plugin_loader_repos_func (GsPluginLoader *plugin_loader)
+{
+       gboolean ret;
+       g_autoptr(GsApp) app = NULL;
+       g_autoptr(GError) error = NULL;
+
+       /* get the extra bits */
+       app = gs_app_new ("testrepos.desktop");
+       gs_app_set_origin (app, "utopia");
+       ret = gs_plugin_loader_app_refine (plugin_loader, app,
+                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN_HOSTNAME,
+                                          NULL,
+                                          &error);
+       g_assert_no_error (error);
+       g_assert (ret);
+       g_assert_cmpstr (gs_app_get_origin_hostname (app), ==, "people.freedesktop.org");
+}
+
+static void
 gs_plugin_loader_flatpak_func (GsPluginLoader *plugin_loader)
 {
        GsApp *app;
@@ -967,6 +986,7 @@ main (int argc, char **argv)
        gboolean ret;
        g_autofree gchar *fn = NULL;
        g_autofree gchar *xml = NULL;
+       g_autofree gchar *reposdir = NULL;
        g_autoptr(GError) error = NULL;
        g_autoptr(GsPluginLoader) plugin_loader = NULL;
        const gchar *whitelist[] = {
@@ -984,6 +1004,7 @@ main (int argc, char **argv)
                "provenance",
                "provenance-license",
                "packagekit-local",
+               "repos",
                NULL
        };
 
@@ -1006,6 +1027,11 @@ main (int argc, char **argv)
                g_assert (!g_file_test (tmp_root, G_FILE_TEST_EXISTS));
        }
 
+       /* dummy data */
+       reposdir = gs_test_get_filename ("tests/yum.repos.d");
+       g_assert (reposdir != NULL);
+       g_setenv ("GS_SELF_TEST_REPOS_DIR", reposdir, TRUE);
+
        fn = gs_test_get_filename ("icons/hicolor/48x48/org.gnome.Software.png");
        g_assert (fn != NULL);
        xml = g_strdup_printf ("<?xml version=\"1.0\"?>\n"
@@ -1113,6 +1139,9 @@ main (int argc, char **argv)
        g_test_add_data_func ("/gnome-software/plugin-loader{plugin-cache}",
                              plugin_loader,
                              (GTestDataFunc) gs_plugin_loader_plugin_cache_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{repos}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_repos_func);
        g_test_add_data_func ("/gnome-software/plugin-loader{flatpak}",
                              plugin_loader,
                              (GTestDataFunc) gs_plugin_loader_flatpak_func);
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index b1f049d..75abf3d 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -41,6 +41,7 @@ plugin_LTLIBRARIES =                                  \
        libgs_plugin_fedora-distro-upgrades.la          \
        libgs_plugin_provenance.la                      \
        libgs_plugin_provenance-license.la              \
+       libgs_plugin_repos.la                           \
        libgs_plugin_fedora-tagger-usage.la             \
        libgs_plugin_epiphany.la                        \
        libgs_plugin_icons.la                           \
@@ -219,6 +220,11 @@ libgs_plugin_steam_la_LDFLAGS = -module -avoid-version
 libgs_plugin_steam_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 endif
 
+libgs_plugin_repos_la_SOURCES = gs-plugin-repos.c
+libgs_plugin_repos_la_LIBADD = $(GS_PLUGIN_LIBS) $(RPM_LIBS)
+libgs_plugin_repos_la_LDFLAGS = -module -avoid-version
+libgs_plugin_repos_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
+
 libgs_plugin_desktop_categories_la_SOURCES =           \
        gs-plugin-desktop-categories.c                  \
        gs-desktop-common.c                             \
diff --git a/src/plugins/gs-plugin-repos.c b/src/plugins/gs-plugin-repos.c
new file mode 100644
index 0000000..d96f315
--- /dev/null
+++ b/src/plugins/gs-plugin-repos.c
@@ -0,0 +1,184 @@
+/* -*- 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>
+
+struct GsPluginData {
+       GHashTable      *urls;          /* origin : url */
+       GFileMonitor    *monitor;
+       gchar           *reposdir;
+       gboolean         valid;
+};
+
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+       GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
+
+       /* for debugging and the self tests */
+       priv->reposdir = g_strdup (g_getenv ("GS_SELF_TEST_REPOS_DIR"));
+       if (priv->reposdir == NULL)
+               priv->reposdir = g_strdup ("/etc/yum.repos.d");
+
+       /* plugin only makes sense if this exists at startup */
+       if (!g_file_test (priv->reposdir, G_FILE_TEST_EXISTS)) {
+               gs_plugin_set_enabled (plugin, FALSE);
+               return;
+       }
+
+       /* we also watch this for changes */
+       priv->urls = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+       /* need application IDs */
+       gs_plugin_add_rule (plugin, GS_PLUGIN_RULE_RUN_AFTER, "packagekit-refine");
+}
+
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       g_free (priv->reposdir);
+       if (priv->urls != NULL)
+               g_hash_table_unref (priv->urls);
+       if (priv->monitor != NULL)
+               g_object_unref (priv->monitor);
+}
+
+static gboolean
+gs_plugin_repos_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       g_autoptr(GDir) dir = NULL;
+       const gchar *fn;
+
+       /* already valid */
+       if (priv->valid)
+               return TRUE;
+
+       /* clear existing */
+       g_hash_table_remove_all (priv->urls);
+
+       /* search all files */
+       dir = g_dir_open (priv->reposdir, 0, error);
+       if (dir == NULL)
+               return FALSE;
+       while ((fn = g_dir_read_name (dir)) != NULL) {
+               g_autofree gchar *filename = NULL;
+               g_auto(GStrv) groups = NULL;
+               g_autoptr(GKeyFile) kf = g_key_file_new ();
+               guint i;
+
+               /* not a repo */
+               if (!g_str_has_suffix (fn, ".repo"))
+                       continue;
+
+               /* load file */
+               filename = g_build_filename (priv->reposdir, fn, NULL);
+               if (!g_key_file_load_from_file (kf, filename,
+                                               G_KEY_FILE_NONE,
+                                               error))
+                       return FALSE;
+
+               /* we can have multiple repos in one file */
+               groups = g_key_file_get_groups (kf, NULL);
+               for (i = 0; groups[i] != NULL; i++) {
+                       g_autofree gchar *tmp = NULL;
+                       tmp = g_key_file_get_string (kf, groups[i], "baseurl", NULL);
+                       if (tmp != NULL) {
+                               g_hash_table_insert (priv->urls,
+                                                    g_strdup (groups[i]),
+                                                    g_strdup (tmp));
+                               continue;
+                       }
+                       tmp = g_key_file_get_string (kf, groups[i], "metalink", NULL);
+                       if (tmp != NULL) {
+                               g_hash_table_insert (priv->urls,
+                                                    g_strdup (groups[i]),
+                                                    g_strdup (tmp));
+                               continue;
+                       }
+               }
+       }
+
+       /* success */
+       priv->valid = TRUE;
+       return TRUE;
+}
+
+static void
+gs_plugin_repos_changed_cb (GFileMonitor *monitor,
+                           GFile *file,
+                           GFile *other_file,
+                           GFileMonitorEvent event_type,
+                           GsPlugin *plugin)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       priv->valid = FALSE;
+}
+
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       g_autoptr(GFile) file = g_file_new_for_path (priv->reposdir);
+
+       /* watch for changes */
+       priv->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, cancellable, error);
+       if (priv->monitor == NULL)
+               return FALSE;
+       g_signal_connect (priv->monitor, "changed",
+                         G_CALLBACK (gs_plugin_repos_changed_cb), plugin);
+
+       /* unconditionally at startup */
+       return gs_plugin_repos_setup (plugin, cancellable, error);
+}
+
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       const gchar *tmp;
+
+       /* not required */
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN_HOSTNAME) == 0)
+               return TRUE;
+       if (gs_app_get_origin_hostname (app) != NULL)
+               return TRUE;
+
+       /* ensure valid */
+       if (!gs_plugin_repos_setup (plugin, cancellable, error))
+               return FALSE;
+
+       /* find hostname */
+       if (gs_app_get_origin (app) == NULL)
+               return TRUE;
+       tmp = g_hash_table_lookup (priv->urls, gs_app_get_origin (app));
+       if (tmp != NULL)
+               gs_app_set_origin_hostname (app, tmp);
+
+       return TRUE;
+}


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