diff options
author | Colin Walters <walters@verbum.org> | 2014-06-20 04:58:31 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2014-06-20 15:36:46 -0400 |
commit | 2265ccdeb310eb9055f4e1dd110d53e150f8576e (patch) | |
tree | a453ea8cb744c8eefebdba8cd915df455603ad49 | |
parent | b2329cf87536482c03c1babbc183c098bd8a53ba (diff) | |
download | ostree-2265ccdeb310eb9055f4e1dd110d53e150f8576e.tar.gz |
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
-rw-r--r-- | src/libostree/ostree-repo.c | 129 | ||||
-rw-r--r-- | src/libostree/ostree-repo.h | 7 | ||||
-rw-r--r-- | 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 aa2bd2df..45d0fbcb 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 ccd9f407..7a57d335 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 442e118c..43750309 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")) { |