From 0d19e60ce3c562bc33aa59453bfe0a87e03d1d7a Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 6 Jul 2018 19:13:11 +0200 Subject: [PATCH] system-helper: Add EnsureRepo operation This is used to create the /var/lib/flatpak repo if needed so that other later operations work. We have some partial support for it not working in various operations (using the allow_empty argument) but this is in no way complete. For example, this can easily happen if you have a per-user installation but no system one and then you run flatpak install with no --user, then it will try to figure out which one to use and die. --- common/flatpak-dir.c | 201 +++++++++++++++----------- data/org.freedesktop.Flatpak.xml | 4 + system-helper/flatpak-system-helper.c | 31 ++++ 3 files changed, 151 insertions(+), 85 deletions(-) diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index 6ccc78c4..78ff663f 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -1877,12 +1877,85 @@ _flatpak_dir_ensure_repo (FlatpakDir *self, g_autoptr(GFile) repodir = NULL; g_autoptr(OstreeRepo) repo = NULL; g_autoptr(GError) my_error = NULL; - gboolean use_helper = FALSE; + gboolean use_helper; - if (self->repo == NULL) + if (self->repo != NULL) + return TRUE; + + use_helper = + !self->no_system_helper && !self->user && getuid () != 0; + + if (!g_file_query_exists (self->basedir, cancellable)) { - if (!flatpak_dir_ensure_path (self, cancellable, &my_error)) + if (use_helper) { + g_autoptr(GError) local_error = NULL; + FlatpakSystemHelper *system_helper; + + system_helper = flatpak_dir_get_system_helper (self); + if (system_helper) + { + const char *installation = flatpak_dir_get_id (self); + if (!flatpak_system_helper_call_ensure_repo_sync (system_helper, + installation ? installation : "", + NULL, &local_error)) + { + if (allow_empty) + return TRUE; + + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + } + else + { + g_autoptr(GError) local_error = NULL; + if (!flatpak_dir_ensure_path (self, cancellable, &local_error)) + { + if (allow_empty) + return TRUE; + + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + } + + repodir = g_file_get_child (self->basedir, "repo"); + + if (use_helper) + { + g_autoptr(GFile) cache_dir = NULL; + g_autofree char *cache_path = NULL; + + repo = system_ostree_repo_new (repodir); + + cache_dir = flatpak_ensure_user_cache_dir_location (error); + if (cache_dir == NULL) + return FALSE; + + cache_path = g_file_get_path (cache_dir); + if (!ostree_repo_set_cache_dir (repo, + AT_FDCWD, cache_path, + cancellable, error)) + return FALSE; + } + else if (self->user) + repo = ostree_repo_new (repodir); + else + repo = system_ostree_repo_new (repodir); + + if (!g_file_query_exists (repodir, cancellable)) + { + /* We always use bare-user-only these days, except old installations + that still user bare-user */ + OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER_ONLY; + + if (!ostree_repo_create (repo, mode, cancellable, &my_error)) + { + flatpak_rm_rf (repodir, cancellable, NULL); + if (allow_empty) return TRUE; @@ -1890,91 +1963,49 @@ _flatpak_dir_ensure_repo (FlatpakDir *self, return FALSE; } - repodir = g_file_get_child (self->basedir, "repo"); - if (self->no_system_helper || self->user || getuid () == 0) + /* Create .changes file early to avoid polling non-existing file in monitor */ + if (!flatpak_dir_mark_changed (self, &my_error)) { - repo = system_ostree_repo_new (repodir); + g_warning ("Error marking directory as changed: %s", my_error->message); + g_clear_error (&my_error); } - else - { - g_autoptr(GFile) cache_dir = NULL; - g_autofree char *cache_path = NULL; - - repo = system_ostree_repo_new (repodir); - use_helper = TRUE; - - cache_dir = flatpak_ensure_user_cache_dir_location (error); - if (cache_dir == NULL) - return FALSE; - - cache_path = g_file_get_path (cache_dir); - if (!ostree_repo_set_cache_dir (repo, - AT_FDCWD, cache_path, - cancellable, error)) - return FALSE; - } - - if (!g_file_query_exists (repodir, cancellable)) - { - /* We always use bare-user-only these days, except old installations - that still user bare-user */ - OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER_ONLY; - - if (!ostree_repo_create (repo, mode, cancellable, &my_error)) - { - flatpak_rm_rf (repodir, cancellable, NULL); - - if (allow_empty) - return TRUE; - - g_propagate_error (error, g_steal_pointer (&my_error)); - return FALSE; - } - - /* Create .changes file early to avoid polling non-existing file in monitor */ - if (!flatpak_dir_mark_changed (self, &my_error)) - { - g_warning ("Error marking directory as changed: %s", my_error->message); - g_clear_error (&my_error); - } - } - else - { - if (!ostree_repo_open (repo, cancellable, error)) - { - g_autofree char *repopath = NULL; - - repopath = g_file_get_path (repodir); - g_prefix_error (error, _("While opening repository %s: "), repopath); - return FALSE; - } - } - - /* Reset min-free-space-percent to 0, this keeps being a problem for a lot of people */ - if (!use_helper) - { - GKeyFile *orig_config = NULL; - g_autofree char *orig_min_free_space_percent = NULL; - - orig_config = ostree_repo_get_config (repo); - orig_min_free_space_percent = g_key_file_get_value (orig_config, "core", "min-free-space-percent", NULL); - if (orig_min_free_space_percent == NULL) - { - g_autoptr(GKeyFile) config = ostree_repo_copy_config (repo); - - g_key_file_set_string (config, "core", "min-free-space-percent", "0"); - if (!ostree_repo_write_config (repo, config, error)) - return FALSE; - - if (!ostree_repo_reload_config (repo, cancellable, error)) - return FALSE; - } - } - - /* Make sure we didn't reenter weirdly */ - g_assert (self->repo == NULL); - self->repo = g_object_ref (repo); } + else + { + if (!ostree_repo_open (repo, cancellable, error)) + { + g_autofree char *repopath = NULL; + + repopath = g_file_get_path (repodir); + g_prefix_error (error, _("While opening repository %s: "), repopath); + return FALSE; + } + } + + /* Reset min-free-space-percent to 0, this keeps being a problem for a lot of people */ + if (!use_helper) + { + GKeyFile *orig_config = NULL; + g_autofree char *orig_min_free_space_percent = NULL; + + orig_config = ostree_repo_get_config (repo); + orig_min_free_space_percent = g_key_file_get_value (orig_config, "core", "min-free-space-percent", NULL); + if (orig_min_free_space_percent == NULL) + { + g_autoptr(GKeyFile) config = ostree_repo_copy_config (repo); + + g_key_file_set_string (config, "core", "min-free-space-percent", "0"); + if (!ostree_repo_write_config (repo, config, error)) + return FALSE; + + if (!ostree_repo_reload_config (repo, cancellable, error)) + return FALSE; + } + } + + /* Make sure we didn't reenter weirdly */ + g_assert (self->repo == NULL); + self->repo = g_object_ref (repo); return TRUE; } diff --git a/data/org.freedesktop.Flatpak.xml b/data/org.freedesktop.Flatpak.xml index d2241d6e..713c3efa 100644 --- a/data/org.freedesktop.Flatpak.xml +++ b/data/org.freedesktop.Flatpak.xml @@ -136,6 +136,10 @@ + + + + diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c index 55d8fdcf..97ab9b83 100644 --- a/system-helper/flatpak-system-helper.c +++ b/system-helper/flatpak-system-helper.c @@ -1013,6 +1013,35 @@ handle_prune_local_repo (FlatpakSystemHelper *object, return TRUE; } + +static gboolean +handle_ensure_repo (FlatpakSystemHelper *object, + GDBusMethodInvocation *invocation, + const gchar *arg_installation) +{ + g_autoptr(FlatpakDir) system = NULL; + g_autoptr(GError) error = NULL; + + g_debug ("EnsureRepo %s", arg_installation); + + system = dir_get_system (arg_installation, &error); + if (system == NULL) + { + g_dbus_method_invocation_return_gerror (invocation, error); + return TRUE; + } + + if (!flatpak_dir_ensure_repo (system, NULL, &error)) + { + g_dbus_method_invocation_return_gerror (invocation, error); + return TRUE; + } + + flatpak_system_helper_complete_ensure_repo (object, invocation); + + return TRUE; +} + static gboolean handle_run_triggers (FlatpakSystemHelper *object, GDBusMethodInvocation *invocation, @@ -1172,6 +1201,7 @@ flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface, } else if (g_strcmp0 (method_name, "RemoveLocalRef") == 0 || g_strcmp0 (method_name, "PruneLocalRepo") == 0 || + g_strcmp0 (method_name, "EnsureRepo") == 0 || g_strcmp0 (method_name, "RunTriggers") == 0) { const char *remote; @@ -1240,6 +1270,7 @@ on_bus_acquired (GDBusConnection *connection, g_signal_connect (helper, "handle-update-remote", G_CALLBACK (handle_update_remote), NULL); g_signal_connect (helper, "handle-remove-local-ref", G_CALLBACK (handle_remove_local_ref), NULL); g_signal_connect (helper, "handle-prune-local-repo", G_CALLBACK (handle_prune_local_repo), NULL); + g_signal_connect (helper, "handle-ensure-repo", G_CALLBACK (handle_ensure_repo), NULL); g_signal_connect (helper, "handle-run-triggers", G_CALLBACK (handle_run_triggers), NULL); g_signal_connect (helper, "g-authorize-method",