[gnome-software] flatpak: Do not try to install a duplicate RuntimeRepo
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] flatpak: Do not try to install a duplicate RuntimeRepo
- Date: Mon, 17 Jul 2017 16:14:42 +0000 (UTC)
commit dd45ff4f1fcda072c4e2b669373b501224cbccc4
Author: Richard Hughes <richard hughsie com>
Date: Fri Jul 14 16:56:59 2017 +0100
flatpak: Do not try to install a duplicate RuntimeRepo
Check if the runtime is available in an already-installed remote before
attempting to install the new source.
Based on a patch by Joaquim Rocha <jrocha endlessm com>, many thanks.
plugins/flatpak/gs-flatpak.c | 62 +++++++++++--
plugins/flatpak/gs-plugin-flatpak.c | 13 +--
plugins/flatpak/gs-self-test.c | 178 ++++++++++++++++++++++++++++++++++-
3 files changed, 237 insertions(+), 16 deletions(-)
---
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index 42a3c4c..e6768fb 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -915,6 +915,7 @@ gs_flatpak_find_app_by_name_branch (GsFlatpak *self,
GCancellable *cancellable,
GError **error)
{
+ g_autoptr(GPtrArray) xremotes = NULL;
g_autoptr(GPtrArray) xrefs = NULL;
g_return_val_if_fail (name != NULL, FALSE);
@@ -940,6 +941,49 @@ gs_flatpak_find_app_by_name_branch (GsFlatpak *self,
gs_app_list_add (list, app);
}
}
+
+ /* look at each remote xref */
+ xremotes = flatpak_installation_list_remotes (self->installation, cancellable, error);
+ if (xremotes == NULL) {
+ gs_flatpak_error_convert (error);
+ return FALSE;
+ }
+ for (guint i = 0; i < xremotes->len; i++) {
+ FlatpakRemote *xremote = g_ptr_array_index (xremotes, i);
+ g_autoptr(GPtrArray) refs_remote = NULL;
+ refs_remote = flatpak_installation_list_remote_refs_sync (self->installation,
+ flatpak_remote_get_name (xremote),
+ cancellable, error);
+ if (refs_remote == NULL) {
+ gs_flatpak_error_convert (error);
+ return FALSE;
+ }
+ for (guint j = 0; j < refs_remote->len; j++) {
+ FlatpakRef *xref = g_ptr_array_index (refs_remote, j);
+ if (g_strcmp0 (flatpak_ref_get_name (xref), name) == 0 &&
+ g_strcmp0 (flatpak_ref_get_branch (xref), branch) == 0) {
+ g_autoptr(GsApp) app = gs_flatpak_create_app (self, xref);
+
+ /* don't 'overwrite' installed apps */
+ if (gs_app_list_lookup (list, gs_app_get_unique_id (app)) != NULL) {
+ g_debug ("ignoring installed %s",
+ gs_app_get_unique_id (app));
+ continue;
+ }
+
+ /* if we added a LOCAL runtime, and then we found
+ * an already installed remote that provides the
+ * exact same thing */
+ if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE_LOCAL)
+ gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+
+ gs_app_set_origin (app, flatpak_remote_get_name (xremote));
+ gs_app_list_add (list, app);
+ }
+ }
+ }
+
return TRUE;
}
@@ -2657,14 +2701,16 @@ gs_flatpak_app_install (GsFlatpak *self,
gs_app_set_state (app_src, AS_APP_STATE_UNKNOWN);
gs_app_set_state (app_src, AS_APP_STATE_AVAILABLE);
- /* install the flatpakrepo */
- if (!gs_flatpak_app_install_source (self,
- app_src,
- cancellable,
- error)) {
- g_prefix_error (error, "cannot install source from %s: ",
- gs_flatpak_app_get_repo_url (app_src));
- return FALSE;
+ /* install the flatpakrepo if not already installed */
+ if (gs_app_get_state (app_src) != AS_APP_STATE_INSTALLED) {
+ if (!gs_flatpak_app_install_source (self,
+ app_src,
+ cancellable,
+ error)) {
+ g_prefix_error (error, "cannot install source from %s: ",
+ gs_flatpak_app_get_repo_url (app_src));
+ return FALSE;
+ }
}
/* get the new state */
diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c
index 3a5efd5..873a80c 100644
--- a/plugins/flatpak/gs-plugin-flatpak.c
+++ b/plugins/flatpak/gs-plugin-flatpak.c
@@ -589,11 +589,9 @@ gs_plugin_flatpak_file_to_app_ref (GsPlugin *plugin,
runtime_app = gs_app_get_runtime (app_tmp);
if (runtime_app != NULL &&
gs_app_get_state (runtime_app) != AS_APP_STATE_INSTALLED) {
- g_autoptr(GsAppList) list_system_runtimes = gs_app_list_new ();
+ g_autoptr(GsAppList) list_runtimes = gs_app_list_new ();
for (guint i = 0; i < priv->flatpaks->len; i++) {
GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
- if (gs_flatpak_get_scope (flatpak) != AS_APP_SCOPE_SYSTEM)
- continue;
g_debug ("looking for %s//%s in %s",
gs_flatpak_app_get_ref_name (runtime_app),
gs_flatpak_app_get_ref_branch (runtime_app),
@@ -601,13 +599,14 @@ gs_plugin_flatpak_file_to_app_ref (GsPlugin *plugin,
if (!gs_flatpak_find_app_by_name_branch (flatpak,
gs_flatpak_app_get_ref_name (runtime_app),
gs_flatpak_app_get_ref_branch (runtime_app),
- list_system_runtimes,
+ list_runtimes,
cancellable, error))
return FALSE;
}
- for (guint i = 0; i < gs_app_list_length (list_system_runtimes); i++) {
- GsApp *runtime_old = gs_app_list_index (list_system_runtimes, i);
- if (gs_app_get_state (runtime_old) == AS_APP_STATE_INSTALLED) {
+ for (guint i = 0; i < gs_app_list_length (list_runtimes); i++) {
+ GsApp *runtime_old = gs_app_list_index (list_runtimes, i);
+ if (gs_app_get_state (runtime_old) == AS_APP_STATE_INSTALLED ||
+ gs_app_get_state (runtime_old) == AS_APP_STATE_AVAILABLE) {
g_debug ("already have %s, using instead of %s",
gs_app_get_unique_id (runtime_old),
gs_app_get_unique_id (runtime_app));
diff --git a/plugins/flatpak/gs-self-test.c b/plugins/flatpak/gs-self-test.c
index 8455b1b..52105eb 100644
--- a/plugins/flatpak/gs-self-test.c
+++ b/plugins/flatpak/gs-self-test.c
@@ -40,7 +40,7 @@ gs_flatpak_test_write_repo_file (const gchar *fn, const gchar *testdir, GError *
g_string_append (str, "Comment=Longer one line comment\n");
g_string_append (str, "Description=Longer multiline comment that "
"does into detail.\n");
- g_string_append (str, "DefaultBranch=stable\n");
+ g_string_append (str, "DefaultBranch=master\n");
g_string_append_printf (str, "Url=%s\n", testdir_repourl);
g_string_append (str, "Homepage=http://foo.bar\n");
g_string_append (str, "GPGKey=FOOBAR==\n");
@@ -713,6 +713,179 @@ gs_plugins_flatpak_runtime_repo_func (GsPluginLoader *plugin_loader)
g_assert_cmpint (gs_app_get_state (app_source), ==, AS_APP_STATE_AVAILABLE);
}
+/* same as gs_plugins_flatpak_runtime_repo_func, but this time manually
+ * installing the flatpakrepo BEFORE the flatpakref is installed */
+static void
+gs_plugins_flatpak_runtime_repo_redundant_func (GsPluginLoader *plugin_loader)
+{
+ GsApp *app_source;
+ GsApp *runtime;
+ const gchar *fn_ref = "/var/tmp/self-test/test.flatpakref";
+ const gchar *fn_repo = "/var/tmp/self-test/test.flatpakrepo";
+ gboolean ret;
+ g_autofree gchar *fn_repourl = NULL;
+ g_autofree gchar *testdir2 = NULL;
+ g_autofree gchar *testdir2_repourl = NULL;
+ g_autofree gchar *testdir = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFile) file_repo = NULL;
+ g_autoptr(GsApp) app = NULL;
+ g_autoptr(GsApp) app_src = NULL;
+ g_autoptr(GsAppList) sources2 = NULL;
+ g_autoptr(GsAppList) sources = NULL;
+ g_autoptr(GsPluginJob) plugin_job = NULL;
+ g_autoptr(GString) str2 = g_string_new (NULL);
+
+ /* drop all caches */
+ gs_plugin_loader_setup_again (plugin_loader);
+
+ /* write a flatpakrepo file */
+ testdir = gs_test_get_filename (TESTDATADIR, "only-runtime");
+ if (testdir == NULL)
+ return;
+ ret = gs_flatpak_test_write_repo_file (fn_repo, testdir, &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+
+ /* convert it to a GsApp */
+ file_repo = g_file_new_for_path (fn_repo);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_FILE_TO_APP,
+ "file", file_repo,
+ "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
+ GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME,
+ NULL);
+ app_src = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (app_src != NULL);
+ g_assert_cmpint (gs_app_get_kind (app_src), ==, AS_APP_KIND_SOURCE);
+ g_assert_cmpint (gs_app_get_state (app_src), ==, AS_APP_STATE_AVAILABLE_LOCAL);
+ g_assert_cmpstr (gs_app_get_id (app_src), ==, "test");
+ g_assert_cmpstr (gs_app_get_unique_id (app_src), ==, "user/*/*/source/test/master");
+ g_assert (gs_app_get_local_file (app_src) != NULL);
+
+ /* install the source manually */
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+ "app", app_src,
+ NULL);
+ ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (gs_app_get_state (app_src), ==, AS_APP_STATE_INSTALLED);
+
+ /* write a flatpakref file */
+ fn_repourl = g_strdup_printf ("file://%s", fn_repo);
+ testdir2 = gs_test_get_filename (TESTDATADIR, "app-missing-runtime");
+ if (testdir2 == NULL)
+ return;
+ testdir2_repourl = g_strdup_printf ("file://%s/repo", testdir2);
+ g_string_append (str2, "[Flatpak Ref]\n");
+ g_string_append (str2, "Title=Chiron\n");
+ g_string_append (str2, "Name=org.test.Chiron\n");
+ g_string_append (str2, "Branch=master\n");
+ g_string_append_printf (str2, "Url=%s\n", testdir2_repourl);
+ g_string_append (str2, "IsRuntime=False\n");
+ g_string_append (str2, "Comment=Single line synopsis\n");
+ g_string_append (str2, "Description=A Testing Application\n");
+ g_string_append (str2, "Icon=https://getfedora.org/static/images/fedora-logotext.png\n");
+ g_string_append_printf (str2, "RuntimeRepo=%s\n", fn_repourl);
+ ret = g_file_set_contents (fn_ref, str2->str, -1, &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+
+ /* convert it to a GsApp */
+ file = g_file_new_for_path (fn_ref);
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_FILE_TO_APP,
+ "file", file,
+ "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
+ GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME,
+ NULL);
+ app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (app != NULL);
+ g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
+ g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_AVAILABLE_LOCAL);
+ g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron.desktop");
+ g_assert (as_utils_unique_id_equal (gs_app_get_unique_id (app),
+ "user/flatpak/org.test.Chiron-origin/desktop/org.test.Chiron.desktop/master"));
+ g_assert (gs_app_get_local_file (app) != NULL);
+
+ /* get runtime */
+ runtime = gs_app_get_runtime (app);
+ g_assert_cmpstr (gs_app_get_unique_id (runtime), ==,
"user/flatpak/test/runtime/org.test.Runtime/master");
+ g_assert_cmpint (gs_app_get_state (runtime), ==, AS_APP_STATE_AVAILABLE);
+
+ /* check the number of sources */
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_SOURCES, NULL);
+ sources = gs_plugin_loader_job_process (plugin_loader, plugin_job,
+ NULL, &error);
+ g_assert_no_error (error);
+ g_assert (sources != NULL);
+ g_assert_cmpint (gs_app_list_length (sources), ==, 1); /* repo */
+
+ /* install, which will NOT install the runtime from the RuntimeRemote,
+ * but from the existing test repo */
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+ "app", app,
+ NULL);
+ ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+ g_assert_cmpint (gs_app_get_state (runtime), ==, AS_APP_STATE_INSTALLED);
+
+ /* check the number of sources */
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_SOURCES, NULL);
+ sources2 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (sources2 != NULL);
+
+ /* remove the app */
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+ "app", app,
+ NULL);
+ ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_UNKNOWN);
+
+ /* remove the runtime */
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+ "app", runtime,
+ NULL);
+ ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (gs_app_get_state (runtime), ==, AS_APP_STATE_AVAILABLE);
+
+ /* remove the remote */
+ app_source = gs_app_list_index (sources2, 0);
+ g_assert (app_source != NULL);
+ g_assert_cmpstr (gs_app_get_unique_id (app_source), ==, "user/*/*/source/test/*");
+ g_object_unref (plugin_job);
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+ "app", app_source,
+ NULL);
+ ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+ gs_test_flush_main_context ();
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (gs_app_get_state (app_source), ==, AS_APP_STATE_AVAILABLE);
+}
+
static void
gs_plugins_flatpak_ref_func (GsPluginLoader *plugin_loader)
{
@@ -1234,6 +1407,9 @@ main (int argc, char **argv)
g_test_add_data_func ("/gnome-software/plugins/flatpak/runtime-repo",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_runtime_repo_func);
+ g_test_add_data_func ("/gnome-software/plugins/flatpak/runtime-repo-redundant",
+ plugin_loader,
+ (GTestDataFunc) gs_plugins_flatpak_runtime_repo_redundant_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/app-update-runtime",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_app_update_func);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]