[ostree] libostree: Add ostree_repo_remote_add() API, port "ostree remote add"



commit 2265ccdeb310eb9055f4e1dd110d53e150f8576e
Author: Colin Walters <walters verbum org>
Date:   Fri Jun 20 04:58:31 2014 -0400

    libostree: Add ostree_repo_remote_add() API, port "ostree remote add"
    
    At least one external tool is using the API, and wants to add a
    remote, but all of the logic right now is in the tool.  Move it to the
    library.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=731984

 src/libostree/ostree-repo.c    |  129 +++++++++++++++++++++++++++++++++++++++-
 src/libostree/ostree-repo.h    |    7 ++
 src/ostree/ot-builtin-remote.c |  117 +++++++++---------------------------
 3 files changed, 163 insertions(+), 90 deletions(-)
---
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index aa2bd2d..45d0fbc 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -342,6 +342,132 @@ ostree_repo_write_config (OstreeRepo *self,
   return ret;
 }
 
+/* Bind a subset of an a{sv} to options in a given GKeyfile section */
+static void
+keyfile_set_from_vardict (GKeyFile     *keyfile,
+                          const char   *section,
+                          GVariant     *vardict)
+{
+  GVariantIter viter;
+  const char *key;
+  GVariant *val;
+
+  g_variant_iter_init (&viter, vardict);
+  while (g_variant_iter_loop (&viter, "{&s v}", &key, &val))
+    {
+      gs_unref_variant GVariant *child = g_variant_get_variant (val);
+      if (g_variant_is_of_type (child, G_VARIANT_TYPE_STRING))
+        g_key_file_set_string (keyfile, section, key, g_variant_get_string (child, NULL));
+      else if (g_variant_is_of_type (child, G_VARIANT_TYPE_BOOLEAN))
+        g_key_file_set_boolean (keyfile, section, key, g_variant_get_boolean (child));
+      else if (g_variant_is_of_type (child, G_VARIANT_TYPE_STRING_ARRAY))
+        {
+          gsize len;
+          const char *const*strv_child = g_variant_get_strv (child, &len);
+          g_key_file_set_string_list (keyfile, section, key, strv_child, len);
+        }
+      else
+        g_critical ("Unhandled type '%s' in " G_GNUC_FUNCTION,
+                    (char*)g_variant_get_type (child));
+    }
+}
+
+GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, local_keyfile_unref, g_key_file_unref)
+#define local_cleanup_keyfile __attribute__ ((cleanup(local_keyfile_unref)))
+
+/**
+ * ostree_repo_remote_add:
+ * @self: Repo
+ * @name: Name of remote
+ * @url: URL for remote
+ * @options: (allow-none): GVariant of type a{sv}
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Create a new remote named @name pointing to @url.  If @options is
+ * provided, then it will be mapped to #GKeyFile entries, where the
+ * GVariant dictionary key is an option string, and the value is
+ * mapped as follows:
+ *   * s: g_key_file_set_string()
+ *   * b: g_key_file_set_boolean()
+ *   * as: g_key_file_set_string_list()
+ *
+ */
+gboolean
+ostree_repo_remote_add (OstreeRepo     *self,
+                        const char     *name,
+                        const char     *url,
+                        GVariant       *options,
+                        GCancellable   *cancellable,
+                        GError        **error)
+{
+  gboolean ret = FALSE;
+  gboolean is_system;
+  gs_free char *section = NULL;
+  gs_unref_object GFile *etc_ostree_remotes_d = g_file_new_for_path (SYSCONFDIR "/ostree/remotes.d");
+  local_cleanup_keyfile GKeyFile *target_keyfile = NULL;
+  gs_free char *target_name = NULL;
+  gs_unref_object GFile *target_conf = NULL;
+
+  g_return_val_if_fail (name != NULL, FALSE);
+  g_return_val_if_fail (url != NULL, FALSE);
+  g_return_val_if_fail (g_variant_is_of_type (options, G_VARIANT_TYPE ("a{sv}")), FALSE);
+
+  if (strchr (name, '/') != NULL)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Invalid character '/' in remote name: %s",
+                   name);
+      goto out;
+    }
+
+  section = g_strdup_printf ("remote \"%s\"", name);
+
+  is_system = ostree_repo_is_system (self);
+  if (is_system)
+    {
+      target_keyfile = g_key_file_new ();
+
+      target_name = g_strconcat (name, ".conf", NULL);
+      target_conf = g_file_get_child (etc_ostree_remotes_d, target_name);
+          
+      if (g_file_query_exists (target_conf, NULL))
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Remote configuration already exists: %s",
+                       gs_file_get_path_cached (target_conf));
+          goto out;
+        }
+    }
+  else
+    {
+      target_keyfile = ostree_repo_copy_config (self);
+    }
+
+  g_key_file_set_string (target_keyfile, section, "url", url);
+  if (options)
+    keyfile_set_from_vardict (target_keyfile, section, options);
+
+  if (is_system)
+    {
+      gsize len;
+      gs_free char *data = g_key_file_to_data (target_keyfile, &len, error);
+      if (!g_file_replace_contents (target_conf, data, len,
+                                    NULL, FALSE, 0, NULL,
+                                    cancellable, error))
+        goto out;
+    }
+  else
+    {
+      if (!ostree_repo_write_config (self, target_keyfile, error))
+        goto out;
+    }
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
 static gboolean
 ostree_repo_mode_to_string (OstreeRepoMode   mode,
                             const char     **out_mode,
@@ -504,9 +630,6 @@ enumerate_directory_allow_noent (GFile               *dirpath,
   return ret;
 }
 
-GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, local_keyfile_unref, g_key_file_unref)
-#define local_cleanup_keyfile __attribute__ ((cleanup(local_keyfile_unref)))
-
 static gboolean
 append_one_remote_config (OstreeRepo      *self,
                           GFile           *path,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index ccd9f40..7a57d33 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -67,6 +67,13 @@ GKeyFile *    ostree_repo_get_config (OstreeRepo *self);
 
 GKeyFile *    ostree_repo_copy_config (OstreeRepo *self);
 
+gboolean      ostree_repo_remote_add (OstreeRepo     *self,
+                                      const char     *name,
+                                      const char     *url,
+                                      GVariant       *options,
+                                      GCancellable   *cancellable,
+                                      GError        **error);
+
 OstreeRepo * ostree_repo_get_parent (OstreeRepo  *self);
 
 gboolean      ostree_repo_write_config (OstreeRepo *self,
diff --git a/src/ostree/ot-builtin-remote.c b/src/ostree/ot-builtin-remote.c
index 442e118..4375030 100644
--- a/src/ostree/ot-builtin-remote.c
+++ b/src/ostree/ot-builtin-remote.c
@@ -63,47 +63,6 @@ parse_keyvalue (const char  *keyvalue,
   return TRUE;
 }
 
-GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, local_keyfile_unref, g_key_file_unref)
-#define local_cleanup_keyfile __attribute__ ((cleanup(local_keyfile_unref)))
-
-static gboolean
-add_remote_to_keyfile (GKeyFile       *new_keyfile,
-                       const char     *key,
-                       const char     *url,
-                       GPtrArray      *branches,
-                       GError        **error)
-{
-  gboolean ret = FALSE;
-  char **iter;
-
-  g_key_file_set_string (new_keyfile, key, "url", url);
-
-  for (iter = opt_set; iter && *iter; iter++)
-    {
-      const char *keyvalue = *iter;
-      gs_free char *subkey = NULL;
-      gs_free char *subvalue = NULL;
-
-      if (!parse_keyvalue (keyvalue, &subkey, &subvalue, error))
-        goto out;
-
-      g_key_file_set_string (new_keyfile, key, subkey, subvalue);
-    }
-
-  if (branches->len > 0)
-    g_key_file_set_string_list (new_keyfile, key, "branches",
-                                    (const char *const *)branches->pdata,
-                                branches->len);
-  
-  if (opt_no_gpg_verify)
-    g_key_file_set_boolean (new_keyfile, key, "gpg-verify", FALSE);
-
-  ret = TRUE;
- out:
-  return ret;
-}
-                       
-
 gboolean
 ostree_builtin_remote (int argc, char **argv, OstreeRepo *repo, GCancellable *cancellable, GError **error)
 {
@@ -140,71 +99,55 @@ ostree_builtin_remote (int argc, char **argv, OstreeRepo *repo, GCancellable *ca
   if (!strcmp (op, "add"))
     {
       const char *url = argv[3];
-      gs_unref_object GFile *etc_ostree_remotes_d = g_file_new_for_path (SYSCONFDIR "/ostree/remotes.d");
+      char **iter;
       gs_free char *target_name = NULL;
       gs_unref_object GFile *target_conf = NULL;
-      local_cleanup_keyfile GKeyFile *new_keyfile = NULL;
-      GKeyFile *target_keyfile = NULL;
       gs_unref_ptrarray GPtrArray *branches = NULL;
+      gs_unref_variant_builder GVariantBuilder *optbuilder = NULL;
 
-      if (strchr (remote_name, '/') != NULL)
-        {
-          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                       "Invalid character '/' in remote name: %s",
-                       remote_name);
-          goto out;
-        }
-      
       if (argc < 4)
         {
           usage_error (context, "URL must be specified", error);
           goto out;
         }
 
-      branches = g_ptr_array_new ();
-      for (i = 4; i < argc; i++)
-        g_ptr_array_add (branches, argv[i]);
+      optbuilder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
 
-      if (ostree_repo_is_system (repo))
+      if (branches)
         {
-          new_keyfile = g_key_file_new ();
+          gs_unref_ptrarray GPtrArray *branchesp = g_ptr_array_new ();
 
-          target_keyfile = new_keyfile;
+          for (i = 4; i < argc; i++)
+            g_ptr_array_add (branchesp, argv[i]);
+          g_ptr_array_add (branchesp, NULL);
 
-          target_name = g_strconcat (remote_name, ".conf", NULL);
-          target_conf = g_file_get_child (etc_ostree_remotes_d, target_name);
-          
-          if (g_file_query_exists (target_conf, NULL))
-            {
-              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                           "Remote configuration already exists: %s",
-                           gs_file_get_path_cached (target_conf));
-              goto out;
-            }
-        }
-      else
-        {
-          target_keyfile = config;
+          g_variant_builder_add (optbuilder, "{s v}",
+                                 "branches",
+                                 g_variant_new_variant (g_variant_new_strv ((const 
char*const*)branchesp->pdata, -1)));
         }
 
-      if (!add_remote_to_keyfile (target_keyfile, key, url, branches, error))
-        goto out;
-
-      /* For the system repository, write to /etc/ostree/remotes.d */
-      if (ostree_repo_is_system (repo))
-        {
-          gsize len;
-          gs_free char *data = g_key_file_to_data (target_keyfile, &len, error);
-          if (!g_file_replace_contents (target_conf, data, len,
-                                        NULL, FALSE, 0, NULL,
-                                        cancellable, error))
-            goto out;
-        }
-      else
+      for (iter = opt_set; iter && *iter; iter++)
         {
-          if (!ostree_repo_write_config (repo, config, error))
+          const char *keyvalue = *iter;
+          gs_free char *subkey = NULL;
+          gs_free char *subvalue = NULL;
+          
+          if (!parse_keyvalue (keyvalue, &subkey, &subvalue, error))
             goto out;
+          
+          g_variant_builder_add (optbuilder, "{s v}",
+                                 subkey, g_variant_new_variant (g_variant_new_string (subvalue)));
         }
+                                 
+      if (opt_no_gpg_verify)
+        g_variant_builder_add (optbuilder, "{s v}",
+                               "gpg-verify",
+                               g_variant_new_variant (g_variant_new_boolean (FALSE)));
+
+      if (!ostree_repo_remote_add (repo, remote_name, url,
+                                   g_variant_builder_end (optbuilder),
+                                   cancellable, error))
+        goto out;
     }
   else if (!strcmp (op, "show-url"))
     {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]