diff options
author | Colin Walters <walters@verbum.org> | 2014-05-08 09:16:36 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2014-05-08 18:59:24 -0400 |
commit | f47a20fb816a16532d6f9885b046d6a4aed278c1 (patch) | |
tree | 4eb23638c9abfc3e908e9d19e309ed967452d846 /src/ostree/ot-builtin-remote.c | |
parent | 466671407de87cc366b4cb5c590d108a5516e30d (diff) | |
download | ostree-f47a20fb816a16532d6f9885b046d6a4aed278c1.tar.gz |
Support /etc/ostree/remotes.d
For many OS install scenarios, one runs through an installer which may
come with embedded data, and then the OS is configured post-install to
receive updates.
In this model, it'd be nice to avoid the post-install having to rewrite
the /ostree/repo/config file.
Additionally, it feels weird for admins to interact with "/ostree" -
let's make the system feel more like Unix and have our important
configuration in /etc.
https://bugzilla.gnome.org/show_bug.cgi?id=729343
Diffstat (limited to 'src/ostree/ot-builtin-remote.c')
-rw-r--r-- | src/ostree/ot-builtin-remote.c | 121 |
1 files changed, 96 insertions, 25 deletions
diff --git a/src/ostree/ot-builtin-remote.c b/src/ostree/ot-builtin-remote.c index de6dcba8..442e118c 100644 --- a/src/ostree/ot-builtin-remote.c +++ b/src/ostree/ot-builtin-remote.c @@ -63,6 +63,47 @@ 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) { @@ -71,8 +112,8 @@ ostree_builtin_remote (int argc, char **argv, OstreeRepo *repo, GCancellable *ca const char *op; gs_free char *key = NULL; guint i; - gs_unref_ptrarray GPtrArray *branches = NULL; GKeyFile *config = NULL; + const char *remote_name; context = g_option_context_new ("OPERATION NAME [args] - Control remote repository configuration"); g_option_context_add_main_entries (context, options, NULL); @@ -91,13 +132,29 @@ ostree_builtin_remote (int argc, char **argv, OstreeRepo *repo, GCancellable *ca } op = argv[1]; - key = g_strdup_printf ("remote \"%s\"", argv[2]); + remote_name = argv[2]; + key = g_strdup_printf ("remote \"%s\"", remote_name); config = ostree_repo_copy_config (repo); if (!strcmp (op, "add")) { - char **iter; + const char *url = argv[3]; + gs_unref_object GFile *etc_ostree_remotes_d = g_file_new_for_path (SYSCONFDIR "/ostree/remotes.d"); + 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; + + 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); @@ -108,29 +165,46 @@ ostree_builtin_remote (int argc, char **argv, OstreeRepo *repo, GCancellable *ca for (i = 4; i < argc; i++) g_ptr_array_add (branches, argv[i]); - g_key_file_set_string (config, key, "url", argv[3]); - - for (iter = opt_set; iter && *iter; iter++) + if (ostree_repo_is_system (repo)) { - 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 (config, key, subkey, subvalue); + new_keyfile = g_key_file_new (); + + target_keyfile = new_keyfile; + + 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; } - if (branches->len > 0) - g_key_file_set_string_list (config, key, "branches", - (const char *const *)branches->pdata, - branches->len); - - if (opt_no_gpg_verify) - g_key_file_set_boolean (config, key, "gpg-verify", FALSE); + if (!add_remote_to_keyfile (target_keyfile, key, url, branches, error)) + goto out; - g_free (key); + /* 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 + { + if (!ostree_repo_write_config (repo, config, error)) + goto out; + } } else if (!strcmp (op, "show-url")) { @@ -147,9 +221,6 @@ ostree_builtin_remote (int argc, char **argv, OstreeRepo *repo, GCancellable *ca usage_error (context, "Unknown operation", error); goto out; } - - if (!ostree_repo_write_config (repo, config, error)) - goto out; ret = TRUE; out: |