summaryrefslogtreecommitdiff
path: root/src/libostree/ostree-repo-commit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libostree/ostree-repo-commit.c')
-rw-r--r--src/libostree/ostree-repo-commit.c125
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;
+}