flatpak/flatpak-allow-direct-installation-from-oci-images.patch
Jan Grulich 34285389a4 Update to 1.16.0
Resolves: RHEL-72779

Add support for preinstalling Flatpaks
Resolves: RHEL-26066
2025-01-13 15:54:17 +01:00

4179 lines
175 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 7a77045bdd30b0000207cbf066c0ef105be0764b Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Mon, 14 Oct 2024 09:12:39 -0400
Subject: [PATCH 01/12] image-source: Refactor - add FlatpakImageSource type
To avoid passing around combinations of a FlaptakOciRegistry with
repository and digest, add a FlatpakImageSource type.
This also reduces duplicated code where every place that did
this independently retrieved the repository and image config.
---
app/flatpak-builtins-build-import-bundle.c | 65 +-----
common/flatpak-common-types-private.h | 1 +
common/flatpak-dir.c | 80 +++-----
common/flatpak-image-source-private.h | 57 ++++++
common/flatpak-image-source.c | 227 +++++++++++++++++++++
common/flatpak-oci-registry-private.h | 11 +-
common/flatpak-oci-registry.c | 46 ++---
common/meson.build | 1 +
doc/reference/meson.build | 1 +
system-helper/flatpak-system-helper.c | 57 +-----
10 files changed, 348 insertions(+), 198 deletions(-)
create mode 100644 common/flatpak-image-source-private.h
create mode 100644 common/flatpak-image-source.c
diff --git a/app/flatpak-builtins-build-import-bundle.c b/app/flatpak-builtins-build-import-bundle.c
index d5d6fc2..f350870 100644
--- a/app/flatpak-builtins-build-import-bundle.c
+++ b/app/flatpak-builtins-build-import-bundle.c
@@ -30,9 +30,10 @@
#include "libglnx.h"
#include "flatpak-builtins.h"
+#include "flatpak-image-source-private.h"
+#include "flatpak-oci-registry-private.h"
#include "flatpak-repo-utils-private.h"
#include "flatpak-utils-private.h"
-#include "flatpak-oci-registry-private.h"
static char *opt_ref;
static gboolean opt_oci = FALSE;
@@ -58,65 +59,17 @@ import_oci (OstreeRepo *repo, GFile *file,
GCancellable *cancellable, GError **error)
{
g_autofree char *commit_checksum = NULL;
- g_autofree char *dir_uri = NULL;
g_autofree char *target_ref = NULL;
- const char *oci_digest;
- g_autoptr(FlatpakOciRegistry) registry = NULL;
- g_autoptr(FlatpakOciVersioned) versioned = NULL;
- g_autoptr(FlatpakOciImage) image_config = NULL;
- FlatpakOciManifest *manifest = NULL;
- g_autoptr(FlatpakOciIndex) index = NULL;
- const FlatpakOciManifestDescriptor *desc;
+ g_autoptr(FlatpakImageSource) image_source = NULL;
GHashTable *labels;
- dir_uri = g_file_get_uri (file);
- registry = flatpak_oci_registry_new (dir_uri, FALSE, -1, cancellable, error);
- if (registry == NULL)
- return NULL;
-
- index = flatpak_oci_registry_load_index (registry, cancellable, error);
- if (index == NULL)
- return NULL;
-
- if (opt_ref)
- {
- desc = flatpak_oci_index_get_manifest (index, opt_ref);
- if (desc == NULL)
- {
- flatpak_fail (error, _("Ref '%s' not found in registry"), opt_ref);
- return NULL;
- }
- }
- else
- {
- desc = flatpak_oci_index_get_only_manifest (index);
- if (desc == NULL)
- {
- flatpak_fail (error, _("Multiple images in registry, specify a ref with --ref"));
- return NULL;
- }
- }
-
- oci_digest = desc->parent.digest;
-
- versioned = flatpak_oci_registry_load_versioned (registry, NULL,
- oci_digest, NULL, NULL,
- cancellable, error);
- if (versioned == NULL)
+ image_source = flatpak_image_source_new_local (file, opt_ref, cancellable, error);
+ if (image_source == NULL)
return NULL;
- manifest = FLATPAK_OCI_MANIFEST (versioned);
-
- image_config = flatpak_oci_registry_load_image_config (registry, NULL,
- manifest->config.digest, NULL,
- NULL, cancellable, error);
- if (image_config == NULL)
- return FALSE;
-
- labels = flatpak_oci_image_get_labels (image_config);
- if (labels)
- flatpak_oci_parse_commit_labels (labels, NULL, NULL, NULL,
- &target_ref, NULL, NULL, NULL);
+ labels = flatpak_image_source_get_labels (image_source);
+ flatpak_oci_parse_commit_labels (labels, NULL, NULL, NULL,
+ &target_ref, NULL, NULL, NULL);
if (target_ref == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
@@ -124,7 +77,7 @@ import_oci (OstreeRepo *repo, GFile *file,
return NULL;
}
- commit_checksum = flatpak_pull_from_oci (repo, registry, NULL, oci_digest, NULL, manifest, image_config,
+ commit_checksum = flatpak_pull_from_oci (repo, image_source, NULL,
NULL, target_ref, FLATPAK_PULL_FLAGS_NONE, NULL, NULL, cancellable, error);
if (commit_checksum == NULL)
return NULL;
diff --git a/common/flatpak-common-types-private.h b/common/flatpak-common-types-private.h
index 0513014..d7f3913 100644
--- a/common/flatpak-common-types-private.h
+++ b/common/flatpak-common-types-private.h
@@ -53,6 +53,7 @@ typedef enum {
typedef struct FlatpakDir FlatpakDir;
typedef struct FlatpakDeploy FlatpakDeploy;
+typedef struct _FlatpakImageSource FlatpakImageSource;
typedef struct FlatpakOciRegistry FlatpakOciRegistry;
typedef struct _FlatpakOciManifest FlatpakOciManifest;
typedef struct _FlatpakOciImage FlatpakOciImage;
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index fe423b7..338573e 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -52,6 +52,7 @@
#include "flatpak-dir-utils-private.h"
#include "flatpak-error.h"
#include "flatpak-locale-utils-private.h"
+#include "flatpak-image-source-private.h"
#include "flatpak-oci-registry-private.h"
#include "flatpak-ref.h"
#include "flatpak-repo-utils-private.h"
@@ -1058,14 +1059,16 @@ lookup_oci_registry_uri_from_summary (GVariant *summary,
return g_steal_pointer (&registry_uri);
}
-static FlatpakOciRegistry *
-flatpak_remote_state_new_oci_registry (FlatpakRemoteState *self,
+static FlatpakImageSource *
+flatpak_remote_state_new_image_source (FlatpakRemoteState *self,
+ const char *oci_repository,
+ const char *digest,
const char *token,
GCancellable *cancellable,
GError **error)
{
g_autofree char *registry_uri = NULL;
- g_autoptr(FlatpakOciRegistry) registry = NULL;
+ g_autoptr(FlatpakImageSource) image_source = NULL;
if (!flatpak_remote_state_ensure_summary (self, error))
return NULL;
@@ -1074,13 +1077,13 @@ flatpak_remote_state_new_oci_registry (FlatpakRemoteState *self,
if (registry_uri == NULL)
return NULL;
- registry = flatpak_oci_registry_new (registry_uri, FALSE, -1, NULL, error);
- if (registry == NULL)
+ image_source = flatpak_image_source_new_remote (registry_uri, oci_repository, digest, NULL, error);
+ if (image_source == NULL)
return NULL;
- flatpak_oci_registry_set_token (registry, token);
+ flatpak_image_source_set_token (image_source, token);
- return g_steal_pointer (&registry);
+ return g_steal_pointer (&image_source);
}
static GVariant *
@@ -1092,9 +1095,7 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
GCancellable *cancellable,
GError **error)
{
- g_autoptr(FlatpakOciRegistry) registry = NULL;
- g_autoptr(FlatpakOciVersioned) versioned = NULL;
- g_autoptr(FlatpakOciImage) image_config = NULL;
+ g_autoptr(FlatpakImageSource) image_source = NULL;
g_autofree char *oci_digest = NULL;
g_autofree char *latest_rev = NULL;
VarRefInfoRef latest_rev_info;
@@ -1109,10 +1110,6 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
g_autoptr(GVariantBuilder) metadata_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_autoptr(GVariant) metadata_v = NULL;
- registry = flatpak_remote_state_new_oci_registry (self, token, cancellable, error);
- if (registry == NULL)
- return NULL;
-
/* We extract the rev info from the latest, even if we don't use the latest digest, assuming refs don't move */
if (!flatpak_remote_state_lookup_ref (self, ref, &latest_rev, NULL, &latest_rev_info, NULL, error))
return NULL;
@@ -1130,25 +1127,11 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
oci_digest = g_strconcat ("sha256:", checksum, NULL);
- versioned = flatpak_oci_registry_load_versioned (registry, oci_repository, oci_digest,
- NULL, NULL, cancellable, error);
- if (versioned == NULL)
- return NULL;
-
- if (!FLATPAK_IS_OCI_MANIFEST (versioned))
- {
- flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Image is not a manifest"));
- return NULL;
- }
-
- image_config = flatpak_oci_registry_load_image_config (registry, oci_repository,
- FLATPAK_OCI_MANIFEST (versioned)->config.digest,
- (const char **)FLATPAK_OCI_MANIFEST (versioned)->config.urls,
- NULL, cancellable, error);
- if (image_config == NULL)
+ image_source = flatpak_remote_state_new_image_source (self, oci_repository, oci_digest, token, cancellable, error);
+ if (image_source == NULL)
return NULL;
- labels = flatpak_oci_image_get_labels (image_config);
+ labels = flatpak_image_source_get_labels (image_source);
if (labels)
flatpak_oci_parse_commit_labels (labels, &timestamp,
&subject, &body,
@@ -6123,7 +6106,7 @@ flatpak_dir_mirror_oci (FlatpakDir *self,
GCancellable *cancellable,
GError **error)
{
- g_autoptr(FlatpakOciRegistry) registry = NULL;
+ g_autoptr(FlatpakImageSource) image_source = NULL;
g_autofree char *oci_digest = NULL;
g_autofree char *latest_rev = NULL;
VarRefInfoRef latest_rev_info;
@@ -6156,15 +6139,15 @@ flatpak_dir_mirror_oci (FlatpakDir *self,
oci_digest = g_strconcat ("sha256:", rev, NULL);
- registry = flatpak_remote_state_new_oci_registry (state, token, cancellable, error);
- if (registry == 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);
g_info ("Mirroring OCI image %s", oci_digest);
- res = flatpak_mirror_image_from_oci (dst_registry, registry, oci_repository, oci_digest, state->remote_name, ref, delta_url, self->repo, oci_pull_progress_cb,
+ res = flatpak_mirror_image_from_oci (dst_registry, image_source, state->remote_name, ref, delta_url, self->repo, oci_pull_progress_cb,
progress, cancellable, error);
if (!res)
@@ -6186,9 +6169,8 @@ flatpak_dir_pull_oci (FlatpakDir *self,
GCancellable *cancellable,
GError **error)
{
- g_autoptr(FlatpakOciRegistry) registry = NULL;
- g_autoptr(FlatpakOciVersioned) versioned = NULL;
- g_autoptr(FlatpakOciImage) image_config = NULL;
+ 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;
@@ -6219,23 +6201,8 @@ flatpak_dir_pull_oci (FlatpakDir *self,
if (latest_alt_commit != NULL && strcmp (oci_digest + strlen ("sha256:"), latest_alt_commit) == 0)
return TRUE;
- registry = flatpak_remote_state_new_oci_registry (state, token, cancellable, error);
- if (registry == NULL)
- return FALSE;
-
- versioned = flatpak_oci_registry_load_versioned (registry, oci_repository, oci_digest,
- NULL, NULL, cancellable, error);
- if (versioned == NULL)
- return FALSE;
-
- if (!FLATPAK_IS_OCI_MANIFEST (versioned))
- return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Image is not a manifest"));
-
- image_config = flatpak_oci_registry_load_image_config (registry, oci_repository,
- FLATPAK_OCI_MANIFEST (versioned)->config.digest,
- (const char **)FLATPAK_OCI_MANIFEST (versioned)->config.urls,
- NULL, cancellable, error);
- if (image_config == NULL)
+ 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)
@@ -6245,7 +6212,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
g_info ("Pulling OCI image %s", oci_digest);
- checksum = flatpak_pull_from_oci (repo, registry, oci_repository, oci_digest, delta_url, FLATPAK_OCI_MANIFEST (versioned), image_config,
+ checksum = flatpak_pull_from_oci (repo, image_source, delta_url,
state->remote_name, ref, flatpak_flags, oci_pull_progress_cb, progress, cancellable, error);
if (checksum == NULL)
@@ -6261,6 +6228,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
name = g_file_get_path (file);
}
+ registry = flatpak_image_source_get_registry (image_source);
(flatpak_dir_log) (self, __FILE__, __LINE__, __FUNCTION__, name,
"pull oci", flatpak_oci_registry_get_uri (registry), ref, NULL, NULL, NULL,
"Pulled %s from %s", ref, flatpak_oci_registry_get_uri (registry));
diff --git a/common/flatpak-image-source-private.h b/common/flatpak-image-source-private.h
new file mode 100644
index 0000000..ebd856a
--- /dev/null
+++ b/common/flatpak-image-source-private.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2024 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ */
+
+#ifndef __FLATPAK_IMAGE_SOURCE_H__
+#define __FLATPAK_IMAGE_SOURCE_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <flatpak-common-types-private.h>
+
+#define FLATPAK_TYPE_IMAGE_SOURCE flatpak_image_source_get_type ()
+G_DECLARE_FINAL_TYPE (FlatpakImageSource,
+ flatpak_image_source,
+ FLATPAK, IMAGE_SOURCE,
+ GObject)
+
+FlatpakImageSource *flatpak_image_source_new_local (GFile *file,
+ const char *reference,
+ GCancellable *cancellable,
+ GError **error);
+FlatpakImageSource *flatpak_image_source_new_remote (const char *uri,
+ const char *oci_repository,
+ const char *digest,
+ GCancellable *cancellable,
+ GError **error);
+
+void flatpak_image_source_set_token (FlatpakImageSource *self,
+ const char *token);
+
+FlatpakOciRegistry *flatpak_image_source_get_registry (FlatpakImageSource *self);
+const char *flatpak_image_source_get_oci_repository (FlatpakImageSource *self);
+const char *flatpak_image_source_get_digest (FlatpakImageSource *self);
+FlatpakOciManifest *flatpak_image_source_get_manifest (FlatpakImageSource *self);
+size_t flatpak_image_source_get_manifest_size (FlatpakImageSource *self);
+FlatpakOciImage *flatpak_image_source_get_image_config (FlatpakImageSource *self);
+
+GHashTable *flatpak_image_source_get_labels (FlatpakImageSource *self);
+
+#endif /* __FLATPAK_IMAGE_SOURCE_H__ */
diff --git a/common/flatpak-image-source.c b/common/flatpak-image-source.c
new file mode 100644
index 0000000..22497cc
--- /dev/null
+++ b/common/flatpak-image-source.c
@@ -0,0 +1,227 @@
+/* vi:set et sw=2 sts=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e-s:
+ * Copyright © 2024 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include "flatpak-image-source-private.h"
+#include "flatpak-oci-registry-private.h"
+
+struct _FlatpakImageSource
+{
+ GObject parent;
+
+ FlatpakOciRegistry *registry;
+ char *repository;
+ char *digest;
+
+ FlatpakOciManifest *manifest;
+ size_t manifest_size;
+ FlatpakOciImage *image_config;
+};
+
+G_DEFINE_TYPE (FlatpakImageSource, flatpak_image_source, G_TYPE_OBJECT)
+
+static void
+flatpak_image_source_finalize (GObject *object)
+{
+ FlatpakImageSource *self = FLATPAK_IMAGE_SOURCE (object);
+
+ g_clear_object (&self->registry);
+ g_clear_pointer (&self->repository, g_free);
+ g_clear_pointer (&self->digest, g_free);
+ g_clear_object (&self->manifest);
+ g_clear_object (&self->image_config);
+
+ G_OBJECT_CLASS (flatpak_image_source_parent_class)->finalize (object);
+}
+
+static void
+flatpak_image_source_class_init (FlatpakImageSourceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = flatpak_image_source_finalize;
+}
+
+static void
+flatpak_image_source_init (FlatpakImageSource *self)
+{
+}
+
+static FlatpakImageSource *
+flatpak_image_source_new (FlatpakOciRegistry *registry,
+ const char *repository,
+ const char *digest,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FlatpakImageSource) self = NULL;
+ g_autoptr(FlatpakOciVersioned) versioned = NULL;
+ GHashTable *labels;
+
+ self = g_object_new (FLATPAK_TYPE_IMAGE_SOURCE, NULL);
+ self->registry = g_object_ref (registry);
+ self->repository = g_strdup (repository);
+ self->digest = g_strdup (digest);
+
+ versioned = flatpak_oci_registry_load_versioned (self->registry, self->repository,
+ self->digest, NULL, &self->manifest_size,
+ cancellable, error);
+ if (versioned == NULL)
+ return NULL;
+
+ if (!FLATPAK_IS_OCI_MANIFEST (versioned))
+ {
+ flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Image is not a manifest"));
+ return NULL;
+ }
+
+ self->manifest = FLATPAK_OCI_MANIFEST (g_steal_pointer (&versioned));
+
+ if (self->manifest->config.digest == NULL)
+ {
+ flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Image is not a manifest"));
+ return NULL;
+ }
+
+ self->image_config = flatpak_oci_registry_load_image_config (self->registry, self->repository,
+ self->manifest->config.digest, NULL,
+ NULL, cancellable, error);
+ if (self->image_config == NULL)
+ return NULL;
+
+ labels = flatpak_image_source_get_labels (self);
+ if (!g_hash_table_contains (labels, "org.flatpak.ref"))
+ {
+ flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("No org.flatpak.ref found in image"));
+ return NULL;
+ }
+
+ return g_steal_pointer (&self);
+}
+
+FlatpakImageSource *
+flatpak_image_source_new_local (GFile *file,
+ const char *reference,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autofree char *dir_uri = NULL;
+ g_autofree char *target_ref = NULL;
+ g_autoptr(FlatpakImageSource) image_source = NULL;
+ g_autoptr(FlatpakOciRegistry) registry = NULL;
+ g_autoptr(FlatpakOciIndex) index = NULL;
+ const FlatpakOciManifestDescriptor *desc;
+
+ dir_uri = g_file_get_uri (file);
+ registry = flatpak_oci_registry_new (dir_uri, FALSE, -1, cancellable, error);
+ if (registry == NULL)
+ return NULL;
+
+ index = flatpak_oci_registry_load_index (registry, cancellable, error);
+ if (index == NULL)
+ return NULL;
+
+ if (reference)
+ {
+ desc = flatpak_oci_index_get_manifest (index, reference);
+ if (desc == NULL)
+ {
+ flatpak_fail (error, _("Ref '%s' not found in registry"), reference);
+ return NULL;
+ }
+ }
+ else
+ {
+ desc = flatpak_oci_index_get_only_manifest (index);
+ if (desc == NULL)
+ {
+ flatpak_fail (error, _("Multiple images in registry, specify a ref with --ref"));
+ return NULL;
+ }
+ }
+
+ return flatpak_image_source_new (registry, NULL, desc->parent.digest, cancellable, error);
+}
+
+FlatpakImageSource *
+flatpak_image_source_new_remote (const char *uri,
+ const char *oci_repository,
+ const char *digest,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FlatpakOciRegistry) registry = NULL;
+
+ registry = flatpak_oci_registry_new (uri, FALSE, -1, cancellable, error);
+ if (!registry)
+ return NULL;
+
+ return flatpak_image_source_new (registry, oci_repository, digest, cancellable, error);
+}
+
+void
+flatpak_image_source_set_token (FlatpakImageSource *self,
+ const char *token)
+{
+ flatpak_oci_registry_set_token (self->registry, token);
+}
+
+FlatpakOciRegistry *
+flatpak_image_source_get_registry (FlatpakImageSource *self)
+{
+ return self->registry;
+}
+
+const char *
+flatpak_image_source_get_oci_repository (FlatpakImageSource *self)
+{
+ return self->repository;
+}
+
+const char *
+flatpak_image_source_get_digest (FlatpakImageSource *self)
+{
+ return self->digest;
+}
+
+FlatpakOciManifest *
+flatpak_image_source_get_manifest (FlatpakImageSource *self)
+{
+ return self->manifest;
+}
+
+size_t
+flatpak_image_source_get_manifest_size (FlatpakImageSource *self)
+{
+ return self->manifest_size;
+}
+
+FlatpakOciImage *
+flatpak_image_source_get_image_config (FlatpakImageSource *self)
+{
+ return self->image_config;
+}
+
+GHashTable *
+flatpak_image_source_get_labels (FlatpakImageSource *self)
+{
+ return flatpak_oci_image_get_labels (self->image_config);
+}
diff --git a/common/flatpak-oci-registry-private.h b/common/flatpak-oci-registry-private.h
index 2c0608d..47ffc7b 100644
--- a/common/flatpak-oci-registry-private.h
+++ b/common/flatpak-oci-registry-private.h
@@ -183,6 +183,7 @@ GBytes *flatpak_oci_index_make_appstream (FlatpakHttpSession *http_session,
GCancellable *cancellable,
GError **error);
+
typedef void (*FlatpakOciPullProgress) (guint64 total_size,
guint64 pulled_size,
guint32 n_layers,
@@ -190,12 +191,8 @@ typedef void (*FlatpakOciPullProgress) (guint64 total_size,
gpointer data);
char * flatpak_pull_from_oci (OstreeRepo *repo,
- FlatpakOciRegistry *registry,
- const char *oci_repository,
- const char *digest,
+ FlatpakImageSource *image_source,
const char *delta_url,
- FlatpakOciManifest *manifest,
- FlatpakOciImage *image_config,
const char *remote,
const char *ref,
FlatpakPullFlags flags,
@@ -205,9 +202,7 @@ char * flatpak_pull_from_oci (OstreeRepo *repo,
GError **error);
gboolean flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
- FlatpakOciRegistry *registry,
- const char *oci_repository,
- const char *digest,
+ FlatpakImageSource *image_source,
const char *remote,
const char *ref,
const char *delta_url,
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
index ad595e5..9e2b163 100644
--- a/common/flatpak-oci-registry.c
+++ b/common/flatpak-oci-registry.c
@@ -28,6 +28,7 @@
#include <archive.h>
#include <gpgme.h>
+#include "flatpak-image-source-private.h"
#include "flatpak-oci-registry-private.h"
#include "flatpak-repo-utils-private.h"
#include "flatpak-utils-base-private.h"
@@ -3422,9 +3423,7 @@ oci_layer_progress (guint64 downloaded_bytes,
gboolean
flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
- FlatpakOciRegistry *registry,
- const char *oci_repository,
- const char *digest,
+ FlatpakImageSource *image_source,
const char *remote,
const char *ref,
const char *delta_url,
@@ -3435,8 +3434,11 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
GError **error)
{
FlatpakOciPullProgressData progress_data = { progress_cb, progress_user_data };
- g_autoptr(FlatpakOciVersioned) versioned = NULL;
- FlatpakOciManifest *manifest = NULL;
+ FlatpakOciRegistry *registry = flatpak_image_source_get_registry (image_source);
+ const char *oci_repository = flatpak_image_source_get_oci_repository (image_source);
+ const char *digest = flatpak_image_source_get_digest (image_source);
+ FlatpakOciManifest *manifest = flatpak_image_source_get_manifest (image_source);
+ FlatpakOciImage *image_config = flatpak_image_source_get_image_config (image_source);
g_autoptr(FlatpakOciDescriptor) manifest_desc = NULL;
g_autoptr(FlatpakOciManifest) delta_manifest = NULL;
g_autofree char *old_checksum = NULL;
@@ -3444,36 +3446,16 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
g_autoptr(GFile) old_root = NULL;
OstreeRepoCommitState old_state = 0;
g_autofree char *old_diffid = NULL;
- gsize versioned_size;
g_autoptr(FlatpakOciIndex) index = NULL;
- g_autoptr(FlatpakOciImage) image_config = NULL;
int n_layers;
int i;
if (!flatpak_oci_registry_mirror_blob (dst_registry, registry, oci_repository, TRUE, digest, NULL, NULL, NULL, cancellable, error))
return FALSE;
- versioned = flatpak_oci_registry_load_versioned (dst_registry, NULL, digest, NULL, &versioned_size, cancellable, error);
- if (versioned == NULL)
- return FALSE;
-
- if (!FLATPAK_IS_OCI_MANIFEST (versioned))
- return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Image is not a manifest"));
-
- manifest = FLATPAK_OCI_MANIFEST (versioned);
-
- if (manifest->config.digest == NULL)
- return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Image is not a manifest"));
-
if (!flatpak_oci_registry_mirror_blob (dst_registry, registry, oci_repository, FALSE, manifest->config.digest, (const char **)manifest->config.urls, NULL, NULL, cancellable, error))
return FALSE;
- image_config = flatpak_oci_registry_load_image_config (dst_registry, NULL,
- manifest->config.digest, NULL,
- NULL, cancellable, error);
- if (image_config == NULL)
- return FALSE;
-
/* For deltas we ensure that the diffid and regular layers exists and match up */
n_layers = flatpak_oci_manifest_get_n_layers (manifest);
if (n_layers == 0 || n_layers != flatpak_oci_image_get_n_layers (image_config))
@@ -3557,7 +3539,8 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
if (index == NULL)
index = flatpak_oci_index_new ();
- manifest_desc = flatpak_oci_descriptor_new (versioned->mediatype, digest, versioned_size);
+ manifest_desc = flatpak_oci_descriptor_new (manifest->parent.mediatype, digest,
+ flatpak_image_source_get_manifest_size (image_source));
flatpak_oci_index_add_manifest (index, ref, manifest_desc);
@@ -3569,12 +3552,8 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
char *
flatpak_pull_from_oci (OstreeRepo *repo,
- FlatpakOciRegistry *registry,
- const char *oci_repository,
- const char *digest,
+ FlatpakImageSource *image_source,
const char *delta_url,
- FlatpakOciManifest *manifest,
- FlatpakOciImage *image_config,
const char *remote,
const char *ref,
FlatpakPullFlags flags,
@@ -3583,6 +3562,11 @@ flatpak_pull_from_oci (OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
+ FlatpakOciRegistry *registry = flatpak_image_source_get_registry (image_source);
+ const char *oci_repository = flatpak_image_source_get_oci_repository (image_source);
+ const char *digest = flatpak_image_source_get_digest (image_source);
+ FlatpakOciManifest *manifest = flatpak_image_source_get_manifest (image_source);
+ FlatpakOciImage *image_config = flatpak_image_source_get_image_config (image_source);
gboolean force_disable_deltas = (flags & FLATPAK_PULL_FLAGS_NO_STATIC_DELTAS) != 0;
g_autoptr(OstreeMutableTree) archive_mtree = NULL;
g_autoptr(GFile) archive_root = NULL;
diff --git a/common/meson.build b/common/meson.build
index bd5dbf3..beed1f0 100644
--- a/common/meson.build
+++ b/common/meson.build
@@ -172,6 +172,7 @@ sources = [
'flatpak-error.c',
'flatpak-exports.c',
'flatpak-glib-backports.c',
+ 'flatpak-image-source.c',
'flatpak-installation.c',
'flatpak-installed-ref.c',
'flatpak-instance.c',
diff --git a/doc/reference/meson.build b/doc/reference/meson.build
index a881b0c..92f1482 100644
--- a/doc/reference/meson.build
+++ b/doc/reference/meson.build
@@ -46,6 +46,7 @@ gnome.gtkdoc(
'flatpak-document-dbus-generated.h',
'flatpak-enum-types.h',
'flatpak-exports-private.h',
+ 'flatpak-image-source-private.h',
'flatpak-installed-ref-private.h',
'flatpak-json-oci-private.h',
'flatpak-json-private.h',
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
index c39d0d7..263bf0b 100644
--- a/system-helper/flatpak-system-helper.c
+++ b/system-helper/flatpak-system-helper.c
@@ -39,6 +39,7 @@
#include "flatpak-dbus-generated.h"
#include "flatpak-dir-private.h"
#include "flatpak-error.h"
+#include "flatpak-image-source-private.h"
#include "flatpak-oci-registry-private.h"
#include "flatpak-progress-private.h"
#include "flatpak-system-helper.h"
@@ -530,15 +531,11 @@ handle_deploy (FlatpakSystemHelper *object,
if (strlen (arg_repo_path) > 0 && is_oci)
{
g_autoptr(GFile) registry_file = g_file_new_for_path (arg_repo_path);
- g_autofree char *registry_uri = g_file_get_uri (registry_file);
- g_autoptr(FlatpakOciRegistry) registry = NULL;
- g_autoptr(FlatpakOciIndex) index = NULL;
- const FlatpakOciManifestDescriptor *desc;
- g_autoptr(FlatpakOciVersioned) versioned = NULL;
- g_autoptr(FlatpakOciImage) image_config = NULL;
+ g_autoptr(FlatpakImageSource) image_source = NULL;
g_autoptr(FlatpakRemoteState) state = NULL;
g_autoptr(GHashTable) remote_refs = NULL;
g_autofree char *checksum = NULL;
+ const char *image_source_digest;
const char *verified_digest;
g_autofree char *upstream_url = NULL;
@@ -554,50 +551,14 @@ handle_deploy (FlatpakSystemHelper *object,
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
- registry = flatpak_oci_registry_new (registry_uri, FALSE, -1, NULL, &error);
- if (registry == NULL)
+ image_source = flatpak_image_source_new_local (registry_file, arg_ref, NULL, &error);
+ if (image_source == NULL)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
"Can't open child OCI registry: %s", error->message);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
- index = flatpak_oci_registry_load_index (registry, NULL, &error);
- if (index == NULL)
- {
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "Can't open child OCI registry index: %s", error->message);
- return G_DBUS_METHOD_INVOCATION_HANDLED;
- }
-
- desc = flatpak_oci_index_get_manifest (index, arg_ref);
- if (desc == NULL)
- {
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "Can't find ref %s in child OCI registry index", arg_ref);
- return G_DBUS_METHOD_INVOCATION_HANDLED;
- }
-
- versioned = flatpak_oci_registry_load_versioned (registry, NULL, desc->parent.digest, (const char **)desc->parent.urls, NULL,
- NULL, &error);
- if (versioned == NULL || !FLATPAK_IS_OCI_MANIFEST (versioned))
- {
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "Can't open child manifest");
- return G_DBUS_METHOD_INVOCATION_HANDLED;
- }
-
- image_config = flatpak_oci_registry_load_image_config (registry, NULL,
- FLATPAK_OCI_MANIFEST (versioned)->config.digest,
- (const char **)FLATPAK_OCI_MANIFEST (versioned)->config.urls,
- NULL, NULL, &error);
- if (image_config == NULL)
- {
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "Can't open child image config");
- return G_DBUS_METHOD_INVOCATION_HANDLED;
- }
-
state = flatpak_dir_get_remote_state (system, arg_origin, FALSE, NULL, &error);
if (state == NULL)
{
@@ -624,15 +585,17 @@ handle_deploy (FlatpakSystemHelper *object,
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
- if (!g_str_has_prefix (desc->parent.digest, "sha256:") ||
- strcmp (desc->parent.digest + strlen ("sha256:"), verified_digest) != 0)
+ image_source_digest = flatpak_image_source_get_digest (image_source);
+
+ if (!g_str_has_prefix (image_source_digest, "sha256:") ||
+ strcmp (image_source_digest + strlen ("sha256:"), verified_digest) != 0)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
"%s: manifest hash in downloaded content does not match ref %s", arg_origin, arg_ref);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
- checksum = flatpak_pull_from_oci (flatpak_dir_get_repo (system), registry, NULL, desc->parent.digest, NULL, FLATPAK_OCI_MANIFEST (versioned), image_config,
+ checksum = flatpak_pull_from_oci (flatpak_dir_get_repo (system), image_source, NULL,
arg_origin, arg_ref, FLATPAK_PULL_FLAGS_NONE, NULL, NULL, NULL, &error);
if (checksum == NULL)
{
--
2.47.1
From d7d4f790bf7103c5ac5afff294578afea7308227 Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Mon, 28 Oct 2024 12:35:33 -0400
Subject: [PATCH 02/12] image-source: Replace flatpak_oci_parse_commit_labels
with getters
Instead of having one function with a pile of out arguments in
arbitrary order, add getters to FlatpakImageSource.
---
app/flatpak-builtins-build-import-bundle.c | 18 ++--
common/flatpak-dir.c | 25 ++----
common/flatpak-image-source-private.h | 11 ++-
common/flatpak-image-source.c | 96 ++++++++++++++++++++--
common/flatpak-json-oci-private.h | 8 --
common/flatpak-json-oci.c | 66 ---------------
common/flatpak-oci-registry.c | 28 +++----
7 files changed, 125 insertions(+), 127 deletions(-)
diff --git a/app/flatpak-builtins-build-import-bundle.c b/app/flatpak-builtins-build-import-bundle.c
index f350870..d79fbbd 100644
--- a/app/flatpak-builtins-build-import-bundle.c
+++ b/app/flatpak-builtins-build-import-bundle.c
@@ -59,30 +59,22 @@ import_oci (OstreeRepo *repo, GFile *file,
GCancellable *cancellable, GError **error)
{
g_autofree char *commit_checksum = NULL;
- g_autofree char *target_ref = NULL;
g_autoptr(FlatpakImageSource) image_source = NULL;
- GHashTable *labels;
+ const char *ref;
image_source = flatpak_image_source_new_local (file, opt_ref, cancellable, error);
if (image_source == NULL)
return NULL;
- labels = flatpak_image_source_get_labels (image_source);
- flatpak_oci_parse_commit_labels (labels, NULL, NULL, NULL,
- &target_ref, NULL, NULL, NULL);
- if (target_ref == NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
- "The OCI image didn't specify a ref, use --ref to specify one");
- return NULL;
- }
+ ref = flatpak_image_source_get_ref (image_source);
commit_checksum = flatpak_pull_from_oci (repo, image_source, NULL,
- NULL, target_ref, FLATPAK_PULL_FLAGS_NONE, NULL, NULL, cancellable, error);
+ NULL, ref, FLATPAK_PULL_FLAGS_NONE,
+ NULL, NULL, cancellable, error);
if (commit_checksum == NULL)
return NULL;
- g_print (_("Importing %s (%s)\n"), target_ref, commit_checksum);
+ g_print (_("Importing %s (%s)\n"), ref, commit_checksum);
return g_strdup (commit_checksum);
}
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 338573e..d2c8b55 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -1101,12 +1101,7 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
VarRefInfoRef latest_rev_info;
VarMetadataRef metadata;
const char *oci_repository = NULL;
- GHashTable *labels;
- g_autofree char *subject = NULL;
- g_autofree char *body = NULL;
- g_autofree char *manifest_ref = NULL;
- g_autofree char *parent = NULL;
- guint64 timestamp = 0;
+ const char *parent = NULL;
g_autoptr(GVariantBuilder) metadata_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_autoptr(GVariant) metadata_v = NULL;
@@ -1131,30 +1126,26 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
if (image_source == NULL)
return NULL;
- labels = flatpak_image_source_get_labels (image_source);
- if (labels)
- flatpak_oci_parse_commit_labels (labels, &timestamp,
- &subject, &body,
- &manifest_ref, NULL, &parent,
- metadata_builder);
-
-
- if (g_strcmp0 (manifest_ref, ref) != 0)
+ if (g_strcmp0 (flatpak_image_source_get_ref (image_source), ref) != 0)
{
flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Commit has no requested ref %s in ref binding metadata"), ref);
return NULL;
}
+ flatpak_image_source_build_commit_metadata (image_source, metadata_builder);
metadata_v = g_variant_ref_sink (g_variant_builder_end (metadata_builder));
+ parent = flatpak_image_source_get_parent_commit (image_source);
+
/* This isn't going to be exactly the same as the reconstructed one from the pull, because we don't have the contents, but its useful to get metadata */
return
g_variant_ref_sink (g_variant_new ("(@a{sv}@ay@a(say)sst@ay@ay)",
metadata_v,
parent ? ostree_checksum_to_bytes_v (parent) : g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL),
g_variant_new_array (G_VARIANT_TYPE ("(say)"), NULL, 0),
- subject, body,
- GUINT64_TO_BE (timestamp),
+ flatpak_image_source_get_commit_subject (image_source),
+ flatpak_image_source_get_commit_body (image_source),
+ GUINT64_TO_BE (flatpak_image_source_get_commit_timestamp (image_source)),
ostree_checksum_to_bytes_v ("0000000000000000000000000000000000000000000000000000000000000000"),
ostree_checksum_to_bytes_v ("0000000000000000000000000000000000000000000000000000000000000000")));
}
diff --git a/common/flatpak-image-source-private.h b/common/flatpak-image-source-private.h
index ebd856a..fe8f02b 100644
--- a/common/flatpak-image-source-private.h
+++ b/common/flatpak-image-source-private.h
@@ -52,6 +52,15 @@ FlatpakOciManifest *flatpak_image_source_get_manifest (FlatpakImageSource
size_t flatpak_image_source_get_manifest_size (FlatpakImageSource *self);
FlatpakOciImage *flatpak_image_source_get_image_config (FlatpakImageSource *self);
-GHashTable *flatpak_image_source_get_labels (FlatpakImageSource *self);
+const char *flatpak_image_source_get_ref (FlatpakImageSource *self);
+const char *flatpak_image_source_get_metadata (FlatpakImageSource *self);
+const char *flatpak_image_source_get_commit (FlatpakImageSource *self);
+const char *flatpak_image_source_get_parent_commit (FlatpakImageSource *self);
+guint64 flatpak_image_source_get_commit_timestamp (FlatpakImageSource *self);
+const char *flatpak_image_source_get_commit_subject (FlatpakImageSource *self);
+const char *flatpak_image_source_get_commit_body (FlatpakImageSource *self);
+
+void flatpak_image_source_build_commit_metadata (FlatpakImageSource *self,
+ GVariantBuilder *metadata_builder);
#endif /* __FLATPAK_IMAGE_SOURCE_H__ */
diff --git a/common/flatpak-image-source.c b/common/flatpak-image-source.c
index 22497cc..feb4fe2 100644
--- a/common/flatpak-image-source.c
+++ b/common/flatpak-image-source.c
@@ -74,7 +74,6 @@ flatpak_image_source_new (FlatpakOciRegistry *registry,
{
g_autoptr(FlatpakImageSource) self = NULL;
g_autoptr(FlatpakOciVersioned) versioned = NULL;
- GHashTable *labels;
self = g_object_new (FLATPAK_TYPE_IMAGE_SOURCE, NULL);
self->registry = g_object_ref (registry);
@@ -107,8 +106,7 @@ flatpak_image_source_new (FlatpakOciRegistry *registry,
if (self->image_config == NULL)
return NULL;
- labels = flatpak_image_source_get_labels (self);
- if (!g_hash_table_contains (labels, "org.flatpak.ref"))
+ if (flatpak_image_source_get_ref (self) == NULL)
{
flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("No org.flatpak.ref found in image"));
return NULL;
@@ -220,8 +218,94 @@ flatpak_image_source_get_image_config (FlatpakImageSource *self)
return self->image_config;
}
-GHashTable *
-flatpak_image_source_get_labels (FlatpakImageSource *self)
+const char *
+flatpak_image_source_get_ref (FlatpakImageSource *self)
+{
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+
+ return g_hash_table_lookup (labels, "org.flatpak.ref");
+}
+
+const char *
+flatpak_image_source_get_metadata (FlatpakImageSource *self)
+{
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+
+ return g_hash_table_lookup (labels, "org.flatpak.metadata");
+}
+
+const char *
+flatpak_image_source_get_commit (FlatpakImageSource *self)
+{
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+
+ return g_hash_table_lookup (labels, "org.flatpak.commit");
+}
+
+const char *
+flatpak_image_source_get_parent_commit (FlatpakImageSource *self)
+{
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+
+ return g_hash_table_lookup (labels, "org.flatpak.parent-commit");
+}
+
+guint64
+flatpak_image_source_get_commit_timestamp (FlatpakImageSource *self)
{
- return flatpak_oci_image_get_labels (self->image_config);
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+ const char *oci_timestamp = g_hash_table_lookup (labels, "org.flatpak.timestamp");
+
+ if (oci_timestamp != NULL)
+ return g_ascii_strtoull (oci_timestamp, NULL, 10);
+ else
+ return 0;
+}
+
+const char *
+flatpak_image_source_get_commit_subject (FlatpakImageSource *self)
+{
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+
+ return g_hash_table_lookup (labels, "org.flatpak.subject");
+}
+
+const char *
+flatpak_image_source_get_commit_body (FlatpakImageSource *self)
+{
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+
+ return g_hash_table_lookup (labels, "org.flatpak.body");
+}
+
+void
+flatpak_image_source_build_commit_metadata (FlatpakImageSource *self,
+ GVariantBuilder *metadata_builder)
+{
+ GHashTable *labels = flatpak_oci_image_get_labels (self->image_config);
+ GHashTableIter iter;
+ const char *key;
+ const char *value;
+
+ g_hash_table_iter_init (&iter, labels);
+ while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
+ {
+ g_autoptr(GVariant) data = NULL;
+ uint8_t *bin;
+ size_t bin_len;
+
+ if (!g_str_has_prefix (key, "org.flatpak.commit-metadata."))
+ continue;
+
+ key += strlen ("org.flatpak.commit-metadata.");
+
+ bin = g_base64_decode (value, &bin_len);
+ data = g_variant_ref_sink (g_variant_new_from_data (G_VARIANT_TYPE ("v"),
+ bin,
+ bin_len,
+ FALSE,
+ g_free,
+ bin));
+ g_variant_builder_add (metadata_builder, "{s@v}", key, data);
+ }
}
diff --git a/common/flatpak-json-oci-private.h b/common/flatpak-json-oci-private.h
index edb22ee..87573c1 100644
--- a/common/flatpak-json-oci-private.h
+++ b/common/flatpak-json-oci-private.h
@@ -246,14 +246,6 @@ void flatpak_oci_add_labels_for_commit (GHashTable *labels,
const char *ref,
const char *commit,
GVariant *commit_data);
-void flatpak_oci_parse_commit_labels (GHashTable *labels,
- guint64 *out_timestamp,
- char **out_subject,
- char **out_body,
- char **out_ref,
- char **out_commit,
- char **out_parent_commit,
- GVariantBuilder *metadata_builder);
#define FLATPAK_TYPE_OCI_SIGNATURE flatpak_oci_signature_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciSignature, flatpak_oci_signature, FLATPAK, OCI_SIGNATURE, FlatpakJson)
diff --git a/common/flatpak-json-oci.c b/common/flatpak-json-oci.c
index 42647d1..2b55b9d 100644
--- a/common/flatpak-json-oci.c
+++ b/common/flatpak-json-oci.c
@@ -927,72 +927,6 @@ flatpak_oci_add_labels_for_commit (GHashTable *labels,
}
}
-void
-flatpak_oci_parse_commit_labels (GHashTable *labels,
- guint64 *out_timestamp,
- char **out_subject,
- char **out_body,
- char **out_ref,
- char **out_commit,
- char **out_parent_commit,
- GVariantBuilder *metadata_builder)
-{
- const char *oci_timestamp, *oci_subject, *oci_body, *oci_parent_commit, *oci_commit, *oci_ref;
- GHashTableIter iter;
- gpointer _key, _value;
-
- oci_ref = g_hash_table_lookup (labels, "org.flatpak.ref");
-
- /* Early return if this is not a flatpak manifest */
- if (oci_ref == NULL)
- return;
-
- if (oci_ref != NULL && out_ref != NULL && *out_ref == NULL)
- *out_ref = g_strdup (oci_ref);
-
- oci_commit = g_hash_table_lookup (labels, "org.flatpak.commit");
- if (oci_commit != NULL && out_commit != NULL && *out_commit == NULL)
- *out_commit = g_strdup (oci_commit);
-
- oci_parent_commit = g_hash_table_lookup (labels, "org.flatpak.parent-commit");
- if (oci_parent_commit != NULL && out_parent_commit != NULL && *out_parent_commit == NULL)
- *out_parent_commit = g_strdup (oci_parent_commit);
-
- oci_timestamp = g_hash_table_lookup (labels, "org.flatpak.timestamp");
- if (oci_timestamp != NULL && out_timestamp != NULL && *out_timestamp == 0)
- *out_timestamp = g_ascii_strtoull (oci_timestamp, NULL, 10);
-
- oci_subject = g_hash_table_lookup (labels, "org.flatpak.subject");
- if (oci_subject != NULL && out_subject != NULL && *out_subject == NULL)
- *out_subject = g_strdup (oci_subject);
-
- oci_body = g_hash_table_lookup (labels, "org.flatpak.body");
- if (oci_body != NULL && out_body != NULL && *out_body == NULL)
- *out_body = g_strdup (oci_body);
-
- if (metadata_builder)
- {
- g_hash_table_iter_init (&iter, labels);
- while (g_hash_table_iter_next (&iter, &_key, &_value))
- {
- const char *key = _key;
- const char *value = _value;
- guchar *bin;
- gsize bin_len;
- g_autoptr(GVariant) data = NULL;
-
- if (!g_str_has_prefix (key, "org.flatpak.commit-metadata."))
- continue;
- key += strlen ("org.flatpak.commit-metadata.");
-
- bin = g_base64_decode (value, &bin_len);
- data = g_variant_ref_sink (g_variant_new_from_data (G_VARIANT_TYPE ("v"), bin, bin_len, FALSE,
- g_free, bin));
- g_variant_builder_add (metadata_builder, "{s@v}", key, data);
- }
- }
-}
-
G_DEFINE_TYPE (FlatpakOciSignature, flatpak_oci_signature, FLATPAK_TYPE_JSON);
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
index 9e2b163..d8616f4 100644
--- a/common/flatpak-oci-registry.c
+++ b/common/flatpak-oci-registry.c
@@ -3578,28 +3578,18 @@ flatpak_pull_from_oci (OstreeRepo *repo,
g_autofree char *old_diffid = NULL;
g_autofree char *commit_checksum = NULL;
const char *parent = NULL;
- g_autofree char *subject = NULL;
- g_autofree char *body = NULL;
- g_autofree char *manifest_ref = NULL;
+ const char *manifest_ref = NULL;
g_autofree char *full_ref = NULL;
const char *diffid;
- guint64 timestamp = 0;
FlatpakOciPullProgressData progress_data = { progress_cb, progress_user_data };
g_autoptr(GVariantBuilder) metadata_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_autoptr(GVariant) metadata = NULL;
- GHashTable *labels;
int n_layers;
int i;
- g_assert (ref != NULL);
g_assert (g_str_has_prefix (digest, "sha256:"));
- labels = flatpak_oci_image_get_labels (image_config);
- if (labels)
- flatpak_oci_parse_commit_labels (labels, &timestamp,
- &subject, &body,
- &manifest_ref, NULL, NULL,
- metadata_builder);
+ manifest_ref = flatpak_image_source_get_ref (image_source);
if (manifest_ref == NULL)
{
@@ -3607,12 +3597,18 @@ flatpak_pull_from_oci (OstreeRepo *repo,
return NULL;
}
- if (strcmp (manifest_ref, ref) != 0)
+ if (ref == NULL)
+ {
+ ref = manifest_ref;
+ }
+ else if (g_strcmp0 (manifest_ref, ref) != 0)
{
flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Wrong ref (%s) specified for OCI image %s, expected %s"), manifest_ref, digest, ref);
return NULL;
}
+ flatpak_image_source_build_commit_metadata (image_source, metadata_builder);
+
g_variant_builder_add (metadata_builder, "{s@v}", "xa.alt-id",
g_variant_new_variant (g_variant_new_string (digest + strlen ("sha256:"))));
@@ -3786,11 +3782,11 @@ flatpak_pull_from_oci (OstreeRepo *repo,
metadata = g_variant_ref_sink (g_variant_builder_end (metadata_builder));
if (!ostree_repo_write_commit_with_time (repo,
parent,
- subject,
- body,
+ flatpak_image_source_get_commit_subject (image_source),
+ flatpak_image_source_get_commit_body (image_source),
metadata,
OSTREE_REPO_FILE (archive_root),
- timestamp,
+ flatpak_image_source_get_commit_timestamp (image_source),
&commit_checksum,
cancellable, error))
goto error;
--
2.47.1
From f0c124f1a7c4ffba1045297a03475fed8c1fd6cc Mon Sep 17 00:00:00 2001
From: Sebastian Wick <sebastian.wick@redhat.com>
Date: Wed, 18 Dec 2024 00:32:32 +0100
Subject: [PATCH 03/12] transaction: Typedef structs directly
---
common/flatpak-transaction.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c
index 9b777c3..7122a6c 100644
--- a/common/flatpak-transaction.c
+++ b/common/flatpak-transaction.c
@@ -139,15 +139,11 @@ struct _FlatpakTransactionOperation
GPtrArray *related_to_ops; /* (element-type FlatpakTransactionOperation) (nullable) */
};
-typedef struct _FlatpakTransactionPrivate FlatpakTransactionPrivate;
-
-typedef struct _BundleData BundleData;
-
-struct _BundleData
+typedef struct _BundleData
{
GFile *file;
GBytes *gpg_data;
-};
+} BundleData;
typedef struct {
FlatpakTransaction *transaction;
@@ -158,7 +154,7 @@ typedef struct {
GVariant *results;
} RequestData;
-struct _FlatpakTransactionPrivate
+typedef struct _FlatpakTransactionPrivate
{
GObject parent;
@@ -199,7 +195,7 @@ struct _FlatpakTransactionPrivate
gboolean needs_resolve;
gboolean needs_tokens;
-};
+} FlatpakTransactionPrivate;
enum {
NEW_OPERATION,
--
2.47.1
From 5d735cc9ad088f01f677c8fcb1f113d40a68e487 Mon Sep 17 00:00:00 2001
From: Sebastian Wick <sebastian.wick@redhat.com>
Date: Wed, 18 Dec 2024 00:38:15 +0100
Subject: [PATCH 04/12] transaction: Use g_clear_pointer/object functions for
op finalize
---
common/flatpak-transaction.c | 45 +++++++++++++++---------------------
1 file changed, 18 insertions(+), 27 deletions(-)
diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c
index 7122a6c..ac92469 100644
--- a/common/flatpak-transaction.c
+++ b/common/flatpak-transaction.c
@@ -594,34 +594,25 @@ flatpak_transaction_operation_finalize (GObject *object)
{
FlatpakTransactionOperation *self = (FlatpakTransactionOperation *) object;
- g_free (self->remote);
- flatpak_decomposed_unref (self->ref);
- g_free (self->commit);
- g_strfreev (self->subpaths);
+ g_clear_pointer (&self->remote, g_free);
+ g_clear_pointer (&self->ref, flatpak_decomposed_unref);
+ g_clear_pointer (&self->commit, g_free);
+ g_clear_pointer (&self->subpaths, g_strfreev);
g_clear_object (&self->bundle);
- g_free (self->eol);
- g_free (self->eol_rebase);
- if (self->previous_ids)
- g_strfreev (self->previous_ids);
- if (self->external_metadata)
- g_bytes_unref (self->external_metadata);
- g_free (self->resolved_commit);
- if (self->resolved_sideload_path)
- g_object_unref (self->resolved_sideload_path);
- if (self->resolved_metadata)
- g_bytes_unref (self->resolved_metadata);
- if (self->resolved_metakey)
- g_key_file_unref (self->resolved_metakey);
- if (self->resolved_old_metadata)
- g_bytes_unref (self->resolved_old_metadata);
- if (self->resolved_old_metakey)
- g_key_file_unref (self->resolved_old_metakey);
- g_free (self->resolved_token);
- g_list_free (self->run_before_ops);
- if (self->related_to_ops)
- g_ptr_array_unref (self->related_to_ops);
- if (self->summary_metadata)
- g_variant_unref (self->summary_metadata);
+ g_clear_pointer (&self->eol, g_free);
+ g_clear_pointer (&self->eol_rebase, g_free);
+ g_clear_pointer (&self->previous_ids, g_strfreev);
+ g_clear_pointer (&self->external_metadata, g_bytes_unref);
+ g_clear_pointer (&self->resolved_commit, g_free);
+ g_clear_object (&self->resolved_sideload_path);
+ g_clear_pointer (&self->resolved_metadata, g_bytes_unref);
+ g_clear_pointer (&self->resolved_metakey, g_key_file_unref);
+ g_clear_pointer (&self->resolved_old_metadata, g_bytes_unref);
+ g_clear_pointer (&self->resolved_old_metakey, g_key_file_unref);
+ g_clear_pointer (&self->resolved_token, g_free);
+ 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_OBJECT_CLASS (flatpak_transaction_operation_parent_class)->finalize (object);
}
--
2.47.1
From 158cd4a77f9cf6903d6e7f9c33cb4d83a0f8b79e Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Wed, 18 Dec 2024 00:46:33 +0100
Subject: [PATCH 05/12] image-source: Add flatpak_image_source_new_for_location
Which allows one to create an image source from a container location.
It also adds a new FlatpakDockerReference to access different parts of a
docker reference and changes to FlatpakOciIndex to get a manifest for a
specific architecture.
This will become useful in the next commit when we're going to add
support for installing OCI images.
---
common/flatpak-docker-reference-private.h | 20 ++++
common/flatpak-docker-reference.c | 140 ++++++++++++++++++++++
common/flatpak-image-source-private.h | 3 +
common/flatpak-image-source.c | 122 +++++++++++++++++++
common/flatpak-json-oci-private.h | 4 +-
common/flatpak-json-oci.c | 21 ++++
common/meson.build | 1 +
7 files changed, 310 insertions(+), 1 deletion(-)
create mode 100644 common/flatpak-docker-reference-private.h
create mode 100644 common/flatpak-docker-reference.c
diff --git a/common/flatpak-docker-reference-private.h b/common/flatpak-docker-reference-private.h
new file mode 100644
index 0000000..8205064
--- /dev/null
+++ b/common/flatpak-docker-reference-private.h
@@ -0,0 +1,20 @@
+#ifndef __FLATPAK_DOCKER_REFERENCE_H__
+#define __FLATPAK_DOCKER_REFERENCE_H__
+
+#include <glib.h>
+
+typedef struct _FlatpakDockerReference FlatpakDockerReference;
+
+FlatpakDockerReference *flatpak_docker_reference_parse (const char *reference_str,
+ GError **error);
+
+const char *flatpak_docker_reference_get_uri (FlatpakDockerReference *reference);
+const char *flatpak_docker_reference_get_repository (FlatpakDockerReference *reference);
+const char *flatpak_docker_reference_get_tag (FlatpakDockerReference *reference);
+const char *flatpak_docker_reference_get_digest (FlatpakDockerReference *reference);
+
+void flatpak_docker_reference_free (FlatpakDockerReference *reference);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(FlatpakDockerReference, flatpak_docker_reference_free);
+
+#endif /* __FLATPAK_DOCKER_REFERENCE_H__ */
diff --git a/common/flatpak-docker-reference.c b/common/flatpak-docker-reference.c
new file mode 100644
index 0000000..6df3011
--- /dev/null
+++ b/common/flatpak-docker-reference.c
@@ -0,0 +1,140 @@
+/* vi:set et sw=2 sts=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e-s:
+ * Copyright © 2024 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Owen Taylor <otaylor@redhat.com>
+ */
+
+#include "flatpak-docker-reference-private.h"
+#include "flatpak-utils-private.h"
+
+struct _FlatpakDockerReference
+{
+ char *uri;
+ char *repository;
+ char *tag;
+ char *digest;
+};
+
+/*
+ * Parsing here is loosely based off:
+ *
+ * https://github.com/containers/image/tree/main/docker/reference
+ *
+ * The major simplification is that we require a domain component, and
+ * don't have any default domain. This removes ambiguity between domains and paths
+ * and makes parsing much simpler. We also don't normalize single component
+ * paths (e.g. ubuntu => library/ubuntu.)
+ */
+
+#define TAG "[0-9A-Za-z_][0-9A-Za-z_-]{0,127}"
+#define DIGEST "[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}"
+#define REMAINDER_TAG_AND_DIGEST_RE "^(.*?)(:" TAG ")?" "(@" DIGEST ")?$"
+
+static GRegex *
+get_remainder_tag_and_digest_regex (void)
+{
+ static gsize regex = 0;
+
+ if (g_once_init_enter (&regex))
+ {
+ g_autoptr(GRegex) compiled = g_regex_new (REMAINDER_TAG_AND_DIGEST_RE,
+ G_REGEX_DEFAULT,
+ G_REGEX_MATCH_DEFAULT,
+ NULL);
+ g_once_init_leave (&regex, (gsize)g_steal_pointer (&compiled));
+ }
+
+ return (GRegex *)regex;
+}
+
+FlatpakDockerReference *
+flatpak_docker_reference_parse (const char *reference_str,
+ GError **error)
+{
+ g_autoptr(FlatpakDockerReference) reference = g_new0 (FlatpakDockerReference, 1);
+ GRegex *regex = get_remainder_tag_and_digest_regex ();
+ g_autoptr(GMatchInfo) match_info = NULL;
+ g_autofree char *tag_match = NULL;
+ g_autofree char *digest_match = NULL;
+ g_autofree char *remainder = NULL;
+ g_autofree char *domain = NULL;
+ gboolean matched;
+ const char *slash;
+
+ matched = g_regex_match (regex, reference_str, G_REGEX_MATCH_DEFAULT, &match_info);
+ g_assert (matched);
+
+ tag_match = g_match_info_fetch (match_info, 2);
+ if (tag_match[0] == '\0')
+ reference->tag = NULL;
+ else
+ reference->tag = g_strdup (tag_match + 1);
+
+ digest_match = g_match_info_fetch (match_info, 3);
+ if (digest_match[0] == '\0')
+ reference->digest = NULL;
+ else
+ reference->digest = g_strdup (digest_match + 1);
+
+ remainder = g_match_info_fetch (match_info, 1);
+ slash = strchr (remainder, '/');
+ if (slash == NULL || slash == reference_str || *slash == '\0')
+ {
+ flatpak_fail(error, "Can't parse %s into <domain>/<repository>", remainder);
+ return NULL;
+ }
+
+ domain = g_strndup (remainder, slash - remainder);
+ reference->uri = g_strconcat ("https://", domain, NULL);
+ reference->repository = g_strdup (slash + 1);
+
+ return g_steal_pointer (&reference);
+}
+
+const char *
+flatpak_docker_reference_get_uri (FlatpakDockerReference *reference)
+{
+ return reference->uri;
+}
+
+const char *
+flatpak_docker_reference_get_repository (FlatpakDockerReference *reference)
+{
+ return reference->repository;
+}
+
+const char *
+flatpak_docker_reference_get_tag (FlatpakDockerReference *reference)
+{
+ return reference->tag;
+}
+
+const char *
+flatpak_docker_reference_get_digest (FlatpakDockerReference *reference)
+{
+ return reference->digest;
+}
+
+void
+flatpak_docker_reference_free (FlatpakDockerReference *reference)
+{
+ g_clear_pointer (&reference->uri, g_free);
+ g_clear_pointer (&reference->repository, g_free);
+ g_clear_pointer (&reference->tag, g_free);
+ g_clear_pointer (&reference->digest, g_free);
+ g_free (reference);
+}
diff --git a/common/flatpak-image-source-private.h b/common/flatpak-image-source-private.h
index fe8f02b..b1e5d2f 100644
--- a/common/flatpak-image-source-private.h
+++ b/common/flatpak-image-source-private.h
@@ -41,6 +41,9 @@ FlatpakImageSource *flatpak_image_source_new_remote (const char *uri,
const char *digest,
GCancellable *cancellable,
GError **error);
+FlatpakImageSource *flatpak_image_source_new_for_location (const char *location,
+ GCancellable *cancellable,
+ GError **error);
void flatpak_image_source_set_token (FlatpakImageSource *self,
const char *token);
diff --git a/common/flatpak-image-source.c b/common/flatpak-image-source.c
index feb4fe2..0503de5 100644
--- a/common/flatpak-image-source.c
+++ b/common/flatpak-image-source.c
@@ -20,6 +20,7 @@
#include <glib/gi18n-lib.h>
+#include "flatpak-docker-reference-private.h"
#include "flatpak-image-source-private.h"
#include "flatpak-oci-registry-private.h"
@@ -175,6 +176,127 @@ flatpak_image_source_new_remote (const char *uri,
return flatpak_image_source_new (registry, oci_repository, digest, cancellable, error);
}
+/* Parse an oci: or oci-archive: image location into a path
+ * and an optional reference
+ */
+static void
+get_path_and_reference (const char *image_location,
+ GFile **path,
+ char **reference)
+{
+ g_autofree char *path_str = NULL;
+ const char *bare;
+ const char *colon;
+
+ colon = strchr (image_location, ':');
+ g_assert (colon != NULL);
+
+ bare = colon + 1;
+ colon = strchr (bare, ':');
+ if (colon)
+ {
+ path_str = g_strndup (bare, colon - bare);
+ *reference = g_strdup (colon + 1);
+ }
+ else
+ {
+ path_str = g_strdup (bare);
+ *reference = NULL;
+ }
+
+ *path = g_file_new_for_path (path_str);
+}
+
+FlatpakImageSource *
+flatpak_image_source_new_for_location (const char *location,
+ GCancellable *cancellable,
+ GError **error)
+{
+ if (g_str_has_prefix (location, "oci:"))
+ {
+ g_autoptr(GFile) path = NULL;
+ g_autofree char *reference = NULL;
+
+ get_path_and_reference (location, &path, &reference);
+
+ return flatpak_image_source_new_local (path, reference, cancellable, error);
+ }
+ else if (g_str_has_prefix (location, "docker:"))
+ {
+ g_autoptr(FlatpakOciRegistry) registry = NULL;
+ g_autoptr(FlatpakDockerReference) docker_reference = NULL;
+ g_autofree char *local_digest = NULL;
+ const char *repository = NULL;
+
+ if (!g_str_has_prefix (location, "docker://"))
+ {
+ flatpak_fail (error, "docker: location must start docker://");
+ return NULL;
+ }
+
+ docker_reference = flatpak_docker_reference_parse (location + 9, error);
+ if (docker_reference == NULL)
+ return NULL;
+
+ registry = flatpak_oci_registry_new (flatpak_docker_reference_get_uri (docker_reference),
+ FALSE, -1, cancellable, error);
+ if (registry == NULL)
+ return NULL;
+
+ repository = flatpak_docker_reference_get_repository (docker_reference);
+
+ local_digest = g_strdup (flatpak_docker_reference_get_digest (docker_reference));
+ if (local_digest == NULL)
+ {
+ g_autoptr(GBytes) bytes = NULL;
+ g_autoptr(FlatpakOciVersioned) versioned = NULL;
+ const char *tag = flatpak_docker_reference_get_tag (docker_reference);
+
+ if (tag == NULL)
+ tag = "latest";
+
+ bytes = flatpak_oci_registry_load_blob (registry, repository, TRUE, tag,
+ NULL, NULL, cancellable, error);
+ if (!bytes)
+ return NULL;
+
+ versioned = flatpak_oci_versioned_from_json (bytes, NULL, error);
+ if (!versioned)
+ return NULL;
+
+ if (FLATPAK_IS_OCI_MANIFEST (versioned))
+ {
+ g_autofree char *checksum = NULL;
+
+ checksum = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, bytes);
+ local_digest = g_strconcat ("sha256:", checksum, NULL);
+ }
+ else if (FLATPAK_IS_OCI_INDEX (versioned))
+ {
+ const char *oci_arch = flatpak_arch_to_oci_arch (flatpak_get_arch ());
+ FlatpakOciManifestDescriptor *descriptor;
+
+ descriptor = flatpak_oci_index_get_manifest_for_arch (FLATPAK_OCI_INDEX (versioned), oci_arch);
+ if (descriptor == NULL)
+ {
+ flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA,
+ "Can't find manifest for %s in image index", oci_arch);
+ return NULL;
+ }
+
+ local_digest = g_strdup (descriptor->parent.digest);
+ }
+ }
+
+ return flatpak_image_source_new (registry, repository, local_digest, cancellable, error);
+ }
+ else
+ {
+ flatpak_fail (error, "unsupported image location: %s", location);
+ return NULL;
+ }
+}
+
void
flatpak_image_source_set_token (FlatpakImageSource *self,
const char *token)
diff --git a/common/flatpak-json-oci-private.h b/common/flatpak-json-oci-private.h
index 87573c1..e8924ee 100644
--- a/common/flatpak-json-oci-private.h
+++ b/common/flatpak-json-oci-private.h
@@ -166,8 +166,10 @@ gboolean flatpak_oci_index_remove_manifest (FlatpakOciIndex
FlatpakOciManifestDescriptor *flatpak_oci_index_get_manifest (FlatpakOciIndex *self,
const char *ref);
FlatpakOciManifestDescriptor *flatpak_oci_index_get_only_manifest (FlatpakOciIndex *self);
-int flatpak_oci_index_get_n_manifests (FlatpakOciIndex *self);
+FlatpakOciManifestDescriptor *flatpak_oci_index_get_manifest_for_arch (FlatpakOciIndex *self,
+ const char *oci_arch);
+int flatpak_oci_index_get_n_manifests (FlatpakOciIndex *self);
/* Only useful for delta index */
FlatpakOciDescriptor *flatpak_oci_index_find_delta_for (FlatpakOciIndex *delta_index,
const char *for_digest);
diff --git a/common/flatpak-json-oci.c b/common/flatpak-json-oci.c
index 2b55b9d..3a339a0 100644
--- a/common/flatpak-json-oci.c
+++ b/common/flatpak-json-oci.c
@@ -577,6 +577,27 @@ flatpak_oci_index_get_only_manifest (FlatpakOciIndex *self)
return NULL;
}
+FlatpakOciManifestDescriptor *
+flatpak_oci_index_get_manifest_for_arch (FlatpakOciIndex *self,
+ const char *oci_arch)
+{
+ int i, found = -1;
+
+ if (self->manifests == NULL)
+ return NULL;
+
+ for (i = 0; self->manifests[i] != NULL; i++)
+ {
+ if (strcmp (self->manifests[i]->platform.architecture, oci_arch) == 0)
+ return self->manifests[i];
+ }
+
+ if (found >= 0)
+ return self->manifests[found];
+
+ return NULL;
+}
+
gboolean
flatpak_oci_index_remove_manifest (FlatpakOciIndex *self,
const char *ref)
diff --git a/common/meson.build b/common/meson.build
index beed1f0..c14337b 100644
--- a/common/meson.build
+++ b/common/meson.build
@@ -169,6 +169,7 @@ sources = [
'flatpak-context.c',
'flatpak-dir.c',
'flatpak-dir-utils.c',
+ 'flatpak-docker-reference.c',
'flatpak-error.c',
'flatpak-exports.c',
'flatpak-glib-backports.c',
--
2.47.1
From 53ebfb48cce60b66bd47d99774739c1825f33295 Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Wed, 18 Dec 2024 00:52:27 +0100
Subject: [PATCH 06/12] common: Add OCI image installation support
---
common/flatpak-dir-private.h | 3 +
common/flatpak-dir.c | 131 ++++++++++--------
common/flatpak-installation.c | 4 +-
common/flatpak-transaction.c | 183 +++++++++++++++++++++++---
common/flatpak-transaction.h | 4 +
system-helper/flatpak-system-helper.c | 6 +-
6 files changed, 252 insertions(+), 79 deletions(-)
diff --git a/common/flatpak-dir-private.h b/common/flatpak-dir-private.h
index a10a202..6d25196 100644
--- a/common/flatpak-dir-private.h
+++ b/common/flatpak-dir-private.h
@@ -586,6 +586,7 @@ gboolean flatpak_dir_pull (Fla
const char *opt_rev,
const char **subpaths,
GFile *sideload_repo,
+ FlatpakImageSource *image_source,
GBytes *require_metadata,
const char *token,
OstreeRepo *repo,
@@ -708,6 +709,7 @@ gboolean flatpak_dir_install (Fla
const char **subpaths,
const char **previous_ids,
GFile *sideload_repo,
+ FlatpakImageSource *image_source,
GBytes *require_metadata,
const char *token,
FlatpakProgress *progress,
@@ -754,6 +756,7 @@ gboolean flatpak_dir_update (Fla
const char **opt_subpaths,
const char **opt_previous_ids,
GFile *sideload_repo,
+ FlatpakImageSource *image_source,
GBytes *require_metadata,
const char *token,
FlatpakProgress *progress,
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index d2c8b55..e6b3364 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -132,7 +132,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,
@@ -5495,7 +5495,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))
{
@@ -5539,7 +5539,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))
{
@@ -6091,7 +6091,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,
@@ -6099,40 +6099,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);
@@ -6152,6 +6154,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,
@@ -6162,40 +6165,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);
+
+ 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);
- 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;
@@ -6234,6 +6246,7 @@ flatpak_dir_pull (FlatpakDir *self,
const char *opt_rev,
const char **subpaths,
GFile *sideload_repo,
+ FlatpakImageSource *image_source,
GBytes *require_metadata,
const char *token,
OstreeRepo *repo,
@@ -6264,8 +6277,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 (image_source || flatpak_dir_get_remote_oci (self, state->remote_name))
+ return flatpak_dir_pull_oci (self, state, ref, opt_rev, image_source, repo, flatpak_flags,
flags, token, progress, cancellable, error);
if (!ostree_repo_remote_get_url (self->repo,
@@ -10036,6 +10049,7 @@ flatpak_dir_install (FlatpakDir *self,
const char **opt_subpaths,
const char **opt_previous_ids,
GFile *sideload_repo,
+ FlatpakImageSource *image_source,
GBytes *require_metadata,
const char *token,
FlatpakProgress *progress,
@@ -10100,7 +10114,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, image_source, token, progress, cancellable, error))
return FALSE;
}
else if (!gpg_verify_summary || !gpg_verify)
@@ -10194,7 +10209,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,
@@ -10272,7 +10287,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, image_source, require_metadata, token, NULL,
flatpak_flags, OSTREE_REPO_PULL_FLAGS_NONE,
progress, cancellable, error))
return FALSE;
@@ -10720,6 +10736,7 @@ flatpak_dir_update (FlatpakDir *self,
const char **opt_subpaths,
const char **opt_previous_ids,
GFile *sideload_repo,
+ FlatpakImageSource *image_source,
GBytes *require_metadata,
const char *token,
FlatpakProgress *progress,
@@ -10807,7 +10824,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, image_source, token, progress, cancellable, error))
return FALSE;
}
else if (!gpg_verify_summary || !gpg_verify)
@@ -10887,7 +10904,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))
@@ -10953,7 +10970,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, 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 38d4e8d..be70617 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, 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 ac92469..ddc0318 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;
@@ -116,6 +119,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;
@@ -145,6 +149,11 @@ typedef struct _BundleData
GBytes *gpg_data;
} BundleData;
+typedef struct _ImageData
+{
+ char *image_location;
+} ImageData;
+
typedef struct {
FlatpakTransaction *transaction;
const char *remote;
@@ -169,6 +178,7 @@ typedef struct _FlatpakTransactionPrivate
GList *flatpakrefs; /* GKeyFiles */
GList *bundles; /* BundleData */
+ GList *images; /* ImageData */
guint next_request_id;
guint active_request_id;
@@ -261,6 +271,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 };
/**
@@ -613,6 +640,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);
}
@@ -996,6 +1025,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);
@@ -2608,6 +2638,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,
gboolean update_preinstalled_on_deploy,
@@ -2737,6 +2768,9 @@ flatpak_transaction_add_ref (FlatpakTransaction *self,
commit, bundle, kind, pin_on_deploy,
update_preinstalled_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));
@@ -2790,7 +2824,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, FALSE, NULL, error))
+ NULL, NULL, NULL, pin_on_deploy, FALSE, NULL, error))
return FALSE;
return TRUE;
@@ -2850,7 +2884,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, 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, FALSE, NULL, error);
}
/**
@@ -2926,12 +2960,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, FALSE, &rebase_op, error))
+ NULL, NULL, NULL, FALSE, 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, FALSE, &uninstall_op, &local_error))
+ NULL, NULL, NULL, FALSE, FALSE, &uninstall_op, &local_error))
{
/* If the user is trying to install an eol-rebased app from scratch, the
* @old_ref cant be uninstalled because its not installed already.
@@ -2984,6 +3018,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
@@ -3091,7 +3155,7 @@ flatpak_transaction_add_sync_preinstalled (FlatpakTransaction *self,
if (!flatpak_transaction_add_ref (self, remote, decomposed, NULL, NULL, NULL,
FLATPAK_TRANSACTION_OPERATION_INSTALL,
- NULL, NULL, FALSE, TRUE, NULL,
+ NULL, NULL, NULL, FALSE, TRUE, NULL,
&local_error))
g_info ("Failed to add preinstall ref %s: %s", flatpak_decomposed_get_ref (decomposed),
local_error->message);
@@ -3116,7 +3180,7 @@ flatpak_transaction_add_sync_preinstalled (FlatpakTransaction *self,
g_info ("Preinstalled ref %s is no longer listed as wanted in preinstall.d config; uninstalling", flatpak_decomposed_get_ref (decomposed));
- if (!flatpak_transaction_add_ref (self, NULL, decomposed, NULL, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_UNINSTALL, NULL, NULL, FALSE, TRUE, NULL, &local_error))
+ if (!flatpak_transaction_add_ref (self, NULL, decomposed, NULL, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_UNINSTALL, NULL, NULL, NULL, FALSE, TRUE, NULL, &local_error))
{
if (!g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED))
{
@@ -3166,7 +3230,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, FALSE, NULL, error);
+ return flatpak_transaction_add_ref (self, NULL, decomposed, subpaths, NULL, commit, FLATPAK_TRANSACTION_OPERATION_UPDATE, NULL, NULL, NULL, FALSE, FALSE, NULL, error);
}
/**
@@ -3193,7 +3257,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, FALSE, NULL, error);
+ return flatpak_transaction_add_ref (self, NULL, decomposed, NULL, NULL, NULL, FLATPAK_TRANSACTION_OPERATION_UNINSTALL, NULL, NULL, NULL, FALSE, FALSE, NULL, error);
}
static gboolean
@@ -3305,7 +3369,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, FALSE, NULL,
+ NULL, NULL, NULL, FALSE, FALSE, NULL,
&local_error))
g_info ("Failed to add auto-install ref %s: %s", flatpak_decomposed_get_ref (auto_install_ref),
local_error->message);
@@ -3403,6 +3467,7 @@ static gboolean
mark_op_resolved (FlatpakTransactionOperation *op,
const char *commit,
GFile *sideload_path,
+ FlatpakImageSource *image_source,
GBytes *metadata,
GBytes *old_metadata,
GError **error)
@@ -3411,7 +3476,7 @@ mark_op_resolved (FlatpakTransactionOperation *op,
g_assert (op != NULL);
- g_assert (commit != NULL);
+ g_assert (commit != NULL || image_source != NULL);
op->resolved = TRUE;
@@ -3424,6 +3489,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 ();
@@ -3457,13 +3525,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;
@@ -3514,7 +3583,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
@@ -3579,7 +3648,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
@@ -3622,7 +3691,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;
}
@@ -3637,7 +3706,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;
}
@@ -3645,7 +3714,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;
}
@@ -3669,8 +3738,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);
@@ -4808,7 +4882,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, FALSE, NULL, error))
+ data->file, NULL, metadata, FALSE, 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, FALSE, &op, error))
return FALSE;
}
@@ -4867,7 +5008,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))
@@ -4886,6 +5027,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,
@@ -4959,6 +5101,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,
@@ -5273,6 +5416,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 6e67a7b..71f7e19 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 263bf0b..6c117de 100644
--- a/system-helper/flatpak-system-helper.c
+++ b/system-helper/flatpak-system-helper.c
@@ -642,7 +642,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))
{
@@ -877,11 +877,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))
{
--
2.47.1
From 3b5959db9b22fc77c988db78e82df3a56afa43fb Mon Sep 17 00:00:00 2001
From: Sebastian Wick <sebastian.wick@redhat.com>
Date: Wed, 18 Dec 2024 00:40:45 +0100
Subject: [PATCH 07/12] builtins/install: Create install transaction in common
function
---
app/flatpak-builtins-install.c | 85 +++++++++++++---------------------
1 file changed, 33 insertions(+), 52 deletions(-)
diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c
index d4d9ae3..c5132da 100644
--- a/app/flatpak-builtins-install.c
+++ b/app/flatpak-builtins-install.c
@@ -129,6 +129,36 @@ read_gpg_data (GCancellable *cancellable,
return flatpak_read_stream (source_stream, FALSE, error);
}
+static FlatpakTransaction *
+create_install_transaction (FlatpakDir *dir,
+ GError **error)
+{
+ g_autoptr(FlatpakTransaction) transaction = NULL;
+
+ if (opt_noninteractive)
+ transaction = flatpak_quiet_transaction_new (dir, error);
+ else
+ transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, opt_arch != NULL, error);
+
+ if (transaction == NULL)
+ return NULL;
+
+ flatpak_transaction_set_no_pull (transaction, opt_no_pull);
+ flatpak_transaction_set_no_deploy (transaction, opt_no_deploy);
+ flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas);
+ flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps);
+ flatpak_transaction_set_disable_related (transaction, opt_no_related);
+ flatpak_transaction_set_disable_auto_pin (transaction, opt_no_auto_pin);
+ flatpak_transaction_set_reinstall (transaction, opt_reinstall);
+ flatpak_transaction_set_auto_install_sdk (transaction, opt_include_sdk);
+ flatpak_transaction_set_auto_install_debug (transaction, opt_include_debug);
+
+ for (int i = 0; opt_sideload_repos != NULL && opt_sideload_repos[i] != NULL; i++)
+ flatpak_transaction_add_sideload_repo (transaction, opt_sideload_repos[i]);
+
+ return g_steal_pointer (&transaction);
+}
+
static gboolean
install_bundle (FlatpakDir *dir,
GOptionContext *context,
@@ -162,26 +192,10 @@ install_bundle (FlatpakDir *dir,
return FALSE;
}
- if (opt_noninteractive)
- transaction = flatpak_quiet_transaction_new (dir, error);
- else
- transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, opt_arch != NULL, error);
+ transaction = create_install_transaction (dir, error);
if (transaction == NULL)
return FALSE;
- flatpak_transaction_set_no_pull (transaction, opt_no_pull);
- flatpak_transaction_set_no_deploy (transaction, opt_no_deploy);
- flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas);
- flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps);
- flatpak_transaction_set_disable_related (transaction, opt_no_related);
- flatpak_transaction_set_disable_auto_pin (transaction, opt_no_auto_pin);
- flatpak_transaction_set_reinstall (transaction, opt_reinstall);
- flatpak_transaction_set_auto_install_sdk (transaction, opt_include_sdk);
- flatpak_transaction_set_auto_install_debug (transaction, opt_include_debug);
-
- for (int i = 0; opt_sideload_repos != NULL && opt_sideload_repos[i] != NULL; i++)
- flatpak_transaction_add_sideload_repo (transaction, opt_sideload_repos[i]);
-
if (!flatpak_transaction_add_install_bundle (transaction, file, gpg_data, error))
return FALSE;
@@ -241,27 +255,10 @@ install_from (FlatpakDir *dir,
file_data = g_bytes_new_take (g_steal_pointer (&data), data_len);
}
- if (opt_noninteractive)
- transaction = flatpak_quiet_transaction_new (dir, error);
- else
- transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, opt_arch != NULL, error);
+ transaction = create_install_transaction (dir, error);
if (transaction == NULL)
return FALSE;
- flatpak_transaction_set_no_pull (transaction, opt_no_pull);
- flatpak_transaction_set_no_deploy (transaction, opt_no_deploy);
- flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas);
- flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps);
- flatpak_transaction_set_disable_related (transaction, opt_no_related);
- flatpak_transaction_set_disable_auto_pin (transaction, opt_no_auto_pin);
- flatpak_transaction_set_reinstall (transaction, opt_reinstall);
- flatpak_transaction_set_default_arch (transaction, opt_arch);
- flatpak_transaction_set_auto_install_sdk (transaction, opt_include_sdk);
- flatpak_transaction_set_auto_install_debug (transaction, opt_include_debug);
-
- for (int i = 0; opt_sideload_repos != NULL && opt_sideload_repos[i] != NULL; i++)
- flatpak_transaction_add_sideload_repo (transaction, opt_sideload_repos[i]);
-
if (!flatpak_transaction_add_install_flatpakref (transaction, file_data, error))
return FALSE;
@@ -485,26 +482,10 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
default_branch = flatpak_dir_get_remote_default_branch (dir, remote);
- if (opt_noninteractive)
- transaction = flatpak_quiet_transaction_new (dir, error);
- else
- transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, opt_arch != NULL, error);
+ transaction = create_install_transaction (dir, error);
if (transaction == NULL)
return FALSE;
- flatpak_transaction_set_no_pull (transaction, opt_no_pull);
- flatpak_transaction_set_no_deploy (transaction, opt_no_deploy);
- flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas);
- flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps);
- flatpak_transaction_set_disable_related (transaction, opt_no_related);
- flatpak_transaction_set_disable_auto_pin (transaction, opt_no_auto_pin);
- flatpak_transaction_set_reinstall (transaction, opt_reinstall);
- flatpak_transaction_set_auto_install_sdk (transaction, opt_include_sdk);
- flatpak_transaction_set_auto_install_debug (transaction, opt_include_debug);
-
- for (i = 0; opt_sideload_repos != NULL && opt_sideload_repos[i] != NULL; i++)
- flatpak_transaction_add_sideload_repo (transaction, opt_sideload_repos[i]);
-
for (i = 0; i < n_prefs; i++)
{
const char *pref = prefs[i];
--
2.47.1
From 575943dad6c67eb2fb9e2503bedfa6ec86f4e819 Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Wed, 18 Dec 2024 00:53:59 +0100
Subject: [PATCH 08/12] builtins/install: Allow direct installation from OCI
images
Similar to bundle installs, add:
flatpak install [--image] docker://registry.example.com/image:latest
flatpak install [--image] oci:/path/to/image
These is useful for testing purposes and in certain cases when installing
Flatpaks on disconnected systems.
---
app/flatpak-builtins-install.c | 60 ++++++++++++++++++++++++++++++++--
app/flatpak-cli-transaction.c | 2 +-
doc/flatpak-install.xml | 24 ++++++++++----
tests/test-oci-registry.sh | 33 ++++++++++++++++++-
tests/test-oci.sh | 22 ++++++++++++-
5 files changed, 129 insertions(+), 12 deletions(-)
diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c
index c5132da..70474bb 100644
--- a/app/flatpak-builtins-install.c
+++ b/app/flatpak-builtins-install.c
@@ -56,6 +56,7 @@ static gboolean opt_include_sdk;
static gboolean opt_include_debug;
static gboolean opt_bundle;
static gboolean opt_from;
+static gboolean opt_image;
static gboolean opt_yes;
static gboolean opt_reinstall;
static gboolean opt_noninteractive;
@@ -76,6 +77,7 @@ static GOptionEntry options[] = {
{ "include-debug", 0, 0, G_OPTION_ARG_NONE, &opt_include_debug, N_("Additionally install the debug info for the given refs and their dependencies") },
{ "bundle", 0, 0, G_OPTION_ARG_NONE, &opt_bundle, N_("Assume LOCATION is a .flatpak single-file bundle"), NULL },
{ "from", 0, 0, G_OPTION_ARG_NONE, &opt_from, N_("Assume LOCATION is a .flatpakref application description"), NULL },
+ { "image", 0, 0, G_OPTION_ARG_NONE, &opt_image, N_("Assume LOCATION is containers-transports(5) reference to an OCI image"), NULL },
{ "gpg-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, N_("Check bundle signatures with GPG key from FILE (- for stdin)"), N_("FILE") },
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, N_("Only install this subpath"), N_("PATH") },
{ "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("Automatically answer yes for all questions"), NULL },
@@ -273,6 +275,52 @@ install_from (FlatpakDir *dir,
return TRUE;
}
+static gboolean
+install_image (FlatpakDir *dir,
+ GOptionContext *context,
+ int argc,
+ char **argv,
+ GCancellable *cancellable,
+ GError **error)
+{
+ const char *location;
+ g_autoptr(GBytes) gpg_data = NULL;
+ g_autoptr(FlatpakTransaction) transaction = NULL;
+
+ if (argc < 2)
+ return usage_error (context, _("Image location must be specified"), error);
+
+ if (argc > 2)
+ return usage_error (context, _("Too many arguments"), error);
+
+ location = argv[1];
+
+ if (opt_gpg_file != NULL)
+ {
+ /* Override gpg_data from file */
+ gpg_data = read_gpg_data (cancellable, error);
+ if (gpg_data == NULL)
+ return FALSE;
+ }
+
+ transaction = create_install_transaction (dir, error);
+ if (transaction == NULL)
+ return FALSE;
+
+ if (!flatpak_transaction_add_install_image (transaction, location, error))
+ return FALSE;
+
+ if (!flatpak_transaction_run (transaction, cancellable, error))
+ {
+ if (g_error_matches (*error, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED))
+ g_clear_error (error); /* Don't report on stderr */
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
gboolean
flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GError **error)
{
@@ -301,11 +349,14 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
/* Start with the default or specified dir, this is fine for opt_bundle or opt_from */
dir = g_object_ref (g_ptr_array_index (dirs, 0));
- if (!opt_bundle && !opt_from && argc >= 2)
+ if (!opt_bundle && !opt_from && !opt_image && argc >= 2)
{
- if (flatpak_file_arg_has_suffix (argv[1], ".flatpakref"))
+ if (g_str_has_prefix (argv[1], "oci:") ||
+ g_str_has_prefix (argv[1], "docker:"))
+ opt_image = TRUE;
+ else if (flatpak_file_arg_has_suffix (argv[1], ".flatpakref"))
opt_from = TRUE;
- if (flatpak_file_arg_has_suffix (argv[1], ".flatpak"))
+ else if (flatpak_file_arg_has_suffix (argv[1], ".flatpak"))
opt_bundle = TRUE;
}
@@ -315,6 +366,9 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
if (opt_from)
return install_from (dir, context, argc, argv, cancellable, error);
+ if (opt_image)
+ return install_image (dir, context, argc, argv, cancellable, error);
+
if (argc < 2)
return usage_error (context, _("At least one REF must be specified"), error);
diff --git a/app/flatpak-cli-transaction.c b/app/flatpak-cli-transaction.c
index e7c8c90..8c02c55 100644
--- a/app/flatpak-cli-transaction.c
+++ b/app/flatpak-cli-transaction.c
@@ -1350,7 +1350,7 @@ transaction_ready_pre_auth (FlatpakTransaction *transaction)
GList *l;
int i;
FlatpakTablePrinter *printer;
- const char *op_shorthand[] = { "i", "u", "i", "r" };
+ const char *op_shorthand[] = { "i", "u", "i", "r", "i" };
/* These caches may no longer be valid once the transaction runs */
g_clear_pointer (&self->runtime_app_map, g_hash_table_unref);
diff --git a/doc/flatpak-install.xml b/doc/flatpak-install.xml
index ab4bb1f..f75deda 100644
--- a/doc/flatpak-install.xml
+++ b/doc/flatpak-install.xml
@@ -38,7 +38,7 @@
<cmdsynopsis>
<command>flatpak install</command>
<arg choice="opt" rep="repeat">OPTION</arg>
- <arg choice="opt">--from|--bundle</arg>
+ <arg choice="opt">--from|--bundle|--image</arg>
<arg choice="plain">LOCATION</arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -85,11 +85,11 @@
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
</para>
<para>
- The alternative form of the command (with <option>--from</option> or
- <option>--bundle</option>) allows to install directly from a source such as a
- <filename>.flatpak</filename> single-file bundle or a <filename>.flatpakref</filename>
- application description. The options are optional if the first argument has the expected
- filename extension.
+ The alternative form of the command (with <option>--from</option>, <option>--bundle</option>,
+ or <option>--image</option>) allows to install directly from a source. The source can be a
+ <filename>.flatpak</filename> single-file bundle, <filename>.flatpakref</filename>
+ application description, or a reference to an OCI image. The options are optional if the
+ first argument has the expected filename extension or prefix.
</para>
<para>
Note that flatpak allows to have multiple branches of an application and runtimes
@@ -139,6 +139,18 @@
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--image</option></term>
+ <listitem><para>
+ Treat <arg choice="plain">LOCATION</arg> as the location of a Flatpak in
+ OCI image format. <arg choice="plan>">LOCATION</arg> is in the format of
+ <citerefentry><refentrytitle>containers-transports</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ Supported schemes are <literal>docker://</literal> and <literal>oci:</literal>.
+ This is assumed if the argument starts
+ with one of these schemes.
+ </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--reinstall</option></term>
diff --git a/tests/test-oci-registry.sh b/tests/test-oci-registry.sh
index da234de..9503656 100755
--- a/tests/test-oci-registry.sh
+++ b/tests/test-oci-registry.sh
@@ -23,7 +23,7 @@ set -euo pipefail
skip_without_bwrap
-echo "1..14"
+echo "1..16"
# Start the fake registry server
@@ -315,3 +315,34 @@ assert_file_has_content remotes-list "^hello-origin.*[ ]${scheme}://127\.0\.0\.
assert_not_has_file $base/oci/hello-origin.index.gz
ok "change remote origin via bundle"
+
+${FLATPAK} ${U} -y uninstall org.test.Hello >&2
+${FLATPAK} ${U} -y uninstall org.test.Platform >&2
+
+${FLATPAK} ${U} list --columns=application,origin > flatpak-list
+assert_not_file_has_content flatpak-list 'org.test.Platform'
+assert_not_file_has_content flatpak-list 'org.test.Hello'
+
+${FLATPAK} ${U} remotes --show-disabled > remotes-list
+assert_not_file_has_content remotes-list '^platform-origin'
+assert_not_file_has_content remotes-list '^hello-origin'
+
+ok "clean up"
+
+# Install from registry via a docker:// location
+# TODO: docker:// locations only support HTTPS
+# This needs https://github.com/flatpak/flatpak/pull/5916
+
+if false && [ x${USE_SYSTEMDIR-} != xyes ]; then
+ $FLATPAK --user -y install docker://127.0.0.1/platform-image:latest >&2
+
+ ${FLATPAK} ${U} list --columns=application,origin > flatpak-list
+ assert_file_has_content flatpak-list '^org.test.Platform *platform-origin$'
+
+ ${FLATPAK} ${U} remotes --show-disabled > remotes-list
+ assert_file_has_content remotes-list '^platform-origin'
+
+ ok "install image from registry"
+else
+ ok "install image from registry # skip Not supported"
+fi
diff --git a/tests/test-oci.sh b/tests/test-oci.sh
index a7baf88..431fa6d 100755
--- a/tests/test-oci.sh
+++ b/tests/test-oci.sh
@@ -23,7 +23,7 @@ set -euo pipefail
skip_without_bwrap
-echo "1..2"
+echo "1..3"
setup_repo_no_add oci
@@ -66,3 +66,23 @@ assert_has_file checked-out/files/bin/hello.sh
assert_has_file checked-out/metadata
ok "import oci"
+
+# Trying installing the bundle directly
+
+${FLATPAK} build-bundle --runtime --oci $FL_GPGARGS repos/oci oci/platform-image org.test.Platform >&2
+
+${FLATPAK} --user list --columns=application,origin > flatpak-list
+assert_not_file_has_content flatpak-list 'org.test.Platform'
+
+${FLATPAK} --user remotes --show-disabled > remotes-list
+assert_not_file_has_content remotes-list '^platform-origin'
+
+$FLATPAK --user -y install oci:oci/platform-image >&2
+
+${FLATPAK} --user list --columns=application,origin > flatpak-list
+assert_file_has_content flatpak-list '^org.test.Platform *platform-origin$'
+
+${FLATPAK} --user remotes --show-disabled > remotes-list
+assert_file_has_content remotes-list '^platform-origin'
+
+ok "install oci"
--
2.47.1
From 13b4a9690fd1c914e3d27d404bfad9467f1b8703 Mon Sep 17 00:00:00 2001
From: Sebastian Wick <sebastian.wick@redhat.com>
Date: Fri, 20 Dec 2024 00:25:55 +0100
Subject: [PATCH 09/12] oci-registry: Remove a bunch of double newlines
---
common/flatpak-oci-registry-private.h | 1 -
common/flatpak-oci-registry.c | 6 ------
2 files changed, 7 deletions(-)
diff --git a/common/flatpak-oci-registry-private.h b/common/flatpak-oci-registry-private.h
index 47ffc7b..a051b0a 100644
--- a/common/flatpak-oci-registry-private.h
+++ b/common/flatpak-oci-registry-private.h
@@ -183,7 +183,6 @@ GBytes *flatpak_oci_index_make_appstream (FlatpakHttpSession *http_session,
GCancellable *cancellable,
GError **error);
-
typedef void (*FlatpakOciPullProgress) (guint64 total_size,
guint64 pulled_size,
guint32 n_layers,
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
index ad05c9f..e104ab4 100644
--- a/common/flatpak-oci-registry.c
+++ b/common/flatpak-oci-registry.c
@@ -255,7 +255,6 @@ flatpak_oci_registry_set_token (FlatpakOciRegistry *self,
0, NULL, NULL);
}
-
FlatpakOciRegistry *
flatpak_oci_registry_new (const char *uri,
gboolean for_write,
@@ -830,7 +829,6 @@ flatpak_oci_registry_download_blob (FlatpakOciRegistry *self,
return -1;
}
-
if (!flatpak_open_in_tmpdir_at (self->tmp_dfd, 0600, tmpfile_name,
&out_stream, cancellable, error))
return -1;
@@ -1357,7 +1355,6 @@ flatpak_oci_layer_writer_reset (FlatpakOciLayerWriter *self)
g_clear_object (&self->compressor);
}
-
static void
flatpak_oci_layer_writer_finalize (GObject *object)
{
@@ -1725,7 +1722,6 @@ delta_read_byte (GInputStream *in,
return TRUE;
}
-
static gboolean
delta_read_varuint (GInputStream *in,
guint64 *out,
@@ -2731,7 +2727,6 @@ get_image_metadata (FlatpakOciIndexImage *img, const char *key)
return NULL;
}
-
static const char *
get_image_ref (FlatpakOciIndexImage *img)
{
@@ -2838,7 +2833,6 @@ flatpak_oci_index_ensure_cached (FlatpakHttpSession *http_session,
oci_arch = flatpak_arch_to_oci_arch (flatpak_get_arch ());
-
query = g_string_new (NULL);
flatpak_uri_encode_query_arg (query, "label:org.flatpak.ref:exists", "1");
flatpak_uri_encode_query_arg (query, "architecture", oci_arch);
--
2.47.1
From f0b4b4f1a522cfbad5565a248eef671729f86857 Mon Sep 17 00:00:00 2001
From: Sebastian Wick <sebastian.wick@redhat.com>
Date: Fri, 20 Dec 2024 00:27:29 +0100
Subject: [PATCH 10/12] oci-registry: Allow passing a NULL URI
---
common/flatpak-oci-registry.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
index e104ab4..a4b914a 100644
--- a/common/flatpak-oci-registry.c
+++ b/common/flatpak-oci-registry.c
@@ -142,10 +142,13 @@ flatpak_oci_registry_set_property (GObject *object,
case PROP_URI:
/* Ensure the base uri ends with a / so relative urls work */
uri = g_value_get_string (value);
- if (g_str_has_suffix (uri, "/"))
- self->uri = g_strdup (uri);
- else
- self->uri = g_strconcat (uri, "/", NULL);
+ if (uri)
+ {
+ if (g_str_has_suffix (uri, "/"))
+ self->uri = g_strdup (uri);
+ else
+ self->uri = g_strconcat (uri, "/", NULL);
+ }
break;
case PROP_FOR_WRITE:
--
2.47.1
From 36b43b17ffa210b0bc4a8a7d246e6ba84010527f Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Wed, 18 Dec 2024 00:53:59 +0100
Subject: [PATCH 11/12] image-source: Support `oci-archive:` image sources
Add support for `oci-archive:` image sources by temporarily
unpacking the archive using libarchive.
Co-authored-by: Sebastian Wick <sebastian.wick@redhat.com>
---
app/flatpak-builtins-install.c | 1 +
common/flatpak-image-source.c | 50 ++++--
common/flatpak-oci-registry-private.h | 14 +-
common/flatpak-oci-registry.c | 247 +++++++++++++++++++++++---
common/flatpak-transaction.c | 2 +-
doc/flatpak-install.xml | 4 +-
tests/test-oci.sh | 24 ++-
7 files changed, 297 insertions(+), 45 deletions(-)
diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c
index 70474bb..e1f7f31 100644
--- a/app/flatpak-builtins-install.c
+++ b/app/flatpak-builtins-install.c
@@ -352,6 +352,7 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
if (!opt_bundle && !opt_from && !opt_image && argc >= 2)
{
if (g_str_has_prefix (argv[1], "oci:") ||
+ g_str_has_prefix (argv[1], "oci-archive:") ||
g_str_has_prefix (argv[1], "docker:"))
opt_image = TRUE;
else if (flatpak_file_arg_has_suffix (argv[1], ".flatpakref"))
diff --git a/common/flatpak-image-source.c b/common/flatpak-image-source.c
index 0503de5..20c94b6 100644
--- a/common/flatpak-image-source.c
+++ b/common/flatpak-image-source.c
@@ -116,24 +116,15 @@ flatpak_image_source_new (FlatpakOciRegistry *registry,
return g_steal_pointer (&self);
}
-FlatpakImageSource *
-flatpak_image_source_new_local (GFile *file,
- const char *reference,
- GCancellable *cancellable,
- GError **error)
+static FlatpakImageSource *
+flatpak_image_source_new_local_for_registry (FlatpakOciRegistry *registry,
+ const char *reference,
+ GCancellable *cancellable,
+ GError **error)
{
- g_autofree char *dir_uri = NULL;
- g_autofree char *target_ref = NULL;
- g_autoptr(FlatpakImageSource) image_source = NULL;
- g_autoptr(FlatpakOciRegistry) registry = NULL;
g_autoptr(FlatpakOciIndex) index = NULL;
const FlatpakOciManifestDescriptor *desc;
- dir_uri = g_file_get_uri (file);
- registry = flatpak_oci_registry_new (dir_uri, FALSE, -1, cancellable, error);
- if (registry == NULL)
- return NULL;
-
index = flatpak_oci_registry_load_index (registry, cancellable, error);
if (index == NULL)
return NULL;
@@ -160,6 +151,23 @@ flatpak_image_source_new_local (GFile *file,
return flatpak_image_source_new (registry, NULL, desc->parent.digest, cancellable, error);
}
+FlatpakImageSource *
+flatpak_image_source_new_local (GFile *file,
+ const char *reference,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autofree char *dir_uri = NULL;
+ g_autoptr(FlatpakOciRegistry) registry = NULL;
+
+ dir_uri = g_file_get_uri (file);
+ registry = flatpak_oci_registry_new (dir_uri, FALSE, -1, cancellable, error);
+ if (registry == NULL)
+ return NULL;
+
+ return flatpak_image_source_new_local_for_registry (registry, reference, cancellable, error);
+}
+
FlatpakImageSource *
flatpak_image_source_new_remote (const char *uri,
const char *oci_repository,
@@ -221,6 +229,20 @@ flatpak_image_source_new_for_location (const char *location,
return flatpak_image_source_new_local (path, reference, cancellable, error);
}
+ else if (g_str_has_prefix (location, "oci-archive:"))
+ {
+ g_autoptr(FlatpakOciRegistry) registry = NULL;
+ g_autoptr(GFile) path = NULL;
+ g_autofree char *reference = NULL;
+
+ get_path_and_reference (location, &path, &reference);
+
+ registry = flatpak_oci_registry_new_for_archive (path, cancellable, error);
+ if (registry == NULL)
+ return NULL;
+
+ return flatpak_image_source_new_local_for_registry (registry, reference, cancellable, error);
+ }
else if (g_str_has_prefix (location, "docker:"))
{
g_autoptr(FlatpakOciRegistry) registry = NULL;
diff --git a/common/flatpak-oci-registry-private.h b/common/flatpak-oci-registry-private.h
index a051b0a..d48c8ed 100644
--- a/common/flatpak-oci-registry-private.h
+++ b/common/flatpak-oci-registry-private.h
@@ -50,11 +50,15 @@ typedef struct FlatpakOciLayerWriter FlatpakOciLayerWriter;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciLayerWriter, g_object_unref)
-FlatpakOciRegistry * flatpak_oci_registry_new (const char *uri,
- gboolean for_write,
- int tmp_dfd,
- GCancellable * cancellable,
- GError **error);
+
+FlatpakOciRegistry * flatpak_oci_registry_new (const char *uri,
+ gboolean for_write,
+ int tmp_dfd,
+ GCancellable *cancellable,
+ GError **error);
+FlatpakOciRegistry * flatpak_oci_registry_new_for_archive (GFile *archive,
+ GCancellable *cancellable,
+ GError **error);
void flatpak_oci_registry_set_token (FlatpakOciRegistry *self,
const char *token);
gboolean flatpak_oci_registry_is_local (FlatpakOciRegistry *self);
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
index a4b914a..ebf000f 100644
--- a/common/flatpak-oci-registry.c
+++ b/common/flatpak-oci-registry.c
@@ -27,6 +27,7 @@
#include "libglnx.h"
#include <archive.h>
+#include <archive_entry.h>
#include <gpgme.h>
#include "flatpak-image-source-private.h"
#include "flatpak-oci-registry-private.h"
@@ -69,11 +70,13 @@ struct FlatpakOciRegistry
gboolean valid;
gboolean is_docker;
char *uri;
+ GFile *archive;
int tmp_dfd;
char *token;
/* Local repos */
int dfd;
+ GLnxTmpDir *tmp_dir;
/* Remote repos */
FlatpakHttpSession *http_session;
@@ -90,6 +93,7 @@ enum {
PROP_0,
PROP_URI,
+ PROP_ARCHIVE,
PROP_FOR_WRITE,
PROP_TMP_DFD,
};
@@ -98,6 +102,14 @@ G_DEFINE_TYPE_WITH_CODE (FlatpakOciRegistry, flatpak_oci_registry, G_TYPE_OBJECT
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
flatpak_oci_registry_initable_iface_init))
+static void
+glnx_tmpdir_free (GLnxTmpDir *tmpf)
+{
+ (void)glnx_tmpdir_delete (tmpf, NULL, NULL);
+ g_free (tmpf);
+}
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GLnxTmpDir, glnx_tmpdir_free)
+
static gchar *
parse_relative_uri (GUri *base_uri,
const char *subpath,
@@ -124,6 +136,8 @@ flatpak_oci_registry_finalize (GObject *object)
g_clear_pointer (&self->base_uri, g_uri_unref);
g_free (self->uri);
g_free (self->token);
+ g_clear_object (&self->archive);
+ g_clear_pointer (&self->tmp_dir, glnx_tmpdir_free);
G_OBJECT_CLASS (flatpak_oci_registry_parent_class)->finalize (object);
}
@@ -151,6 +165,10 @@ flatpak_oci_registry_set_property (GObject *object,
}
break;
+ case PROP_ARCHIVE:
+ self->archive = g_value_dup_object (value);
+ break;
+
case PROP_FOR_WRITE:
self->for_write = g_value_get_boolean (value);
break;
@@ -179,6 +197,10 @@ flatpak_oci_registry_get_property (GObject *object,
g_value_set_string (value, self->uri);
break;
+ case PROP_ARCHIVE:
+ g_value_set_object (value, self->archive);
+ break;
+
case PROP_FOR_WRITE:
g_value_set_boolean (value, self->for_write);
break;
@@ -209,6 +231,13 @@ flatpak_oci_registry_class_init (FlatpakOciRegistryClass *klass)
"",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_ARCHIVE,
+ g_param_spec_object ("archive",
+ "",
+ "",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_TMP_DFD,
g_param_spec_int ("tmp-dfd",
@@ -277,6 +306,21 @@ flatpak_oci_registry_new (const char *uri,
return oci_registry;
}
+FlatpakOciRegistry *
+flatpak_oci_registry_new_for_archive (GFile *archive,
+ GCancellable *cancellable,
+ GError **error)
+{
+ FlatpakOciRegistry *oci_registry;
+
+ oci_registry = g_initable_new (FLATPAK_TYPE_OCI_REGISTRY,
+ cancellable, error,
+ "archive", archive,
+ NULL);
+
+ return oci_registry;
+}
+
static int
local_open_file (int dfd,
const char *subpath,
@@ -457,13 +501,164 @@ verify_oci_version (GBytes *oci_layout_bytes, gboolean *not_json, GCancellable *
return TRUE;
}
+/*
+ * Code to extract an archive such as a tarfile into a temporary directory
+ *
+ * Based on: https://github.com/libarchive/libarchive/wiki/Examples#A_Complete_Extractor
+ *
+ * We treat ARCHIVE_WARNING as fatal - while this might be too strict, it
+ * will avoid surprises.
+ */
+
+static gboolean
+propagate_libarchive_error (GError **error,
+ struct archive *a)
+{
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", archive_error_string (a));
+ return FALSE;
+}
+
+static gboolean
+copy_data (struct archive *ar,
+ struct archive *aw,
+ GError **error)
+{
+ int r;
+ const void *buff;
+ size_t size;
+ gint64 offset;
+
+ while (TRUE)
+ {
+ r = archive_read_data_block (ar, &buff, &size, &offset);
+
+ if (r == ARCHIVE_EOF)
+ return TRUE;
+
+ if (r == ARCHIVE_RETRY)
+ continue;
+
+ if (r != ARCHIVE_OK)
+ return propagate_libarchive_error (error, ar);
+
+ while (TRUE)
+ {
+ r = archive_write_data_block (aw, buff, size, offset);
+
+ if (r == ARCHIVE_RETRY)
+ continue;
+
+ if (r == ARCHIVE_OK)
+ break;
+
+ return propagate_libarchive_error (error, aw);
+ }
+ }
+}
+
+static gboolean
+unpack_archive (GFile *archive,
+ char *destination,
+ GError **error)
+{
+ g_autoptr(FlatpakAutoArchiveRead) a = NULL;
+ g_autoptr(FlatpakAutoArchiveWrite) ext = NULL;
+ int flags;
+ int r;
+
+ flags = 0;
+ flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+ flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
+
+ a = archive_read_new ();
+ archive_read_support_format_all (a);
+ archive_read_support_filter_all (a);
+
+ ext = archive_write_disk_new ();
+ archive_write_disk_set_options (ext, flags);
+ archive_write_disk_set_standard_lookup (ext);
+
+ r = archive_read_open_filename (a, g_file_get_path(archive), 10240);
+ if (r != ARCHIVE_OK)
+ return propagate_libarchive_error (error, a);
+
+ while (TRUE)
+ {
+ g_autofree char *target_path = NULL;
+ struct archive_entry *entry;
+
+ r = archive_read_next_header (a, &entry);
+ if (r == ARCHIVE_EOF)
+ break;
+
+ if (r != ARCHIVE_OK)
+ return propagate_libarchive_error (error, a);
+
+ target_path = g_build_filename (destination, archive_entry_pathname (entry), NULL);
+ archive_entry_set_pathname (entry, target_path);
+
+ r = archive_write_header (ext, entry);
+ if (r != ARCHIVE_OK)
+ return propagate_libarchive_error (error, ext);
+
+ if (archive_entry_size (entry) > 0)
+ {
+ if (!copy_data (a, ext, error))
+ return FALSE;
+ }
+
+ r = archive_write_finish_entry (ext);
+ if (r != ARCHIVE_OK)
+ return propagate_libarchive_error (error, ext);
+ }
+
+ r = archive_read_close (a);
+ if (r != ARCHIVE_OK)
+ return propagate_libarchive_error (error, a);
+
+ r = archive_write_close (ext);
+ if (r != ARCHIVE_OK)
+ return propagate_libarchive_error (error, ext);
+
+ return TRUE;
+}
+
+static const char *
+get_download_tmpdir (void)
+{
+ /* We don't use TMPDIR because the downloaded artifacts can be
+ * very big, and we want to prefer /var/tmp to /tmp.
+ */
+ const char *tmpdir = g_getenv ("FLATPAK_DOWNLOAD_TMPDIR");
+ if (tmpdir)
+ return tmpdir;
+
+ return "/var/tmp";
+}
+
+static GLnxTmpDir *
+download_tmpdir_new (GError **error)
+{
+ g_autoptr(GLnxTmpDir) tmp_dir = g_new0 (GLnxTmpDir, 1);
+ glnx_autofd int base_dfd = -1;
+
+ if (!glnx_opendirat (AT_FDCWD, get_download_tmpdir (), TRUE, &base_dfd, error))
+ return NULL;
+
+ if (!glnx_mkdtempat (base_dfd, "oci-XXXXXX", 0700, tmp_dir, error))
+ return NULL;
+
+ return g_steal_pointer (&tmp_dir);
+}
+
static gboolean
flatpak_oci_registry_ensure_local (FlatpakOciRegistry *self,
gboolean for_write,
GCancellable *cancellable,
GError **error)
{
- g_autoptr(GFile) dir = g_file_new_for_uri (self->uri);
+ g_autoptr(GLnxTmpDir) local_tmp_dir = NULL;
glnx_autofd int local_dfd = -1;
int dfd;
g_autoptr(GError) local_error = NULL;
@@ -472,9 +667,28 @@ flatpak_oci_registry_ensure_local (FlatpakOciRegistry *self,
gboolean not_json;
if (self->dfd != -1)
- dfd = self->dfd;
+ {
+ dfd = self->dfd;
+ }
+ else if (self->archive)
+ {
+ local_tmp_dir = download_tmpdir_new (error);
+ if (!local_tmp_dir)
+ return FALSE;
+
+ if (!unpack_archive (self->archive, local_tmp_dir->path, error))
+ return FALSE;
+
+ if (!glnx_opendirat (AT_FDCWD, local_tmp_dir->path,
+ TRUE, &local_dfd, error))
+ return FALSE;
+
+ dfd = local_dfd;
+ }
else
{
+ g_autoptr(GFile) dir = g_file_new_for_uri (self->uri);
+
if (!glnx_opendirat (AT_FDCWD, flatpak_file_get_path_cached (dir),
TRUE, &local_dfd, &local_error))
{
@@ -537,8 +751,11 @@ flatpak_oci_registry_ensure_local (FlatpakOciRegistry *self,
self->token = g_strndup (g_bytes_get_data (token_bytes, NULL), g_bytes_get_size (token_bytes));
}
- if (self->dfd == -1 && local_dfd != -1)
- self->dfd = g_steal_fd (&local_dfd);
+ if (self->dfd == -1)
+ {
+ self->dfd = g_steal_fd (&local_dfd);
+ self->tmp_dir = g_steal_pointer (&local_tmp_dir);
+ }
return TRUE;
}
@@ -589,20 +806,15 @@ flatpak_oci_registry_initable_init (GInitable *initable,
FlatpakOciRegistry *self = FLATPAK_OCI_REGISTRY (initable);
gboolean res;
+ g_warn_if_fail (self->archive || self->uri);
+
if (self->tmp_dfd == -1)
{
- /* We don't use TMPDIR because the downloaded artifacts can be
- * very big, and we want to prefer /var/tmp to /tmp.
- */
- const char *tmpdir = g_getenv ("FLATPAK_DOWNLOAD_TMPDIR");
- if (tmpdir == NULL)
- tmpdir = "/var/tmp";
-
- if (!glnx_opendirat (AT_FDCWD, tmpdir, TRUE, &self->tmp_dfd, error))
+ if (!glnx_opendirat (AT_FDCWD, get_download_tmpdir (), TRUE, &self->tmp_dfd, error))
return FALSE;
}
- if (g_str_has_prefix (self->uri, "file:/"))
+ if (self->archive || g_str_has_prefix (self->uri, "file:/"))
res = flatpak_oci_registry_ensure_local (self, self->for_write, cancellable, error);
else
res = flatpak_oci_registry_ensure_remote (self, self->for_write, cancellable, error);
@@ -1332,15 +1544,6 @@ typedef struct
G_DEFINE_TYPE (FlatpakOciLayerWriter, flatpak_oci_layer_writer, G_TYPE_OBJECT)
-static gboolean
-propagate_libarchive_error (GError **error,
- struct archive *a)
-{
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "%s", archive_error_string (a));
- return FALSE;
-}
-
static void
flatpak_oci_layer_writer_reset (FlatpakOciLayerWriter *self)
{
diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c
index baf9075..b72a9bd 100644
--- a/common/flatpak-transaction.c
+++ b/common/flatpak-transaction.c
@@ -3035,7 +3035,7 @@ flatpak_transaction_add_install_bundle (FlatpakTransaction *self,
* reference.
*
* @image_location is specified in containers-transports(5) form. Only a subset
- * of transports are supported: oci: and docker:.
+ * of transports are supported: oci:, oci-archive:, and docker:.
*
* Returns: %TRUE on success; %FALSE with @error set on failure.
*/
diff --git a/doc/flatpak-install.xml b/doc/flatpak-install.xml
index f75deda..99aa546 100644
--- a/doc/flatpak-install.xml
+++ b/doc/flatpak-install.xml
@@ -145,8 +145,8 @@
Treat <arg choice="plain">LOCATION</arg> as the location of a Flatpak in
OCI image format. <arg choice="plan>">LOCATION</arg> is in the format of
<citerefentry><refentrytitle>containers-transports</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- Supported schemes are <literal>docker://</literal> and <literal>oci:</literal>.
- This is assumed if the argument starts
+ Supported schemes are <literal>docker://</literal>, <literal>oci:</literal>,
+ and <literal>oci-archive:</literal>. This is assumed if the argument starts
with one of these schemes.
</para></listitem>
</varlistentry>
diff --git a/tests/test-oci.sh b/tests/test-oci.sh
index 431fa6d..861310a 100755
--- a/tests/test-oci.sh
+++ b/tests/test-oci.sh
@@ -23,7 +23,7 @@ set -euo pipefail
skip_without_bwrap
-echo "1..3"
+echo "1..4"
setup_repo_no_add oci
@@ -85,4 +85,26 @@ assert_file_has_content flatpak-list '^org.test.Platform *platform-origin$'
${FLATPAK} --user remotes --show-disabled > remotes-list
assert_file_has_content remotes-list '^platform-origin'
+${FLATPAK} ${U} -y uninstall org.test.Platform >&2
+
ok "install oci"
+
+# Trying installing an OCI archive bundle
+
+(cd oci/platform-image && tar cf - .) > oci/platform-image.tar
+
+${FLATPAK} --user list --columns=application,origin > flatpak-list
+assert_not_file_has_content flatpak-list 'org.test.Platform'
+
+${FLATPAK} --user remotes --show-disabled > remotes-list
+assert_not_file_has_content remotes-list '^platform-origin'
+
+$FLATPAK --user -y install oci-archive:oci/platform-image.tar >&2
+
+${FLATPAK} --user list --columns=application,origin > flatpak-list
+assert_file_has_content flatpak-list '^org.test.Platform *platform-origin$'
+
+${FLATPAK} --user remotes --show-disabled > remotes-list
+assert_file_has_content remotes-list '^platform-origin'
+
+ok "install oci archive"
--
2.47.1
From ac197c01494df5af00a480ca4162fd1aa6d1b6cc Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Tue, 29 Oct 2024 16:59:40 -0400
Subject: [PATCH 12/12] common: Move delta_url into the FlatpakImageSource
Instead of passing the delta URL along with the image source, when
we create an image source for a remote registry, if we find a delta
URL in the metadata, set it on the FlatpakImageSource for later use.
Centralize duplicated code for creating an image source for a remote
repository based on a summary lookup into one place.
---
app/flatpak-builtins-build-import-bundle.c | 2 +-
common/flatpak-dir.c | 131 +++++++--------------
common/flatpak-image-source-private.h | 4 +
common/flatpak-image-source.c | 41 +++++++
common/flatpak-oci-registry-private.h | 2 -
common/flatpak-oci-registry.c | 4 +-
system-helper/flatpak-system-helper.c | 2 +-
7 files changed, 89 insertions(+), 97 deletions(-)
diff --git a/app/flatpak-builtins-build-import-bundle.c b/app/flatpak-builtins-build-import-bundle.c
index d79fbbd..d623386 100644
--- a/app/flatpak-builtins-build-import-bundle.c
+++ b/app/flatpak-builtins-build-import-bundle.c
@@ -69,7 +69,7 @@ import_oci (OstreeRepo *repo, GFile *file,
ref = flatpak_image_source_get_ref (image_source);
commit_checksum = flatpak_pull_from_oci (repo, image_source, NULL,
- NULL, ref, FLATPAK_PULL_FLAGS_NONE,
+ ref, FLATPAK_PULL_FLAGS_NONE,
NULL, NULL, cancellable, error);
if (commit_checksum == NULL)
return NULL;
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 88c0106..5a879a2 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -1086,14 +1086,14 @@ flatpak_remote_state_new_image_source (FlatpakRemoteState *self,
return g_steal_pointer (&image_source);
}
-static GVariant *
-flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
- FlatpakDir *dir,
- const char *ref,
- const char *checksum,
- const char *token,
- GCancellable *cancellable,
- GError **error)
+static FlatpakImageSource *
+flatpak_remote_state_fetch_image_source (FlatpakRemoteState *self,
+ FlatpakDir *dir,
+ const char *ref,
+ const char *opt_rev,
+ const char *token,
+ GCancellable *cancellable,
+ GError **error)
{
g_autoptr(FlatpakImageSource) image_source = NULL;
g_autofree char *oci_digest = NULL;
@@ -1101,9 +1101,7 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
VarRefInfoRef latest_rev_info;
VarMetadataRef metadata;
const char *oci_repository = NULL;
- const char *parent = NULL;
- g_autoptr(GVariantBuilder) metadata_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
- g_autoptr(GVariant) metadata_v = NULL;
+ const char *delta_url = NULL;
/* We extract the rev info from the latest, even if we don't use the latest digest, assuming refs don't move */
if (!flatpak_remote_state_lookup_ref (self, ref, &latest_rev, NULL, &latest_rev_info, NULL, error))
@@ -1119,8 +1117,9 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
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:", checksum, NULL);
+ oci_digest = g_strconcat ("sha256:", opt_rev ? opt_rev : latest_rev, NULL);
image_source = flatpak_remote_state_new_image_source (self, oci_repository, oci_digest, token, cancellable, error);
if (image_source == NULL)
@@ -1132,22 +1131,28 @@ flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
return NULL;
}
- flatpak_image_source_build_commit_metadata (image_source, metadata_builder);
- metadata_v = g_variant_ref_sink (g_variant_builder_end (metadata_builder));
+ flatpak_image_source_set_delta_url (image_source, delta_url);
+
+ return g_steal_pointer (&image_source);
+}
+
- parent = flatpak_image_source_get_parent_commit (image_source);
+static GVariant *
+flatpak_remote_state_fetch_commit_object_oci (FlatpakRemoteState *self,
+ FlatpakDir *dir,
+ const char *ref,
+ const char *checksum,
+ const char *token,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(FlatpakImageSource) image_source = NULL;
+
+ image_source = flatpak_remote_state_fetch_image_source (self, dir, ref, checksum, token, cancellable, error);
+ if (image_source == NULL)
+ return NULL;
- /* This isn't going to be exactly the same as the reconstructed one from the pull, because we don't have the contents, but its useful to get metadata */
- return
- g_variant_ref_sink (g_variant_new ("(@a{sv}@ay@a(say)sst@ay@ay)",
- metadata_v,
- parent ? ostree_checksum_to_bytes_v (parent) : g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL),
- g_variant_new_array (G_VARIANT_TYPE ("(say)"), NULL, 0),
- flatpak_image_source_get_commit_subject (image_source),
- flatpak_image_source_get_commit_body (image_source),
- GUINT64_TO_BE (flatpak_image_source_get_commit_timestamp (image_source)),
- ostree_checksum_to_bytes_v ("0000000000000000000000000000000000000000000000000000000000000000"),
- ostree_checksum_to_bytes_v ("0000000000000000000000000000000000000000000000000000000000000000")));
+ return flatpak_image_source_make_fake_commit (image_source);
}
static GVariant *
@@ -6095,49 +6100,18 @@ flatpak_dir_mirror_oci (FlatpakDir *self,
GError **error)
{
g_autoptr(FlatpakImageSource) image_source = NULL;
- g_autofree char *oci_digest = NULL;
- const char *delta_url = NULL;
gboolean res;
if (opt_image_source)
- {
- image_source = g_object_ref (opt_image_source);
- oci_digest = g_strdup (flatpak_image_source_get_digest (image_source));
- }
+ image_source = g_object_ref (opt_image_source);
else
- {
- g_autofree char *latest_rev = NULL;
- VarRefInfoRef latest_rev_info;
- VarMetadataRef metadata;
- const char *oci_repository = NULL;
- const char *rev;
-
- /* 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;
-
- 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;
- }
+ image_source = flatpak_remote_state_fetch_image_source (state, self, ref, opt_rev, token, cancellable, error);
flatpak_progress_start_oci_pull (progress);
- g_info ("Mirroring OCI image %s", oci_digest);
+ g_info ("Mirroring OCI image %s", flatpak_image_source_get_digest (image_source));
- res = flatpak_mirror_image_from_oci (dst_registry, image_source, state->remote_name, ref, delta_url, self->repo, oci_pull_progress_cb,
+ res = flatpak_mirror_image_from_oci (dst_registry, image_source, state->remote_name, ref, self->repo, oci_pull_progress_cb,
progress, cancellable, error);
if (!res)
@@ -6162,8 +6136,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
{
g_autoptr(FlatpakImageSource) image_source = NULL;
FlatpakOciRegistry *registry = NULL;
- const char *delta_url = NULL;
- g_autofree char *oci_digest = NULL;
+ const char *oci_digest = NULL;
g_autofree char *checksum = NULL;
g_autofree char *latest_alt_commit = NULL;
G_GNUC_UNUSED g_autofree char *latest_commit =
@@ -6171,35 +6144,11 @@ flatpak_dir_pull_oci (FlatpakDir *self,
g_autofree char *name = NULL;
if (opt_image_source)
- {
- image_source = g_object_ref (opt_image_source);
- oci_digest = g_strdup (flatpak_image_source_get_digest (image_source));
- }
+ image_source = g_object_ref (opt_image_source);
else
- {
- VarMetadataRef metadata;
- VarRefInfoRef latest_rev_info;
- const char *oci_repository = NULL;
- g_autofree char *latest_rev = NULL;
+ image_source = flatpak_remote_state_fetch_image_source (state, self, ref, opt_rev, token, cancellable, error);
- /* 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);
-
- 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;
- }
+ oci_digest = flatpak_image_source_get_digest (image_source);
/* Short circuit if we've already got this commit */
if (latest_alt_commit != NULL && strcmp (oci_digest + strlen ("sha256:"), latest_alt_commit) == 0)
@@ -6212,7 +6161,7 @@ flatpak_dir_pull_oci (FlatpakDir *self,
g_info ("Pulling OCI image %s", oci_digest);
- checksum = flatpak_pull_from_oci (repo, image_source, delta_url,
+ checksum = flatpak_pull_from_oci (repo, image_source,
state->remote_name, ref, flatpak_flags, oci_pull_progress_cb, progress, cancellable, error);
if (checksum == NULL)
diff --git a/common/flatpak-image-source-private.h b/common/flatpak-image-source-private.h
index b1e5d2f..94e4cc1 100644
--- a/common/flatpak-image-source-private.h
+++ b/common/flatpak-image-source-private.h
@@ -47,10 +47,13 @@ FlatpakImageSource *flatpak_image_source_new_for_location (const char *locatio
void flatpak_image_source_set_token (FlatpakImageSource *self,
const char *token);
+void flatpak_image_source_set_delta_url (FlatpakImageSource *self,
+ const char *delta_url);
FlatpakOciRegistry *flatpak_image_source_get_registry (FlatpakImageSource *self);
const char *flatpak_image_source_get_oci_repository (FlatpakImageSource *self);
const char *flatpak_image_source_get_digest (FlatpakImageSource *self);
+const char *flatpak_image_source_get_delta_url (FlatpakImageSource *self);
FlatpakOciManifest *flatpak_image_source_get_manifest (FlatpakImageSource *self);
size_t flatpak_image_source_get_manifest_size (FlatpakImageSource *self);
FlatpakOciImage *flatpak_image_source_get_image_config (FlatpakImageSource *self);
@@ -66,4 +69,5 @@ const char *flatpak_image_source_get_commit_body (FlatpakImageSource *self)
void flatpak_image_source_build_commit_metadata (FlatpakImageSource *self,
GVariantBuilder *metadata_builder);
+GVariant *flatpak_image_source_make_fake_commit (FlatpakImageSource *image_source);
#endif /* __FLATPAK_IMAGE_SOURCE_H__ */
diff --git a/common/flatpak-image-source.c b/common/flatpak-image-source.c
index 20c94b6..9d13cf0 100644
--- a/common/flatpak-image-source.c
+++ b/common/flatpak-image-source.c
@@ -31,6 +31,7 @@ struct _FlatpakImageSource
FlatpakOciRegistry *registry;
char *repository;
char *digest;
+ char *delta_url;
FlatpakOciManifest *manifest;
size_t manifest_size;
@@ -47,6 +48,7 @@ flatpak_image_source_finalize (GObject *object)
g_clear_object (&self->registry);
g_clear_pointer (&self->repository, g_free);
g_clear_pointer (&self->digest, g_free);
+ g_clear_pointer (&self->delta_url, g_free);
g_clear_object (&self->manifest);
g_clear_object (&self->image_config);
@@ -326,6 +328,20 @@ flatpak_image_source_set_token (FlatpakImageSource *self,
flatpak_oci_registry_set_token (self->registry, token);
}
+void
+flatpak_image_source_set_delta_url (FlatpakImageSource *self,
+ const char *delta_url)
+{
+ g_free (self->delta_url);
+ self->delta_url = g_strdup (delta_url);
+}
+
+const char *
+flatpak_image_source_get_delta_url (FlatpakImageSource *self)
+{
+ return self->delta_url;
+}
+
FlatpakOciRegistry *
flatpak_image_source_get_registry (FlatpakImageSource *self)
{
@@ -453,3 +469,28 @@ flatpak_image_source_build_commit_metadata (FlatpakImageSource *self,
g_variant_builder_add (metadata_builder, "{s@v}", key, data);
}
}
+
+GVariant *
+flatpak_image_source_make_fake_commit (FlatpakImageSource *self)
+{
+ const char *parent = NULL;
+ g_autoptr(GVariantBuilder) metadata_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+ g_autoptr(GVariant) metadata_v = NULL;
+
+ flatpak_image_source_build_commit_metadata (self, metadata_builder);
+ metadata_v = g_variant_ref_sink (g_variant_builder_end (metadata_builder));
+
+ parent = flatpak_image_source_get_parent_commit (self);
+
+ /* This isn't going to be exactly the same as the reconstructed one from the pull, because we don't have the contents, but its useful to get metadata */
+ return
+ g_variant_ref_sink (g_variant_new ("(@a{sv}@ay@a(say)sst@ay@ay)",
+ metadata_v,
+ parent ? ostree_checksum_to_bytes_v (parent) : g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL),
+ g_variant_new_array (G_VARIANT_TYPE ("(say)"), NULL, 0),
+ flatpak_image_source_get_commit_subject (self),
+ flatpak_image_source_get_commit_body (self),
+ GUINT64_TO_BE (flatpak_image_source_get_commit_timestamp (self)),
+ ostree_checksum_to_bytes_v ("0000000000000000000000000000000000000000000000000000000000000000"),
+ ostree_checksum_to_bytes_v ("0000000000000000000000000000000000000000000000000000000000000000")));
+}
diff --git a/common/flatpak-oci-registry-private.h b/common/flatpak-oci-registry-private.h
index d48c8ed..7867c76 100644
--- a/common/flatpak-oci-registry-private.h
+++ b/common/flatpak-oci-registry-private.h
@@ -195,7 +195,6 @@ typedef void (*FlatpakOciPullProgress) (guint64 total_size,
char * flatpak_pull_from_oci (OstreeRepo *repo,
FlatpakImageSource *image_source,
- const char *delta_url,
const char *remote,
const char *ref,
FlatpakPullFlags flags,
@@ -208,7 +207,6 @@ gboolean flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
FlatpakImageSource *image_source,
const char *remote,
const char *ref,
- const char *delta_url,
OstreeRepo *repo,
FlatpakOciPullProgress progress_cb,
gpointer progress_data,
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
index ebf000f..c3dff5d 100644
--- a/common/flatpak-oci-registry.c
+++ b/common/flatpak-oci-registry.c
@@ -3658,7 +3658,6 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
FlatpakImageSource *image_source,
const char *remote,
const char *ref,
- const char *delta_url,
OstreeRepo *repo,
FlatpakOciPullProgress progress_cb,
gpointer progress_user_data,
@@ -3670,6 +3669,7 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
const char *oci_repository = flatpak_image_source_get_oci_repository (image_source);
const char *digest = flatpak_image_source_get_digest (image_source);
FlatpakOciManifest *manifest = flatpak_image_source_get_manifest (image_source);
+ const char *delta_url = flatpak_image_source_get_delta_url (image_source);
FlatpakOciImage *image_config = flatpak_image_source_get_image_config (image_source);
g_autoptr(FlatpakOciDescriptor) manifest_desc = NULL;
g_autoptr(FlatpakOciManifest) delta_manifest = NULL;
@@ -3785,7 +3785,6 @@ flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
char *
flatpak_pull_from_oci (OstreeRepo *repo,
FlatpakImageSource *image_source,
- const char *delta_url,
const char *remote,
const char *ref,
FlatpakPullFlags flags,
@@ -3798,6 +3797,7 @@ flatpak_pull_from_oci (OstreeRepo *repo,
const char *oci_repository = flatpak_image_source_get_oci_repository (image_source);
const char *digest = flatpak_image_source_get_digest (image_source);
FlatpakOciManifest *manifest = flatpak_image_source_get_manifest (image_source);
+ const char *delta_url = flatpak_image_source_get_delta_url (image_source);
FlatpakOciImage *image_config = flatpak_image_source_get_image_config (image_source);
gboolean force_disable_deltas = (flags & FLATPAK_PULL_FLAGS_NO_STATIC_DELTAS) != 0;
g_autoptr(OstreeMutableTree) archive_mtree = NULL;
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
index 6c117de..623c2fa 100644
--- a/system-helper/flatpak-system-helper.c
+++ b/system-helper/flatpak-system-helper.c
@@ -595,7 +595,7 @@ handle_deploy (FlatpakSystemHelper *object,
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
- checksum = flatpak_pull_from_oci (flatpak_dir_get_repo (system), image_source, NULL,
+ checksum = flatpak_pull_from_oci (flatpak_dir_get_repo (system), image_source,
arg_origin, arg_ref, FLATPAK_PULL_FLAGS_NONE, NULL, NULL, NULL, &error);
if (checksum == NULL)
{
--
2.47.1