diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index b529854e..3d56bb55 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -933,6 +933,40 @@ ostree_repo_write_config (OstreeRepo *self, { g_return_val_if_fail (self->inited, FALSE); + /* Ensure that any remotes in the new config aren't defined in a + * separate config file. + */ + gsize num_groups; + g_auto(GStrv) groups = g_key_file_get_groups (new_config, &num_groups); + for (gsize i = 0; i < num_groups; i++) + { + g_autoptr(OstreeRemote) new_remote = ostree_remote_new_from_keyfile (new_config, groups[i]); + if (new_remote != NULL) + { + g_autoptr(GError) local_error = NULL; + + g_autoptr(OstreeRemote) cur_remote = + _ostree_repo_get_remote (self, new_remote->name, &local_error); + if (cur_remote == NULL) + { + if (!g_error_matches (local_error, G_IO_ERROR, + G_IO_ERROR_NOT_FOUND)) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + else if (cur_remote->file != NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS, + "Remote \"%s\" already defined in %s", + new_remote->name, + gs_file_get_path_cached (cur_remote->file)); + return FALSE; + } + } + } + gsize len; g_autofree char *data = g_key_file_to_data (new_config, &len, error); if (!glnx_file_replace_contents_at (self->repo_dir_fd, "config", diff --git a/tests/test-remotes-config-dir.js b/tests/test-remotes-config-dir.js index 11d77348..7b6585c9 100755 --- a/tests/test-remotes-config-dir.js +++ b/tests/test-remotes-config-dir.js @@ -32,7 +32,7 @@ function assertNotEquals(a, b) { throw new Error("assertion failed " + JSON.stringify(a) + " != " + JSON.stringify(b)); } -print('1..4') +print('1..6') let remotesDir = Gio.File.new_for_path('remotes.d'); remotesDir.make_directory(null); @@ -85,3 +85,30 @@ assertNotEquals(remotes.indexOf('baz'), -1); assertEquals(remotesDir.get_child('baz.conf').query_exists(null), true); print("ok add-in-remotes-config-dir"); + +// Trying to set a remote config option via write_config() for a remote +// defined in the config file should succeed +let [, gpg_verify] = repo.remote_get_gpg_verify('bar'); +assertEquals(gpg_verify, true); +repoConfig = repo.copy_config(); +repoConfig.set_boolean('remote "bar"', 'gpg-verify', false); +repo.write_config(repoConfig); +repo.reload_config(null); +[, gpg_verify] = repo.remote_get_gpg_verify('bar'); +assertEquals(gpg_verify, false); + +print("ok config-remote-in-config-file-succeeds"); + +// Trying to set a remote config option via write_config() for a remote +// defined in the config dir should fail with G_IO_ERROR_EXISTS +repoConfig = repo.copy_config(); +repoConfig.set_boolean('remote "baz"', 'gpg-verify', false); +try { + if (repo.write_config(repoConfig)) + throw new Error("config of remote in config dir should fail"); +} catch (e) { + if (!(e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS))) + throw e; +} + +print("ok config-remote-in-config-dir-fails");