diff options
Diffstat (limited to 'src/libostree/ostree-repo-commit.c')
-rw-r--r-- | src/libostree/ostree-repo-commit.c | 125 |
1 files changed, 100 insertions, 25 deletions
diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index de79d64a..32119c47 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -47,7 +47,7 @@ #endif /* Understanding ostree's fsync strategy - * + * * A long time ago, ostree used to invoke fsync() on each object, * then move it into the objects directory. However, it turned * out to be a *lot* faster to write the objects into a separate "staging" @@ -678,12 +678,13 @@ create_regular_tmpfile_linkable_with_content (OstreeRepo *self, * e.g. 10 bytes but is actually gigabytes. * - Due to GLib bugs that pointlessly calls `poll()` on the output fd for every write */ - char buf[8192]; + gsize buf_size = MIN(length, 1048576); + g_autofree gchar * buf = g_malloc(buf_size); guint64 remaining = length; while (remaining > 0) { const gssize bytes_read = - g_input_stream_read (input, buf, MIN (remaining, sizeof (buf)), cancellable, error); + g_input_stream_read (input, buf, MIN (remaining, buf_size), cancellable, error); if (bytes_read < 0) return FALSE; else if (bytes_read == 0) @@ -1210,7 +1211,8 @@ write_content_object (OstreeRepo *self, /* Update statistics */ g_mutex_lock (&self->txn_lock); self->txn.stats.content_objects_written++; - self->txn.stats.content_bytes_written += g_file_info_get_size (file_info); + if (g_file_info_has_attribute (file_info, "standard::size")) + self->txn.stats.content_bytes_written += g_file_info_get_size (file_info); self->txn.stats.content_objects_total++; g_mutex_unlock (&self->txn_lock); @@ -2350,7 +2352,8 @@ ostree_repo_commit_transaction (OstreeRepo *self, /* Update the summary if auto-update-summary is set, because doing so was * delayed for each ref change during the transaction. */ - if ((self->txn.refs || self->txn.collection_refs) && + if (!self->txn.disable_auto_summary && + (self->txn.refs || self->txn.collection_refs) && !_ostree_repo_maybe_regenerate_summary (self, cancellable, error)) return FALSE; @@ -2444,9 +2447,9 @@ ostree_repo_abort_transaction (OstreeRepo *self, * ostree_repo_write_metadata: * @self: Repo * @objtype: Object type - * @expected_checksum: (allow-none): If provided, validate content against this checksum + * @expected_checksum: (nullable): If provided, validate content against this checksum * @object: Metadata - * @out_csum: (out) (array fixed-size=32) (allow-none): Binary checksum + * @out_csum: (out) (array fixed-size=32) (optional): Binary checksum * @cancellable: Cancellable * @error: Error * @@ -2619,7 +2622,7 @@ write_metadata_thread (GTask *task, * ostree_repo_write_metadata_async: * @self: Repo * @objtype: Object type - * @expected_checksum: (allow-none): If provided, validate content against this checksum + * @expected_checksum: (nullable): If provided, validate content against this checksum * @object: Metadata * @cancellable: Cancellable * @callback: Invoked when metadata is writed @@ -2739,7 +2742,7 @@ ostree_repo_write_content_trusted (OstreeRepo *self, * @expected_checksum: (allow-none): If provided, validate content against this checksum * @object_input: Content object stream * @length: Length of @object_input - * @out_csum: (out) (array fixed-size=32) (allow-none): Binary checksum + * @out_csum: (out) (array fixed-size=32) (optional) (nullable): Binary checksum * @cancellable: Cancellable * @error: Error * @@ -2856,7 +2859,7 @@ ostree_repo_write_regfile_inline (OstreeRepo *self, * Returns: (transfer full): Checksum (as a hex string) of the committed file * Since: 2021.2 */ -char * +char * ostree_repo_write_symlink (OstreeRepo *self, const char *expected_checksum, guint32 uid, @@ -2888,14 +2891,14 @@ ostree_repo_write_symlink (OstreeRepo *self, * @content_len: Expected content length * @xattrs: (allow-none): Extended attributes (GVariant type `(ayay)`) * @error: Error - * + * * Create an `OstreeContentWriter` that allows streaming output into * the repository. * * Returns: (transfer full): A new writer, or %NULL on error * Since: 2021.2 */ -OstreeContentWriter * +OstreeContentWriter * ostree_repo_write_regfile (OstreeRepo *self, const char *expected_checksum, guint32 uid, @@ -2994,7 +2997,8 @@ ostree_repo_write_content_async (OstreeRepo *self, * ostree_repo_write_content_finish: * @self: a #OstreeRepo * @result: a #GAsyncResult - * @out_csum: (out) (transfer full): A binary SHA256 checksum of the content object + * @out_csum: (out) (transfer full) (optional): A binary SHA256 + * checksum of the content object * @error: a #GError * * Completes an invocation of ostree_repo_write_content_async(). @@ -3032,12 +3036,13 @@ create_empty_gvariant_dict (void) /** * ostree_repo_write_commit: * @self: Repo - * @parent: (allow-none): ASCII SHA256 checksum for parent, or %NULL for none - * @subject: (allow-none): Subject - * @body: (allow-none): Body - * @metadata: (allow-none): GVariant of type a{sv}, or %NULL for none + * @parent: (nullable): ASCII SHA256 checksum for parent, or %NULL for none + * @subject: (nullable): Subject + * @body: (nullable): Body + * @metadata: (nullable): GVariant of type a{sv}, or %NULL for none * @root: The tree to point the commit to - * @out_commit: (out): Resulting ASCII SHA256 checksum for commit + * @out_commit: (out) (optional): Resulting ASCII SHA256 checksum for + * commit * @cancellable: Cancellable * @error: Error * @@ -3085,13 +3090,14 @@ ostree_repo_write_commit (OstreeRepo *self, /** * ostree_repo_write_commit_with_time: * @self: Repo - * @parent: (allow-none): ASCII SHA256 checksum for parent, or %NULL for none - * @subject: (allow-none): Subject - * @body: (allow-none): Body - * @metadata: (allow-none): GVariant of type a{sv}, or %NULL for none + * @parent: (nullable): ASCII SHA256 checksum for parent, or %NULL for none + * @subject: (nullable): Subject + * @body: (nullable): Body + * @metadata: (nullable): GVariant of type a{sv}, or %NULL for none * @root: The tree to point the commit to * @time: The time to use to stamp the commit - * @out_commit: (out): Resulting ASCII SHA256 checksum for commit + * @out_commit: (out) (optional): Resulting ASCII SHA256 checksum for + * commit * @cancellable: Cancellable * @error: Error * @@ -3190,7 +3196,7 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self, * ostree_repo_write_commit_detached_metadata: * @self: Repo * @checksum: ASCII SHA256 commit checksum - * @metadata: (allow-none): Metadata to associate with commit in with format "a{sv}", or %NULL to delete + * @metadata: (nullable): Metadata to associate with commit in with format "a{sv}", or %NULL to delete * @cancellable: Cancellable * @error: Error * @@ -4402,7 +4408,7 @@ ostree_repo_commit_modifier_set_sepolicy (OstreeRepoCommitModifier * * Since: 2020.4 */ -gboolean +gboolean ostree_repo_commit_modifier_set_sepolicy_from_commit (OstreeRepoCommitModifier *modifier, OstreeRepo *repo, const char *rev, @@ -4870,3 +4876,72 @@ ostree_repo_transaction_stats_free (OstreeRepoTransactionStats *stats) G_DEFINE_BOXED_TYPE(OstreeRepoTransactionStats, ostree_repo_transaction_stats, ostree_repo_transaction_stats_copy, ostree_repo_transaction_stats_free); + + +gboolean +_ostree_repo_transaction_write_repo_metadata (OstreeRepo *self, + GVariant *additional_metadata, + char **out_checksum, + GCancellable *cancellable, + GError **error) +{ + g_assert (self != NULL); + g_assert (OSTREE_IS_REPO (self)); + g_assert (self->in_transaction == TRUE); + + const char *collection_id = ostree_repo_get_collection_id (self); + if (collection_id == NULL) + return glnx_throw (error, "Repository must have collection ID to write repo metadata"); + + OstreeCollectionRef collection_ref = { (gchar *) collection_id, + (gchar *) OSTREE_REPO_METADATA_REF }; + g_autofree char *old_checksum = NULL; + if (!ostree_repo_resolve_rev (self, OSTREE_REPO_METADATA_REF, TRUE, + &old_checksum, error)) + return FALSE; + + /* Add bindings to the commit metadata. */ + g_autoptr(GVariantDict) metadata_dict = g_variant_dict_new (additional_metadata); + g_variant_dict_insert (metadata_dict, OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, + "s", collection_ref.collection_id); + g_variant_dict_insert_value (metadata_dict, OSTREE_COMMIT_META_KEY_REF_BINDING, + g_variant_new_strv ((const gchar * const *) &collection_ref.ref_name, 1)); + g_autoptr(GVariant) metadata = g_variant_dict_end (metadata_dict); + + /* Set up an empty mtree. */ + g_autoptr(OstreeMutableTree) mtree = ostree_mutable_tree_new (); + + glnx_unref_object GFileInfo *fi = g_file_info_new (); + g_file_info_set_attribute_uint32 (fi, "unix::uid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::gid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::mode", (0755 | S_IFDIR)); + + g_autoptr(GVariant) dirmeta = ostree_create_directory_metadata (fi, NULL /* xattrs */); + + g_autofree guchar *csum_raw = NULL; + if (!ostree_repo_write_metadata (self, OSTREE_OBJECT_TYPE_DIR_META, NULL, + dirmeta, &csum_raw, cancellable, error)) + return FALSE; + + g_autofree char *csum = ostree_checksum_from_bytes (csum_raw); + ostree_mutable_tree_set_metadata_checksum (mtree, csum); + + g_autoptr(OstreeRepoFile) repo_file = NULL; + if (!ostree_repo_write_mtree (self, mtree, (GFile **) &repo_file, cancellable, error)) + return FALSE; + + g_autofree gchar *new_checksum = NULL; + if (!ostree_repo_write_commit (self, old_checksum, + NULL /* subject */, NULL /* body */, + metadata, repo_file, + &new_checksum, + cancellable, error)) + return FALSE; + + ostree_repo_transaction_set_collection_ref (self, &collection_ref, new_checksum); + + if (out_checksum != NULL) + *out_checksum = g_steal_pointer (&new_checksum); + + return TRUE; +} |