repo: Add ostree_repo_write_symlink
authorColin Walters <walters@verbum.org>
Wed, 7 Apr 2021 21:03:15 +0000 (21:03 +0000)
committerColin Walters <walters@verbum.org>
Thu, 8 Apr 2021 21:10:00 +0000 (21:10 +0000)
Continuation of the addition of `ostree_repo_write_regfile_inline()`.
This will be helpful for ostree-rs-ext and importing from tar, it's
quite inefficient and awkward for small files to end up creating
a whole `GInputStream` and `GFileInfo` and etc. for small files.

apidoc/ostree-sections.txt
src/libostree/libostree-devel.sym
src/libostree/ostree-repo-commit.c
src/libostree/ostree-repo.h
tests/test-core.js
tests/test-repo.c

index 3f48ef3aef3dd77b2e8472672528c6963a234b9c..65b9e7fd25592b9d366e459b5d7f4ad09dcb313a 100644 (file)
@@ -356,6 +356,7 @@ ostree_repo_write_metadata_async
 ostree_repo_write_metadata_finish
 ostree_repo_write_content
 ostree_repo_write_regfile_inline
+ostree_repo_write_symlink
 ostree_repo_write_metadata_trusted
 ostree_repo_write_metadata_stream_trusted
 ostree_repo_write_content_trusted
index c4a70938dcbafb407374c1f7157dc97c527dfcfa..e218dddacad90aeb861a11fa234216a5a2129125 100644 (file)
@@ -25,6 +25,7 @@
 LIBOSTREE_2021.2 {
 global:
   ostree_repo_write_regfile_inline;
+  ostree_repo_write_symlink;
 } LIBOSTREE_2021.1;
 
 /* Stub section for the stable release *after* this development one; don't
index 409738ad170d394c7426c63142aa71c70a81cbbb..ae93eedbc4bd2283b0205bb40b1e8176122b19d3 100644 (file)
@@ -2814,6 +2814,47 @@ ostree_repo_write_regfile_inline (OstreeRepo       *self,
   return ostree_checksum_from_bytes (csum);
 }
 
+/**
+ * ostree_repo_write_symlink:
+ * @self: repo
+ * @expected_checksum: (allow-none): The expected checksum
+ * @uid: User id
+ * @gid: Group id
+ * @xattrs: (allow-none): Extended attributes, GVariant of type (ayay)
+ * @symlink_target: Target of the symbolic link
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Synchronously create a symlink object.
+ *
+ * Unlike `ostree_repo_write_content()`, if @expected_checksum is provided,
+ * this function will not check for the presence of the object beforehand.
+ *
+ * Returns: (transfer full): Checksum (as a hex string) of the committed file
+ * Since: 2021.2
+ */
+char *      
+ostree_repo_write_symlink (OstreeRepo       *self,
+                           const char       *expected_checksum,
+                           guint32           uid,
+                           guint32           gid,
+                           GVariant         *xattrs,
+                           const char       *symlink_target,
+                           GCancellable     *cancellable,
+                           GError          **error)
+{
+  g_assert (symlink_target != NULL);
+
+  g_autoptr(GFileInfo) finfo = _ostree_mode_uidgid_to_gfileinfo (S_IFLNK | 0777, uid, gid);
+  g_file_info_set_attribute_byte_string (finfo, "standard::symlink-target", symlink_target);
+  g_autofree guint8* csum = NULL;
+  if (!write_content_object (self, expected_checksum,
+                             NULL, finfo, xattrs, &csum,
+                             cancellable, error))
+    return NULL;
+  return ostree_checksum_from_bytes (csum);
+}
+
 typedef struct {
   OstreeRepo *repo;
   char *expected_checksum;
index cd50fc4306a2e908371925548c48413918287616..7e08361b39d774df5dbe690d5858d52451bbe1d2 100644 (file)
@@ -435,6 +435,16 @@ char *      ostree_repo_write_regfile_inline (OstreeRepo       *self,
                                                 GCancellable     *cancellable,
                                                 GError          **error);
 
+_OSTREE_PUBLIC
+char *      ostree_repo_write_symlink (OstreeRepo       *self,
+                                       const char       *expected_checksum,
+                                       guint32           uid,
+                                       guint32           gid,
+                                       GVariant         *xattrs,
+                                       const char       *symlink_target,
+                                       GCancellable     *cancellable,
+                                       GError          **error);
+
 _OSTREE_PUBLIC
 gboolean      ostree_repo_write_metadata_trusted (OstreeRepo        *self,
                                                   OstreeObjectType   objtype,
index 8f460a5fedf75daa44a8b99e4b80a84a9b420aab..5f3e9fe356c09de87cb97b41cadd19883c1257bc 100755 (executable)
@@ -56,6 +56,7 @@ let inline_checksum = repo.write_regfile_inline(null, 0, 0, regfile_mode, null,
 assertEquals(inline_checksum, "8aaa9dc13a0c5839fe4a277756798c609c53fac6fa2290314ecfef9041065873");
 let written = false;
 try {
+    // Changed an a to b from above to make the checksum not match
     repo.write_regfile_inline("8baa9dc13a0c5839fe4a277756798c609c53fac6fa2290314ecfef9041065873", 0, 0, regfile_mode, null, inline_content, null);
     written = true;
 } catch (e) {
index ad81a7d6146fdc6cc6bca8f8528dbef74f438f32..35e929f977b8bffa0936df0e39656622bf25be5a 100644 (file)
@@ -236,6 +236,18 @@ test_write_regfile_api (Fixture *fixture,
   g_assert_no_error (error);
   g_assert_cmpstr (checksum, ==, "4f600d252338f93279c51c964915cb2c26f0d09082164c54890d1a3c78cdeb1e");
   g_clear_pointer (&checksum, g_free);
+
+  // Test symlinks
+  g_clear_pointer (&xattrs, g_variant_unref);
+  g_variant_builder_init (&xattrs_builder, (GVariantType*)"a(ayay)");
+  g_variant_builder_add (&xattrs_builder, "(^ay^ay)", "security.selinux", "system_u:object_r:bin_t:s0");
+  g_clear_pointer (&xattrs, g_variant_unref);
+  xattrs = g_variant_ref_sink (g_variant_builder_end (&xattrs_builder));
+
+  g_clear_pointer (&checksum, g_free);
+  checksum = ostree_repo_write_symlink (repo, NULL, 0, 0, xattrs, "bash", NULL, &error);
+  g_assert_no_error (error);
+  g_assert_cmpstr (checksum, ==, "23a2e97d21d960ac7a4e39a8721b1baff7b213e00e5e5641334f50506012fcff");
 }
 
 int