From 8d674234aa357515b148dbdeffc03501de112947 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 8 May 2019 11:56:00 +0200 Subject: [PATCH] lib: Add flatpak_installation_add_remote This is basically modify_remote, but it fails if the remote is already configured instead of modifying it. Although it also has a if_needed option, and if that is set it will silently complete as a no-op (exept resetting filters). Closes: #2888 Approved by: alexlarsson --- common/flatpak-installation.c | 62 ++++++++++++++++++++++++++++++ common/flatpak-installation.h | 5 +++ common/flatpak-remote-private.h | 4 ++ common/flatpak-remote.c | 25 +++++++++++- doc/reference/flatpak-sections.txt | 1 + tests/testlibrary.c | 29 ++++++++++++-- 6 files changed, 122 insertions(+), 4 deletions(-) diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index 7bd0e769..c64aa97e 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -1460,6 +1460,68 @@ flatpak_installation_modify_remote (FlatpakInstallation *self, return TRUE; } + +/** + * flatpak_installation_add_remote: + * @self: a #FlatpakInstallation + * @remote: the new #FlatpakRemote + * @if_needed: if %TRUE, only add if it doesn't exists + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Adds a new @remote object to the set of remotes. This is similar + * to flatpak_installation_modify_remote() for non-existing remote + * names. However, if the named remote already exists then instead of + * modifying it it fails with %FLATPAK_ERROR_ALREADY_INSTALLED, or if + * @if_needed is true it silently succeeds without doing anything. + * + * As an exception to the last, if the local config has a filter defined, + * but the new remote unsets the filter (for example, it comes from an + * unfiltered .flatpakref via flatpak_remote_new_from_file()) the the local + * remote filter gets reset. This is to allow the setup where there is a + * default setup of a filtered remote, yet you can still use the standard + * flatpakref file to get the full contents without getting two remotes. + * + * Returns: %TRUE if the modifications have been committed successfully + * Since: 1.3.4 + */ +gboolean +flatpak_installation_add_remote (FlatpakInstallation *self, + FlatpakRemote *remote, + gboolean if_needed, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir_maybe_no_repo (self); + g_autoptr(FlatpakDir) dir_clone = NULL; + + /* We clone the dir here to make sure we re-read the latest ostree repo config, in case + it has local changes */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_maybe_ensure_repo (dir_clone, cancellable, error)) + return FALSE; + + if (flatpak_dir_has_remote (dir, flatpak_remote_get_name (remote), NULL)) + { + if (!if_needed) + return flatpak_fail_error (error, FLATPAK_ERROR_ALREADY_INSTALLED, _("Remote '%s' already exists"), flatpak_remote_get_name (remote)); + + if (!flatpak_remote_commit_filter (remote, dir_clone, cancellable, error)) + return FALSE; + + return TRUE; + } + + if (!flatpak_remote_commit (remote, dir_clone, cancellable, error)) + return FALSE; + + /* Make sure we pick up the new config */ + flatpak_installation_drop_caches (self, NULL, NULL); + + return TRUE; +} + + /** * flatpak_installation_remove_remote: * @self: a #FlatpakInstallation diff --git a/common/flatpak-installation.h b/common/flatpak-installation.h index 8d52ed7a..c6fa500e 100644 --- a/common/flatpak-installation.h +++ b/common/flatpak-installation.h @@ -267,6 +267,11 @@ FLATPAK_EXTERN FlatpakRemote *flatpak_installation_get_remote_by_name (Fl const gchar *name, GCancellable *cancellable, GError **error); +FLATPAK_EXTERN gboolean flatpak_installation_add_remote (FlatpakInstallation *self, + FlatpakRemote *remote, + gboolean if_needed, + GCancellable *cancellable, + GError **error); FLATPAK_EXTERN gboolean flatpak_installation_modify_remote (FlatpakInstallation *self, FlatpakRemote *remote, GCancellable *cancellable, diff --git a/common/flatpak-remote-private.h b/common/flatpak-remote-private.h index 5dbf2e4a..3f5f0418 100644 --- a/common/flatpak-remote-private.h +++ b/common/flatpak-remote-private.h @@ -40,5 +40,9 @@ gboolean flatpak_remote_commit (FlatpakRemote *self, FlatpakDir *dir, GCancellable *cancellable, GError **error); +gboolean flatpak_remote_commit_filter (FlatpakRemote *self, + FlatpakDir *dir, + GCancellable *cancellable, + GError **error); #endif /* __FLATPAK_REMOTE_PRIVATE_H__ */ diff --git a/common/flatpak-remote.c b/common/flatpak-remote.c index 7a17fb9e..72b0bfe1 100644 --- a/common/flatpak-remote.c +++ b/common/flatpak-remote.c @@ -1078,7 +1078,7 @@ flatpak_remote_new_from_ostree (OstreeRemote *remote, * Returns a new remote object which can be used to configure a new remote. * * Note: This is a local configuration object, you must commit changes - * using flatpak_installation_modify_remote() for the changes to take + * using flatpak_installation_modify_remote() or flatpak_installation_add_remote() for the changes to take * effect. * * Returns: (transfer full): a new #FlatpakRemote @@ -1108,6 +1108,29 @@ g_key_file_is_group_name (const gchar *name) return TRUE; } +gboolean +flatpak_remote_commit_filter (FlatpakRemote *self, + FlatpakDir *dir, + GCancellable *cancellable, + GError **error) +{ + FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self); + g_autofree char *group = g_strdup_printf ("remote \"%s\"", priv->name); + + if (priv->local_filter_set && + !flatpak_dir_compare_remote_filter (dir, priv->name, priv->local_filter)) + { + GKeyFile *config = ostree_repo_copy_config (flatpak_dir_get_repo (dir)); + + g_key_file_set_string (config, group, "xa.filter", priv->local_filter ? priv->local_filter : ""); + + if (!flatpak_dir_modify_remote (dir, priv->name, config, NULL, cancellable, error)) + return FALSE; + } + + return TRUE; +} + gboolean flatpak_remote_commit (FlatpakRemote *self, FlatpakDir *dir, diff --git a/doc/reference/flatpak-sections.txt b/doc/reference/flatpak-sections.txt index b75a41ff..db585b75 100644 --- a/doc/reference/flatpak-sections.txt +++ b/doc/reference/flatpak-sections.txt @@ -41,6 +41,7 @@ flatpak_installation_update_appstream_sync flatpak_installation_install_bundle flatpak_installation_install_ref_file flatpak_installation_drop_caches +flatpak_installation_add_remote flatpak_installation_modify_remote flatpak_installation_remove_remote flatpak_installation_update_remote_sync diff --git a/tests/testlibrary.c b/tests/testlibrary.c index 8ca81cdf..64c33401 100644 --- a/tests/testlibrary.c +++ b/tests/testlibrary.c @@ -630,14 +630,14 @@ test_remote_new (void) g_assert_cmpint (flatpak_remote_get_prio (remote), ==, 1); g_assert_false (flatpak_remote_get_gpg_verify (remote)); - res = flatpak_installation_modify_remote (inst, remote, NULL, &error); + res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error); g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_DATA); g_assert_false (res); g_clear_error (&error); flatpak_remote_set_url (remote, "http://127.0.0.1/nowhere"); - res = flatpak_installation_modify_remote (inst, remote, NULL, &error); + res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error); g_assert_no_error (error); g_assert_true (res); @@ -648,12 +648,35 @@ test_remote_new (void) g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/nowhere"); - res = flatpak_installation_remove_remote (inst, "my-first-remote", NULL, &error); + g_clear_object (&remote); + + remote = flatpak_remote_new ("my-first-remote"); + flatpak_remote_set_url (remote, "http://127.0.0.1/elsewhere"); + + res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error); + g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED); + g_clear_error (&error); + g_assert_false (res); + + /* add if needed */ + res = flatpak_installation_add_remote (inst, remote, TRUE, NULL, &error); g_assert_no_error (error); g_assert_true (res); g_clear_object (&remote); + remote = flatpak_installation_get_remote_by_name (inst, "my-first-remote", NULL, &error); + g_assert_no_error (error); + + /* Should be the old value */ + g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/nowhere"); + + g_clear_object (&remote); + + res = flatpak_installation_remove_remote (inst, "my-first-remote", NULL, &error); + g_assert_no_error (error); + g_assert_true (res); + remote = flatpak_installation_get_remote_by_name (inst, "my-first-remote", NULL, &error); g_assert_null (remote); g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_REMOTE_NOT_FOUND);