diff --git a/common/flatpak-dir-private.h b/common/flatpak-dir-private.h index ca000602..3642425d 100644 --- a/common/flatpak-dir-private.h +++ b/common/flatpak-dir-private.h @@ -574,6 +574,7 @@ gboolean flatpak_dir_pull (Fla const char *opt_rev, const char **subpaths, GFile *sideload_repo, + FlatpakImageSource *opt_image_source, GBytes *require_metadata, const char *token, OstreeRepo *repo, @@ -695,6 +696,7 @@ gboolean flatpak_dir_install (Fla const char **subpaths, const char **previous_ids, GFile *sideload_repo, + FlatpakImageSource *opt_image_source, GBytes *require_metadata, const char *token, FlatpakProgress *progress, @@ -741,6 +743,7 @@ gboolean flatpak_dir_update (Fla const char **opt_subpaths, const char **opt_previous_ids, GFile *sideload_repo, + FlatpakImageSource *opt_image_source, GBytes *require_metadata, const char *token, FlatpakProgress *progress, diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index 2d1f8b3a..7a9b4e5b 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -123,7 +123,7 @@ static gboolean flatpak_dir_mirror_oci (FlatpakDir *self, FlatpakRemoteState *state, const char *ref, const char *opt_rev, - const char *skip_if_current_is, + FlatpakImageSource *opt_image_source, const char *token, FlatpakProgress *progress, GCancellable *cancellable, @@ -5307,7 +5307,7 @@ flatpak_dir_update_appstream (FlatpakDir *self, if (child_repo == NULL) return FALSE; - if (!flatpak_dir_pull (self, state, used_branch, appstream_commit, NULL, appstream_sideload_path, NULL, NULL, + if (!flatpak_dir_pull (self, state, used_branch, appstream_commit, NULL, appstream_sideload_path, NULL, NULL, NULL, child_repo, FLATPAK_PULL_FLAGS_NONE, 0, progress, cancellable, error)) { @@ -5351,7 +5351,7 @@ flatpak_dir_update_appstream (FlatpakDir *self, } - if (!flatpak_dir_pull (self, state, used_branch, appstream_commit, NULL, appstream_sideload_path, NULL, NULL, NULL, + if (!flatpak_dir_pull (self, state, used_branch, appstream_commit, NULL, appstream_sideload_path, NULL, NULL, NULL, NULL, FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_NONE, progress, cancellable, error)) { @@ -5903,7 +5903,7 @@ flatpak_dir_mirror_oci (FlatpakDir *self, FlatpakRemoteState *state, const char *ref, const char *opt_rev, - const char *skip_if_current_is, + FlatpakImageSource *opt_image_source, const char *token, FlatpakProgress *progress, GCancellable *cancellable, @@ -5911,40 +5911,42 @@ flatpak_dir_mirror_oci (FlatpakDir *self, { g_autoptr(FlatpakImageSource) image_source = NULL; g_autofree char *oci_digest = NULL; - g_autofree char *latest_rev = NULL; - VarRefInfoRef latest_rev_info; - VarMetadataRef metadata; - const char *oci_repository = NULL; const char *delta_url = NULL; - const char *rev; gboolean res; - /* We use the summary so that we can reuse any cached json */ - if (!flatpak_remote_state_lookup_ref (state, ref, &latest_rev, NULL, &latest_rev_info, NULL, error)) - return FALSE; - if (latest_rev == NULL) - return flatpak_fail_error (error, FLATPAK_ERROR_REF_NOT_FOUND, - _("Couldn't find latest checksum for ref %s in remote %s"), - ref, state->remote_name); - - rev = opt_rev != NULL ? opt_rev : latest_rev; - - if (skip_if_current_is != NULL && strcmp (rev, skip_if_current_is) == 0) + if (opt_image_source) { - return flatpak_fail_error (error, FLATPAK_ERROR_ALREADY_INSTALLED, - _("%s commit %s already installed"), - ref, rev); + image_source = g_object_ref (opt_image_source); + oci_digest = g_strdup (flatpak_image_source_get_digest (image_source)); } + else + { + g_autofree char *latest_rev = NULL; + VarRefInfoRef latest_rev_info; + VarMetadataRef metadata; + const char *oci_repository = NULL; + const char *rev; - metadata = var_ref_info_get_metadata (latest_rev_info); - oci_repository = var_metadata_lookup_string (metadata, "xa.oci-repository", NULL); - delta_url = var_metadata_lookup_string (metadata, "xa.delta-url", NULL); + /* We use the summary so that we can reuse any cached json */ + if (!flatpak_remote_state_lookup_ref (state, ref, &latest_rev, NULL, &latest_rev_info, NULL, error)) + return FALSE; + if (latest_rev == NULL) + return flatpak_fail_error (error, FLATPAK_ERROR_REF_NOT_FOUND, + _("Couldn't find latest checksum for ref %s in remote %s"), + ref, state->remote_name); - oci_digest = g_strconcat ("sha256:", rev, NULL); + rev = opt_rev != NULL ? opt_rev : latest_rev; - image_source = flatpak_remote_state_new_image_source (state, oci_repository, oci_digest, token, cancellable, error); - if (image_source == NULL) - return FALSE; + metadata = var_ref_info_get_metadata (latest_rev_info); + oci_repository = var_metadata_lookup_string (metadata, "xa.oci-repository", NULL); + delta_url = var_metadata_lookup_string (metadata, "xa.delta-url", NULL); + + oci_digest = g_strconcat ("sha256:", rev, NULL); + + image_source = flatpak_remote_state_new_image_source (state, oci_repository, oci_digest, token, cancellable, error); + if (image_source == NULL) + return FALSE; + } flatpak_progress_start_oci_pull (progress); @@ -5964,6 +5966,7 @@ flatpak_dir_pull_oci (FlatpakDir *self, FlatpakRemoteState *state, const char *ref, const char *opt_rev, + FlatpakImageSource *opt_image_source, OstreeRepo *repo, FlatpakPullFlags flatpak_flags, OstreeRepoPullFlags flags, @@ -5974,40 +5977,49 @@ flatpak_dir_pull_oci (FlatpakDir *self, { g_autoptr(FlatpakImageSource) image_source = NULL; FlatpakOciRegistry *registry = NULL; - const char *oci_repository = NULL; const char *delta_url = NULL; g_autofree char *oci_digest = NULL; g_autofree char *checksum = NULL; - VarRefInfoRef latest_rev_info; g_autofree char *latest_alt_commit = NULL; - VarMetadataRef metadata; - g_autofree char *latest_rev = NULL; G_GNUC_UNUSED g_autofree char *latest_commit = flatpak_dir_read_latest (self, state->remote_name, ref, &latest_alt_commit, cancellable, NULL); g_autofree char *name = NULL; - /* We use the summary so that we can reuse any cached json */ - if (!flatpak_remote_state_lookup_ref (state, ref, &latest_rev, NULL, &latest_rev_info, NULL, error)) - return FALSE; - if (latest_rev == NULL) - return flatpak_fail_error (error, FLATPAK_ERROR_REF_NOT_FOUND, - _("Couldn't find latest checksum for ref %s in remote %s"), - ref, state->remote_name); + if (opt_image_source) + { + image_source = g_object_ref (opt_image_source); + oci_digest = g_strdup (flatpak_image_source_get_digest (image_source)); + } + else + { + VarMetadataRef metadata; + VarRefInfoRef latest_rev_info; + const char *oci_repository = NULL; + g_autofree char *latest_rev = NULL; - metadata = var_ref_info_get_metadata (latest_rev_info); - oci_repository = var_metadata_lookup_string (metadata, "xa.oci-repository", NULL); - delta_url = var_metadata_lookup_string (metadata, "xa.delta-url", NULL); + /* We use the summary so that we can reuse any cached json */ + if (!flatpak_remote_state_lookup_ref (state, ref, &latest_rev, NULL, &latest_rev_info, NULL, error)) + return FALSE; + if (latest_rev == NULL) + return flatpak_fail_error (error, FLATPAK_ERROR_REF_NOT_FOUND, + _("Couldn't find latest checksum for ref %s in remote %s"), + ref, state->remote_name); - oci_digest = g_strconcat ("sha256:", opt_rev != NULL ? opt_rev : latest_rev, NULL); + metadata = var_ref_info_get_metadata (latest_rev_info); + oci_repository = var_metadata_lookup_string (metadata, "xa.oci-repository", NULL); + delta_url = var_metadata_lookup_string (metadata, "xa.delta-url", NULL); + + oci_digest = g_strconcat ("sha256:", opt_rev != NULL ? opt_rev : latest_rev, NULL); + + image_source = flatpak_remote_state_new_image_source (state, oci_repository, oci_digest, token, cancellable, error); + if (image_source == NULL) + return FALSE; + } /* Short circuit if we've already got this commit */ if (latest_alt_commit != NULL && strcmp (oci_digest + strlen ("sha256:"), latest_alt_commit) == 0) return TRUE; - image_source = flatpak_remote_state_new_image_source (state, oci_repository, oci_digest, token, cancellable, error); - if (image_source == NULL) - return FALSE; - if (repo == NULL) repo = self->repo; @@ -6046,6 +6058,7 @@ flatpak_dir_pull (FlatpakDir *self, const char *opt_rev, const char **subpaths, GFile *sideload_repo, + FlatpakImageSource *opt_image_source, GBytes *require_metadata, const char *token, OstreeRepo *repo, @@ -6076,8 +6089,8 @@ flatpak_dir_pull (FlatpakDir *self, if (repo == NULL && !flatpak_dir_repo_lock (self, &lock, LOCK_SH, cancellable, error)) return FALSE; - if (flatpak_dir_get_remote_oci (self, state->remote_name)) - return flatpak_dir_pull_oci (self, state, ref, opt_rev, repo, flatpak_flags, + if (opt_image_source || flatpak_dir_get_remote_oci (self, state->remote_name)) + return flatpak_dir_pull_oci (self, state, ref, opt_rev, opt_image_source, repo, flatpak_flags, flags, token, progress, cancellable, error); if (!ostree_repo_remote_get_url (self->repo, @@ -9849,6 +9862,7 @@ flatpak_dir_install (FlatpakDir *self, const char **opt_subpaths, const char **opt_previous_ids, GFile *sideload_repo, + FlatpakImageSource *opt_image_source, GBytes *require_metadata, const char *token, FlatpakProgress *progress, @@ -9913,7 +9927,8 @@ flatpak_dir_install (FlatpakDir *self, child_repo_path = g_file_get_path (registry_file); - if (!flatpak_dir_mirror_oci (self, registry, state, flatpak_decomposed_get_ref (ref), opt_commit, NULL, token, progress, cancellable, error)) + if (!flatpak_dir_mirror_oci (self, registry, state, flatpak_decomposed_get_ref (ref), + opt_commit, opt_image_source, token, progress, cancellable, error)) return FALSE; } else if (!gpg_verify_summary || !gpg_verify) @@ -10007,7 +10022,7 @@ flatpak_dir_install (FlatpakDir *self, flatpak_flags |= FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA; - if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), opt_commit, subpaths, sideload_repo, require_metadata, token, + if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), opt_commit, subpaths, sideload_repo, NULL, require_metadata, token, child_repo, flatpak_flags, 0, @@ -10082,7 +10097,8 @@ flatpak_dir_install (FlatpakDir *self, if (!no_pull) { - if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), opt_commit, opt_subpaths, sideload_repo, require_metadata, token, NULL, + if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), opt_commit, opt_subpaths, + sideload_repo, opt_image_source, require_metadata, token, NULL, flatpak_flags, OSTREE_REPO_PULL_FLAGS_NONE, progress, cancellable, error)) return FALSE; @@ -10529,6 +10545,7 @@ flatpak_dir_update (FlatpakDir *self, const char **opt_subpaths, const char **opt_previous_ids, GFile *sideload_repo, + FlatpakImageSource *opt_image_source, GBytes *require_metadata, const char *token, FlatpakProgress *progress, @@ -10616,7 +10633,7 @@ flatpak_dir_update (FlatpakDir *self, child_repo_path = g_file_get_path (registry_file); if (!flatpak_dir_mirror_oci (self, registry, state, flatpak_decomposed_get_ref (ref), - commit, NULL, token, progress, cancellable, error)) + commit, opt_image_source, token, progress, cancellable, error)) return FALSE; } else if (!gpg_verify_summary || !gpg_verify) @@ -10696,7 +10713,7 @@ flatpak_dir_update (FlatpakDir *self, flatpak_flags |= FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA; if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), - commit, subpaths, sideload_repo, require_metadata, token, + commit, subpaths, sideload_repo, NULL, require_metadata, token, child_repo, flatpak_flags, 0, progress, cancellable, error)) @@ -10762,7 +10779,7 @@ flatpak_dir_update (FlatpakDir *self, if (!no_pull) { if (!flatpak_dir_pull (self, state, flatpak_decomposed_get_ref (ref), - commit, subpaths, sideload_repo, require_metadata, token, + commit, subpaths, sideload_repo, opt_image_source, require_metadata, token, NULL, flatpak_flags, OSTREE_REPO_PULL_FLAGS_NONE, progress, cancellable, error)) return FALSE; diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index c7d2e1dd..3a8677e8 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -1930,7 +1930,7 @@ flatpak_installation_install_full (FlatpakInstallation *self, (flags & FLATPAK_INSTALL_FLAGS_NO_DEPLOY) != 0, (flags & FLATPAK_INSTALL_FLAGS_NO_STATIC_DELTAS) != 0, FALSE, FALSE, FALSE, state, - ref, NULL, (const char **) subpaths, NULL, NULL, NULL, NULL, + ref, NULL, (const char **) subpaths, NULL, NULL, NULL, NULL, NULL, progress, cancellable, error)) return NULL; @@ -2098,7 +2098,7 @@ flatpak_installation_update_full (FlatpakInstallation *self, (flags & FLATPAK_UPDATE_FLAGS_NO_STATIC_DELTAS) != 0, FALSE, FALSE, FALSE, state, ref, target_commit, - (const char **) subpaths, NULL, NULL, NULL, NULL, + (const char **) subpaths, NULL, NULL, NULL, NULL, NULL, progress, cancellable, error)) return NULL; diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c index 7039d86e..ffee385e 100644 --- a/common/flatpak-transaction.c +++ b/common/flatpak-transaction.c @@ -26,7 +26,9 @@ #include "flatpak-auth-private.h" #include "flatpak-dir-private.h" #include "flatpak-error.h" +#include "flatpak-image-source-private.h" #include "flatpak-installation-private.h" +#include "flatpak-oci-registry-private.h" #include "flatpak-progress-private.h" #include "flatpak-repo-utils-private.h" #include "flatpak-transaction-private.h" @@ -103,6 +105,7 @@ struct _FlatpakTransactionOperation char **subpaths; char **previous_ids; char *commit; + FlatpakImageSource *image_source; GFile *bundle; GBytes *external_metadata; FlatpakTransactionOperationType kind; @@ -115,6 +118,7 @@ struct _FlatpakTransactionOperation gboolean resolved; char *resolved_commit; GFile *resolved_sideload_path; + FlatpakImageSource *resolved_image_source; GBytes *resolved_metadata; GKeyFile *resolved_metakey; GBytes *resolved_old_metadata; @@ -144,6 +148,11 @@ typedef struct _BundleData GBytes *gpg_data; } BundleData; +typedef struct _ImageData +{ + char *image_location; +} ImageData; + typedef struct { FlatpakTransaction *transaction; const char *remote; @@ -168,6 +177,7 @@ typedef struct _FlatpakTransactionPrivate GList *flatpakrefs; /* GKeyFiles */ GList *bundles; /* BundleData */ + GList *images; /* ImageData */ guint next_request_id; guint active_request_id; @@ -260,6 +270,23 @@ bundle_data_free (BundleData *data) g_free (data); } +static ImageData * +image_data_new (const char *image_location) +{ + ImageData *data = g_new0 (ImageData, 1); + + data->image_location = g_strdup (image_location); + + return data; +} + +static void +image_data_free (ImageData *data) +{ + g_clear_pointer (&data->image_location, g_free); + g_free (data); +} + static guint progress_signals[LAST_SIGNAL] = { 0 }; /** @@ -612,6 +639,8 @@ flatpak_transaction_operation_finalize (GObject *object) g_clear_pointer (&self->run_before_ops, g_list_free); g_clear_pointer (&self->related_to_ops, g_ptr_array_unref); g_clear_pointer (&self->summary_metadata, g_variant_unref); + g_clear_object (&self->image_source); + g_clear_object (&self->resolved_image_source); G_OBJECT_CLASS (flatpak_transaction_operation_parent_class)->finalize (object); } @@ -993,6 +1022,7 @@ flatpak_transaction_finalize (GObject *object) g_free (priv->parent_window); g_list_free_full (priv->flatpakrefs, (GDestroyNotify) g_key_file_unref); g_list_free_full (priv->bundles, (GDestroyNotify) bundle_data_free); + g_list_free_full (priv->images, (GDestroyNotify) image_data_free); g_free (priv->default_arch); g_hash_table_unref (priv->last_op_for_ref); g_hash_table_unref (priv->remote_states); @@ -2603,6 +2633,7 @@ flatpak_transaction_add_ref (FlatpakTransaction *self, const char *commit, FlatpakTransactionOperationType kind, GFile *bundle, + FlatpakImageSource *image_source, const char *external_metadata, gboolean pin_on_deploy, FlatpakTransactionOperation **out_op, @@ -2730,6 +2761,9 @@ flatpak_transaction_add_ref (FlatpakTransaction *self, op = flatpak_transaction_add_op (self, remote, ref, subpaths, previous_ids, commit, bundle, kind, pin_on_deploy); + if (image_source) + op->image_source = g_object_ref (image_source); + if (external_metadata) op->external_metadata = g_bytes_new (external_metadata, strlen (external_metadata)); @@ -2783,7 +2817,7 @@ flatpak_transaction_add_install (FlatpakTransaction *self, if (!flatpak_transaction_add_ref (self, remote, decomposed, subpaths, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_INSTALL, - NULL, NULL, pin_on_deploy, NULL, error)) + NULL, NULL, NULL, pin_on_deploy, NULL, error)) return FALSE; return TRUE; @@ -2843,7 +2877,7 @@ flatpak_transaction_add_rebase (FlatpakTransaction *self, if (dir_ref_is_installed (priv->dir, decomposed, &installed_origin, NULL)) remote = installed_origin; - return flatpak_transaction_add_ref (self, remote, decomposed, subpaths, previous_ids, NULL, FLATPAK_TRANSACTION_OPERATION_INSTALL_OR_UPDATE, NULL, NULL, FALSE, NULL, error); + return flatpak_transaction_add_ref (self, remote, decomposed, subpaths, previous_ids, NULL, FLATPAK_TRANSACTION_OPERATION_INSTALL_OR_UPDATE, NULL, NULL, NULL, FALSE, NULL, error); } /** @@ -2919,12 +2953,12 @@ flatpak_transaction_add_rebase_and_uninstall (FlatpakTransaction *self, if (!flatpak_transaction_add_ref (self, remote, new_decomposed, subpaths, previous_ids, NULL, FLATPAK_TRANSACTION_OPERATION_INSTALL_OR_UPDATE, - NULL, NULL, FALSE, &rebase_op, error)) + NULL, NULL, NULL, FALSE, &rebase_op, error)) return FALSE; if (!flatpak_transaction_add_ref (self, NULL, old_decomposed, NULL, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_UNINSTALL, - NULL, NULL, FALSE, &uninstall_op, &local_error)) + NULL, NULL, NULL, FALSE, &uninstall_op, &local_error)) { /* If the user is trying to install an eol-rebased app from scratch, the * @old_ref can’t be uninstalled because it’s not installed already. @@ -2980,6 +3014,36 @@ flatpak_transaction_add_install_bundle (FlatpakTransaction *self, return TRUE; } +/** + * flatpak_transaction_add_install_image: + * @self: a #FlatpakTransaction + * @image_location: (nullable): location string to install from. + * @error: return location for a #GError + * + * Install a Flatpak from a container image. The image is specified + * + * If the reference from the image was previously installed, then + * that remote will be used as the remote for the newly installed image. If the + * reference was not previously installed, then a remote will be created for the + * reference. + * + * @image_location is specified in containers-transports(5) form. Only a subset + * of transports are supported: oci: and docker:. + * + * Returns: %TRUE on success; %FALSE with @error set on failure. + */ +gboolean +flatpak_transaction_add_install_image (FlatpakTransaction *self, + const char *image_location, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + priv->images = g_list_append (priv->images, image_data_new (image_location)); + + return TRUE; +} + /** * flatpak_transaction_add_install_flatpakref: * @self: a #FlatpakTransaction @@ -3046,7 +3110,7 @@ flatpak_transaction_add_update (FlatpakTransaction *self, return FALSE; /* Note: we implement the merge when subpaths == NULL in flatpak_transaction_add_ref() */ - return flatpak_transaction_add_ref (self, NULL, decomposed, subpaths, NULL, commit, FLATPAK_TRANSACTION_OPERATION_UPDATE, NULL, NULL, FALSE, NULL, error); + return flatpak_transaction_add_ref (self, NULL, decomposed, subpaths, NULL, commit, FLATPAK_TRANSACTION_OPERATION_UPDATE, NULL, NULL, NULL, FALSE, NULL, error); } /** @@ -3073,7 +3137,7 @@ flatpak_transaction_add_uninstall (FlatpakTransaction *self, if (decomposed == NULL) return FALSE; - return flatpak_transaction_add_ref (self, NULL, decomposed, NULL, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_UNINSTALL, NULL, NULL, FALSE, NULL, error); + return flatpak_transaction_add_ref (self, NULL, decomposed, NULL, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_UNINSTALL, NULL, NULL, NULL, FALSE, NULL, error); } static gboolean @@ -3185,7 +3249,7 @@ flatpak_transaction_add_auto_install (FlatpakTransaction *self, if (!flatpak_transaction_add_ref (self, remote, auto_install_ref, NULL, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_INSTALL_OR_UPDATE, - NULL, NULL, FALSE, NULL, + NULL, NULL, NULL, FALSE, NULL, &local_error)) g_info ("Failed to add auto-install ref %s: %s", flatpak_decomposed_get_ref (auto_install_ref), local_error->message); @@ -3283,6 +3347,7 @@ static gboolean mark_op_resolved (FlatpakTransactionOperation *op, const char *commit, GFile *sideload_path, + FlatpakImageSource *image_source, GBytes *metadata, GBytes *old_metadata, GError **error) @@ -3291,7 +3356,7 @@ mark_op_resolved (FlatpakTransactionOperation *op, g_assert (op != NULL); - g_assert (commit != NULL); + g_assert (commit != NULL || image_source != NULL); op->resolved = TRUE; @@ -3304,6 +3369,9 @@ mark_op_resolved (FlatpakTransactionOperation *op, if (sideload_path) op->resolved_sideload_path = g_object_ref (sideload_path); + if (image_source) + op->resolved_image_source = g_object_ref (image_source); + if (metadata) { g_autoptr(GKeyFile) metakey = g_key_file_new (); @@ -3337,13 +3405,14 @@ resolve_op_end (FlatpakTransaction *self, FlatpakTransactionOperation *op, const char *checksum, GFile *sideload_path, + FlatpakImageSource *image_source, GBytes *metadata_bytes, GError **error) { g_autoptr(GBytes) old_metadata_bytes = NULL; old_metadata_bytes = load_deployed_metadata (self, op->ref, NULL, NULL); - if (!mark_op_resolved (op, checksum, sideload_path, metadata_bytes, old_metadata_bytes, error)) + if (!mark_op_resolved (op, checksum, sideload_path, image_source, metadata_bytes, old_metadata_bytes, error)) return FALSE; emit_eol_and_maybe_skip (self, op); return TRUE; @@ -3394,7 +3463,7 @@ resolve_op_from_commit (FlatpakTransaction *self, flatpak_decomposed_get_ref (eolr_decomposed)); } - return resolve_op_end (self, op, checksum, sideload_path, metadata_bytes, error); + return resolve_op_end (self, op, checksum, sideload_path, NULL, metadata_bytes, error); } /* NOTE: In case of non-available summary this returns FALSE with a @@ -3459,7 +3528,7 @@ try_resolve_op_from_metadata (FlatpakTransaction *self, } } - return resolve_op_end (self, op, checksum, sideload_path, metadata_bytes, error); + return resolve_op_end (self, op, checksum, sideload_path, NULL, metadata_bytes, error); } static gboolean @@ -3502,7 +3571,7 @@ resolve_ops (FlatpakTransaction *self, * checksum we got was the version already installed. */ g_assert (op->resolved_commit != NULL); - if (!mark_op_resolved (op, op->resolved_commit, NULL, NULL, NULL, error)) + if (!mark_op_resolved (op, op->resolved_commit, NULL, NULL, NULL, NULL, error)) return FALSE; continue; } @@ -3517,7 +3586,7 @@ resolve_ops (FlatpakTransaction *self, op->skip = TRUE; continue; } - if (!mark_op_resolved (op, checksum, NULL, metadata_bytes, NULL, error)) + if (!mark_op_resolved (op, checksum, NULL, NULL, metadata_bytes, NULL, error)) return FALSE; continue; } @@ -3525,7 +3594,7 @@ resolve_ops (FlatpakTransaction *self, if (op->kind == FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE) { g_assert (op->commit != NULL); - if (!mark_op_resolved (op, op->commit, NULL, op->external_metadata, NULL, error)) + if (!mark_op_resolved (op, op->commit, NULL, NULL, op->external_metadata, NULL, error)) return FALSE; continue; } @@ -3549,8 +3618,13 @@ resolve_ops (FlatpakTransaction *self, if (state == NULL) return FALSE; + if (op->image_source) + { + if (!mark_op_resolved (op, NULL, NULL, op->image_source, op->external_metadata, NULL, error)) + return FALSE; + } /* Should we use local state */ - if (transaction_is_local_only (self, op->kind)) + else if (transaction_is_local_only (self, op->kind)) { g_autoptr(GVariant) commit_data = flatpak_dir_read_latest_commit (priv->dir, op->remote, op->ref, &checksum, NULL, error); @@ -4688,7 +4762,74 @@ flatpak_transaction_resolve_bundles (FlatpakTransaction *self, if (!flatpak_transaction_add_ref (self, remote, ref, NULL, NULL, commit, FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE, - data->file, metadata, FALSE, NULL, error)) + data->file, NULL, metadata, FALSE, NULL, error)) + return FALSE; + } + + return TRUE; +} + +static gboolean +flatpak_transaction_resolve_images (FlatpakTransaction *self, + GCancellable *cancellable, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + GList *l; + + for (l = priv->images; l != NULL; l = l->next) + { + ImageData *data = l->data; + g_autoptr(FlatpakImageSource) image_source = NULL; + g_autofree char *remote = NULL; + g_autoptr(FlatpakDecomposed) ref = NULL; + const char *ref_label; + const char *metadata_label; + FlatpakTransactionOperation *op; + g_autoptr(GBytes) deploy_data = NULL; + + image_source = flatpak_image_source_new_for_location (data->image_location, + cancellable, error); + if (!image_source) + return FALSE; + + ref_label = flatpak_image_source_get_ref (image_source); + ref = flatpak_decomposed_new_from_ref (ref_label, error); + if (ref == NULL) + { + g_prefix_error (error, "Cannot parse org.flatpak.ref label: "); + return FALSE; + } + + metadata_label = flatpak_image_source_get_metadata (image_source); + if (metadata_label == NULL) + return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, + "Image does not have org.flatpak.metadata label"); + + deploy_data = flatpak_dir_get_deploy_data (priv->dir, ref, FLATPAK_DEPLOY_VERSION_ANY, cancellable, NULL); + if (deploy_data != NULL) + remote = g_strdup (flatpak_deploy_data_get_origin (deploy_data)); + + if (remote == NULL) + { + gboolean created_remote; + g_autofree char *id = flatpak_decomposed_dup_id (ref); + + remote = flatpak_dir_create_origin_remote (priv->dir, NULL /* url */, id, + NULL /* title */, ref_label, + NULL /* gpg_data */, NULL /* collection_id */, + &created_remote, + cancellable, error); + if (!remote) + return FALSE; + + if (created_remote) + flatpak_installation_drop_caches (priv->installation, NULL, NULL); + } + + if (!flatpak_transaction_add_ref (self, remote, ref, NULL, NULL, NULL, + FLATPAK_TRANSACTION_OPERATION_INSTALL, + NULL, image_source, metadata_label, FALSE, &op, error)) return FALSE; } @@ -4747,7 +4888,7 @@ _run_op_kind (FlatpakTransaction *self, emit_new_op (self, op, progress); - g_assert (op->resolved_commit != NULL); /* We resolved this before */ + g_assert (op->resolved_commit != NULL || op->resolved_image_source != NULL); /* We resolved this before */ if (op->resolved_metakey && !flatpak_check_required_version (flatpak_decomposed_get_ref (op->ref), op->resolved_metakey, &local_error)) @@ -4765,6 +4906,7 @@ _run_op_kind (FlatpakTransaction *self, (const char **) op->subpaths, (const char **) op->previous_ids, op->resolved_sideload_path, + op->resolved_image_source, op->resolved_metadata, op->resolved_token, progress->progress_obj, @@ -4838,6 +4980,7 @@ _run_op_kind (FlatpakTransaction *self, (const char **) op->subpaths, (const char **) op->previous_ids, op->resolved_sideload_path, + op->resolved_image_source, op->resolved_metadata, op->resolved_token, progress->progress_obj, @@ -5149,6 +5292,12 @@ flatpak_transaction_real_run (FlatpakTransaction *self, return FALSE; } + if (!flatpak_transaction_resolve_images (self, cancellable, error)) + { + g_assert (error == NULL || *error != NULL); + return FALSE; + } + /* Resolve initial ops */ if (!resolve_all_ops (self, cancellable, error)) { diff --git a/common/flatpak-transaction.h b/common/flatpak-transaction.h index 0b8f2de8..3d3f4ce8 100644 --- a/common/flatpak-transaction.h +++ b/common/flatpak-transaction.h @@ -326,6 +326,10 @@ gboolean flatpak_transaction_add_install_bundle (FlatpakTransaction * GBytes *gpg_data, GError **error); FLATPAK_EXTERN +gboolean flatpak_transaction_add_install_image (FlatpakTransaction *self, + const char *image_location, + GError **error); +FLATPAK_EXTERN gboolean flatpak_transaction_add_install_flatpakref (FlatpakTransaction *self, GBytes *flatpakref_data, GError **error); diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c index a4d9708b..2740b299 100644 --- a/system-helper/flatpak-system-helper.c +++ b/system-helper/flatpak-system-helper.c @@ -640,7 +640,7 @@ handle_deploy (FlatpakSystemHelper *object, return G_DBUS_METHOD_INVOCATION_HANDLED; } - if (!flatpak_dir_pull (system, state, arg_ref, NULL, (const char **) arg_subpaths, NULL, NULL, NULL, NULL, + if (!flatpak_dir_pull (system, state, arg_ref, NULL, (const char **) arg_subpaths, NULL, NULL, NULL, NULL, NULL, FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_UNTRUSTED, NULL, NULL, &error)) { @@ -874,11 +874,11 @@ handle_deploy_appstream (FlatpakSystemHelper *object, return G_DBUS_METHOD_INVOCATION_HANDLED; } - if (!flatpak_dir_pull (system, state, new_branch, NULL, NULL, NULL, NULL, NULL, NULL, + if (!flatpak_dir_pull (system, state, new_branch, NULL, NULL, NULL, NULL, NULL, NULL, NULL, FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_UNTRUSTED, NULL, NULL, &first_error)) { - if (!flatpak_dir_pull (system, state, old_branch, NULL, NULL, NULL, NULL, NULL, NULL, + if (!flatpak_dir_pull (system, state, old_branch, NULL, NULL, NULL, NULL, NULL, NULL, NULL, FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_UNTRUSTED, NULL, NULL, &second_error)) {