flatpak/flatpak-allow-direct-installation-from-oci-images.patch

4179 lines
175 KiB
Diff
Raw Normal View History

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