lib/repo: Add collection ID support to OstreeRepo
authorPhilip Withnall <withnall@endlessm.com>
Wed, 7 Jun 2017 11:38:59 +0000 (12:38 +0100)
committerAtomic Bot <atomic-devel@projectatomic.io>
Mon, 26 Jun 2017 15:56:07 +0000 (15:56 +0000)
Add {get,set}_collection_id() methods to OstreeRepo and some documentation
about the concept of a collection ID which globally identifies an
upstream repository. See the documentation for more details.

This will be used in future commits. For now, the new API is marked as
experimental (--enable-experimental-api).

Signed-off-by: Philip Withnall <withnall@endlessm.com>
Closes: #924
Approved by: cgwalters

apidoc/ostree-experimental-sections.txt
src/libostree/libostree-experimental.sym
src/libostree/ostree-repo-private.h
src/libostree/ostree-repo.c
src/libostree/ostree-repo.h

index 30355967ea9ded4eaf0a57b03b76a8b051601671..16983ae898bfdd2056b6f0361358a3a7dc94cad3 100644 (file)
@@ -23,5 +23,7 @@ ostree_remote_get_name
 
 <SECTION>
 <FILE>ostree-misc-experimental</FILE>
+ostree_repo_get_collection_id
+ostree_repo_set_collection_id
 ostree_validate_collection_id
 </SECTION>
index 0dabd59153b2c0c8fc860de77698b78c7ab349ae..dad788b735829dc85806bf3cdf39a258e8efd5b0 100644 (file)
@@ -45,5 +45,7 @@ global:
   ostree_collection_ref_get_type;
   ostree_collection_ref_hash;
   ostree_collection_ref_new;
+  ostree_repo_get_collection_id;
+  ostree_repo_set_collection_id;
   ostree_validate_collection_id;
 } LIBOSTREE_2017.7_EXPERIMENTAL;
index 8f87b103875312e2025cdea6d36c505ad1282da8..825c1ffc6a566074aa11a1a63bf6d3bfe1727e16 100644 (file)
@@ -20,6 +20,7 @@
 
 #pragma once
 
+#include "ostree-ref.h"
 #include "ostree-repo.h"
 #include "ostree-remote-private.h"
 #include "libglnx.h"
@@ -129,6 +130,7 @@ struct OstreeRepo {
   gboolean enable_uncompressed_cache;
   gboolean generate_sizes;
   guint64 tmp_expiry_seconds;
+  gchar *collection_id;
 
   OstreeRepo *parent_repo;
 };
@@ -349,4 +351,13 @@ _ostree_repo_get_remote_inherited (OstreeRepo  *self,
                                    const char  *name,
                                    GError     **error);
 
+#ifndef OSTREE_ENABLE_EXPERIMENTAL_API
+
+const gchar * ostree_repo_get_collection_id (OstreeRepo   *self);
+gboolean      ostree_repo_set_collection_id (OstreeRepo   *self,
+                                             const gchar  *collection_id,
+                                             GError      **error);
+
+#endif  /* !OSTREE_ENABLE_EXPERIMENTAL_API */
+
 G_END_DECLS
index f2b7c21b91f2daeb1b25534a8bcbd92e56036d35..24e94e03ee94edf4c4bc13e7507822399de241fc 100644 (file)
  * Once the #OstreeMutableTree is complete, write all of its metadata
  * with ostree_repo_write_mtree(), and finally create a commit with
  * ostree_repo_write_commit().
+ *
+ * ## Collection IDs
+ *
+ * A collection ID is a globally unique identifier which, if set, is used to
+ * identify refs from a repository which are mirrored elsewhere, such as in
+ * mirror repositories or peer to peer networks.
+ *
+ * This is separate from the `collection-id` configuration key for a remote, which
+ * is used to store the collection ID of the repository that remote points to.
+ *
+ * The collection ID should only be set on an #OstreeRepo if it is the canonical
+ * collection for some refs.
+ *
+ * A collection ID must be a reverse DNS name, where the domain name is under the
+ * control of the curator of the collection, so they can demonstrate ownership
+ * of the collection. The later elements in the reverse DNS name can be used to
+ * disambiguate between multiple collections from the same curator. For example,
+ * `org.exampleos.Main` and `org.exampleos.Apps`. For the complete format of
+ * collection IDs, see ostree_validate_collection_id().
  */
 typedef struct {
   GObjectClass parent_class;
@@ -461,6 +480,7 @@ ostree_repo_finalize (GObject *object)
   g_clear_pointer (&self->dirmeta_cache, (GDestroyNotify) g_hash_table_unref);
   g_mutex_clear (&self->cache_lock);
   g_mutex_clear (&self->txn_stats_lock);
+  g_free (self->collection_id);
 
   g_clear_pointer (&self->remotes, g_hash_table_destroy);
   g_mutex_clear (&self->remotes_lock);
@@ -1707,6 +1727,9 @@ ostree_repo_create (OstreeRepo     *self,
 
           g_string_append_printf (config_data, "mode=%s\n", mode_str);
 
+          if (self->collection_id != NULL)
+            g_string_append_printf (config_data, "collection-id=%s\n", self->collection_id);
+
           if (!glnx_file_replace_contents_at (dfd, "config",
                                               (guint8*)config_data->str, config_data->len,
                                               0, cancellable, error))
@@ -1939,6 +1962,13 @@ reload_core_config (OstreeRepo          *self,
       self->zlib_compression_level = OSTREE_ARCHIVE_DEFAULT_COMPRESSION_LEVEL;
   }
 
+  {
+    g_clear_pointer (&self->collection_id, g_free);
+    if (!ot_keyfile_get_value_with_default (self->config, "core", "collection-id",
+                                            NULL, &self->collection_id, NULL))
+      return FALSE;
+  }
+
   if (!ot_keyfile_get_value_with_default (self->config, "core", "parent",
                                           NULL, &parent_repo_path, error))
     return FALSE;
@@ -4827,3 +4857,56 @@ _ostree_repo_memory_cache_ref_destroy (OstreeRepoMemoryCacheRef *state)
   g_mutex_unlock (lock);
   g_object_unref (repo);
 }
+
+/**
+ * ostree_repo_get_collection_id:
+ * @self: an #OstreeRepo
+ *
+ * Get the collection ID of this repository. See [collection IDs][collection-ids].
+ *
+ * Returns: (nullable): collection ID for the repository
+ * Since: 2017.8
+ */
+const gchar *
+ostree_repo_get_collection_id (OstreeRepo *self)
+{
+  g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
+
+  return self->collection_id;
+}
+
+/**
+ * ostree_repo_set_collection_id:
+ * @self: an #OstreeRepo
+ * @collection_id: (nullable): new collection ID, or %NULL to unset it
+ * @error: return location for a #GError, or %NULL
+ *
+ * Set or clear the collection ID of this repository. See [collection IDs][collection-ids].
+ * The update will be made in memory, but must be written out to the repository
+ * configuration on disk using ostree_repo_write_config().
+ *
+ * Returns: %TRUE on success, %FALSE otherwise
+ * Since: 2017.8
+ */
+gboolean
+ostree_repo_set_collection_id (OstreeRepo   *self,
+                               const gchar  *collection_id,
+                               GError      **error)
+{
+  if (collection_id != NULL && !ostree_validate_collection_id (collection_id, error))
+    return FALSE;
+
+  g_autofree gchar *new_collection_id = g_strdup (collection_id);
+  g_free (self->collection_id);
+  self->collection_id = g_steal_pointer (&new_collection_id);
+
+  if (self->config != NULL)
+    {
+      if (collection_id != NULL)
+        g_key_file_set_string (self->config, "core", "collection-id", collection_id);
+      else
+        return g_key_file_remove_key (self->config, "core", "collection-id", error);
+    }
+
+  return TRUE;
+}
index 04294f33d1bfa644266db4daf64a5f76c8c00d31..566754d4067a61f39245a665618ded26ce33e250 100644 (file)
@@ -89,6 +89,17 @@ gboolean      ostree_repo_create (OstreeRepo     *self,
                                   GCancellable   *cancellable,
                                   GError        **error);
 
+#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
+
+_OSTREE_PUBLIC
+const gchar * ostree_repo_get_collection_id (OstreeRepo   *self);
+_OSTREE_PUBLIC
+gboolean      ostree_repo_set_collection_id (OstreeRepo   *self,
+                                             const gchar  *collection_id,
+                                             GError      **error);
+
+#endif  /* OSTREE_ENABLE_EXPERIMENTAL_API */
+
 _OSTREE_PUBLIC
 GFile *       ostree_repo_get_path (OstreeRepo  *self);