From 11bdbe1fb860b1bd4693343adb4d53a223d3c8d6 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 14 Aug 2013 18:18:10 -0400 Subject: [PATCH] repo: Add API to load any object as a stream We have APIs to load metadata as variants, and files as parsed content/info/xattrs, but for some cases such as static deltas, all we want is to operate on all objects in their canonical representation. https://bugzilla.gnome.org/show_bug.cgi?id=706031 --- src/libgsystem | 2 +- src/libostree/ostree-repo.c | 163 ++++++++++++++++++++--------- src/libostree/ostree-repo.h | 8 ++ src/ostree/ot-builtin-pull-local.c | 14 +-- 4 files changed, 126 insertions(+), 61 deletions(-) diff --git a/src/libgsystem b/src/libgsystem index 4150e633..4501b425 160000 --- a/src/libgsystem +++ b/src/libgsystem @@ -1 +1 @@ -Subproject commit 4150e6336881faec1a31f557567ca89c283b38c9 +Subproject commit 4501b425953c3849112206c4a3f6f27cd3264936 diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index d585ad83..f6964409 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2041,6 +2041,73 @@ list_loose_objects (OstreeRepo *self, return ret; } +static gboolean +load_metadata_internal (OstreeRepo *self, + OstreeObjectType objtype, + const char *sha256, + gboolean error_if_not_found, + GVariant **out_variant, + GInputStream **out_stream, + guint64 *out_size, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + gs_unref_object GFile *object_path = NULL; + gs_unref_object GInputStream *ret_stream = NULL; + gs_unref_variant GVariant *ret_variant = NULL; + + g_return_val_if_fail (OSTREE_OBJECT_TYPE_IS_META (objtype), FALSE); + + if (!repo_find_object (self, objtype, sha256, &object_path, + cancellable, error)) + goto out; + + if (object_path != NULL) + { + if (out_variant) + { + if (!ot_util_variant_map (object_path, ostree_metadata_variant_type (objtype), + TRUE, &ret_variant, error)) + goto out; + if (out_size) + *out_size = g_variant_get_size (ret_variant); + } + else if (out_stream) + { + ret_stream = gs_file_read_noatime (object_path, cancellable, error); + if (!ret_stream) + goto out; + if (out_size) + { + struct stat stbuf; + + if (!gs_stream_fstat ((GFileDescriptorBased*)ret_stream, &stbuf, cancellable, error)) + goto out; + *out_size = stbuf.st_size; + } + } + } + else if (self->parent_repo) + { + if (!ostree_repo_load_variant (self->parent_repo, objtype, sha256, &ret_variant, error)) + goto out; + } + else if (error_if_not_found) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "No such metadata object %s.%s", + sha256, ostree_object_type_to_string (objtype)); + goto out; + } + + ret = TRUE; + ot_transfer_out_value (out_variant, &ret_variant); + ot_transfer_out_value (out_stream, &ret_stream); + out: + return ret; +} + gboolean ostree_repo_load_file (OstreeRepo *self, const char *checksum, @@ -2164,6 +2231,49 @@ ostree_repo_load_file (OstreeRepo *self, return ret; } +gboolean +ostree_repo_load_object_stream (OstreeRepo *self, + OstreeObjectType objtype, + const char *checksum, + GInputStream **out_input, + guint64 *out_size, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + guint64 size; + gs_unref_object GInputStream *ret_input = NULL; + + if (OSTREE_OBJECT_TYPE_IS_META (objtype)) + { + if (!load_metadata_internal (self, objtype, checksum, TRUE, NULL, + &ret_input, &size, + cancellable, error)) + goto out; + } + else + { + gs_unref_object GInputStream *input = NULL; + gs_unref_object GFileInfo *finfo = NULL; + gs_unref_variant GVariant *xattrs = NULL; + + if (!ostree_repo_load_file (self, checksum, &input, &finfo, &xattrs, + cancellable, error)) + goto out; + + if (!ostree_raw_file_to_content_stream (input, finfo, xattrs, + &ret_input, &size, + cancellable, error)) + goto out; + } + + ret = TRUE; + ot_transfer_out_value (out_input, &ret_input); + *out_size = size; + out: + return ret; +} + static gboolean repo_find_object (OstreeRepo *self, OstreeObjectType objtype, @@ -2305,50 +2415,6 @@ ostree_repo_load_variant_c (OstreeRepo *self, return ret; } -static gboolean -load_variant_internal (OstreeRepo *self, - OstreeObjectType objtype, - const char *sha256, - gboolean error_if_not_found, - GVariant **out_variant, - GError **error) -{ - gboolean ret = FALSE; - GCancellable *cancellable = NULL; - gs_unref_object GFile *object_path = NULL; - gs_unref_variant GVariant *ret_variant = NULL; - - g_return_val_if_fail (OSTREE_OBJECT_TYPE_IS_META (objtype), FALSE); - - if (!repo_find_object (self, objtype, sha256, &object_path, - cancellable, error)) - goto out; - - if (object_path != NULL) - { - if (!ot_util_variant_map (object_path, ostree_metadata_variant_type (objtype), - TRUE, &ret_variant, error)) - goto out; - } - else if (self->parent_repo) - { - if (!ostree_repo_load_variant (self->parent_repo, objtype, sha256, &ret_variant, error)) - goto out; - } - else if (error_if_not_found) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No such metadata object %s.%s", - sha256, ostree_object_type_to_string (objtype)); - goto out; - } - - ret = TRUE; - ot_transfer_out_value (out_variant, &ret_variant); - out: - return ret; -} - /** * ostree_repo_load_variant_if_exists: * @@ -2363,8 +2429,8 @@ ostree_repo_load_variant_if_exists (OstreeRepo *self, GVariant **out_variant, GError **error) { - return load_variant_internal (self, objtype, sha256, FALSE, - out_variant, error); + return load_metadata_internal (self, objtype, sha256, FALSE, + out_variant, NULL, NULL, NULL, error); } /** @@ -2385,11 +2451,10 @@ ostree_repo_load_variant (OstreeRepo *self, GVariant **out_variant, GError **error) { - return load_variant_internal (self, objtype, sha256, TRUE, - out_variant, error); + return load_metadata_internal (self, objtype, sha256, TRUE, + out_variant, NULL, NULL, NULL, error); } - /** * ostree_repo_list_objects: * @self: diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index e67a6f39..89be951f 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -198,6 +198,14 @@ gboolean ostree_repo_load_file (OstreeRepo *self, GCancellable *cancellable, GError **error); +gboolean ostree_repo_load_object_stream (OstreeRepo *self, + OstreeObjectType objtype, + const char *checksum, + GInputStream **out_input, + guint64 *out_size, + GCancellable *cancellable, + GError **error); + gboolean ostree_repo_query_object_storage_size (OstreeRepo *self, OstreeObjectType objtype, const char *sha256, diff --git a/src/ostree/ot-builtin-pull-local.c b/src/ostree/ot-builtin-pull-local.c index cd63450c..d98a3a74 100644 --- a/src/ostree/ot-builtin-pull-local.c +++ b/src/ostree/ot-builtin-pull-local.c @@ -68,18 +68,10 @@ import_one_object (OtLocalCloneData *data, { guint64 length; gs_unref_object GInputStream *file_object = NULL; - gs_unref_object GInputStream *input = NULL; - gs_unref_object GFileInfo *file_info = NULL; - gs_unref_variant GVariant *xattrs = NULL; - if (!ostree_repo_load_file (data->src_repo, checksum, - &input, &file_info, &xattrs, - cancellable, error)) - goto out; - - if (!ostree_raw_file_to_content_stream (input, file_info, xattrs, - &file_object, &length, - cancellable, error)) + if (!ostree_repo_load_object_stream (data->src_repo, objtype, checksum, + &file_object, &length, + cancellable, error)) goto out; if (!ostree_repo_stage_content_trusted (data->dest_repo, checksum,