diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index f2b95752..83bc9311 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -2987,12 +2987,34 @@ flatpak_dir_install (FlatpakDir *self, g_autofree char *child_repo_path = NULL; FlatpakSystemHelper *system_helper; FlatpakHelperDeployFlags helper_flags = 0; + g_autofree char *url = NULL; system_helper = flatpak_dir_get_system_helper (self); g_assert (system_helper != NULL); - if (!no_pull) + if (!ostree_repo_remote_get_url (self->repo, + remote_name, + &url, + error)) + return FALSE; + + if (no_pull) { + /* Do nothing */ + } + else if (g_str_has_prefix (url, "file:")) + { + /* In the local case we let the system-helper do all the work. That way we can trust its + reading from the right source, and its not doing any network i/o. */ + + helper_flags |= FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL; + } + else + { + /* We're pulling from a remote source, we do the network mirroring pull as a + user and hand back the resulting data to the system-helper, that trusts us + due to the GPG signatures in the repo */ + child_repo = flatpak_dir_create_system_child_repo (self, &child_repo_lock, error); if (child_repo == NULL) return FALSE; @@ -3061,6 +3083,7 @@ flatpak_dir_update (FlatpakDir *self, FlatpakSystemHelper *system_helper; g_autofree char *child_repo_path = NULL; FlatpakHelperDeployFlags helper_flags = 0; + g_autofree char *url = NULL; if (checksum_or_latest != NULL) return flatpak_fail (error, "Can't update to a specific commit without root permissions"); @@ -3068,13 +3091,32 @@ flatpak_dir_update (FlatpakDir *self, system_helper = flatpak_dir_get_system_helper (self); g_assert (system_helper != NULL); + if (!ostree_repo_remote_get_url (self->repo, + remote_name, + &url, + error)) + return FALSE; + + helper_flags = FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE; + if (no_pull) { if (!ostree_repo_resolve_rev (self->repo, ref, FALSE, &latest_checksum, error)) return FALSE; } + else if (g_str_has_prefix (url, "file:")) + { + /* In the local case we let the system-helper do all the work. That way we can trust its + reading from the right source, and its not doing any network i/o. */ + + helper_flags |= FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL; + } else { + /* We're pulling from a remote source, we do the network mirroring pull as a + user and hand back the resulting data to the system-helper, that trusts us + due to the GPG signatures in the repo */ + child_repo = flatpak_dir_create_system_child_repo (self, &child_repo_lock, error); if (child_repo == NULL) return FALSE; @@ -3090,7 +3132,6 @@ flatpak_dir_update (FlatpakDir *self, child_repo_path = g_file_get_path (ostree_repo_get_path (child_repo)); } - helper_flags = FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE; if (no_deploy) helper_flags |= FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY; diff --git a/common/flatpak-dir.h b/common/flatpak-dir.h index 541819b3..5532b408 100644 --- a/common/flatpak-dir.h +++ b/common/flatpak-dir.h @@ -44,9 +44,10 @@ typedef enum { FLATPAK_HELPER_DEPLOY_FLAGS_NONE = 0, FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE = 1 << 0, FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY = 1 << 1, + FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL = 1 << 2, } FlatpakHelperDeployFlags; -#define FLATPAK_HELPER_DEPLOY_FLAGS_ALL (FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE|FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY) +#define FLATPAK_HELPER_DEPLOY_FLAGS_ALL (FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE|FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY|FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL) typedef enum { FLATPAK_HELPER_UNINSTALL_FLAGS_NONE = 0, diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c index 08043c5c..e458c955 100644 --- a/system-helper/flatpak-system-helper.c +++ b/system-helper/flatpak-system-helper.c @@ -139,7 +139,9 @@ handle_deploy (FlatpakSystemHelper *object, g_autoptr(GFile) deploy_dir = NULL; gboolean is_update; gboolean no_deploy; + gboolean local_pull; g_autoptr(GMainContext) main_context = NULL; + g_autofree char *url = NULL; g_debug ("Deploy %s %u %s %s", arg_repo_path, arg_flags, arg_ref, arg_origin); @@ -158,6 +160,7 @@ handle_deploy (FlatpakSystemHelper *object, is_update = (arg_flags & FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE) != 0; no_deploy = (arg_flags & FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY) != 0; + local_pull = (arg_flags & FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL) != 0; deploy_dir = flatpak_dir_get_if_deployed (system, arg_ref, NULL, NULL); @@ -216,6 +219,40 @@ handle_deploy (FlatpakSystemHelper *object, } g_main_context_pop_thread_default (main_context); } + else if (local_pull) + { + if (!ostree_repo_remote_get_url (flatpak_dir_get_repo (system), + arg_origin, + &url, + &error)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Error getting remote url: %s", error->message); + return TRUE; + } + + if (!g_str_has_prefix (url, "file:")) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Local pull url doesn't start with file://"); + return TRUE; + } + + /* Work around ostree-pull spinning the default main context for the sync calls */ + main_context = g_main_context_new (); + g_main_context_push_thread_default (main_context); + + if (!flatpak_dir_pull (system, arg_origin, arg_ref, (char **)arg_subpaths, NULL, + OSTREE_REPO_PULL_FLAGS_UNTRUSTED, NULL, + NULL, &error)) + { + g_main_context_pop_thread_default (main_context); + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Error pulling from repo: %s", error->message); + return TRUE; + } + g_main_context_pop_thread_default (main_context); + } if (!no_deploy) {