From 40a54e3d273296c7aa8f2ea783a03bf55a80cbd4 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 11 Jan 2019 10:46:36 -0500 Subject: [PATCH 01/50] Post-release bump Closes: #1800 Approved by: jlebon --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 101a8a17..3a2b1362 100644 --- a/configure.ac +++ b/configure.ac @@ -4,10 +4,10 @@ dnl update libostree-released.sym from libostree-devel.sym, and update the check dnl in test-symbols.sh, and also set is_release_build=yes below. Then make dnl another post-release commit to bump the version, and set is_release_build=no. m4_define([year_version], [2019]) -m4_define([release_version], [1]) +m4_define([release_version], [2]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) -is_release_build=yes +is_release_build=no AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) From 620a3138aeb9ec1967095ad70b7fe779e019242d Mon Sep 17 00:00:00 2001 From: Micah Abbott Date: Tue, 15 Jan 2019 09:45:02 -0500 Subject: [PATCH 02/50] README: add note about Liri OS Closes: #1802 Approved by: rfairley --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ea343ee..aa7b23e0 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ version of - Support for parallel installing more than just 2 bootable roots - Binary history on the server side (and client) - Introspectable shared library API for build and deployment systems - - Flexible support for multiple branches and repositories, supporting + - Flexible support for multiple branches and repositories, supporting projects like [flatpak](https://github.com/flatpak/flatpak) which use libostree for applications, rather than hosts. @@ -74,6 +74,9 @@ The [BuildStream](https://gitlab.com/BuildStream/buildstream) build and integration tool uses libostree as a caching system to store and share built artifacts. +[Liri OS](https://liri.io/download/silverblue/) has the option to install +their distribution using ostree. + Language bindings ---- From c79d792fd583e92750bdaabcbc9275866bda9976 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 16 Jan 2019 08:30:53 -0500 Subject: [PATCH 03/50] =?UTF-8?q?lib/commit:=20Fix=20bare=20=E2=86=92=20ba?= =?UTF-8?q?re=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression from https://github.com/ostreedev/ostree/pull/1771 This broke rpmostreepayload in Anaconda where we import a bare repo: https://openqa.fedoraproject.org/tests/345339#step/_do_install_and_reboot/4 Reported-by: Adam Williamson Closes: #1803 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 533cf03a..c95e0b61 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -4269,7 +4269,7 @@ import_one_object_direct (OstreeRepo *dest_repo, G_IN_SET (src_repo->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER); if (src_is_bare_or_bare_user && !OSTREE_OBJECT_TYPE_IS_META(objtype)) { - if (src_repo == OSTREE_REPO_MODE_BARE) + if (src_repo->mode == OSTREE_REPO_MODE_BARE) { g_autoptr(GVariant) xattrs = NULL; if (!glnx_fd_get_all_xattrs (src_fd, &xattrs, From c63ee3cef4fc77f995999035bcc57833653a94b0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 16 Jan 2019 08:36:55 -0500 Subject: [PATCH 04/50] =?UTF-8?q?lib/commit:=20Set=20xattr=20on=20correct?= =?UTF-8?q?=20fd=20for=20bare-user=20=E2=86=92=20bare-user=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Another fix to https://github.com/ostreedev/ostree/pull/1771 Closes: #1803 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index c95e0b61..dfdd4853 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -4287,7 +4287,7 @@ import_one_object_direct (OstreeRepo *dest_repo, if (bytes == NULL) return FALSE; - if (TEMP_FAILURE_RETRY (fsetxattr (src_fd, "user.ostreemeta", + if (TEMP_FAILURE_RETRY (fsetxattr (tmp_dest.fd, "user.ostreemeta", (char*)g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), 0)) != 0) return glnx_throw_errno_prefix (error, "fsetxattr"); From 6649032a375238255052a43adb8bc56faac989ca Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 16 Jan 2019 13:45:34 +0000 Subject: [PATCH 05/50] =?UTF-8?q?lib/commit:=20Don't=20set=20user.ostreeme?= =?UTF-8?q?ta=20for=20bare=20=E2=86=92=20bare-user-only=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The point of `bare-user-only` is it doesn't have xattrs; it's a special case in import handling. Closes: #1803 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index dfdd4853..f44446ca 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -4279,8 +4279,18 @@ import_one_object_direct (OstreeRepo *dest_repo, cancellable, error)) return FALSE; } + else if (dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY) + { + /* Nothing; this is the "bareuser-only conversion case", + * we don't need to set any xattrs in the dest repo. + */ + } else { + /* And this case must be bare-user → bare-user */ + g_assert (src_repo->mode == OSTREE_REPO_MODE_BARE_USER); + g_assert (src_repo->mode == dest_repo->mode); + /* bare-user; we just want ostree.usermeta */ g_autoptr(GBytes) bytes = glnx_fgetxattr_bytes (src_fd, "user.ostreemeta", error); From 6e935ee26fc9bf8629100a0f949b550971a25108 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Wed, 6 Feb 2019 14:50:13 -0800 Subject: [PATCH 06/50] lib/repo-pull: Fix docs for n-network-retries option Add "Since: 2018.6" and copy the docs to ostree_repo_pull_from_remotes_async() which also supports it. Closes: #1812 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 4b596da1..d0b7b6ea 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -3504,7 +3504,7 @@ initiate_request (OtPullData *pull_data, * * append-user-agent (s): Additional string to append to the user agent * * n-network-retries (u): Number of times to retry each download on receiving * a transient network error, such as a socket timeout; default is 5, 0 - * means return errors without retrying + * means return errors without retrying. Since: 2018.6 */ gboolean ostree_repo_pull_with_options (OstreeRepo *self, @@ -4950,7 +4950,7 @@ static void find_remotes_cb (GObject *obj, * provided. * * `n-network-retries` (`u`): Number of times to retry each download on * receiving a transient network error, such as a socket timeout; default is - * 5, 0 means return errors without retrying. + * 5, 0 means return errors without retrying. Since: 2018.6 * * @finders must be a non-empty %NULL-terminated array of the #OstreeRepoFinder * instances to use, or %NULL to use the system default set of finders, which @@ -5795,6 +5795,9 @@ copy_option (GVariantDict *master_options, * * `update-frequency` (`u`): Frequency to call the async progress callback in * milliseconds, if any; only values higher than 0 are valid * * `append-user-agent` (`s`): Additional string to append to the user agent + * * `n-network-retries` (`u`): Number of times to retry each download on receiving + * a transient network error, such as a socket timeout; default is 5, 0 + * means return errors without retrying. Since: 2018.6 * * Since: 2018.6 */ From 15ba2007a1d0e009eb0a0536a872adc46651166b Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 12 Sep 2017 12:23:31 -0500 Subject: [PATCH 07/50] repo: Add OstreeRepoRemoteChange replace operation Add the OSTREE_REPO_REMOTE_CHANGE_REPLACE operation to the OstreeRepoRemoteChange enum. This operation will add a remote or replace an existing one. It respects the location of the remote configuration file when replacing and the remotes config dir settings when adding a new remote. Closes: #1166 Approved by: cgwalters --- src/libostree/ostree-repo.c | 85 ++++++++++++++++++++++++++++++++ src/libostree/ostree-repo.h | 4 +- tests/test-remotes-config-dir.js | 56 +++++++++++++++++++-- 3 files changed, 141 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index fc884481..37a6cdf0 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1735,6 +1735,88 @@ ostree_repo_remote_delete (OstreeRepo *self, return impl_repo_remote_delete (self, NULL, FALSE, name, cancellable, error); } + +static gboolean +impl_repo_remote_replace (OstreeRepo *self, + GFile *sysroot, + const char *name, + const char *url, + GVariant *options, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (url != NULL, FALSE); + g_return_val_if_fail (options == NULL || g_variant_is_of_type (options, G_VARIANT_TYPE ("a{sv}")), FALSE); + + if (!ostree_validate_remote_name (name, error)) + return FALSE; + + g_autoptr(GError) local_error = NULL; + g_autoptr(OstreeRemote) remote = _ostree_repo_get_remote (self, name, &local_error); + if (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; + } + g_clear_error (&local_error); + if (!impl_repo_remote_add (self, sysroot, FALSE, name, url, options, + cancellable, error)) + return FALSE; + } + else + { + /* Replace the entire option group */ + if (!g_key_file_remove_group (remote->options, remote->group, error)) + return FALSE; + + if (g_str_has_prefix (url, "metalink=")) + g_key_file_set_string (remote->options, remote->group, "metalink", + url + strlen ("metalink=")); + else + g_key_file_set_string (remote->options, remote->group, "url", url); + + if (options != NULL) + keyfile_set_from_vardict (remote->options, remote->group, options); + + /* Write out updated settings */ + if (remote->file != NULL) + { + gsize length; + g_autofree char *data = g_key_file_to_data (remote->options, &length, + NULL); + + if (!g_file_replace_contents (remote->file, data, length, + NULL, FALSE, 0, NULL, + cancellable, error)) + return FALSE; + } + else + { + g_autoptr(GKeyFile) config = ostree_repo_copy_config (self); + + /* Remove the existing group if it exists */ + if (!g_key_file_remove_group (config, remote->group, &local_error)) + { + if (!g_error_matches (local_error, G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + + ot_keyfile_copy_group (remote->options, config, remote->group); + if (!ostree_repo_write_config (self, config, error)) + return FALSE; + } + } + + return TRUE; +} + /** * ostree_repo_remote_change: * @self: Repo @@ -1776,6 +1858,9 @@ ostree_repo_remote_change (OstreeRepo *self, case OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS: return impl_repo_remote_delete (self, sysroot, TRUE, name, cancellable, error); + case OSTREE_REPO_REMOTE_CHANGE_REPLACE: + return impl_repo_remote_replace (self, sysroot, name, url, options, + cancellable, error); } g_assert_not_reached (); } diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 007cbedd..b92b7083 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -166,12 +166,14 @@ gboolean ostree_repo_remote_delete (OstreeRepo *self, * @OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS: Like above, but do nothing if the remote exists * @OSTREE_REPO_REMOTE_CHANGE_DELETE: Delete a remote * @OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS: Delete a remote, do nothing if the remote does not exist + * @OSTREE_REPO_REMOTE_CHANGE_REPLACE: Add or replace a remote (Since: 2019.1) */ typedef enum { OSTREE_REPO_REMOTE_CHANGE_ADD, OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS, OSTREE_REPO_REMOTE_CHANGE_DELETE, - OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS + OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS, + OSTREE_REPO_REMOTE_CHANGE_REPLACE, } OstreeRepoRemoteChange; _OSTREE_PUBLIC diff --git a/tests/test-remotes-config-dir.js b/tests/test-remotes-config-dir.js index 8cd61844..5588116b 100755 --- a/tests/test-remotes-config-dir.js +++ b/tests/test-remotes-config-dir.js @@ -34,7 +34,7 @@ function assertNotEquals(a, b) { throw new Error("assertion failed " + JSON.stringify(a) + " != " + JSON.stringify(b)); } -print('1..6') +print('1..9') let remotesDir = Gio.File.new_for_path('remotes.d'); remotesDir.make_directory(null); @@ -45,6 +45,10 @@ remoteConfig.set_value('remote "foo"', 'url', 'http://foo') let remoteConfigFile = remotesDir.get_child('foo.conf') remoteConfig.save_to_file(remoteConfigFile.get_path()) +let remoteOptions = GLib.Variant.new('a{sv}', { + 'branches': GLib.Variant.new('as', ['test']), +}); + // Use the full Repo constructor to set remotes-config-dir let repoFile = Gio.File.new_for_path('repo'); let repo = new OSTree.Repo({path: repoFile, @@ -60,7 +64,7 @@ print("ok read-remotes-config-dir"); // Adding a remote should not go in the remotes.d dir unless this is a // system repo or add-remotes-config-dir is set to true -repo.remote_add('bar', 'http://bar', null, null); +repo.remote_add('bar', 'http://bar', remoteOptions, null); remotes = repo.remote_list() assertNotEquals(remotes.indexOf('bar'), -1); assertEquals(remotesDir.get_child('bar.conf').query_exists(null), false); @@ -81,7 +85,7 @@ let repoConfig = repo.copy_config(); repoConfig.set_boolean('core', 'add-remotes-config-dir', true); repo.write_config(repoConfig); repo.reload_config(null); -repo.remote_add('baz', 'http://baz', null, null); +repo.remote_add('baz', 'http://baz', remoteOptions, null); remotes = repo.remote_list() assertNotEquals(remotes.indexOf('baz'), -1); assertEquals(remotesDir.get_child('baz.conf').query_exists(null), true); @@ -114,3 +118,49 @@ try { } print("ok config-remote-in-config-dir-fails"); + +// Replacing a non-existent remote should succeed. This should go in the +// config dir since add-remote-config-dir is set to true above +repo.remote_change(null, OSTree.RepoRemoteChange.REPLACE, + 'nonexistent', 'http://nonexistent', + null, null); +remotes = repo.remote_list(); +assertNotEquals(remotes.indexOf('nonexistent'), -1); +assertEquals(remotesDir.get_child('nonexistent.conf').query_exists(null), true); + +print("ok replace-missing-remote-succeeds"); + +// Test replacing remote options in config dir. This should remove the +// branches setting above +repo.remote_change(null, OSTree.RepoRemoteChange.REPLACE, 'baz', + 'http://baz2', null, null); +remoteConfigFile = remotesDir.get_child('baz.conf'); +remoteConfig = GLib.KeyFile.new(); +remoteConfig.load_from_file(remoteConfigFile.get_path(), + GLib.KeyFileFlags.NONE); +assertEquals(remoteConfig.get_value('remote "baz"', 'url'), 'http://baz2'); +try { + remoteConfig.get_string_list('remote "baz"', 'branches'); + throw new Error('baz remote should not have branches option'); +} catch (e) { + if (!(e.matches(GLib.KeyFileError, GLib.KeyFileError.KEY_NOT_FOUND))) + throw e; +} + +print("ok replace-remote-in-config-dir"); + +// Test replacing remote options in config file. This should remove the +// branches setting above +repo.remote_change(null, OSTree.RepoRemoteChange.REPLACE, 'bar', + 'http://bar2', null, null); +repoConfig = repo.get_config(); +assertEquals(repoConfig.get_value('remote "bar"', 'url'), 'http://bar2'); +try { + repoConfig.get_string_list('remote "bar"', 'branches'); + throw new Error('bar remote should not have branches option'); +} catch (e) { + if (!(e.matches(GLib.KeyFileError, GLib.KeyFileError.KEY_NOT_FOUND))) + throw e; +} + +print("ok replace-remote-in-config-file"); From 8431bb54066ae8ab677ba95ed7c016eb9bc03230 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 12 Sep 2017 15:20:46 -0500 Subject: [PATCH 08/50] man: Document remote add --if-not-exists option Closes: #1166 Approved by: cgwalters --- man/ostree-remote.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/man/ostree-remote.xml b/man/ostree-remote.xml index e908315f..5e218058 100644 --- a/man/ostree-remote.xml +++ b/man/ostree-remote.xml @@ -128,6 +128,14 @@ Boston, MA 02111-1307, USA. + + + + + Do nothing if the provided remote exists. + + + From b33a4e9b1e5df8c4126dedb9f24f66ee0b1d7ad5 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 12 Sep 2017 17:05:08 -0500 Subject: [PATCH 09/50] remote-add: Add --force option to add or replace remote This uses the OSTREE_REPO_REMOTE_CHANGE_REPLACE operation to add a remote or replace an existing one. This is roughly the opposite of --if-not-exists and will raise an error if both options are passed. Closes: #1166 Approved by: cgwalters --- bash/ostree | 1 + man/ostree-remote.xml | 8 ++++++++ src/ostree/ot-remote-builtin-add.c | 21 ++++++++++++++++++--- tests/test-remote-add.sh | 14 +++++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/bash/ostree b/bash/ostree index 52b111ec..5ba3d475 100644 --- a/bash/ostree +++ b/bash/ostree @@ -985,6 +985,7 @@ _ostree_remote_add() { local boolean_options=" $main_boolean_options --if-not-exists + --force --no-gpg-verify " diff --git a/man/ostree-remote.xml b/man/ostree-remote.xml index 5e218058..407f7e3d 100644 --- a/man/ostree-remote.xml +++ b/man/ostree-remote.xml @@ -136,6 +136,14 @@ Boston, MA 02111-1307, USA. + + + + + Replace the provided remote if it exists. + + + diff --git a/src/ostree/ot-remote-builtin-add.c b/src/ostree/ot-remote-builtin-add.c index 8b339dbd..f81f7580 100644 --- a/src/ostree/ot-remote-builtin-add.c +++ b/src/ostree/ot-remote-builtin-add.c @@ -30,6 +30,7 @@ static char **opt_set; static gboolean opt_no_gpg_verify; static gboolean opt_if_not_exists; +static gboolean opt_force; static char *opt_gpg_import; static char *opt_contenturl; static char *opt_collection_id; @@ -45,6 +46,7 @@ static GOptionEntry option_entries[] = { { "set", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_set, "Set config option KEY=VALUE for remote", "KEY=VALUE" }, { "no-gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_no_gpg_verify, "Disable GPG verification", NULL }, { "if-not-exists", 0, 0, G_OPTION_ARG_NONE, &opt_if_not_exists, "Do nothing if the provided remote exists", NULL }, + { "force", 0, 0, G_OPTION_ARG_NONE, &opt_force, "Replace the provided remote if it exists", NULL }, { "gpg-import", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_import, "Import GPG key from FILE", "FILE" }, { "contenturl", 0, 0, G_OPTION_ARG_STRING, &opt_contenturl, "Use URL when fetching content", "URL" }, { "collection-id", 0, 0, G_OPTION_ARG_STRING, &opt_collection_id, @@ -84,6 +86,14 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio goto out; } + if (opt_if_not_exists && opt_force) + { + ot_util_usage_error (context, + "Can only specify one of --if-not-exists and --force", + error); + goto out; + } + remote_name = argv[1]; remote_url = argv[2]; @@ -135,9 +145,14 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio options = g_variant_ref_sink (g_variant_builder_end (optbuilder)); - if (!ostree_repo_remote_change (repo, NULL, - opt_if_not_exists ? OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS : - OSTREE_REPO_REMOTE_CHANGE_ADD, + OstreeRepoRemoteChange changeop; + if (opt_if_not_exists) + changeop = OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS; + else if (opt_force) + changeop = OSTREE_REPO_REMOTE_CHANGE_REPLACE; + else + changeop = OSTREE_REPO_REMOTE_CHANGE_ADD; + if (!ostree_repo_remote_change (repo, NULL, changeop, remote_name, remote_url, options, cancellable, error)) diff --git a/tests/test-remote-add.sh b/tests/test-remote-add.sh index 9aa5c6a2..57fe7eec 100755 --- a/tests/test-remote-add.sh +++ b/tests/test-remote-add.sh @@ -23,7 +23,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -echo '1..14' +echo '1..16' setup_test_repository "bare" $OSTREE remote add origin http://example.com/ostree/gnome @@ -106,3 +106,15 @@ assert_not_file_has_content list.txt "origin" # Can't grep for 'another' because of 'another-noexist' assert_file_has_content list.txt "another-noexist" echo "ok remote list remaining" + +# Both --if-not-exists and --force cannot be used +if $OSTREE remote add --if-not-exists --force yetanother http://yetanother.com/repo 2>/dev/null; then + assert_not_reached "Adding remote with --if-not-exists and --force unexpectedly succeeded" +fi +echo "ok remote add fail --if-not-exists and --force" + +# Overwrite with --force +$OSTREE remote add --force another http://another.example.com/anotherrepo +$OSTREE remote list --show-urls > list.txt +assert_file_has_content list.txt "^another \+http://another.example.com/anotherrepo$" +echo "ok remote add --force" From 27d354da860c268c67e1fc62c4c3a3fb2efa85cc Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Fri, 8 Feb 2019 13:52:52 -0800 Subject: [PATCH 10/50] lib/repo: Fix Since: annotation for REMOTE_CHANGE_REPLACE Closes: #1813 Approved by: jlebon --- src/libostree/ostree-repo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index b92b7083..6e325b8b 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -166,7 +166,7 @@ gboolean ostree_repo_remote_delete (OstreeRepo *self, * @OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS: Like above, but do nothing if the remote exists * @OSTREE_REPO_REMOTE_CHANGE_DELETE: Delete a remote * @OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS: Delete a remote, do nothing if the remote does not exist - * @OSTREE_REPO_REMOTE_CHANGE_REPLACE: Add or replace a remote (Since: 2019.1) + * @OSTREE_REPO_REMOTE_CHANGE_REPLACE: Add or replace a remote (Since: 2019.2) */ typedef enum { OSTREE_REPO_REMOTE_CHANGE_ADD, From f7a0ec9bf7808b1ca67ad386b24d8d58c424eb99 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Tue, 22 Jan 2019 16:50:32 -0800 Subject: [PATCH 11/50] tests: Don't skip collection-based summary test OSTree's P2P support used to be a compile time option but is now always enabled. One of the tests was still checking for the old feature flag, "experimental", which has been renamed to "p2p" and skipping for that reason. Delete the check so the test always runs. Closes: #1804 Approved by: pwithnall --- tests/test-summary-update.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/test-summary-update.sh b/tests/test-summary-update.sh index faa54e38..6fb5a4be 100755 --- a/tests/test-summary-update.sh +++ b/tests/test-summary-update.sh @@ -58,12 +58,7 @@ assert_file_has_content summary "^map: {}$" echo "ok 1 update summary" -# Test again, but with collections enabled in the repository (if supported). -if ! ostree --version | grep -q -e '- experimental'; then - echo "ok 2 # skip No experimental API is compiled in" - exit 0 -fi - +# Test again, but with collections enabled in the repository. cd ${test_tmpdir} rm -rf repo ostree_repo_init repo --collection-id org.example.Collection1 From 1ec4945c2d6b410c6fea460e2121d1f7da80a9f2 Mon Sep 17 00:00:00 2001 From: Jeremy Bicha Date: Sun, 10 Feb 2019 20:54:05 -0500 Subject: [PATCH 12/50] tests: Update for glib 2.59.2 glib 2.59.2 uses a non-breaking space instead of a space to separate the quantity and unit in g_format_size() so update our test to handle both a plain space and a non-breaking space. See https://gitlab.gnome.org/GNOME/glib/issues/1625 Closes: #1818 Approved by: cgwalters --- tests/pull-test.sh | 2 +- tests/pull-test2.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/pull-test.sh b/tests/pull-test.sh index 0b3fa0c9..9d51b151 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -368,7 +368,7 @@ repo_init --no-gpg-verify ${CMD_PREFIX} ostree --repo=repo pull origin main@${prev_rev} ${CMD_PREFIX} ostree --repo=repo pull --dry-run --require-static-deltas origin ${delta_target} >dry-run-pull.txt # Compression can vary, so we support 400-699 -delta_dry_run_regexp='Delta update: 0/1 parts, 0 bytes/[456][0-9][0-9] bytes, 455 bytes total uncompressed' +delta_dry_run_regexp='Delta update: 0/1 parts, 0[  ]bytes/[456][0-9][0-9][  ]bytes, 455[  ]bytes total uncompressed' assert_file_has_content dry-run-pull.txt "${delta_dry_run_regexp}" rev=$(${CMD_PREFIX} ostree --repo=repo rev-parse origin:main) assert_streq "${prev_rev}" "${rev}" diff --git a/tests/pull-test2.sh b/tests/pull-test2.sh index 2b9889c2..1d91e514 100644 --- a/tests/pull-test2.sh +++ b/tests/pull-test2.sh @@ -55,7 +55,7 @@ ${CMD_PREFIX} ostree --repo=ostree-srv/repo static-delta generate ${remote_ref} ${CMD_PREFIX} ostree --repo=ostree-srv/repo summary -u ${CMD_PREFIX} ostree --repo=repo pull origin ${remote_ref}@${prev_rev} ${CMD_PREFIX} ostree --repo=repo pull --dry-run --require-static-deltas origin ${remote_ref} >dry-run-pull.txt -assert_file_has_content dry-run-pull.txt 'Delta update: 0/1 parts, 0 bytes/[45][0-9].[0-9] kB, 1.[678] MB total uncompressed' +assert_file_has_content dry-run-pull.txt 'Delta update: 0/1 parts, 0 bytes/[45][0-9].[0-9][  ]kB, 1.[678][  ]MB total uncompressed' ${CMD_PREFIX} ostree --repo=repo pull --require-static-deltas origin ${remote_ref} final_rev=$(${CMD_PREFIX} ostree --repo=repo rev-parse origin:${remote_ref}) assert_streq "${rev}" "${final_rev}" From 2738bbb6d2e8b3a8eab6828b37e054becb90567d Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Fri, 8 Feb 2019 16:01:54 -0800 Subject: [PATCH 13/50] tests: Remove unused includes in libostreetest.c Since commit a06bd82cd we no longer use OVERLAYFS_SUPER_MAGIC or statfs() so remove the includes for linux/magic.h and sys/vfs.h Closes: #1815 Approved by: cgwalters --- tests/libostreetest.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/libostreetest.c b/tests/libostreetest.c index 1991ffd0..9a2fae09 100644 --- a/tests/libostreetest.c +++ b/tests/libostreetest.c @@ -22,8 +22,6 @@ #include "config.h" #include #include -#include -#include #include "libglnx.h" #include "libostreetest.h" From f5c86c834b31b2bf866dbfbb064d2e74751bcc1c Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 14 Feb 2019 11:08:28 -0800 Subject: [PATCH 14/50] man: Document ostree --version Closes: #1820 Approved by: rfairley --- man/ostree.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/man/ostree.xml b/man/ostree.xml index f865982e..8c08bae6 100644 --- a/man/ostree.xml +++ b/man/ostree.xml @@ -129,6 +129,15 @@ Boston, MA 02111-1307, USA. Produce debug level output. + + + + + + Print version information, including the features enabled + at compile time, and exit. + + From 77f91d6c6be2d264aa14be9d33c0488dc7e141cc Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 14 Feb 2019 01:33:20 -0800 Subject: [PATCH 15/50] lib/repo-refs: Resolve collection-refs in-memory and in parent repos Currently the behavior of ostree_repo_resolve_rev() is that it tries to resolve a ref to a commit by checking the refs/ directories, but also by checking for in-memory ref-checksum pairs which are part of an in-progress transaction and also by checking the parent repo if one exists. Currently ostree_repo_resolve_collection_ref() only checks the refs/ directories, so this commit makes its behavior analagous since it is the analagous API which supports collection-refs. The impetus for this was that currently Flatpak uses ostree_repo_resolve_rev() to load a commit after doing a P2P pull in flatpak_dir_do_resolve_p2p_refs(), but that assumes the ref came from the same remote that originally provided it, which might not be the case if more than one remote has the same collection ID configured. And changing Flatpak to use ostree_repo_resolve_collection_ref() doesn't work without this patch. Closes: #1821 Approved by: pwithnall --- src/libostree/ostree-repo-refs.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index 1267b240..ee11eb53 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -537,7 +537,30 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self, cancellable, error)) return FALSE; - const char *ret_contents = g_hash_table_lookup (refs, ref); + g_autofree char *ret_contents = g_strdup (g_hash_table_lookup (refs, ref)); + + /* Check for refs in the current transaction that haven't been written to + * disk, to match the behavior of ostree_repo_resolve_rev() */ + if (ret_contents == NULL && self->in_transaction) + { + g_mutex_lock (&self->txn_lock); + if (self->txn.collection_refs) + ret_contents = g_strdup (g_hash_table_lookup (self->txn.collection_refs, ref)); + g_mutex_unlock (&self->txn_lock); + } + + /* Check for refs in the parent repo */ + if (ret_contents == NULL && self->parent_repo != NULL) + { + if (!ostree_repo_resolve_collection_ref (self->parent_repo, + ref, + TRUE, + flags, + &ret_contents, + cancellable, + error)) + return FALSE; + } if (ret_contents == NULL && !allow_noent) { @@ -548,7 +571,7 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self, } if (out_rev != NULL) - *out_rev = g_strdup (ret_contents); + *out_rev = g_steal_pointer (&ret_contents); return TRUE; } From eecd989d4661f48c51f49565422ef11d1c231371 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Fri, 28 Sep 2018 15:36:49 -0700 Subject: [PATCH 16/50] ostree/config: Add an "unset" operation Currently there's a way to set a key to the empty string but there's no way to unset it completely (remove the key from the group). This might be helpful for instance if you want to temporarily set "core.lock-timeout-secs" to a specific value for the duration of one operation and then return it to the default after that operation completes. This commit implements an "unset" operation for the config command, adds a unit test, and updates the man page. Closes: #1743 Approved by: cgwalters --- man/ostree-config.xml | 30 +++++++++++++++++++++--- src/ostree/ot-builtin-config.c | 43 +++++++++++++++++++++++++++++++++- tests/test-config.sh | 26 +++++++++++++++++++- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/man/ostree-config.xml b/man/ostree-config.xml index dc180b83..f2b41ec1 100644 --- a/man/ostree-config.xml +++ b/man/ostree-config.xml @@ -62,14 +62,37 @@ Boston, MA 02111-1307, USA. ostree config set --group=GROUPNAME KEYNAME VALUE + + ostree config unset SECTIONNAME.KEYNAME + + + ostree config unset --group=GROUPNAME KEYNAME + Description - - Displays or changes a configuration setting. - + + + ostree config get displays the value of + KEYNAME in the group GROUPNAME + (or SECTIONNAME depending on the + syntax used). + + + ostree config set sets the value of + KEYNAME in the group GROUPNAME + to VALUE. + + + ostree config unset removes the key + KEYNAME from the group GROUPNAME + so that OSTree uses the default value for it. It is not an + error for the specified GROUPNAME or + KEYNAME not to exist. + + @@ -77,5 +100,6 @@ Boston, MA 02111-1307, USA. $ ostree config get core.mode bare $ ostree config set --group='remote "myremote"' url http://example.com/repo + $ ostree config unset core.lock-timeout-secs diff --git a/src/ostree/ot-builtin-config.c b/src/ostree/ot-builtin-config.c index 4368f50c..913ed66d 100644 --- a/src/ostree/ot-builtin-config.c +++ b/src/ostree/ot-builtin-config.c @@ -73,7 +73,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio g_autofree char *key = NULL; GKeyFile *config = NULL; - context = g_option_context_new ("(get KEY|set KEY VALUE)"); + context = g_option_context_new ("(get KEY|set KEY VALUE|unset KEY)"); if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error)) goto out; @@ -155,6 +155,47 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio g_print ("%s\n", value); } + else if (!strcmp (op, "unset")) + { + g_autoptr(GError) local_error = NULL; + if (opt_group) + { + if (argc < 3) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Group name and key must be specified"); + goto out; + } + section = g_strdup(opt_group); + key = g_strdup(argv[2]); + } + else + { + if (argc < 3) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "KEY must be specified"); + goto out; + } + section_key = argv[2]; + if (!split_key_string (section_key, §ion, &key, error)) + goto out; + } + + config = ostree_repo_copy_config (repo); + if (!g_key_file_remove_key (config, section, key, &local_error)) + { + if (!g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND) && + !g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) + { + g_propagate_error (error, g_steal_pointer (&local_error)); + goto out; + } + } + + if (local_error == NULL && !ostree_repo_write_config (repo, config, error)) + goto out; + } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, diff --git a/tests/test-config.sh b/tests/test-config.sh index b1ea3e5e..62f63006 100755 --- a/tests/test-config.sh +++ b/tests/test-config.sh @@ -23,7 +23,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -echo '1..2' +echo '1..3' ostree_repo_init repo ${CMD_PREFIX} ostree remote add --repo=repo --set=xa.title=Flathub --set=xa.title-is-set=true flathub https://dl.flathub.org/repo/ @@ -53,3 +53,27 @@ assert_file_has_content repo/config "Nightly Flathub" assert_file_has_content repo/config "false" assert_file_has_content repo/config "http://example.com/ostree/" echo "ok config set" + +# Check that "ostree config unset" works +${CMD_PREFIX} ostree config --repo=repo set core.lock-timeout-secs 60 +assert_file_has_content repo/config "lock-timeout-secs=60" +${CMD_PREFIX} ostree config --repo=repo unset core.lock-timeout-secs +assert_not_file_has_content repo/config "lock-timeout-secs=" + +# Check that "ostree config get" errors out on the key +if ${CMD_PREFIX} ostree config --repo=repo get core.lock-timeout-secs 2>err.txt; then + assert_not_reached "ostree config get should not work after unsetting a key" +fi +assert_file_has_content err.txt "error: Key file does not have key “lock-timeout-secs” in group “core”" + +# Check that it's idempotent +${CMD_PREFIX} ostree config --repo=repo unset core.lock-timeout-secs +assert_not_file_has_content repo/config "lock-timeout-secs=" + +# Check that the group doesn't need to exist +${CMD_PREFIX} ostree config --repo=repo unset --group='remote "aoeuhtns"' 'xa.title' + +# Check that the key doesn't need to exist +${CMD_PREFIX} ostree config --repo=repo set --group='remote "aoeuhtns"' 'xa.title-is-set' 'false' +${CMD_PREFIX} ostree config --repo=repo unset --group='remote "aoeuhtns"' 'xa.title' +echo "ok config unset" From fe6b19751654b1cb11dec9d4a3c22eba56454544 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Fri, 28 Sep 2018 15:45:43 -0700 Subject: [PATCH 17/50] ostree/config: Use g_autoptr instead of goto It seems cleaner to make the GKeyFile a g_autoptr variable and just return rather than using the "goto out;" idiom. Closes: #1743 Approved by: cgwalters --- src/ostree/ot-builtin-config.c | 41 +++++++++++++++------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/ostree/ot-builtin-config.c b/src/ostree/ot-builtin-config.c index 913ed66d..8e00af08 100644 --- a/src/ostree/ot-builtin-config.c +++ b/src/ostree/ot-builtin-config.c @@ -65,23 +65,22 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio { g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeRepo) repo = NULL; - gboolean ret = FALSE; const char *op; const char *section_key; const char *value; g_autofree char *section = NULL; g_autofree char *key = NULL; - GKeyFile *config = NULL; + g_autoptr(GKeyFile) config = NULL; context = g_option_context_new ("(get KEY|set KEY VALUE|unset KEY)"); if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error)) - goto out; + return FALSE; if (argc < 2) { ot_util_usage_error (context, "OPERATION must be specified", error); - goto out; + return FALSE; } op = argv[1]; @@ -94,7 +93,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "GROUP name, KEY and VALUE must be specified"); - goto out; + return FALSE; } section = g_strdup(opt_group); key = g_strdup(argv[2]); @@ -106,19 +105,19 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "KEY and VALUE must be specified"); - goto out; + return FALSE; } section_key = argv[2]; value = argv[3]; if(!split_key_string (section_key, §ion, &key, error)) - goto out; + return FALSE; } config = ostree_repo_copy_config (repo); g_key_file_set_string (config, section, key, value); if (!ostree_repo_write_config (repo, config, error)) - goto out; + return FALSE; } else if (!strcmp (op, "get")) { @@ -130,7 +129,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Group name and key must be specified"); - goto out; + return FALSE; } section = g_strdup(opt_group); key = g_strdup(argv[2]); @@ -141,17 +140,17 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "KEY must be specified"); - goto out; + return FALSE; } section_key = argv[2]; if (!split_key_string (section_key, §ion, &key, error)) - goto out; + return FALSE; } readonly_config = ostree_repo_get_config (repo); value = g_key_file_get_string (readonly_config, section, key, error); if (value == NULL) - goto out; + return FALSE; g_print ("%s\n", value); } @@ -164,7 +163,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Group name and key must be specified"); - goto out; + return FALSE; } section = g_strdup(opt_group); key = g_strdup(argv[2]); @@ -175,11 +174,11 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "KEY must be specified"); - goto out; + return FALSE; } section_key = argv[2]; if (!split_key_string (section_key, §ion, &key, error)) - goto out; + return FALSE; } config = ostree_repo_copy_config (repo); @@ -189,23 +188,19 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio !g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { g_propagate_error (error, g_steal_pointer (&local_error)); - goto out; + return FALSE; } } if (local_error == NULL && !ostree_repo_write_config (repo, config, error)) - goto out; + return FALSE; } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown operation %s", op); - goto out; + return FALSE; } - ret = TRUE; - out: - if (config) - g_key_file_free (config); - return ret; + return TRUE; } From 656853a98aac0e96167602cbfa2f835890679304 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 28 Feb 2019 15:15:51 -0800 Subject: [PATCH 18/50] man/ostree-config: Consistently use GROUPNAME placeholder It doesn't make much sense to use SECTIONNAME in some places and GROUPNAME in others when they mean the same thing. Closes: #1743 Approved by: cgwalters --- man/ostree-config.xml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/man/ostree-config.xml b/man/ostree-config.xml index f2b41ec1..e5391bbf 100644 --- a/man/ostree-config.xml +++ b/man/ostree-config.xml @@ -51,19 +51,19 @@ Boston, MA 02111-1307, USA. - ostree config get SECTIONNAME.KEYNAME + ostree config get GROUPNAME.KEYNAME ostree config get --group=GROUPNAME KEYNAME - ostree config set SECTIONNAME.KEYNAME VALUE + ostree config set GROUPNAME.KEYNAME VALUE ostree config set --group=GROUPNAME KEYNAME VALUE - ostree config unset SECTIONNAME.KEYNAME + ostree config unset GROUPNAME.KEYNAME ostree config unset --group=GROUPNAME KEYNAME @@ -77,8 +77,6 @@ Boston, MA 02111-1307, USA. ostree config get displays the value of KEYNAME in the group GROUPNAME - (or SECTIONNAME depending on the - syntax used). ostree config set sets the value of From cfc6046689f828cff4f914fdddb1350f7b576f42 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 28 Feb 2019 16:19:41 -0800 Subject: [PATCH 19/50] ostree/config: Check for too many args Currently it's not an error to provide too many arguments to an ostree config command. Change it so we print usage information in that case, and update the unit tests. Closes: #1743 Approved by: cgwalters --- src/ostree/ot-builtin-config.c | 12 ++++++++++++ tests/test-config.sh | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/ostree/ot-builtin-config.c b/src/ostree/ot-builtin-config.c index 8e00af08..811a8381 100644 --- a/src/ostree/ot-builtin-config.c +++ b/src/ostree/ot-builtin-config.c @@ -71,6 +71,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio g_autofree char *section = NULL; g_autofree char *key = NULL; g_autoptr(GKeyFile) config = NULL; + int correct_argc; context = g_option_context_new ("(get KEY|set KEY VALUE|unset KEY)"); @@ -85,6 +86,17 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio op = argv[1]; + if (!strcmp (op, "set")) + correct_argc = 4; + else + correct_argc = 3; + + if (argc > correct_argc) + { + ot_util_usage_error (context, "Too many arguments given", error); + return FALSE; + } + if (!strcmp (op, "set")) { if (opt_group) diff --git a/tests/test-config.sh b/tests/test-config.sh index 62f63006..b98f8d47 100755 --- a/tests/test-config.sh +++ b/tests/test-config.sh @@ -41,6 +41,12 @@ assert_file_has_content list.txt "1" assert_file_has_content list.txt "Flathub" assert_file_has_content list.txt "true" assert_file_has_content list.txt "http://example.com/ostree/repo/" + +# Check that it errors out if too many arguments are given +if ${CMD_PREFIX} ostree config --repo=repo get --group=core lock-timeout-secs extra 2>err.txt; then + assert_not_reached "ostree config get should error out if too many arguments are given" +fi +assert_file_has_content err.txt "error: Too many arguments given" echo "ok config get" ${CMD_PREFIX} ostree config --repo=repo set core.mode bare-user-only @@ -52,6 +58,12 @@ assert_file_has_content repo/config "bare-user-only" assert_file_has_content repo/config "Nightly Flathub" assert_file_has_content repo/config "false" assert_file_has_content repo/config "http://example.com/ostree/" + +# Check that it errors out if too many arguments are given +if ${CMD_PREFIX} ostree config --repo=repo set --group=core lock-timeout-secs 120 extra 2>err.txt; then + assert_not_reached "ostree config set should error out if too many arguments are given" +fi +assert_file_has_content err.txt "error: Too many arguments given" echo "ok config set" # Check that "ostree config unset" works @@ -76,4 +88,10 @@ ${CMD_PREFIX} ostree config --repo=repo unset --group='remote "aoeuhtns"' 'xa.ti # Check that the key doesn't need to exist ${CMD_PREFIX} ostree config --repo=repo set --group='remote "aoeuhtns"' 'xa.title-is-set' 'false' ${CMD_PREFIX} ostree config --repo=repo unset --group='remote "aoeuhtns"' 'xa.title' + +# Check that it errors out if too many arguments are given +if ${CMD_PREFIX} ostree config --repo=repo unset core.lock-timeout-secs extra 2>err.txt; then + assert_not_reached "ostree config unset should error out if too many arguments are given" +fi +assert_file_has_content err.txt "error: Too many arguments given" echo "ok config unset" From bb141d38daf0114f69362a160c2965d3e5f69474 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 24 Jan 2019 11:36:40 +0100 Subject: [PATCH 20/50] ci/rpmostree: Fix use of `fatal` We're not using libtest, just inline it. Closes: #1806 Approved by: jlebon --- ci/rpmostree.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/rpmostree.sh b/ci/rpmostree.sh index 421aca38..85425c3d 100755 --- a/ci/rpmostree.sh +++ b/ci/rpmostree.sh @@ -45,7 +45,7 @@ make -j 8 check # Basic sanity test of rpm-ostree+new ostree by restarting rpm-ostreed if ! make vmsync; then ssh -o User=root vmcheck 'journalctl --no-pager | tail -1000' - fatal "vmsync failed" + echo "vmsync failed"; exit 1 fi # Now run tests; just a subset ⊂ for now to avoid CI overload make vmcheck TESTS="layering-basic-1 layering-basic-2" From 6e1588c022dacbd9298750246b32b8379c5d5a42 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 24 Jan 2019 11:37:46 +0100 Subject: [PATCH 21/50] ci/rpmostree: Bump to 2019.1 Should fix the issue that CI broke due to libsolv not being sync'd. Closes: #1806 Approved by: jlebon --- ci/rpmostree.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/rpmostree.sh b/ci/rpmostree.sh index 85425c3d..9a162972 100755 --- a/ci/rpmostree.sh +++ b/ci/rpmostree.sh @@ -6,7 +6,7 @@ set -xeuo pipefail # Frozen to a tag for now to help predictability; it's # also useful to test building *older* versions since # that must work. -RPMOSTREE_TAG=v2018.8 +RPMOSTREE_TAG=v2019.1 dn=$(dirname $0) . ${dn}/libpaprci/libbuild.sh From b0af96c80a56160c881395a576543917fabeae4b Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Fri, 8 Feb 2019 17:28:56 -0500 Subject: [PATCH 22/50] ostree-grub-generator: Comment wording fix Closes: #1814 Approved by: jlebon --- src/boot/grub2/ostree-grub-generator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/grub2/ostree-grub-generator b/src/boot/grub2/ostree-grub-generator index 10645c74..d1436b65 100644 --- a/src/boot/grub2/ostree-grub-generator +++ b/src/boot/grub2/ostree-grub-generator @@ -65,7 +65,7 @@ read_config() populate_menu() { - # Default to /boot if OSTREE_BOOT_PARTITION is not set and /boot is on the same device than ostree/repo + # Default to /boot if OSTREE_BOOT_PARTITION is not set and /boot is on the same device as /ostree/repo if [ -z ${OSTREE_BOOT_PARTITION+x} ] && [ -d /boot/ostree ] && [ -d /ostree/repo ] && [ $(stat -c '%d' /boot/ostree) -eq $(stat -c '%d' /ostree/repo) ]; then boot_prefix="/boot" else From 52987b532ca3fb02030f3710b9ae7eadcd4e69a3 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Fri, 1 Mar 2019 15:24:07 -0500 Subject: [PATCH 23/50] tests/test-config: Remove extra space Closes: #1814 Approved by: jlebon --- tests/test-config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-config.sh b/tests/test-config.sh index b98f8d47..3499de7a 100755 --- a/tests/test-config.sh +++ b/tests/test-config.sh @@ -34,7 +34,7 @@ ${CMD_PREFIX} ostree config --repo=repo get --group=core repo_version >> list.tx ${CMD_PREFIX} ostree config --repo=repo get --group='remote "flathub"' 'xa.title' >> list.txt ${CMD_PREFIX} ostree config --repo=repo get --group='remote "flathub"' 'xa.title-is-set' >> list.txt ${CMD_PREFIX} ostree config --repo=repo get --group='remote "org.mozilla.FirefoxRepo"' url >> list.txt -${CMD_PREFIX} cat list.txt +${CMD_PREFIX} cat list.txt assert_file_has_content list.txt "bare" assert_file_has_content list.txt "1" From 91892e3c3f31d104796584c6975f4a198faf750f Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Thu, 14 Feb 2019 16:14:03 -0500 Subject: [PATCH 24/50] libotutil: Rename to ot_keyfile_get_string_list_with_separator_choice() Rename ot_keyfile_get_string_as_list() to ot_keyfile_get_string_list_with_separator_choice() which expresses more clearly why the function is needed. Also shorten the function comment. Closes: #1814 Approved by: jlebon --- src/libostree/ostree-repo.c | 8 ++++++-- src/libotutil/ot-keyfile-utils.c | 23 +++++++++++------------ src/libotutil/ot-keyfile-utils.h | 12 ++++++------ 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 37a6cdf0..a71f3bda 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -5186,8 +5186,12 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self, g_auto(GStrv) gpgkeypath_list = NULL; - if (!ot_keyfile_get_string_as_list (remote->options, remote->group, "gpgkeypath", - ";,", &gpgkeypath_list, error)) + if (!ot_keyfile_get_string_list_with_separator_choice (remote->options, + remote->group, + "gpgkeypath", + ";,", + &gpgkeypath_list, + error)) return NULL; if (gpgkeypath_list) diff --git a/src/libotutil/ot-keyfile-utils.c b/src/libotutil/ot-keyfile-utils.c index a0ab75cc..2af48a6e 100644 --- a/src/libotutil/ot-keyfile-utils.c +++ b/src/libotutil/ot-keyfile-utils.c @@ -101,20 +101,19 @@ ot_keyfile_get_value_with_default (GKeyFile *keyfile, return ret; } -/* Read the value of key as a string. If the value string contains - * one of the separators and none of the others, read the - * string as a NULL-terminated array out_value. If the value string contains - * none of the separators, read the string as a single entry into a - * NULL-terminated array out_value. If the value string contains multiple of - * the separators, an error is given. +/* Read the value of key as a string. If the value string contains + * zero or one of the separators and none of the others, read the + * string as a NULL-terminated array out_value. If the value string + * contains multiple of the separators, give an error. + * * Returns TRUE on success, FALSE on error. */ gboolean -ot_keyfile_get_string_as_list (GKeyFile *keyfile, - const char *section, - const char *key, - const char *separators, - char ***out_value, - GError **error) +ot_keyfile_get_string_list_with_separator_choice (GKeyFile *keyfile, + const char *section, + const char *key, + const char *separators, + char ***out_value, + GError **error) { guint sep_count = 0; gchar sep = '\0'; diff --git a/src/libotutil/ot-keyfile-utils.h b/src/libotutil/ot-keyfile-utils.h index 2dcb899c..1a03cc26 100644 --- a/src/libotutil/ot-keyfile-utils.h +++ b/src/libotutil/ot-keyfile-utils.h @@ -45,12 +45,12 @@ ot_keyfile_get_value_with_default (GKeyFile *keyfile, GError **error); gboolean -ot_keyfile_get_string_as_list (GKeyFile *keyfile, - const char *section, - const char *key, - const char *separators, - char ***out_value_list, - GError **error); +ot_keyfile_get_string_list_with_separator_choice (GKeyFile *keyfile, + const char *section, + const char *key, + const char *separators, + char ***out_value_list, + GError **error); gboolean ot_keyfile_get_string_list_with_default (GKeyFile *keyfile, From 99cf13b22519e88d6cce22379d67b50bf6a2aa6b Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 20 Feb 2019 00:56:54 -0500 Subject: [PATCH 25/50] libotutil: Add ot_keyfile_get_value_with_default_group_optional() Add ot_keyfile_get_value_with_default_group_optional() which allows getting values from keys where the group is optional in the config file. This is preparatory to add the sysroot.bootloader repo config key, where the sysroot group is optional. Closes: #1814 Approved by: jlebon --- src/libotutil/ot-keyfile-utils.c | 36 +++++++++++++++ src/libotutil/ot-keyfile-utils.h | 8 ++++ tests/test-keyfile-utils.c | 76 +++++++++++++++++++++++++++++--- 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/src/libotutil/ot-keyfile-utils.c b/src/libotutil/ot-keyfile-utils.c index 2af48a6e..9d5903ce 100644 --- a/src/libotutil/ot-keyfile-utils.c +++ b/src/libotutil/ot-keyfile-utils.c @@ -101,6 +101,42 @@ ot_keyfile_get_value_with_default (GKeyFile *keyfile, return ret; } +gboolean +ot_keyfile_get_value_with_default_group_optional (GKeyFile *keyfile, + const char *section, + const char *value, + const char *default_value, + char **out_value, + GError **error) +{ + gboolean ret = FALSE; + GError *local_error = NULL; + g_autofree char *ret_value = NULL; + + g_return_val_if_fail (keyfile != NULL, ret); + g_return_val_if_fail (section != NULL, ret); + g_return_val_if_fail (value != NULL, ret); + + if (!ot_keyfile_get_value_with_default (keyfile, section, value, default_value, &ret_value, &local_error)) + { + if (g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) + { + g_clear_error (&local_error); + ret_value = g_strdup (default_value); + } + else + { + g_propagate_error (error, local_error); + goto out; + } + } + + ret = TRUE; + ot_transfer_out_value(out_value, &ret_value); + out: + return ret; +} + /* Read the value of key as a string. If the value string contains * zero or one of the separators and none of the others, read the * string as a NULL-terminated array out_value. If the value string diff --git a/src/libotutil/ot-keyfile-utils.h b/src/libotutil/ot-keyfile-utils.h index 1a03cc26..b16571df 100644 --- a/src/libotutil/ot-keyfile-utils.h +++ b/src/libotutil/ot-keyfile-utils.h @@ -44,6 +44,14 @@ ot_keyfile_get_value_with_default (GKeyFile *keyfile, char **out_value, GError **error); +gboolean +ot_keyfile_get_value_with_default_group_optional (GKeyFile *keyfile, + const char *section, + const char *value, + const char *default_value, + char **out_value, + GError **error); + gboolean ot_keyfile_get_string_list_with_separator_choice (GKeyFile *keyfile, const char *section, diff --git a/tests/test-keyfile-utils.c b/tests/test-keyfile-utils.c index 8acd0a1c..258e7dd8 100644 --- a/tests/test-keyfile-utils.c +++ b/tests/test-keyfile-utils.c @@ -79,7 +79,6 @@ test_get_value_with_default (void) /* Avoid that g_return_val_if_fail causes the test to fail. */ always_fatal_mask = g_log_set_always_fatal (0); - g_assert_false (ot_keyfile_get_value_with_default (g_keyfile, NULL, "value_foo", @@ -124,11 +123,75 @@ test_get_value_with_default (void) g_clear_pointer (&out, g_free); g_assert_false (ot_keyfile_get_value_with_default (g_keyfile, - "a_fake_section", - "a_value_true", - "no value", - &out, - &error)); + "a_fake_section", + "a_value_true", + "no value", + &out, + &error)); + g_clear_error (&error); + g_clear_pointer (&out, g_free); +} + +static void +test_get_value_with_default_group_optional (void) +{ + g_autoptr(GError) error = NULL; + g_autofree char *out = NULL; + GLogLevelFlags always_fatal_mask; + const char *section = "section"; + +/* Avoid that g_return_val_if_fail causes the test to fail. */ + always_fatal_mask = g_log_set_always_fatal (0); + + g_assert_false (ot_keyfile_get_value_with_default_group_optional (g_keyfile, + NULL, + "value_foo", + "none", + &out, + &error)); + g_clear_pointer (&out, g_free); + g_assert_false (ot_keyfile_get_value_with_default_group_optional (g_keyfile, + section, + NULL, + "none", + &out, + &error)); + g_clear_pointer (&out, g_free); + g_assert_false (ot_keyfile_get_value_with_default_group_optional (g_keyfile, + section, + NULL, + "something", + &out, + &error)); + g_clear_pointer (&out, g_free); + + /* Restore the old mask. */ + g_log_set_always_fatal (always_fatal_mask); + + g_assert (ot_keyfile_get_value_with_default_group_optional (g_keyfile, + section, + "value_foo", + "none", + &out, + &error)); + g_assert_cmpstr (out, ==, "foo"); + g_clear_pointer (&out, g_free); + + g_assert (ot_keyfile_get_value_with_default_group_optional (g_keyfile, + section, + "a_not_existing_value", + "correct", + &out, + &error)); + g_assert_cmpstr (out, ==, "correct"); + g_clear_pointer (&out, g_free); + + g_assert (ot_keyfile_get_value_with_default_group_optional (g_keyfile, + "an_optional_section", + "a_value_true", + "no value", + &out, + &error)); g_clear_error (&error); g_clear_pointer (&out, g_free); } @@ -191,6 +254,7 @@ int main (int argc, char **argv) g_test_add_func ("/keyfile-utils/get-boolean-with-default", test_get_boolean_with_default); g_test_add_func ("/keyfile-utils/get-value-with-default", test_get_value_with_default); + g_test_add_func ("/keyfile-utils/get-value-with-default-group-optional", test_get_value_with_default_group_optional); g_test_add_func ("/keyfile-utils/copy-group", test_copy_group); ret = g_test_run(); From 21ebc7d21edd00c3fe0ce80ea68ba3f8f5e41ae3 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Thu, 14 Feb 2019 16:18:01 -0500 Subject: [PATCH 26/50] Add sysroot.bootloader repo config key The sysroot.bootloader key configures the bootloader that OSTree uses when deploying a sysroot. Having this key allows specifying behavior not to use the default bootloader backend code, which is preferable when creating a first deployment from the sysroot (#1774). As of now, the key can take the values "auto" or "none". If the key is not given, the value defaults to "auto". "auto" causes _ostree_sysroot_query_bootloader() to be used when writing a new deployment, which is the original behavior that dynamically detects which bootloader to use. "none" avoids querying the bootloader dynamically. The BLS config fragments are still written to sysroot/boot/loader/entries for use by higher-level software. More values can be supported in future to specify a single bootloader, different behavior for the bootloader code, or a list of bootloaders to try. Resolves: #1774 Closes: #1814 Approved by: jlebon --- Makefile-tests.am | 1 + man/ostree.repo-config.xml | 68 ++++++++++++++++++++------- src/libostree/ostree-repo-private.h | 1 + src/libostree/ostree-repo.c | 46 ++++++++++++++++++ src/libostree/ostree-repo.h | 3 ++ src/libostree/ostree-sysroot-deploy.c | 20 +++++++- tests/libtest.sh | 8 ++++ tests/test-admin-deploy-none.sh | 52 ++++++++++++++++++++ 8 files changed, 181 insertions(+), 18 deletions(-) create mode 100755 tests/test-admin-deploy-none.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index 417a304a..2c0916f6 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -102,6 +102,7 @@ _installed_or_uninstalled_test_scripts = \ tests/test-admin-deploy-etcmerge-cornercases.sh \ tests/test-admin-deploy-uboot.sh \ tests/test-admin-deploy-grub2.sh \ + tests/test-admin-deploy-none.sh \ tests/test-admin-deploy-bootid-gc.sh \ tests/test-admin-instutil-set-kargs.sh \ tests/test-admin-upgrade-not-backwards.sh \ diff --git a/man/ostree.repo-config.xml b/man/ostree.repo-config.xml index 618b524b..90ac9083 100644 --- a/man/ostree.repo-config.xml +++ b/man/ostree.repo-config.xml @@ -109,22 +109,22 @@ Boston, MA 02111-1307, USA. ensure files are on stable storage when performing operations such as commits, pulls, and checkouts. Defaults to true. - - If you disable fsync, OSTree will no longer be robust - against kernel crashes or power loss. - - - You might choose to disable this for local development - repositories, under the assumption they can be recreated from - source. Similarly, you could disable for a mirror where you could - re-pull. - - - For the system repository, you might choose to disable fsync - if you have uninterruptable power supplies and a well tested - kernel. - - + + If you disable fsync, OSTree will no longer be robust + against kernel crashes or power loss. + + + You might choose to disable this for local development + repositories, under the assumption they can be recreated from + source. Similarly, you could disable for a mirror where you could + re-pull. + + + For the system repository, you might choose to disable fsync + if you have uninterruptable power supplies and a well tested + kernel. + + @@ -333,6 +333,42 @@ Boston, MA 02111-1307, USA. + + [sysroot] Section Options + + + Options for the sysroot, which contains the OSTree repository, + deployments, and stateroots. The following entries are defined: + + + + + + bootloader + Configure the bootloader that OSTree uses when + deploying the sysroot. This may take the values + bootloader=none or bootloader=auto. + Default is auto. + + + If none, then OSTree will generate only BLS (Boot + Loader Specification) fragments in sysroot/boot/loader/entries/ + for the deployment. + + + If auto, then in addition to generating BLS + fragments, OSTree will dynamically check for the existence of grub2, + uboot, and syslinux bootloaders. If one of the bootloaders is found, + then OSTree will generate a config for the bootloader found. For + example, grub2-mkconfig is run for the grub2 case. + + + + + + + + /etc/ostree/remotes.d diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 40be7263..6bc74c2d 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -169,6 +169,7 @@ struct OstreeRepo { guint64 payload_link_threshold; gint fs_support_reflink; /* The underlying filesystem has support for ioctl (FICLONE..) */ gchar **repo_finders; + gchar *bootloader; /* Configure which bootloader to use. */ OstreeRepo *parent_repo; }; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index a71f3bda..00336503 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3113,6 +3113,32 @@ reload_remote_config (OstreeRepo *self, return TRUE; } +static gboolean +reload_sysroot_config (OstreeRepo *self, + GCancellable *cancellable, + GError **error) +{ + { g_autofree char *bootloader = NULL; + + if (!ot_keyfile_get_value_with_default_group_optional (self->config, "sysroot", + "bootloader", "auto", + &bootloader, error)) + return FALSE; + + /* TODO: possibly later add support for specifying a generic bootloader + * binary "x" in /usr/lib/ostree/bootloaders/x). See: + * https://github.com/ostreedev/ostree/issues/1719 + * https://github.com/ostreedev/ostree/issues/1801 + */ + if (!(g_str_equal (bootloader, "auto") || g_str_equal (bootloader, "none"))) + return glnx_throw (error, "Invalid bootloader configuration: '%s'", bootloader); + + self->bootloader = g_steal_pointer (&bootloader); + } + + return TRUE; +} + /** * ostree_repo_reload_config: * @self: repo @@ -3131,6 +3157,8 @@ ostree_repo_reload_config (OstreeRepo *self, return FALSE; if (!reload_remote_config (self, cancellable, error)) return FALSE; + if (!reload_sysroot_config (self, cancellable, error)) + return FALSE; return TRUE; } @@ -6064,3 +6092,21 @@ ostree_repo_get_default_repo_finders (OstreeRepo *self) return (const gchar * const *)self->repo_finders; } + +/** + * ostree_repo_get_bootloader: + * @self: an #OstreeRepo + * + * Get the bootloader configured. See the documentation for the + * "sysroot.bootloader" config key. + * + * Returns: bootloader configuration for the sysroot + * Since: 2019.2 + */ +const gchar * +ostree_repo_get_bootloader (OstreeRepo *self) +{ + g_return_val_if_fail (OSTREE_IS_REPO (self), NULL); + + return self->bootloader; +} diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 6e325b8b..7eb983cf 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -115,6 +115,9 @@ gboolean ostree_repo_set_collection_id (OstreeRepo *self, _OSTREE_PUBLIC const gchar * const * ostree_repo_get_default_repo_finders (OstreeRepo *self); +_OSTREE_PUBLIC +const gchar * ostree_repo_get_bootloader (OstreeRepo *self); + _OSTREE_PUBLIC GFile * ostree_repo_get_path (OstreeRepo *self); diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index b16f65b3..ec9d1592 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2310,6 +2310,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, gboolean bootloader_is_atomic = FALSE; SyncStats syncstats = { 0, }; g_autoptr(OstreeBootloader) bootloader = NULL; + const char *bootloader_config = NULL; if (!requires_new_bootversion) { if (!create_new_bootlinks (self, self->bootversion, @@ -2342,8 +2343,22 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, return glnx_throw_errno_prefix (error, "Remounting /boot read-write"); } - if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error)) - return FALSE; + OstreeRepo *repo = ostree_sysroot_repo (self); + + bootloader_config = ostree_repo_get_bootloader (repo); + + g_debug ("Using bootloader configuration: %s", bootloader_config); + + if (g_str_equal (bootloader_config, "auto")) + { + if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error)) + return FALSE; + } + else if (g_str_equal (bootloader_config, "none")) + { + /* No bootloader specified; do not query bootloaders to run. */ + } + bootloader_is_atomic = bootloader != NULL && _ostree_bootloader_is_atomic (bootloader); /* Note equivalent of try/finally here */ @@ -2375,6 +2390,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_COMPLETE_ID), "MESSAGE=%s", msg, "OSTREE_BOOTLOADER=%s", bootloader ? _ostree_bootloader_get_name (bootloader) : "none", + "OSTREE_BOOTLOADER_CONFIG=%s", bootloader_config, "OSTREE_BOOTLOADER_ATOMIC=%s", bootloader_is_atomic ? "yes" : "no", "OSTREE_DID_BOOTSWAP=%s", requires_new_bootversion ? "yes" : "no", "OSTREE_N_DEPLOYMENTS=%u", new_deployments->len, diff --git a/tests/libtest.sh b/tests/libtest.sh index f09f4a2c..a737a9bb 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -355,6 +355,11 @@ setup_os_boot_grub2() { esac } +setup_os_boot_configured_bootloader() { + bootloader_keyval=$1 + ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set ${bootloader_keyval} +} + setup_os_repository () { mode=$1 shift @@ -448,6 +453,9 @@ EOF *grub2*) setup_os_boot_grub2 "${bootmode}" ;; + sysroot\.bootloader*) + setup_os_boot_configured_bootloader "${bootmode}" + ;; esac cd ${test_tmpdir} diff --git a/tests/test-admin-deploy-none.sh b/tests/test-admin-deploy-none.sh new file mode 100755 index 00000000..9094036a --- /dev/null +++ b/tests/test-admin-deploy-none.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# +# Copyright (C) 2019 Robert Fairley +# +# SPDX-License-Identifier: LGPL-2.0+ +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +# Exports OSTREE_SYSROOT so --sysroot not needed. +setup_os_repository "archive" "sysroot.bootloader none" + +extra_admin_tests=1 + +. $(dirname $0)/admin-test.sh + +# Test that the bootloader configuration "none" generates BLS config snippets. +cd ${test_tmpdir} +rm httpd osdata testos-repo sysroot -rf +setup_os_repository "archive" "sysroot.bootloader none" +${CMD_PREFIX} ostree pull-local --repo=sysroot/ostree/repo --remote testos testos-repo testos/buildmaster/x86_64-runtime +# Test grub2 does not get detected with bootloader configuration "none" +# (see https://github.com/ostreedev/ostree/issues/1774) +mkdir -p sysroot/boot/grub2 && touch sysroot/boot/grub2/grub.cfg +${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os testos testos/buildmaster/x86_64-runtime > out.txt +assert_file_has_content out.txt "Bootloader updated.*" +assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO' +assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel' +assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0.img 'an initramfs' +echo "ok generate bls config on first deployment" + +# TODO: add tests to try setting with an unsupported bootloader config, +# once https://github.com/ostreedev/ostree/issues/1827 is solved. +# The tests should check that the following commands fail: +# ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set sysroot.bootloader unsupported_bootloader +# ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set sysroot.bootloader "" From 978cffed70640cca66cb1623dea68b179288b453 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 1 Mar 2019 09:16:55 -0500 Subject: [PATCH 27/50] lib/deploy: Don't include version twice in bootmenu title In Silverblue right now, the boot menu title looks like this: Fedora 29.20190301.0 (Workstation Edition) 29.20190301.0 (ostree) This is because RPM-OSTree's `mutate-os-release` feature is enabled, which injects the OSTree version string directly into `VERSION` and `PRETTY_NAME`. So appending the version string again is a bit redundant. Let's just do a simple substring check here before adding the version to the title. Closes: #1829 Approved by: cgwalters --- src/libostree/ostree-sysroot-deploy.c | 2 +- tests/admin-test.sh | 12 +++++++++++- tests/libtest.sh | 3 +-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index ec9d1592..d37861b7 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1739,7 +1739,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, * (specifically, it looks for the substring "(ostree"), so further * changes to the title format may require updating that backend. */ g_autoptr(GString) title_key = g_string_new (val); - if (deployment_version && *deployment_version) + if (deployment_version && *deployment_version && !strstr (val, deployment_version)) { g_string_append_c (title_key, ' '); g_string_append (title_key, deployment_version); diff --git a/tests/admin-test.sh b/tests/admin-test.sh index 4f0b9e93..79a23f59 100644 --- a/tests/admin-test.sh +++ b/tests/admin-test.sh @@ -21,7 +21,7 @@ set -euo pipefail -echo "1..$((25 + ${extra_admin_tests:-0}))" +echo "1..$((26 + ${extra_admin_tests:-0}))" function validate_bootloader() { cd ${test_tmpdir}; @@ -280,6 +280,16 @@ validate_bootloader echo "ok upgrade with multiple kernel args" +os_repository_new_commit +${CMD_PREFIX} ostree admin upgrade --os=testos +assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 ${version} (ostree:testos)$" +os_repository_new_commit 0 0 testos/buildmaster/x86_64-runtime 42 +${CMD_PREFIX} ostree admin upgrade --os=testos +assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 (ostree:testos)$" + +echo "ok no duplicate version strings in title" + + # Test upgrade with and without --override-commit # See https://github.com/GNOME/ostree/pull/147 ${CMD_PREFIX} ostree pull --repo=sysroot/ostree/repo --commit-metadata-only --depth=-1 testos:testos/buildmaster/x86_64-runtime diff --git a/tests/libtest.sh b/tests/libtest.sh index a737a9bb..e0022512 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -473,6 +473,7 @@ os_repository_new_commit () boot_checksum_iteration=${1:-0} content_iteration=${2:-0} branch=${3:-testos/buildmaster/x86_64-runtime} + export version=${4:-$(date "+%Y%m%d.${content_iteration}")} echo "BOOT ITERATION: $boot_checksum_iteration" cd ${test_tmpdir}/osdata kver=3.6.0 @@ -507,8 +508,6 @@ os_repository_new_commit () echo "content iteration ${content_iteration}" > usr/bin/content-iteration - export version=$(date "+%Y%m%d.${content_iteration}") - ${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string "version=${version}" -b $branch -s "Build" cd ${test_tmpdir} } From 8d2e9b8f9e7a0bf112ace44a1b640b42c9d6b157 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 16 Feb 2019 20:22:30 +0000 Subject: [PATCH 28/50] static-delta: Change `show` to display from/to commits When writing a delta to a file this may not always be recorded in the filename, and it's useful data. Ref: https://mail.gnome.org/archives/ostree-list/2019-February/msg00000.html This also required teaching `show` to accept a file path. Note...for some reason `test-deltas.sh` breaks when run from a tty - we get `SIGTTIN` which implies something is reading from the tty but it wasn't obvious to me what. Closes: #1823 Approved by: jlebon --- src/libostree/ostree-repo-static-delta-core.c | 50 +++++++++++++++---- tests/test-delta.sh | 2 + 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c index 57c89736..ade4e9df 100644 --- a/src/libostree/ostree-repo-static-delta-core.c +++ b/src/libostree/ostree-repo-static-delta-core.c @@ -725,16 +725,25 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, GCancellable *cancellable, GError **error) { - g_autofree char *from = NULL; - g_autofree char *to = NULL; - if (!_ostree_parse_delta_name (delta_id, &from, &to, error)) - return FALSE; - - g_autofree char *superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to); - glnx_autofd int superblock_fd = -1; - if (!glnx_openat_rdonly (self->repo_dir_fd, superblock_path, TRUE, &superblock_fd, error)) - return FALSE; + + if (strchr (delta_id, '/')) + { + if (!glnx_openat_rdonly (AT_FDCWD, delta_id, TRUE, &superblock_fd, error)) + return FALSE; + } + else + { + g_autofree char *from = NULL; + g_autofree char *to = NULL; + if (!_ostree_parse_delta_name (delta_id, &from, &to, error)) + return FALSE; + + g_autofree char *superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to); + if (!glnx_openat_rdonly (self->repo_dir_fd, superblock_path, TRUE, &superblock_fd, error)) + return FALSE; + } + g_autoptr(GVariant) delta_superblock = NULL; if (!ot_variant_read_fd (superblock_fd, 0, (GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT, @@ -742,6 +751,26 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, return FALSE; g_print ("Delta: %s\n", delta_id); + g_autoptr(GVariant) from_commit_v = NULL; + g_variant_get_child (delta_superblock, 2, "@ay", &from_commit_v); + g_autofree char *from_commit = NULL; + if (g_variant_n_children (from_commit_v) > 0) + { + if (!ostree_checksum_bytes_peek_validate (from_commit_v, error)) + return FALSE; + from_commit = ostree_checksum_from_bytes_v (from_commit_v); + g_print ("From: %s\n", from_commit); + } + else + { + g_print ("From \n"); + } + g_autoptr(GVariant) to_commit_v = NULL; + g_variant_get_child (delta_superblock, 3, "@ay", &to_commit_v); + if (!ostree_checksum_bytes_peek_validate (to_commit_v, error)) + return FALSE; + g_autofree char *to_commit = ostree_checksum_from_bytes_v (to_commit_v); + g_print ("To: %s\n", to_commit); gboolean swap_endian = FALSE; OstreeDeltaEndianness endianness; @@ -777,6 +806,7 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, g_print ("Endianness: %s\n", endianness_description); } + guint64 ts; g_variant_get_child (delta_superblock, 1, "t", &ts); g_print ("Timestamp: %" G_GUINT64_FORMAT "\n", GUINT64_FROM_BE (ts)); @@ -821,7 +851,7 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, for (guint i = 0; i < n_parts; i++) { - if (!show_one_part (self, swap_endian, from, to, meta_entries, i, + if (!show_one_part (self, swap_endian, from_commit, to_commit, meta_entries, i, &total_size, &total_usize, cancellable, error)) return FALSE; diff --git a/tests/test-delta.sh b/tests/test-delta.sh index 39e066ea..557447bc 100755 --- a/tests/test-delta.sh +++ b/tests/test-delta.sh @@ -135,6 +135,8 @@ rm temp-repo -rf echo 'ok generate' ${CMD_PREFIX} ostree --repo=repo static-delta show ${origrev}-${newrev} > show.txt +assert_file_has_content show.txt "From: ${origrev}" +assert_file_has_content show.txt "To: ${newrev}" assert_file_has_content show.txt 'Endianness: \(little\|big\)' echo 'ok show' From c9725d0befe0d79931c26483f61acf6b848f452c Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 14 Feb 2019 00:54:09 -0800 Subject: [PATCH 29/50] lib/repo-pull: Allow the keyring remote to be overridden Currently the P2P code requires you to trust every remote you have configured to the same extent, because a remote controlled by a malicious actor can serve updates to refs (such as Flatpak apps) installed from other remotes.[1] The way this attack would play out is that the malicious remote would deploy the same collection ID as the victim remote, and would then be able to serve updates for it. One possible remedy would be to make it an error to configure remotes such that two have the same collection ID but differing GPG keys. I attempted to do that in Flatpak[2] but it proved difficult because it is valid to configure two remotes with the same collection ID, and they may then each want to update their keyrings which wouldn't happen atomically. Another potential solution I've considered is to add a `trusted-remotes` option to ostree_repo_find_remotes_async() which would dictate which keyring to use when pulling each ref. However the ostree_repo_finder_resolve_async() API would still remain vulnerable, and changing that would require rewriting a large chunk of libostree's P2P support. So this commit represents a third attempt at mitigating this security hole, namely to have the client specify which remote to use for GPG verification at pull time. This way the pull will fail if the commits are signed with anything other than the keys we actually trust to serve updates. This is implemented as an option "ref-keyring-map" for ostree_repo_pull_from_remotes_async() and ostree_repo_pull_with_options() which dictates the remote to be used for GPG verification of each collection-ref. I think specifying a keyring remote for each ref is better than specifying a remote for each OstreeRepoFinderResult, because there are some edge cases where a result could serve updates to refs which were installed from more than one remote. The PR to make Flatpak use this new option is here[3]. [1] https://github.com/flatpak/flatpak/issues/1447 [2] https://github.com/flatpak/flatpak/pull/2601 [3] https://github.com/flatpak/flatpak/pull/2705 Closes: #1810 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 97 ++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index d0b7b6ea..1377ee92 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -115,6 +115,7 @@ typedef struct { GHashTable *summary_deltas_checksums; GHashTable *ref_original_commits; /* Maps checksum to commit, used by timestamp checks */ GHashTable *gpg_verified_commits; /* Set of commits that have been verified */ + GHashTable *ref_keyring_map; /* Maps OstreeCollectionRef to keyring remote name */ GPtrArray *static_delta_superblocks; GHashTable *expected_commit_sizes; /* Maps commit checksum to known size */ GHashTable *commit_to_depth; /* Maps commit checksum maximum depth */ @@ -260,12 +261,13 @@ static gboolean scan_one_metadata_object (OtPullData *pull_data, GError **error); static void scan_object_queue_data_free (ScanObjectQueueData *scan_data); static gboolean -gpg_verify_unwritten_commit (OtPullData *pull_data, - const char *checksum, - GVariant *commit, - GVariant *detached_metadata, - GCancellable *cancellable, - GError **error); +gpg_verify_unwritten_commit (OtPullData *pull_data, + const char *checksum, + GVariant *commit, + GVariant *detached_metadata, + const OstreeCollectionRef *ref, + GCancellable *cancellable, + GError **error); static gboolean @@ -1307,7 +1309,7 @@ meta_fetch_on_complete (GObject *object, */ GVariant *detached_data = g_hash_table_lookup (pull_data->fetched_detached_metadata, checksum); if (!gpg_verify_unwritten_commit (pull_data, checksum, metadata, detached_data, - pull_data->cancellable, error)) + fetch_data->requested_ref, pull_data->cancellable, error)) goto out; if (!ostree_repo_mark_commit_partial (pull_data->repo, checksum, TRUE, error)) @@ -1462,23 +1464,32 @@ process_verify_result (OtPullData *pull_data, } static gboolean -gpg_verify_unwritten_commit (OtPullData *pull_data, - const char *checksum, - GVariant *commit, - GVariant *detached_metadata, - GCancellable *cancellable, - GError **error) +gpg_verify_unwritten_commit (OtPullData *pull_data, + const char *checksum, + GVariant *commit, + GVariant *detached_metadata, + const OstreeCollectionRef *ref, + GCancellable *cancellable, + GError **error) { if (pull_data->gpg_verify) { + const char *keyring_remote = NULL; + /* Shouldn't happen, but see comment in process_verify_result() */ if (g_hash_table_contains (pull_data->gpg_verified_commits, checksum)) return TRUE; + if (ref != NULL) + keyring_remote = g_hash_table_lookup (pull_data->ref_keyring_map, ref); + if (keyring_remote == NULL) + keyring_remote = pull_data->remote_name; + g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit); g_autoptr(OstreeGpgVerifyResult) result = _ostree_repo_gpg_verify_with_metadata (pull_data->repo, signed_data, - detached_metadata, pull_data->remote_name, + detached_metadata, + keyring_remote, NULL, NULL, cancellable, error); if (!process_verify_result (pull_data, checksum, result, error)) return FALSE; @@ -1788,10 +1799,16 @@ scan_commit_object (OtPullData *pull_data, !g_hash_table_contains (pull_data->gpg_verified_commits, checksum)) { g_autoptr(OstreeGpgVerifyResult) result = NULL; + const char *keyring_remote = NULL; + + if (ref != NULL) + keyring_remote = g_hash_table_lookup (pull_data->ref_keyring_map, ref); + if (keyring_remote == NULL) + keyring_remote = pull_data->remote_name; result = ostree_repo_verify_commit_for_remote (pull_data->repo, checksum, - pull_data->remote_name, + keyring_remote, cancellable, error); if (!process_verify_result (pull_data, checksum, result, error)) @@ -2385,7 +2402,7 @@ process_one_static_delta (OtPullData *pull_data, g_autoptr(GVariant) detached_data = g_variant_lookup_value (metadata, detached_path, G_VARIANT_TYPE("a{sv}")); if (!gpg_verify_unwritten_commit (pull_data, to_revision, to_commit, detached_data, - cancellable, error)) + ref, cancellable, error)) return FALSE; if (detached_data && !ostree_repo_write_commit_detached_metadata (pull_data->repo, @@ -3505,6 +3522,14 @@ initiate_request (OtPullData *pull_data, * * n-network-retries (u): Number of times to retry each download on receiving * a transient network error, such as a socket timeout; default is 5, 0 * means return errors without retrying. Since: 2018.6 + * * ref-keyring-map (a(sss)): Array of (collection ID, ref name, keyring + * remote name) tuples specifying which remote's keyring should be used when + * doing GPG verification of each collection-ref. This is useful to prevent a + * remote from serving malicious updates to refs which did not originate from + * it. This can be a subset or superset of the refs being pulled; any ref + * not being pulled will be ignored and any ref without a keyring remote + * will be verified with the keyring of the remote being pulled from. + * Since: 2019.2 */ gboolean ostree_repo_pull_with_options (OstreeRepo *self, @@ -3539,12 +3564,14 @@ ostree_repo_pull_with_options (OstreeRepo *self, gboolean opt_gpg_verify_summary_set = FALSE; gboolean opt_collection_refs_set = FALSE; gboolean opt_n_network_retries_set = FALSE; + gboolean opt_ref_keyring_map_set = FALSE; const char *main_collection_id = NULL; const char *url_override = NULL; gboolean inherit_transaction = FALSE; g_autoptr(GHashTable) updated_requested_refs_to_fetch = NULL; /* (element-type OstreeCollectionRef utf8) */ int i; g_autofree char **opt_localcache_repos = NULL; + g_autoptr(GVariantIter) ref_keyring_map_iter = NULL; /* If refs or collection-refs has exactly one value, this will point to that * value, otherwise NULL. Used for logging. */ @@ -3584,6 +3611,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, (void) g_variant_lookup (options, "append-user-agent", "s", &pull_data->append_user_agent); opt_n_network_retries_set = g_variant_lookup (options, "n-network-retries", "u", &pull_data->n_network_retries); + opt_ref_keyring_map_set = + g_variant_lookup (options, "ref-keyring-map", "a(sss)", &ref_keyring_map_iter); if (pull_data->remote_refspec_name != NULL) pull_data->remote_name = g_strdup (pull_data->remote_refspec_name); @@ -3644,6 +3673,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, (GDestroyNotify)g_free); pull_data->gpg_verified_commits = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL); + pull_data->ref_keyring_map = g_hash_table_new_full (ostree_collection_ref_hash, ostree_collection_ref_equal, + (GDestroyNotify)ostree_collection_ref_free, (GDestroyNotify)g_free); pull_data->scanned_metadata = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal, (GDestroyNotify)g_variant_unref, NULL); pull_data->fetched_detached_metadata = g_hash_table_new_full (g_str_hash, g_str_equal, @@ -4373,6 +4404,30 @@ ostree_repo_pull_with_options (OstreeRepo *self, } } + if (opt_ref_keyring_map_set) + { + const gchar *collection_id, *ref_name, *keyring_remote_name; + + while (g_variant_iter_loop (ref_keyring_map_iter, "(&s&s&s)", &collection_id, &ref_name, &keyring_remote_name)) + { + g_autoptr(OstreeCollectionRef) c_r = NULL; + + if (!ostree_validate_collection_id (collection_id, error)) + goto out; + if (!ostree_validate_rev (ref_name, error)) + goto out; + if (!ostree_validate_remote_name (keyring_remote_name, error)) + goto out; + + c_r = ostree_collection_ref_new (collection_id, ref_name); + if (!g_hash_table_contains (requested_refs_to_fetch, c_r)) + continue; + g_hash_table_insert (pull_data->ref_keyring_map, + g_steal_pointer (&c_r), + g_strdup (keyring_remote_name)); + } + } + /* Create the state directory here - it's new with the commitpartial code, * and may not exist in older repositories. */ @@ -4664,6 +4719,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_clear_pointer (&pull_data->summary_deltas_checksums, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->ref_original_commits, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->gpg_verified_commits, (GDestroyNotify) g_hash_table_unref); + g_clear_pointer (&pull_data->ref_keyring_map, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->requested_content, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->requested_fallback_content, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->requested_metadata, (GDestroyNotify) g_hash_table_unref); @@ -5798,6 +5854,14 @@ copy_option (GVariantDict *master_options, * * `n-network-retries` (`u`): Number of times to retry each download on receiving * a transient network error, such as a socket timeout; default is 5, 0 * means return errors without retrying. Since: 2018.6 + * * `ref-keyring-map` (`a(sss)`): Array of (collection ID, ref name, keyring + * remote name) tuples specifying which remote's keyring should be used when + * doing GPG verification of each collection-ref. This is useful to prevent a + * remote from serving malicious updates to refs which did not originate from + * it. This can be a subset or superset of the refs being pulled; any ref + * not being pulled will be ignored and any ref without a keyring remote + * will be verified with the keyring of the remote being pulled from. + * Since: 2019.2 * * Since: 2018.6 */ @@ -5918,6 +5982,7 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self, copy_option (&options_dict, &local_options_dict, "update-frequency", G_VARIANT_TYPE ("u")); copy_option (&options_dict, &local_options_dict, "append-user-agent", G_VARIANT_TYPE ("s")); copy_option (&options_dict, &local_options_dict, "n-network-retries", G_VARIANT_TYPE ("u")); + copy_option (&options_dict, &local_options_dict, "ref-keyring-map", G_VARIANT_TYPE ("a(sss)")); local_options = g_variant_dict_end (&local_options_dict); From da57956327d601aa489392cd94e3f976dca29739 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Tue, 2 Apr 2019 13:40:11 -0700 Subject: [PATCH 30/50] lib: Check for http_proxy being the empty string On at least one user's computer, g_getenv("http_proxy") returns the empty string, so check for that and treat it as no proxy rather than printing a warning. See https://github.com/flatpak/flatpak/issues/2790 Closes: #1835 Approved by: cgwalters --- src/libostree/ostree-fetcher-soup.c | 4 ++-- src/libostree/ostree-repo-pull.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-fetcher-soup.c b/src/libostree/ostree-fetcher-soup.c index 3951a927..970ac7a4 100644 --- a/src/libostree/ostree-fetcher-soup.c +++ b/src/libostree/ostree-fetcher-soup.c @@ -645,7 +645,7 @@ _ostree_fetcher_constructed (GObject *object) } http_proxy = g_getenv ("http_proxy"); - if (http_proxy != NULL) + if (http_proxy != NULL && http_proxy[0] != '\0') _ostree_fetcher_set_proxy (self, http_proxy); /* FIXME Maybe implement GInitableIface and use g_thread_try_new() @@ -711,7 +711,7 @@ _ostree_fetcher_set_proxy (OstreeFetcher *self, SoupURI *proxy_uri; g_return_if_fail (OSTREE_IS_FETCHER (self)); - g_return_if_fail (http_proxy != NULL); + g_return_if_fail (http_proxy != NULL && http_proxy[0] != '\0'); proxy_uri = soup_uri_new (http_proxy); diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 1377ee92..5d77bc7e 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -3034,7 +3034,7 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self, &http_proxy, error)) goto out; - if (http_proxy != NULL) + if (http_proxy != NULL && http_proxy[0] != '\0') _ostree_fetcher_set_proxy (fetcher, http_proxy); } From 077b23cc98081d66e0c959bff6351600aa0ca50f Mon Sep 17 00:00:00 2001 From: Laurent Bonnans Date: Thu, 11 Apr 2019 12:04:52 +0200 Subject: [PATCH 31/50] lib/repo: fix leak of `bootloader` field Added in 21ebc7d21edd00c3fe0ce80ea68ba3f8f5e41ae3 Closes: #1837 Approved by: rfairley --- src/libostree/ostree-repo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 00336503..9ffa103f 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1036,6 +1036,7 @@ ostree_repo_finalize (GObject *object) g_mutex_clear (&self->txn_lock); g_free (self->collection_id); g_strfreev (self->repo_finders); + g_free (self->bootloader); g_clear_pointer (&self->remotes, g_hash_table_destroy); g_mutex_clear (&self->remotes_lock); @@ -3133,6 +3134,7 @@ reload_sysroot_config (OstreeRepo *self, if (!(g_str_equal (bootloader, "auto") || g_str_equal (bootloader, "none"))) return glnx_throw (error, "Invalid bootloader configuration: '%s'", bootloader); + g_free (self->bootloader); self->bootloader = g_steal_pointer (&bootloader); } From dd6844a61ef7b82e656481d6ddd1389012ab3fb9 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Mon, 1 Apr 2019 19:01:49 -0700 Subject: [PATCH 32/50] tests: Escape periods when appropriate Don't match any character in a regular expression when we only want to match a period. Closes: #1834 Approved by: rfairley --- tests/admin-test.sh | 4 +- tests/basic-test.sh | 2 +- .../installed/destructive/itest-bare-root.sh | 10 +- .../nondestructive/itest-bare-user-root.sh | 4 +- tests/pull-test2.sh | 2 +- tests/test-admin-pull-deploy-split.sh | 4 +- tests/test-config.sh | 4 +- tests/test-create-usb.sh | 24 ++-- tests/test-find-remotes.sh | 108 +++++++++--------- tests/test-fsck-collections.sh | 40 +++---- tests/test-init-collections.sh | 2 +- tests/test-no-initramfs.sh | 2 +- tests/test-pull-summary-sigs.sh | 2 +- tests/test-refs-collections.sh | 20 ++-- tests/test-remote-add.sh | 14 +-- tests/test-repo-finder-mount-integration.sh | 14 +-- tests/test-summary-collections.sh | 16 +-- tests/test-summary-update.sh | 6 +- tests/test-xattrs.sh | 4 +- 19 files changed, 141 insertions(+), 141 deletions(-) diff --git a/tests/admin-test.sh b/tests/admin-test.sh index 79a23f59..31e969c2 100644 --- a/tests/admin-test.sh +++ b/tests/admin-test.sh @@ -60,7 +60,7 @@ validate_bootloader echo "ok deploy command" ${CMD_PREFIX} ostree admin --print-current-dir > curdir -assert_file_has_content curdir ^`pwd`/sysroot/ostree/deploy/testos/deploy/${rev}.0$ +assert_file_has_content curdir ^`pwd`/sysroot/ostree/deploy/testos/deploy/${rev}\.0$ echo "ok --print-current-dir" @@ -239,7 +239,7 @@ cp ${originfile} saved-origin ${CMD_PREFIX} ostree admin set-origin --index=0 bacon --set=gpg-verify=false http://tasty.com assert_file_has_content "${originfile}" "bacon:testos/buildmaster/x86_64-runtime" ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo remote list -u > remotes.txt -assert_file_has_content remotes.txt 'bacon.*http://tasty.com' +assert_file_has_content remotes.txt 'bacon.*http://tasty\.com' cp saved-origin ${originfile} validate_bootloader diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 0c80a5f5..ba88cc73 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -245,7 +245,7 @@ EOF $OSTREE commit ${COMMIT_ARGS} -b branch-with-commitmsg -F commitmsg.txt -s 'a message' $test_tmpdir/checkout-test2-4 $OSTREE log branch-with-commitmsg > log.txt assert_file_has_content log.txt '^ *This is a long$' -assert_file_has_content log.txt '^ *Build-Host:.*example.com$' +assert_file_has_content log.txt '^ *Build-Host:.*example\.com$' assert_file_has_content log.txt '^ *Crunchy-With.*true$' $OSTREE refs --delete branch-with-commitmsg echo "ok commit body file" diff --git a/tests/installed/destructive/itest-bare-root.sh b/tests/installed/destructive/itest-bare-root.sh index 3a5302ee..18a3931f 100755 --- a/tests/installed/destructive/itest-bare-root.sh +++ b/tests/installed/destructive/itest-bare-root.sh @@ -25,17 +25,17 @@ setfattr -n security.crunchy -v withketchup co/usr/bin csum=$(ostree commit -b testref --link-checkout-speedup --tree=dir=co) ostree fsck ostree ls -X testref ${victim_symlink} > ls.txt -assert_file_has_content ls.txt 'security.biometric' +assert_file_has_content ls.txt 'security\.biometric' ostree ls -X ${host_refspec} ${victim_symlink} > ls.txt -assert_not_file_has_content ls.txt security.biometric +assert_not_file_has_content ls.txt security\.biometric ostree ls -X testref usr/bin > ls.txt -assert_file_has_content ls.txt 'security.crunchy' +assert_file_has_content ls.txt 'security\.crunchy' ostree checkout -H testref co-testref getfattr -n security.biometric co-testref/${victim_symlink} > xattr.txt -assert_file_has_content xattr.txt 'security.biometric="iris"' +assert_file_has_content xattr.txt 'security\.biometric="iris"' getfattr -n security.crunchy co-testref/usr/bin > xattr.txt -assert_file_has_content xattr.txt 'security.crunchy="withketchup"' +assert_file_has_content xattr.txt 'security\.crunchy="withketchup"' rm co -rf rm co-testref -rf diff --git a/tests/installed/nondestructive/itest-bare-user-root.sh b/tests/installed/nondestructive/itest-bare-user-root.sh index 40722384..9e04f7bc 100755 --- a/tests/installed/nondestructive/itest-bare-user-root.sh +++ b/tests/installed/nondestructive/itest-bare-user-root.sh @@ -35,7 +35,7 @@ ostree --repo=repo commit --selinux-policy / -b rootfs --link-checkout-speedup - ostree --repo=repo ls rootfs /usr/bin/systemd >ls.txt assert_file_has_content ls.txt '^-007.. 0 0 .*/usr/bin/systemd' ostree --repo=repo ls -X rootfs /usr/lib/dbus-daemon-helper >ls.txt -assert_file_has_content ls.txt '^-007.. 0 81 .*security.selinux.*/usr/lib/dbus-daemon-helper' -assert_not_file_has_content ls.txt 'user.ostreemeta' +assert_file_has_content ls.txt '^-007.. 0 81 .*security\.selinux.*/usr/lib/dbus-daemon-helper' +assert_not_file_has_content ls.txt 'user\.ostreemeta' echo "ok bare-user link-checkout-speedup with modified xattrs maintains uids" date diff --git a/tests/pull-test2.sh b/tests/pull-test2.sh index 1d91e514..064bbfe6 100644 --- a/tests/pull-test2.sh +++ b/tests/pull-test2.sh @@ -55,7 +55,7 @@ ${CMD_PREFIX} ostree --repo=ostree-srv/repo static-delta generate ${remote_ref} ${CMD_PREFIX} ostree --repo=ostree-srv/repo summary -u ${CMD_PREFIX} ostree --repo=repo pull origin ${remote_ref}@${prev_rev} ${CMD_PREFIX} ostree --repo=repo pull --dry-run --require-static-deltas origin ${remote_ref} >dry-run-pull.txt -assert_file_has_content dry-run-pull.txt 'Delta update: 0/1 parts, 0 bytes/[45][0-9].[0-9][  ]kB, 1.[678][  ]MB total uncompressed' +assert_file_has_content dry-run-pull.txt 'Delta update: 0/1 parts, 0 bytes/[45][0-9]\.[0-9][  ]kB, 1\.[678][  ]MB total uncompressed' ${CMD_PREFIX} ostree --repo=repo pull --require-static-deltas origin ${remote_ref} final_rev=$(${CMD_PREFIX} ostree --repo=repo rev-parse origin:${remote_ref}) assert_streq "${rev}" "${final_rev}" diff --git a/tests/test-admin-pull-deploy-split.sh b/tests/test-admin-pull-deploy-split.sh index 5e38d6fa..1196368d 100755 --- a/tests/test-admin-pull-deploy-split.sh +++ b/tests/test-admin-pull-deploy-split.sh @@ -46,13 +46,13 @@ ${CMD_PREFIX} ostree admin upgrade --os=testos --pull-only --os=testos > out.txt assert_not_file_has_content out.txt 'No update available' assert_has_dir sysroot/ostree/deploy/testos/deploy/${parent_rev}.0 assert_not_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'TestOS 42 1.0.9' +assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'TestOS 42 1\.0\.9' assert_streq "${rev}" $(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) # Now, generate new content upstream; we shouldn't pull it os_repository_new_commit ${CMD_PREFIX} ostree admin upgrade --os=testos --deploy-only --os=testos > out.txt assert_not_file_has_content out.txt 'No update available' -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'TestOS 42 1.0.10' +assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'TestOS 42 1\.0\.10' assert_has_dir sysroot/ostree/deploy/testos/deploy/${parent_rev}.0 assert_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 ${CMD_PREFIX} ostree admin upgrade --os=testos --deploy-only --os=testos > out.txt diff --git a/tests/test-config.sh b/tests/test-config.sh index 3499de7a..483cff41 100755 --- a/tests/test-config.sh +++ b/tests/test-config.sh @@ -40,7 +40,7 @@ assert_file_has_content list.txt "bare" assert_file_has_content list.txt "1" assert_file_has_content list.txt "Flathub" assert_file_has_content list.txt "true" -assert_file_has_content list.txt "http://example.com/ostree/repo/" +assert_file_has_content list.txt "http://example\.com/ostree/repo/" # Check that it errors out if too many arguments are given if ${CMD_PREFIX} ostree config --repo=repo get --group=core lock-timeout-secs extra 2>err.txt; then @@ -57,7 +57,7 @@ ${CMD_PREFIX} ostree config --repo=repo set --group='remote "org.mozilla.Firefox assert_file_has_content repo/config "bare-user-only" assert_file_has_content repo/config "Nightly Flathub" assert_file_has_content repo/config "false" -assert_file_has_content repo/config "http://example.com/ostree/" +assert_file_has_content repo/config "http://example\.com/ostree/" # Check that it errors out if too many arguments are given if ${CMD_PREFIX} ostree config --repo=repo set --group=core lock-timeout-secs 120 extra 2>err.txt; then diff --git a/tests/test-create-usb.sh b/tests/test-create-usb.sh index 392352fd..8040ed9c 100755 --- a/tests/test-create-usb.sh +++ b/tests/test-create-usb.sh @@ -56,9 +56,9 @@ ${CMD_PREFIX} ostree --repo=local-repo create-usb dest-mount1 org.example.Collec assert_has_dir dest-mount1/.ostree/repo ${CMD_PREFIX} ostree --repo=dest-mount1/.ostree/repo refs --collections > dest-refs -assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" -assert_file_has_content dest-refs "^(org.example.Collection1, test-2)$" -assert_not_file_has_content dest-refs "^(org.example.Collection1, test-3)$" +assert_file_has_content dest-refs "^(org\.example\.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org\.example\.Collection1, test-2)$" +assert_not_file_has_content dest-refs "^(org\.example\.Collection1, test-3)$" assert_has_file dest-mount1/.ostree/repo/summary echo "ok 1 simple usb" @@ -83,7 +83,7 @@ ${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo some-dest d assert_has_dir "dest-mount3/some-dest" assert_symlink_has_content "dest-mount3/.ostree/repos.d/00-generated" "/some-dest$" ${CMD_PREFIX} ostree --repo=dest-mount3/.ostree/repos.d/00-generated refs --collections > dest-refs -assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org\.example\.Collection1, test-1)$" assert_has_file dest-mount3/.ostree/repos.d/00-generated/summary echo "ok 3 usb in non-standard location" @@ -93,13 +93,13 @@ ${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo some-dest d assert_has_dir "dest-mount3/some-dest" assert_symlink_has_content "dest-mount3/.ostree/repos.d/00-generated" "/some-dest$" ${CMD_PREFIX} ostree --repo=dest-mount3/.ostree/repos.d/00-generated refs --collections > dest-refs -assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" -assert_file_has_content dest-refs "^(org.example.Collection1, test-2)$" -assert_file_has_content dest-refs "^(org.example.Collection1, test-3)$" +assert_file_has_content dest-refs "^(org\.example\.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org\.example\.Collection1, test-2)$" +assert_file_has_content dest-refs "^(org\.example\.Collection1, test-3)$" ${CMD_PREFIX} ostree --repo=dest-mount3/.ostree/repos.d/00-generated summary -v > dest-summary -assert_file_has_content dest-summary "(org.example.Collection1, test-1)$" -assert_file_has_content dest-summary "(org.example.Collection1, test-2)$" -assert_file_has_content dest-summary "(org.example.Collection1, test-3)$" +assert_file_has_content dest-summary "(org\.example\.Collection1, test-1)$" +assert_file_has_content dest-summary "(org\.example\.Collection1, test-2)$" +assert_file_has_content dest-summary "(org\.example\.Collection1, test-3)$" echo "ok 4 adding ref to an existing usb" @@ -109,7 +109,7 @@ ostree_repo_init finder-repo ${CMD_PREFIX} ostree --repo=finder-repo remote add remote1 file://$(pwd)/just-needed-for-the-keyring --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" ${test_builddir}/repo-finder-mount finder-repo dest-mount1 org.example.Collection1 test-1 org.example.Collection1 test-2 &> out -assert_file_has_content out "^0 .*_2Fdest-mount1_2F.ostree_2Frepo_remote1.trustedkeys.gpg org.example.Collection1 test-1 $(ostree --repo=repo show test-1)$" -assert_file_has_content out "^0 .*_2Fdest-mount1_2F.ostree_2Frepo_remote1.trustedkeys.gpg org.example.Collection1 test-2 $(ostree --repo=repo show test-2)$" +assert_file_has_content out "^0 .*_2Fdest-mount1_2F\.ostree_2Frepo_remote1\.trustedkeys\.gpg org\.example\.Collection1 test-1 $(ostree --repo=repo show test-1)$" +assert_file_has_content out "^0 .*_2Fdest-mount1_2F\.ostree_2Frepo_remote1\.trustedkeys\.gpg org\.example\.Collection1 test-2 $(ostree --repo=repo show test-2)$" echo "ok 5 find from usb repo" diff --git a/tests/test-find-remotes.sh b/tests/test-find-remotes.sh index b9ddc604..226053ce 100755 --- a/tests/test-find-remotes.sh +++ b/tests/test-find-remotes.sh @@ -60,8 +60,8 @@ assert_file_has_content refs "^os-remote:os/amd64/master$" ${CMD_PREFIX} ostree --repo=local refs --collections > refs cat refs | wc -l > refscount -assert_file_has_content refs "^(org.example.AppsCollection, app1)$" -assert_file_has_content refs "^(org.example.OsCollection, os/amd64/master)$" +assert_file_has_content refs "^(org\.example\.AppsCollection, app1)$" +assert_file_has_content refs "^(org\.example\.OsCollection, os/amd64/master)$" assert_file_has_content refscount "^2$" # Create a local mirror repository where we pull the branches *in mirror mode* from the two remotes. @@ -80,8 +80,8 @@ ls -1 local-mirror/refs/remotes | wc -l > remotescount assert_file_has_content remotescount "^0$" ${CMD_PREFIX} ostree --repo=local-mirror refs --collections > refs -assert_file_has_content refs "^(org.example.AppsCollection, app1)$" -assert_file_has_content refs "^(org.example.OsCollection, os/amd64/master)$" +assert_file_has_content refs "^(org\.example\.AppsCollection, app1)$" +assert_file_has_content refs "^(org\.example\.OsCollection, os/amd64/master)$" assert_file_has_content local-mirror/refs/mirrors/org.example.AppsCollection/app1 "^$(cat app1-checksum)$" assert_file_has_content local-mirror/refs/mirrors/org.example.OsCollection/os/amd64/master "^$(cat os-checksum)$" @@ -90,69 +90,69 @@ for repo in local local-mirror; do # Try finding an update for an existing branch. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config org.example.AppsCollection app1 > find assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/apps-collection$" - assert_file_has_content find "^ - Keyring: apps-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.AppsCollection, app1) = $(cat app1-checksum)$" - assert_file_has_content find "^1/1 refs were found.$" - assert_not_file_has_content find "^No results.$" + assert_file_has_content find "^ - Keyring: apps-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.AppsCollection, app1) = $(cat app1-checksum)$" + assert_file_has_content find "^1/1 refs were found\.$" + assert_not_file_has_content find "^No results\.$" # Find several updates for several existing branches. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config org.example.AppsCollection app1 org.example.OsCollection os/amd64/master > find assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/apps-collection$" - assert_file_has_content find "^ - Keyring: apps-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.AppsCollection, app1) = $(cat app1-checksum)$" + assert_file_has_content find "^ - Keyring: apps-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.AppsCollection, app1) = $(cat app1-checksum)$" assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/os-collection$" - assert_file_has_content find "^ - Keyring: os-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.OsCollection, os/amd64/master) = $(cat os-checksum)$" - assert_file_has_content find "^2/2 refs were found.$" - assert_not_file_has_content find "^No results.$" + assert_file_has_content find "^ - Keyring: os-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.OsCollection, os/amd64/master) = $(cat os-checksum)$" + assert_file_has_content find "^2/2 refs were found\.$" + assert_not_file_has_content find "^No results\.$" # Find some updates and a new branch. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config org.example.AppsCollection app1 org.example.AppsCollection app2 org.example.OsCollection os/amd64/master > find assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/apps-collection$" - assert_file_has_content find "^ - Keyring: apps-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.AppsCollection, app1) = $(cat app1-checksum)$" - assert_file_has_content find "^ - (org.example.AppsCollection, app2) = $(cat app2-checksum)$" + assert_file_has_content find "^ - Keyring: apps-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.AppsCollection, app1) = $(cat app1-checksum)$" + assert_file_has_content find "^ - (org\.example\.AppsCollection, app2) = $(cat app2-checksum)$" assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/os-collection$" - assert_file_has_content find "^ - Keyring: os-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.OsCollection, os/amd64/master) = $(cat os-checksum)$" - assert_file_has_content find "^3/3 refs were found.$" - assert_not_file_has_content find "^No results.$" + assert_file_has_content find "^ - Keyring: os-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.OsCollection, os/amd64/master) = $(cat os-checksum)$" + assert_file_has_content find "^3/3 refs were found\.$" + assert_not_file_has_content find "^No results\.$" # Find an update and a non-existent branch. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config org.example.AppsCollection app1 org.example.AppsCollection not-an-app > find assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/apps-collection$" - assert_file_has_content find "^ - Keyring: apps-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.AppsCollection, not-an-app) = (not found)$" - assert_file_has_content find "^ - (org.example.AppsCollection, app1) = $(cat app1-checksum)$" + assert_file_has_content find "^ - Keyring: apps-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.AppsCollection, not-an-app) = (not found)$" + assert_file_has_content find "^ - (org\.example\.AppsCollection, app1) = $(cat app1-checksum)$" assert_file_has_content find "^Refs not found in any remote:$" - assert_file_has_content find "^ - (org.example.AppsCollection, not-an-app)$" - assert_file_has_content find "^1/2 refs were found.$" - assert_not_file_has_content find "^No results.$" + assert_file_has_content find "^ - (org\.example\.AppsCollection, not-an-app)$" + assert_file_has_content find "^1/2 refs were found\.$" + assert_not_file_has_content find "^No results\.$" # Do all the above, but pull this time. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config --pull org.example.AppsCollection app1 > pull || true - assert_file_has_content pull "^1/1 refs were found.$" - assert_file_has_content pull "^Pulled 1/1 refs successfully.$" + assert_file_has_content pull "^1/1 refs were found\.$" + assert_file_has_content pull "^Pulled 1/1 refs successfully\.$" assert_not_file_has_content pull "Failed to pull some refs from the remotes" assert_ref $repo app1 $(cat app1-checksum) ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config --pull org.example.AppsCollection app1 org.example.OsCollection os/amd64/master > pull - assert_file_has_content pull "^2/2 refs were found.$" - assert_file_has_content pull "^Pulled 2/2 refs successfully.$" + assert_file_has_content pull "^2/2 refs were found\.$" + assert_file_has_content pull "^Pulled 2/2 refs successfully\.$" assert_not_file_has_content pull "Failed to pull some refs from the remotes" assert_ref $repo app1 $(cat app1-checksum) assert_ref $repo os/amd64/master $(cat os-checksum) ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config --pull org.example.AppsCollection app1 org.example.AppsCollection app2 org.example.OsCollection os/amd64/master > pull - assert_file_has_content pull "^3/3 refs were found.$" - assert_file_has_content pull "^Pulled 3/3 refs successfully.$" + assert_file_has_content pull "^3/3 refs were found\.$" + assert_file_has_content pull "^Pulled 3/3 refs successfully\.$" assert_not_file_has_content pull "Failed to pull some refs from the remotes" assert_ref $repo app1 $(cat app1-checksum) assert_ref $repo app2 $(cat app2-checksum) assert_ref $repo os/amd64/master $(cat os-checksum) ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config --pull org.example.AppsCollection app1 org.example.AppsCollection not-an-app > pull - assert_file_has_content pull "^1/2 refs were found.$" + assert_file_has_content pull "^1/2 refs were found\.$" assert_not_file_has_content pull "Failed to pull some refs from the remotes" assert_ref $repo app1 $(cat app1-checksum) assert_not_ref $repo not-an-app @@ -168,15 +168,15 @@ for repo in local-mirror; do # Try finding an update for that branch. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config org.example.OsCollection os/amd64/master > find assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/os-collection$" - assert_file_has_content find "^ - Keyring: os-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.OsCollection, os/amd64/master) = $(cat os-checksum-2)$" - assert_file_has_content find "^1/1 refs were found.$" - assert_not_file_has_content find "^No results.$" + assert_file_has_content find "^ - Keyring: os-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.OsCollection, os/amd64/master) = $(cat os-checksum-2)$" + assert_file_has_content find "^1/1 refs were found\.$" + assert_not_file_has_content find "^No results\.$" # Pull it. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config --pull org.example.OsCollection os/amd64/master > pull || true - assert_file_has_content pull "^1/1 refs were found.$" - assert_file_has_content pull "^Pulled 1/1 refs successfully.$" + assert_file_has_content pull "^1/1 refs were found\.$" + assert_file_has_content pull "^Pulled 1/1 refs successfully\.$" assert_not_file_has_content pull "Failed to pull some refs from the remotes" assert_ref $repo os/amd64/master $(cat os-checksum-2) @@ -195,18 +195,18 @@ for repo in local; do # Try finding an update for that branch. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config org.example.OsCollection os/amd64/master > find assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/os-collection$" - assert_file_has_content find "^ - Keyring: os-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.OsCollection, os/amd64/master) = $(cat os-checksum-2)$" + assert_file_has_content find "^ - Keyring: os-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.OsCollection, os/amd64/master) = $(cat os-checksum-2)$" assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/local-mirror$" - assert_file_has_content find "^ - Keyring: os-remote-local-mirror.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.OsCollection, os/amd64/master) = $(cat os-checksum-2)$" - assert_file_has_content find "^1/1 refs were found.$" - assert_not_file_has_content find "^No results.$" + assert_file_has_content find "^ - Keyring: os-remote-local-mirror\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.OsCollection, os/amd64/master) = $(cat os-checksum-2)$" + assert_file_has_content find "^1/1 refs were found\.$" + assert_not_file_has_content find "^No results\.$" # Pull it. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config --pull org.example.OsCollection os/amd64/master > pull || true - assert_file_has_content pull "^1/1 refs were found.$" - assert_file_has_content pull "^Pulled 1/1 refs successfully.$" + assert_file_has_content pull "^1/1 refs were found\.$" + assert_file_has_content pull "^Pulled 1/1 refs successfully\.$" assert_not_file_has_content pull "Failed to pull some refs from the remotes" assert_ref $repo os/amd64/master $(cat os-checksum-2) done @@ -222,15 +222,15 @@ for repo in local; do # Try finding an update for that branch. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config org.example.OsCollection os/amd64/master > find assert_file_has_content find "^Result [0-9]\+: file://$(pwd)/os-collection$" - assert_file_has_content find "^ - Keyring: os-remote.trustedkeys.gpg$" - assert_file_has_content find "^ - (org.example.OsCollection, os/amd64/master) = $(cat os-checksum-3)$" - assert_file_has_content find "^1/1 refs were found.$" - assert_not_file_has_content find "^No results.$" + assert_file_has_content find "^ - Keyring: os-remote\.trustedkeys\.gpg$" + assert_file_has_content find "^ - (org\.example\.OsCollection, os/amd64/master) = $(cat os-checksum-3)$" + assert_file_has_content find "^1/1 refs were found\.$" + assert_not_file_has_content find "^No results\.$" # Pull it. ${CMD_PREFIX} ostree --repo=$repo find-remotes --finders=config --pull org.example.OsCollection os/amd64/master > pull || true - assert_file_has_content pull "^1/1 refs were found.$" - assert_file_has_content pull "^Pulled 1/1 refs successfully.$" + assert_file_has_content pull "^1/1 refs were found\.$" + assert_file_has_content pull "^Pulled 1/1 refs successfully\.$" assert_not_file_has_content pull "Failed to pull some refs from the remotes" assert_ref $repo os/amd64/master $(cat os-checksum-3) done diff --git a/tests/test-fsck-collections.sh b/tests/test-fsck-collections.sh index 79d5d8c9..dc6bcfeb 100755 --- a/tests/test-fsck-collections.sh +++ b/tests/test-fsck-collections.sh @@ -61,7 +61,7 @@ set_up_repo_with_collection_id # fsck at this point should succeed ${CMD_PREFIX} ostree fsck --repo=repo > fsck -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" # Drop the commit the ref points to, and drop the original ref so that fsck doesn’t prematurely fail on that. find repo/objects -name '*.commit' -delete -print | wc -l > commitcount @@ -73,8 +73,8 @@ rm repo/refs/heads/ref1 if ${CMD_PREFIX} ostree fsck --repo=repo > fsck; then assert_not_reached "fsck unexpectedly succeeded after deleting commit!" fi -assert_file_has_content fsck "^Validating refs...$" -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" echo "ok 1 fsck-collections" @@ -84,8 +84,8 @@ set_up_repo_with_collection_id rm -rf repo/refs/mirrors ${CMD_PREFIX} ostree fsck --repo=repo > fsck -assert_file_has_content fsck "^Validating refs...$" -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" echo "ok 2 fsck-collections in old repository" @@ -101,7 +101,7 @@ if ${CMD_PREFIX} ostree fsck --repo=repo --verify-bindings > fsck 2> fsck-error; assert_not_reached "fsck unexpectedly succeeded after adding unbound ref!" fi assert_file_has_content fsck-error "Commit has no requested ref ‘new-ref’ in ref binding metadata (‘ref1’)" -assert_file_has_content fsck "^Validating refs...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" echo "ok 3 fsck detects missing ref bindings" @@ -114,8 +114,8 @@ if ${CMD_PREFIX} ostree fsck --repo=repo --verify-bindings > fsck 2> fsck-error; assert_not_reached "fsck unexpectedly succeeded after adding unbound ref!" fi assert_file_has_content fsck-error "Commit has no requested ref ‘new-ref’ in ref binding metadata (‘ref1’)" -assert_file_has_content fsck "^Validating refs...$" -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" echo "ok 4 fsck detects missing collection–ref bindings" @@ -127,9 +127,9 @@ ${CMD_PREFIX} ostree --repo=repo refs --collections --create=org.example.Collect if ${CMD_PREFIX} ostree fsck --repo=repo --verify-bindings > fsck 2> fsck-error; then assert_not_reached "fsck unexpectedly succeeded after adding unbound ref!" fi -assert_file_has_content fsck-error "Commit has collection ID ‘org.example.Collection’ in collection binding metadata, while the remote it came from has collection ID ‘org.example.Collection2’" -assert_file_has_content fsck "^Validating refs...$" -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck-error "Commit has collection ID ‘org\.example\.Collection’ in collection binding metadata, while the remote it came from has collection ID ‘org\.example\.Collection2’" +assert_file_has_content fsck "^Validating refs\.\.\.$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" echo "ok 5 fsck detects missing collection–ref bindings" @@ -139,7 +139,7 @@ ${CMD_PREFIX} ostree --repo=repo refs --delete ref1 # fsck at this point should succeed ${CMD_PREFIX} ostree fsck --repo=repo > fsck -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" echo "ok 6 fsck ignores unreferenced ref bindings" @@ -147,9 +147,9 @@ echo "ok 6 fsck ignores unreferenced ref bindings" if ${CMD_PREFIX} ostree fsck --repo=repo --verify-back-refs > fsck 2> fsck-error; then assert_not_reached "fsck unexpectedly succeeded after adding unbound ref!" fi -assert_file_has_content fsck-error "Collection–ref (org.example.Collection, ref1) in bindings for commit .* does not exist" -assert_file_has_content fsck "^Validating refs...$" -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck-error "Collection–ref (org\.example\.Collection, ref1) in bindings for commit .* does not exist" +assert_file_has_content fsck "^Validating refs\.\.\.$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" echo "ok 7 fsck ignores unreferenced ref bindings" @@ -161,7 +161,7 @@ set_up_repo_without_collection_id # fsck at this point should succeed ${CMD_PREFIX} ostree fsck --repo=repo --verify-bindings > fsck -assert_file_has_content fsck "^Validating refs in collections...$" +assert_file_has_content fsck "^Validating refs in collections\.\.\.$" # Drop the commit the ref points to, and drop the original ref so that fsck doesn’t prematurely fail on that. find repo/objects -name '*.commit' -delete -print | wc -l > commitcount @@ -173,7 +173,7 @@ rm repo/refs/heads/ref3 if ${CMD_PREFIX} ostree fsck --repo=repo --verify-bindings > fsck; then assert_not_reached "fsck unexpectedly succeeded after deleting commit!" fi -assert_file_has_content fsck "^Validating refs...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" echo "ok 8 fsck-collections" @@ -187,7 +187,7 @@ if ${CMD_PREFIX} ostree fsck --repo=repo --verify-bindings > fsck 2> fsck-error; assert_not_reached "fsck unexpectedly succeeded after adding unbound ref!" fi assert_file_has_content fsck-error "Commit has no requested ref ‘new-ref’ in ref binding metadata (‘ref3’, ‘ref4’)" -assert_file_has_content fsck "^Validating refs...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" echo "ok 9 fsck detects missing ref bindings" @@ -197,7 +197,7 @@ ${CMD_PREFIX} ostree --repo=repo refs --delete ref3 # fsck at this point should succeed ${CMD_PREFIX} ostree fsck --repo=repo > fsck -assert_file_has_content fsck "^Validating refs...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" echo "ok 10 fsck ignores unreferenced ref bindings" @@ -206,6 +206,6 @@ if ${CMD_PREFIX} ostree fsck --repo=repo --verify-back-refs > fsck 2> fsck-error assert_not_reached "fsck unexpectedly succeeded after adding unbound ref!" fi assert_file_has_content fsck-error "Ref ‘ref3’ in bindings for commit .* does not exist" -assert_file_has_content fsck "^Validating refs...$" +assert_file_has_content fsck "^Validating refs\.\.\.$" echo "ok 11 fsck ignores unreferenced ref bindings" diff --git a/tests/test-init-collections.sh b/tests/test-init-collections.sh index 5c3dd4e2..1954f1ae 100755 --- a/tests/test-init-collections.sh +++ b/tests/test-init-collections.sh @@ -30,6 +30,6 @@ cd ${test_tmpdir} # Check that initialising a repository with a collection ID results in the ID being in the config. mkdir repo ostree_repo_init repo --collection-id org.example.Collection -assert_file_has_content repo/config "^collection-id=org.example.Collection$" +assert_file_has_content repo/config "^collection-id=org\.example\.Collection$" echo "ok init-collections" diff --git a/tests/test-no-initramfs.sh b/tests/test-no-initramfs.sh index 60e1f9a7..22846c8f 100755 --- a/tests/test-no-initramfs.sh +++ b/tests/test-no-initramfs.sh @@ -83,7 +83,7 @@ do ${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmaster/x86_64-runtime assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'init=' - assert_file_has_content sysroot/boot/"$(get_key_from_bootloader_conf sysroot/boot/loader/entries/ostree-2-testos.conf 'devicetree')" "my .dtb file" + assert_file_has_content sysroot/boot/"$(get_key_from_bootloader_conf sysroot/boot/loader/entries/ostree-2-testos.conf 'devicetree')" "my \.dtb file" assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'initrd' echo "ok switching from initramfs to no initramfs sysroot with devicetree layout=$layout" diff --git a/tests/test-pull-summary-sigs.sh b/tests/test-pull-summary-sigs.sh index dee186b5..e2864beb 100755 --- a/tests/test-pull-summary-sigs.sh +++ b/tests/test-pull-summary-sigs.sh @@ -146,7 +146,7 @@ assert_file_has_content summary.txt "* main" assert_file_has_content summary.txt "* other" assert_file_has_content summary.txt "* yet-another" assert_file_has_content summary.txt "found 1 signature" -assert_file_has_content summary.txt "Good signature from \"Ostree Tester \"" +assert_file_has_content summary.txt "Good signature from \"Ostree Tester \"" grep static-deltas summary.txt > static-deltas.txt assert_file_has_content static-deltas.txt \ $(${OSTREE} --repo=repo rev-parse origin:main) diff --git a/tests/test-refs-collections.sh b/tests/test-refs-collections.sh index 9a123dd9..bf233970 100755 --- a/tests/test-refs-collections.sh +++ b/tests/test-refs-collections.sh @@ -46,11 +46,11 @@ assert_file_has_content refscount "^5$" ${CMD_PREFIX} ostree --repo=repo refs > refs assert_file_has_content refs "^test\-1$" assert_file_has_content refs "^test\-5$" -assert_not_file_has_content refs "org.example.Collection" +assert_not_file_has_content refs "org\.example\.Collection" ${CMD_PREFIX} ostree --repo=repo refs --collections > refs -assert_file_has_content refs "^(org.example.Collection, test-1)$" -assert_file_has_content refs "^(org.example.Collection, test-5)$" +assert_file_has_content refs "^(org\.example\.Collection, test-1)$" +assert_file_has_content refs "^(org\.example\.Collection, test-5)$" # Similarly, the collection IDs should only be listed when filtering if --collections is passed. ${CMD_PREFIX} ostree --repo=repo refs --list org.example.Collection | wc -l > refscount @@ -102,8 +102,8 @@ assert_file_has_content refs "^ctest$" assert_not_file_has_content refs "^ctest-mirror$" ${CMD_PREFIX} ostree --repo=repo refs --collections > refs -assert_file_has_content refs "^(org.example.Collection, ctest)$" -assert_file_has_content refs "^(org.example.NewCollection, ctest-mirror)$" +assert_file_has_content refs "^(org\.example\.Collection, ctest)$" +assert_file_has_content refs "^(org\.example\.NewCollection, ctest-mirror)$" # Remote refs should be listed if they have collection IDs @@ -116,13 +116,13 @@ ${CMD_PREFIX} ostree --repo=repo remote add --no-gpg-verify --collection-id org. ${CMD_PREFIX} ostree --repo=repo pull collection-repo-remote rcommit ${CMD_PREFIX} ostree --repo=repo refs --collections > refs -assert_file_has_content refs "^(org.example.RemoteCollection, rcommit)$" +assert_file_has_content refs "^(org\.example\.RemoteCollection, rcommit)$" ${CMD_PREFIX} ostree --repo=repo refs --collections org.example.RemoteCollection > refs -assert_file_has_content refs "^(org.example.RemoteCollection, rcommit)$" +assert_file_has_content refs "^(org\.example\.RemoteCollection, rcommit)$" ${CMD_PREFIX} ostree --repo=repo refs --collections org.example.NonexistentID > refs -assert_not_file_has_content refs "^(org.example.RemoteCollection, rcommit)$" +assert_not_file_has_content refs "^(org\.example\.RemoteCollection, rcommit)$" cd ${test_tmpdir} mkdir no-collection-repo @@ -147,8 +147,8 @@ ${CMD_PREFIX} ostree --repo=repo refs --collections rm -rf repo/refs/mirrors ${CMD_PREFIX} ostree --repo=repo refs --collections --create=org.example.NewCollection:ctest-mirror ctest ${CMD_PREFIX} ostree --repo=repo refs --collections > refs -assert_file_has_content refs "^(org.example.Collection, ctest)$" -assert_file_has_content refs "^(org.example.NewCollection, ctest-mirror)$" +assert_file_has_content refs "^(org\.example\.Collection, ctest)$" +assert_file_has_content refs "^(org\.example\.NewCollection, ctest-mirror)$" rm -rf repo/refs/mirrors ${CMD_PREFIX} ostree refs --repo=repo --collections --delete org.example.NonexistentCollection diff --git a/tests/test-remote-add.sh b/tests/test-remote-add.sh index 57fe7eec..bb7eae89 100755 --- a/tests/test-remote-add.sh +++ b/tests/test-remote-add.sh @@ -51,18 +51,18 @@ $OSTREE remote list > list.txt assert_file_has_content list.txt "origin" assert_file_has_content list.txt "another" assert_file_has_content list.txt "another-noexist" -assert_not_file_has_content list.txt "http://example.com/ostree/gnome" -assert_not_file_has_content list.txt "http://another.com/repo" -assert_not_file_has_content list.txt "http://another-noexist.example.com/anotherrepo" +assert_not_file_has_content list.txt "http://example\.com/ostree/gnome" +assert_not_file_has_content list.txt "http://another\.com/repo" +assert_not_file_has_content list.txt "http://another-noexist\.example\.com/anotherrepo" echo "ok remote list" $OSTREE remote list --show-urls > list.txt assert_file_has_content list.txt "origin" assert_file_has_content list.txt "another" assert_file_has_content list.txt "another-noexist" -assert_file_has_content list.txt "http://example.com/ostree/gnome" -assert_file_has_content list.txt "http://another.com/repo" -assert_file_has_content list.txt "http://another-noexist.example.com/anotherrepo" +assert_file_has_content list.txt "http://example\.com/ostree/gnome" +assert_file_has_content list.txt "http://another\.com/repo" +assert_file_has_content list.txt "http://another-noexist\.example\.com/anotherrepo" echo "ok remote list with urls" cd ${test_tmpdir} @@ -116,5 +116,5 @@ echo "ok remote add fail --if-not-exists and --force" # Overwrite with --force $OSTREE remote add --force another http://another.example.com/anotherrepo $OSTREE remote list --show-urls > list.txt -assert_file_has_content list.txt "^another \+http://another.example.com/anotherrepo$" +assert_file_has_content list.txt "^another \+http://another\.example\.com/anotherrepo$" echo "ok remote add --force" diff --git a/tests/test-repo-finder-mount-integration.sh b/tests/test-repo-finder-mount-integration.sh index 283e4b0b..243df591 100755 --- a/tests/test-repo-finder-mount-integration.sh +++ b/tests/test-repo-finder-mount-integration.sh @@ -101,9 +101,9 @@ for fs_type in ext4 vfat; do assert_has_dir "${usb_mount}"/.ostree/repo ${CMD_PREFIX} ostree --repo="${usb_mount}"/.ostree/repo refs --collections > dest-refs - assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" - assert_file_has_content dest-refs "^(org.example.Collection1, test-2)$" - assert_not_file_has_content dest-refs "^(org.example.Collection1, test-3)$" + assert_file_has_content dest-refs "^(org\.example\.Collection1, test-1)$" + assert_file_has_content dest-refs "^(org\.example\.Collection1, test-2)$" + assert_not_file_has_content dest-refs "^(org\.example\.Collection1, test-3)$" assert_has_file "${usb_mount}"/.ostree/repo/summary # Pull into a second local repository (theoretically, a separate computer). @@ -112,15 +112,15 @@ for fs_type in ext4 vfat; do ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type remote add remote1 file://just-here-for-the-keyring --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type find-remotes --finders=mount org.example.Collection1 test-1 > find-results - assert_not_file_has_content find-results "^No results.$" + assert_not_file_has_content find-results "^No results\.$" assert_file_has_content find-results "^Result 0: file://${usb_mount}" - assert_file_has_content find-results "(org.example.Collection1, test-1) = $(cat ref1-checksum)$" + assert_file_has_content find-results "(org\.example\.Collection1, test-1) = $(cat ref1-checksum)$" ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type find-remotes --finders=mount --pull org.example.Collection1 test-1 > pull-results - assert_file_has_content pull-results "^Pulled 1/1 refs successfully.$" + assert_file_has_content pull-results "^Pulled 1/1 refs successfully\.$" ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type refs --collections > refs - assert_file_has_content refs "^(org.example.Collection1, test-1)$" + assert_file_has_content refs "^(org\.example\.Collection1, test-1)$" ${SUDO} umount "${MOUNT_INTEGRATION_DEV}" diff --git a/tests/test-summary-collections.sh b/tests/test-summary-collections.sh index 22921f53..777d3d0c 100755 --- a/tests/test-summary-collections.sh +++ b/tests/test-summary-collections.sh @@ -43,19 +43,19 @@ done ${CMD_PREFIX} ostree --repo=repo summary --update ${CMD_PREFIX} ostree --repo=repo summary --view > summary -assert_file_has_content summary "(org.example.Collection, test-1)$" -assert_file_has_content summary "(org.example.Collection, test-2)$" -assert_file_has_content summary "(org.example.Collection, test-3)$" -assert_file_has_content summary "(org.example.Collection, test-4)$" -assert_file_has_content summary "(org.example.Collection, test-5)$" -assert_file_has_content summary "^Collection ID (ostree\.summary\.collection-id): org.example.Collection$" +assert_file_has_content summary "(org\.example\.Collection, test-1)$" +assert_file_has_content summary "(org\.example\.Collection, test-2)$" +assert_file_has_content summary "(org\.example\.Collection, test-3)$" +assert_file_has_content summary "(org\.example\.Collection, test-4)$" +assert_file_has_content summary "(org\.example\.Collection, test-5)$" +assert_file_has_content summary "^Collection ID (ostree\.summary\.collection-id): org\.example\.Collection$" # Test that mirrored branches are listed too. ${CMD_PREFIX} ostree --repo=repo refs --collections --create=org.example.OtherCollection:test-1-mirror test-1 ${CMD_PREFIX} ostree --repo=repo summary --update ${CMD_PREFIX} ostree --repo=repo summary --view > summary -assert_file_has_content summary "(org.example.OtherCollection, test-1-mirror)$" +assert_file_has_content summary "(org\.example\.OtherCollection, test-1-mirror)$" # Test that remote refs are listed, but only if they have collection IDs cd ${test_tmpdir} @@ -68,7 +68,7 @@ ${CMD_PREFIX} ostree --repo=repo pull collection-repo-remote rcommit ${CMD_PREFIX} ostree --repo=repo summary --update ${CMD_PREFIX} ostree --repo=repo summary --view > summary -assert_file_has_content summary "(org.example.RemoteCollection, rcommit)$" +assert_file_has_content summary "(org\.example\.RemoteCollection, rcommit)$" cd ${test_tmpdir} mkdir no-collection-repo diff --git a/tests/test-summary-update.sh b/tests/test-summary-update.sh index 6fb5a4be..062d5bd4 100755 --- a/tests/test-summary-update.sh +++ b/tests/test-summary-update.sh @@ -90,12 +90,12 @@ assert_file_has_content summary "^map: {}$" # Check the ostree-metadata ref has also been created with the same content and appropriate bindings. ${CMD_PREFIX} ostree --repo=repo refs --collections > refs -assert_file_has_content refs "^(org.example.Collection1, ostree-metadata)$" +assert_file_has_content refs "^(org\.example\.Collection1, ostree-metadata)$" ${CMD_PREFIX} ostree --repo=repo show ostree-metadata --raw > metadata assert_file_has_content metadata "'map': <@a{sv} {}>" -assert_file_has_content metadata "'ostree.ref-binding': <\['ostree-metadata'\]>" -assert_file_has_content metadata "'ostree.collection-binding': <'org.example.Collection1'>" +assert_file_has_content metadata "'ostree\.ref-binding': <\['ostree-metadata'\]>" +assert_file_has_content metadata "'ostree\.collection-binding': <'org\.example\.Collection1'>" # There should be 5 commits in the ostree-metadata branch, since we’ve updated the summary 5 times. ${CMD_PREFIX} ostree --repo=repo log ostree-metadata | grep 'commit ' | wc -l > commit-count diff --git a/tests/test-xattrs.sh b/tests/test-xattrs.sh index e2a192a9..07c9ac38 100755 --- a/tests/test-xattrs.sh +++ b/tests/test-xattrs.sh @@ -42,8 +42,8 @@ echo "ok commit with xattrs" ${CMD_PREFIX} ostree --repo=repo checkout test2 test2-checkout2 getfattr -m . test2-checkout2/firstfile > attrs -assert_file_has_content attrs '^user.ostree-test' -assert_file_has_content attrs '^user.test0' +assert_file_has_content attrs '^user\.ostree-test' +assert_file_has_content attrs '^user\.test0' getfattr -n user.ostree-test --only-values test2-checkout2/firstfile > v0 assert_file_has_content v0 '^testvalue$' getfattr -n user.test0 --only-values test2-checkout2/firstfile > v1 From 89c00e7eb72ddc5aaee3469f281fb5560ff7bd5d Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Mon, 1 Apr 2019 19:04:05 -0700 Subject: [PATCH 33/50] tests: Put a regex in quotes Closes: #1834 Approved by: rfairley --- tests/installed/destructive/itest-bare-root.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/installed/destructive/itest-bare-root.sh b/tests/installed/destructive/itest-bare-root.sh index 18a3931f..055d873c 100755 --- a/tests/installed/destructive/itest-bare-root.sh +++ b/tests/installed/destructive/itest-bare-root.sh @@ -27,7 +27,7 @@ ostree fsck ostree ls -X testref ${victim_symlink} > ls.txt assert_file_has_content ls.txt 'security\.biometric' ostree ls -X ${host_refspec} ${victim_symlink} > ls.txt -assert_not_file_has_content ls.txt security\.biometric +assert_not_file_has_content ls.txt 'security\.biometric' ostree ls -X testref usr/bin > ls.txt assert_file_has_content ls.txt 'security\.crunchy' From a8754ae3708431d72be63723a6362a4edc82df84 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 12 Apr 2019 13:49:08 -0400 Subject: [PATCH 34/50] boot: Activate ostree-finalize-staged even earlier Really, all `ostree admin finalize-staged` needs is access to `/sysroot` and `/boot`. So let's activate it right after `local-fs.target` so that it gets deactivated later in the shutdown process. This should allow us to conflict with less services still running and possibly writing things to `/etc`. Related: https://bugzilla.redhat.com/show_bug.cgi?id=1672283 Closes: #1840 Approved by: cgwalters --- src/boot/ostree-finalize-staged.service | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boot/ostree-finalize-staged.service b/src/boot/ostree-finalize-staged.service index 10e551e4..e112bc0c 100644 --- a/src/boot/ostree-finalize-staged.service +++ b/src/boot/ostree-finalize-staged.service @@ -24,8 +24,8 @@ ConditionPathExists=/run/ostree-booted DefaultDependencies=no RequiresMountsFor=/sysroot -After=basic.target -Before=multi-user.target final.target +After=local-fs.target +Before=basic.target final.target Conflicts=final.target [Service] From 23304b8c15835e75e257c7eb589808e40f3e39c9 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Wed, 20 Feb 2019 13:18:31 -0800 Subject: [PATCH 35/50] lib/repo-refs: Fix resolving collection-refs My last commit "lib/repo-refs: Resolve collection-refs in-memory and in parent repos" changed ostree_repo_resolve_collection_ref() to check the in-memory set of refs *after* failing to find the ref on disk but that's not what we want. We want to use the in-memory set of refs first, because those are the most up to date commits, and then fall back to the on-disk repo and finally fall back to checking any parent repo. This commit makes such a change to the order of operations, which is consistent with how ostree_repo_resolve_rev() works. Aside from this change being logical, it also fixes some unit test failures on an unmerged branch of flatpak: https://github.com/flatpak/flatpak/pull/2705 Also, tweak the comments here. Closes: #1825 Approved by: jlebon --- src/libostree/ostree-repo-refs.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index ee11eb53..be2eb59a 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -525,23 +525,17 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self, GCancellable *cancellable, GError **error) { + g_autofree char *ret_contents = NULL; + g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); g_return_val_if_fail (ref != NULL, FALSE); g_return_val_if_fail (ref->collection_id != NULL && ref->ref_name != NULL, FALSE); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */ - if (!ostree_repo_list_collection_refs (self, ref->collection_id, &refs, - OSTREE_REPO_LIST_REFS_EXT_NONE, - cancellable, error)) - return FALSE; - - g_autofree char *ret_contents = g_strdup (g_hash_table_lookup (refs, ref)); - - /* Check for refs in the current transaction that haven't been written to - * disk, to match the behavior of ostree_repo_resolve_rev() */ - if (ret_contents == NULL && self->in_transaction) + /* Check for the ref in the current transaction in case it hasn't been + * written to disk, to match the behavior of ostree_repo_resolve_rev() */ + if (self->in_transaction) { g_mutex_lock (&self->txn_lock); if (self->txn.collection_refs) @@ -549,7 +543,19 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self, g_mutex_unlock (&self->txn_lock); } - /* Check for refs in the parent repo */ + /* Check for the ref on disk in the repo */ + if (ret_contents == NULL) + { + g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */ + if (!ostree_repo_list_collection_refs (self, ref->collection_id, &refs, + OSTREE_REPO_LIST_REFS_EXT_NONE, + cancellable, error)) + return FALSE; + + ret_contents = g_strdup (g_hash_table_lookup (refs, ref)); + } + + /* Check for the ref in the parent repo */ if (ret_contents == NULL && self->parent_repo != NULL) { if (!ostree_repo_resolve_collection_ref (self->parent_repo, From 0ecbc6f2a9ddd6ab9700e98da794eef7290ffdc7 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 21 Feb 2019 15:39:45 -0800 Subject: [PATCH 36/50] lib/repo-refs: Add a flag to exclude listing from refs/mirrors Currently the flag OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES for ostree_repo_list_collection_refs() means that refs in refs/remotes/ should be excluded but refs in refs/mirrors/ should still be checked, in addition to refs/heads/ which is always checked. However in some situations you want to exclude both remote and mirrored refs and only check local "owned" ones. So this commit adds a new flag OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS which lets you exclude refs/mirrors/ from the listing. This way we can avoid breaking API but still allow the listing of local collection-refs. The impetus for this change is that I'm changing Flatpak to make more use of refs/mirrors, and we need a way to specify that a collection-ref is local when using ostree_repo_resolve_collection_ref() in, for example, the implementation of the repo command. The subsequent commit will make the changes needed there. Closes: #1825 Approved by: jlebon --- src/libostree/ostree-repo-refs.c | 15 ++++++++++----- src/libostree/ostree-repo.h | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index be2eb59a..fec36420 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -1247,7 +1247,9 @@ _ostree_repo_update_collection_refs (OstreeRepo *self, * (ostree_repo_get_collection_id()). * * If you want to exclude refs from `refs/remotes`, use - * %OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES in @flags. + * %OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES in @flags. Similarly use + * %OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS to exclude refs from + * `refs/mirrors`. * * Returns: %TRUE on success, %FALSE otherwise * Since: 2018.6 @@ -1269,9 +1271,12 @@ ostree_repo_list_collection_refs (OstreeRepo *self, if (match_collection_id != NULL && !ostree_validate_collection_id (match_collection_id, error)) return FALSE; - const gchar *refs_dirs[] = { "refs/mirrors", "refs/remotes", NULL }; - if (flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES) - refs_dirs[1] = NULL; + g_autoptr(GPtrArray) refs_dirs = g_ptr_array_new (); + if (!(flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS)) + g_ptr_array_add (refs_dirs, "refs/mirrors"); + if (!(flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES)) + g_ptr_array_add (refs_dirs, "refs/remotes"); + g_ptr_array_add (refs_dirs, NULL); g_autoptr(GHashTable) ret_all_refs = NULL; @@ -1301,7 +1306,7 @@ ostree_repo_list_collection_refs (OstreeRepo *self, g_string_truncate (base_path, 0); - for (const char **iter = refs_dirs; iter && *iter; iter++) + for (const char **iter = (const char **)refs_dirs->pdata; iter && *iter; iter++) { const char *refs_dir = *iter; gboolean refs_dir_exists = FALSE; diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 7eb983cf..d24077c9 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -499,11 +499,13 @@ gboolean ostree_repo_list_refs (OstreeRepo *self, * @OSTREE_REPO_LIST_REFS_EXT_NONE: No flags. * @OSTREE_REPO_LIST_REFS_EXT_ALIASES: Only list aliases. Since: 2017.10 * @OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES: Exclude remote refs. Since: 2017.11 + * @OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS: Exclude mirrored refs. Since: 2019.2 */ typedef enum { OSTREE_REPO_LIST_REFS_EXT_NONE = 0, OSTREE_REPO_LIST_REFS_EXT_ALIASES = (1 << 0), OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES = (1 << 1), + OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS = (1 << 2), } OstreeRepoListRefsExtFlags; _OSTREE_PUBLIC From 78747a8a17fccf73486fe9e74b180f4cc8c2ad72 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 21 Feb 2019 15:47:16 -0800 Subject: [PATCH 37/50] lib/repo-refs: Allow resolving local collection-refs Currently for a "normal" refspec you can choose to use ostree_repo_resolve_rev_ext() instead of ostree_repo_resolve_rev() if you only want to look at local refs (in refs/heads/) not remote ones. This commit provides the analogous functionality for ostree_repo_resolve_collection_ref() by adding a flag OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY and implementing it. This will be used by Flatpak. Closes: #1825 Approved by: jlebon --- src/libostree/ostree-repo-refs.c | 28 ++++++++++++++++++++++++---- src/libostree/ostree-repo.h | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index fec36420..c512787a 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -479,6 +479,9 @@ ostree_repo_resolve_rev (OstreeRepo *self, * the parameter @out_rev. Differently from ostree_repo_resolve_rev(), * this will not fall back to searching through remote repos if a * local ref is specified but not found. + * + * The flag %OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY is implied so + * using it has no effect. */ gboolean ostree_repo_resolve_rev_ext (OstreeRepo *self, @@ -511,7 +514,9 @@ ostree_repo_resolve_rev_ext (OstreeRepo *self, * the given @ref cannot be found, a %G_IO_ERROR_NOT_FOUND error will be * returned. * - * There are currently no @flags which affect the behaviour of this function. + * If you want to check only local refs, not remote or mirrored ones, use the + * flag %OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY. This is analogous to using + * ostree_repo_resolve_rev_ext() but for collection-refs. * * Returns: %TRUE on success, %FALSE on failure * Since: 2018.6 @@ -539,7 +544,16 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self, { g_mutex_lock (&self->txn_lock); if (self->txn.collection_refs) - ret_contents = g_strdup (g_hash_table_lookup (self->txn.collection_refs, ref)); + { + const char *repo_collection_id = ostree_repo_get_collection_id (self); + /* If the collection ID doesn't match it's a remote ref */ + if (!(flags & OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY) || + repo_collection_id == NULL || + g_strcmp0 (repo_collection_id, ref->collection_id) == 0) + { + ret_contents = g_strdup (g_hash_table_lookup (self->txn.collection_refs, ref)); + } + } g_mutex_unlock (&self->txn_lock); } @@ -547,9 +561,15 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self, if (ret_contents == NULL) { g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */ + OstreeRepoListRefsExtFlags list_refs_flags; + + if (flags & OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY) + list_refs_flags = OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES | OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS; + else + list_refs_flags = OSTREE_REPO_LIST_REFS_EXT_NONE; + if (!ostree_repo_list_collection_refs (self, ref->collection_id, &refs, - OSTREE_REPO_LIST_REFS_EXT_NONE, - cancellable, error)) + list_refs_flags, cancellable, error)) return FALSE; ret_contents = g_strdup (g_hash_table_lookup (refs, ref)); diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index d24077c9..afa33155 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -465,9 +465,11 @@ gboolean ostree_repo_resolve_rev (OstreeRepo *self, /** * OstreeRepoResolveRevExtFlags: * @OSTREE_REPO_RESOLVE_REV_EXT_NONE: No flags. + * @OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY: Exclude remote and mirrored refs. Since: 2019.2 */ typedef enum { OSTREE_REPO_RESOLVE_REV_EXT_NONE = 0, + OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY = (1 << 0), } OstreeRepoResolveRevExtFlags; _OSTREE_PUBLIC From 298c601d889adf835b1dd4be4702ff2c6f8f70b6 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Tue, 25 Sep 2018 15:42:28 -0400 Subject: [PATCH 38/50] ostree-prepare-root: Log journal message after finding deployment Log a structured journal message when resolving the deployment path. This will be used by the `rpm-ostree history` command to find past deployments the system has booted into. Closes: #1842 Approved by: cgwalters --- Makefile-switchroot.am | 5 +++++ src/switchroot/ostree-prepare-root.c | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Makefile-switchroot.am b/Makefile-switchroot.am index 4423fdcd..586a8cd5 100644 --- a/Makefile-switchroot.am +++ b/Makefile-switchroot.am @@ -57,6 +57,11 @@ ostree_remount_SOURCES = \ $(NULL) ostree_remount_CPPFLAGS = $(AM_CPPFLAGS) -Isrc/switchroot +if BUILDOPT_SYSTEMD +ostree_prepare_root_CPPFLAGS += -DHAVE_SYSTEMD=1 +ostree_prepare_root_LDADD = $(AM_LDFLAGS) $(LIBSYSTEMD_LIBS) +endif + # This is the "new mode" of using a generator for /var; see # https://github.com/ostreedev/ostree/issues/855 if BUILDOPT_SYSTEMD_AND_LIBMOUNT diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 01a85569..c4208750 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -47,6 +47,11 @@ #include #include +#ifdef HAVE_LIBSYSTEMD +#include +#define OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG SD_ID128_MAKE(71,70,33,6a,73,ba,46,01,ba,d3,1a,f8,88,aa,0d,f7) +#endif + #include "ostree-mount-util.h" /* Initialized early in main */ @@ -71,9 +76,19 @@ resolve_deploy_path (const char * root_mountpoint) deploy_path = realpath (destpath, NULL); if (deploy_path == NULL) err (EXIT_FAILURE, "realpath(%s) failed", destpath); + if (stat (deploy_path, &stbuf) < 0) + err (EXIT_FAILURE, "stat(%s) failed", deploy_path); /* Quiet logs if there's no journal */ - if (!running_as_pid1) - printf ("Resolved OSTree target to: %s\n", deploy_path); +#ifdef HAVE_LIBSYSTEMD + const char *resolved_path = deploy_path + strlen (root_mountpoint); + sd_journal_send ("MESSAGE=Resolved OSTree target to: %s", deploy_path, + "MESSAGE_ID=" SD_ID128_FORMAT_STR, + SD_ID128_FORMAT_VAL(OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG), + "DEPLOYMENT_PATH=%s", resolved_path, + "DEPLOYMENT_DEVICE=%u", stbuf.st_dev, + "DEPLOYMENT_INODE=%u", stbuf.st_ino, + NULL); +#endif return deploy_path; } From 95d6701fb9c4f7cfe152b8f5f2f47f8c0ba81402 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Fri, 12 Apr 2019 12:10:41 -0400 Subject: [PATCH 39/50] travis: Update to Debian Stretch Update to Stretch to use updated version of glib2.0. Fixes CI failure when parsing error output in tests/test-config.sh. See: https://github.com/ostreedev/ostree/pull/1838#issuecomment-482186680 https://api.travis-ci.org/v3/job/518830164/log.txt Closes: #1839 Approved by: cgwalters --- .travis.yml | 4 ++-- ci/travis-install.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 140e7ada..c2342b0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ sudo: required env: - ci_distro=ubuntu ci_suite=trusty ci_test=no # TODO: use libcurl on this - - ci_docker=debian:jessie-slim ci_distro=debian ci_suite=jessie - - ci_docker=debian:jessie-slim ci_distro=debian ci_suite=jessie ci_configopts="--with-curl" + - ci_docker=debian:stretch-slim ci_distro=debian ci_suite=stretch + - ci_docker=debian:stretch-slim ci_distro=debian ci_suite=stretch ci_configopts="--with-curl" - ci_docker=debian:stretch-slim ci_distro=debian ci_suite=stretch ci_test=no # TODO gpgme flake https://github.com/ostreedev/ostree/pull/664#issuecomment-276033383 - ci_docker=ubuntu:xenial ci_distro=ubuntu ci_suite=xenial diff --git a/ci/travis-install.sh b/ci/travis-install.sh index 8dd373d3..8992aed0 100755 --- a/ci/travis-install.sh +++ b/ci/travis-install.sh @@ -48,7 +48,7 @@ NULL= # Typical values for ci_distro=ubuntu: xenial, trusty # Typical values for ci_distro=debian: sid, jessie # Typical values for ci_distro=fedora might be 25, rawhide -: "${ci_suite:=jessie}" +: "${ci_suite:=stretch}" # ci_configopts: Additional arguments for configure : "${ci_configopts:=}" From 498a8bd404db86b6b46662ccde5a51344b212187 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 17 Apr 2019 12:03:55 -0400 Subject: [PATCH 40/50] tests/test-config: Fix regex causing Debian test failure Fix CI failure due to mismatching quotes in the error output given between Fedora and Debian test suites. Example of the error in Debian Stretch: https://api.travis-ci.org/v3/job/519335717/log.txt Closes: #1839 Approved by: cgwalters --- tests/test-config.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test-config.sh b/tests/test-config.sh index 483cff41..7e913d32 100755 --- a/tests/test-config.sh +++ b/tests/test-config.sh @@ -76,7 +76,9 @@ assert_not_file_has_content repo/config "lock-timeout-secs=" if ${CMD_PREFIX} ostree config --repo=repo get core.lock-timeout-secs 2>err.txt; then assert_not_reached "ostree config get should not work after unsetting a key" fi -assert_file_has_content err.txt "error: Key file does not have key “lock-timeout-secs” in group “core”" +# Check for any character where quotation marks would be as they appear differently in the Fedora and Debian +# test suites (“” and '' respectively). See: https://github.com/ostreedev/ostree/pull/1839 +assert_file_has_content err.txt "error: Key file does not have key .lock-timeout-secs. in group .core." # Check that it's idempotent ${CMD_PREFIX} ostree config --repo=repo unset core.lock-timeout-secs From 794f75ca61badfe34f4ba1f8eb50a574d83d3c58 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Tue, 23 Apr 2019 16:03:48 -0400 Subject: [PATCH 41/50] lib/sysroot: Call `chmod` on overlay dirs when unlocking Otherwise, we'll be subject to whatever `umask` is currently. Normally, processes should respect `umask` when creating files and directories, but specifically for `ostree admin unlock` (or `rpm-ostree usroverlay`), this poses a problem since e.g. a `/usr` with mode 0700 will break any daemon that doesn't run as root and needs to read files under `/usr`, such as polkitd. This patch just does a `chmod()` after the `mkdir()`. An alternative would be to do `umask(0000)` after forking into the child process that'll call `mount()`, but that'd require also moving the `mkdir()` calls into there, making for a more intrusive patch. Closes: #1843 Approved by: cgwalters --- src/libostree/ostree-sysroot.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 84c12301..200af99f 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1699,6 +1699,22 @@ clone_deployment (OstreeSysroot *sysroot, return TRUE; } +/* Do `mkdir()` followed by `chmod()` immediately afterwards to ensure `umask()` isn't + * masking permissions where we don't want it to. Thus we avoid calling `umask()`, which + * would affect the whole process. */ +static gboolean mkdir_unmasked (int dfd, + const char *path, + int mode, + GCancellable *cancellable, + GError **error) +{ + if (!glnx_shutil_mkdir_p_at (dfd, path, mode, cancellable, error)) + return FALSE; + if (fchmodat (dfd, path, mode, 0) < 0) + return glnx_throw_errno_prefix (error, "chmod(%s)", path); + return TRUE; +} + /** * ostree_sysroot_deployment_unlock: * @self: Sysroot @@ -1768,9 +1784,9 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, * directly for hotfixes. The ostree-prepare-root.c helper * is also set up to detect and mount these. */ - if (!glnx_shutil_mkdir_p_at (deployment_dfd, ".usr-ovl-upper", 0755, cancellable, error)) + if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-upper", 0755, cancellable, error)) return FALSE; - if (!glnx_shutil_mkdir_p_at (deployment_dfd, ".usr-ovl-work", 0755, cancellable, error)) + if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-work", 0755, cancellable, error)) return FALSE; ovl_options = hotfix_ovl_options; } @@ -1796,10 +1812,10 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, } development_ovl_upper = glnx_strjoina (development_ovldir, "/upper"); - if (!glnx_shutil_mkdir_p_at (AT_FDCWD, development_ovl_upper, 0755, cancellable, error)) + if (!mkdir_unmasked (AT_FDCWD, development_ovl_upper, 0755, cancellable, error)) return FALSE; development_ovl_work = glnx_strjoina (development_ovldir, "/work"); - if (!glnx_shutil_mkdir_p_at (AT_FDCWD, development_ovl_work, 0755, cancellable, error)) + if (!mkdir_unmasked (AT_FDCWD, development_ovl_work, 0755, cancellable, error)) return FALSE; ovl_options = glnx_strjoina ("lowerdir=usr,upperdir=", development_ovl_upper, ",workdir=", development_ovl_work); From ba96d7ed7af1919eba54ebc3c2923d9947a22f57 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 24 Apr 2019 09:42:56 -0400 Subject: [PATCH 42/50] lib/sysroot: Match deployment /usr mode for overlay Rather than hardcoding 0755, let's directly look at what `/usr`'s mode is and copy it when creating the overlay. Closes: #1843 Approved by: cgwalters --- src/libostree/ostree-sysroot.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 200af99f..21ea1734 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1771,6 +1771,14 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, if (!sepolicy) return FALSE; + /* we want our /usr overlay to have the same permission bits as the one we'll shadow */ + mode_t usr_mode; + { struct stat stbuf; + if (!glnx_fstatat (deployment_dfd, "usr", &stbuf, 0, error)) + return FALSE; + usr_mode = stbuf.st_mode; + } + const char *ovl_options = NULL; static const char hotfix_ovl_options[] = "lowerdir=usr,upperdir=.usr-ovl-upper,workdir=.usr-ovl-work"; switch (unlocked_state) @@ -1784,9 +1792,9 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, * directly for hotfixes. The ostree-prepare-root.c helper * is also set up to detect and mount these. */ - if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-upper", 0755, cancellable, error)) + if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-upper", usr_mode, cancellable, error)) return FALSE; - if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-work", 0755, cancellable, error)) + if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-work", usr_mode, cancellable, error)) return FALSE; ovl_options = hotfix_ovl_options; } @@ -1804,7 +1812,7 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, { g_auto(OstreeSepolicyFsCreatecon) con = { 0, }; if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy, - "/usr", 0755, error)) + "/usr", usr_mode, error)) return FALSE; if (g_mkdtemp_full (development_ovldir, 0755) == NULL) @@ -1812,10 +1820,10 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, } development_ovl_upper = glnx_strjoina (development_ovldir, "/upper"); - if (!mkdir_unmasked (AT_FDCWD, development_ovl_upper, 0755, cancellable, error)) + if (!mkdir_unmasked (AT_FDCWD, development_ovl_upper, usr_mode, cancellable, error)) return FALSE; development_ovl_work = glnx_strjoina (development_ovldir, "/work"); - if (!mkdir_unmasked (AT_FDCWD, development_ovl_work, 0755, cancellable, error)) + if (!mkdir_unmasked (AT_FDCWD, development_ovl_work, usr_mode, cancellable, error)) return FALSE; ovl_options = glnx_strjoina ("lowerdir=usr,upperdir=", development_ovl_upper, ",workdir=", development_ovl_work); From 144e99ce47041fbc29c648bafe06121bbdc5ada2 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Thu, 14 Mar 2019 19:17:37 -0400 Subject: [PATCH 43/50] tests/test-admin-deploy-none: Update comment for #1774 status Closes: #1831 Approved by: jlebon --- tests/test-admin-deploy-none.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-admin-deploy-none.sh b/tests/test-admin-deploy-none.sh index 9094036a..d798e60e 100755 --- a/tests/test-admin-deploy-none.sh +++ b/tests/test-admin-deploy-none.sh @@ -35,8 +35,8 @@ cd ${test_tmpdir} rm httpd osdata testos-repo sysroot -rf setup_os_repository "archive" "sysroot.bootloader none" ${CMD_PREFIX} ostree pull-local --repo=sysroot/ostree/repo --remote testos testos-repo testos/buildmaster/x86_64-runtime -# Test grub2 does not get detected with bootloader configuration "none" -# (see https://github.com/ostreedev/ostree/issues/1774) +# Test that configuring sysroot.bootloader="none" is a workaround for previous +# grub2 bootloader issue (see https://github.com/ostreedev/ostree/issues/1774) mkdir -p sysroot/boot/grub2 && touch sysroot/boot/grub2/grub.cfg ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os testos testos/buildmaster/x86_64-runtime > out.txt assert_file_has_content out.txt "Bootloader updated.*" From 42573eae5989dd5f67c341877ef2ee37ef8f24c0 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 3 Apr 2019 12:25:04 -0400 Subject: [PATCH 44/50] tests/test-admin-deploy-none: Split grub.cfg directory and file creation Split the creation of the directory containing grub.cfg, and the creation of the file, so that a failure in the mkdir command will fail the test and not attempt the touch command. Closes: #1831 Approved by: jlebon --- tests/test-admin-deploy-none.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test-admin-deploy-none.sh b/tests/test-admin-deploy-none.sh index d798e60e..66a1491f 100755 --- a/tests/test-admin-deploy-none.sh +++ b/tests/test-admin-deploy-none.sh @@ -37,7 +37,8 @@ setup_os_repository "archive" "sysroot.bootloader none" ${CMD_PREFIX} ostree pull-local --repo=sysroot/ostree/repo --remote testos testos-repo testos/buildmaster/x86_64-runtime # Test that configuring sysroot.bootloader="none" is a workaround for previous # grub2 bootloader issue (see https://github.com/ostreedev/ostree/issues/1774) -mkdir -p sysroot/boot/grub2 && touch sysroot/boot/grub2/grub.cfg +mkdir -p sysroot/boot/grub2 +touch sysroot/boot/grub2/grub.cfg ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os testos testos/buildmaster/x86_64-runtime > out.txt assert_file_has_content out.txt "Bootloader updated.*" assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO' From d69214ade3d5b187ebfbb791d7cfb36155c4f8dd Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Thu, 14 Mar 2019 19:16:07 -0400 Subject: [PATCH 45/50] grub2: Generate config from pending deployment Generate a grub2 config using the pending deployment, if a grub2 bootloader is detected in the sysroot. Allows grub2-mkconfig to run if there are no previous deployments. Fixes: #1774 Closes: #1831 Approved by: jlebon --- src/libostree/ostree-bootloader-grub2.c | 11 +++++------ src/libostree/ostree-bootloader-syslinux.c | 9 +++++---- src/libostree/ostree-bootloader-uboot.c | 9 +++++---- src/libostree/ostree-bootloader.c | 6 ++++-- src/libostree/ostree-bootloader.h | 2 ++ src/libostree/ostree-sysroot-deploy.c | 3 ++- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/libostree/ostree-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c index 57673c7d..ceea682e 100644 --- a/src/libostree/ostree-bootloader-grub2.c +++ b/src/libostree/ostree-bootloader-grub2.c @@ -332,6 +332,7 @@ grub2_child_setup (gpointer user_data) static gboolean _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader, int bootversion, + GPtrArray *new_deployments, GCancellable *cancellable, GError **error) { @@ -357,15 +358,11 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader, if (use_system_grub2_mkconfig && ostree_sysroot_get_booted_deployment (self->sysroot) == NULL && g_file_has_parent (self->sysroot->path, NULL)) { - g_autoptr(GPtrArray) deployments = NULL; OstreeDeployment *tool_deployment; g_autoptr(GFile) tool_deployment_root = NULL; - deployments = ostree_sysroot_get_deployments (self->sysroot); - - g_assert_cmpint (deployments->len, >, 0); - - tool_deployment = deployments->pdata[0]; + g_assert_cmpint (new_deployments->len, >, 0); + tool_deployment = new_deployments->pdata[0]; /* Sadly we have to execute code to generate the bootloader configuration. * If we're in a booted deployment, we just don't chroot. @@ -380,6 +377,8 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader, grub2_mkconfig_chroot = g_file_get_path (tool_deployment_root); } + g_debug ("Using grub2-mkconfig chroot: %s\n", grub2_mkconfig_chroot); + g_autoptr(GFile) new_config_path = NULL; g_autoptr(GFile) config_path_efi_dir = NULL; if (self->is_efi) diff --git a/src/libostree/ostree-bootloader-syslinux.c b/src/libostree/ostree-bootloader-syslinux.c index 8b09a861..5fb8a1db 100644 --- a/src/libostree/ostree-bootloader-syslinux.c +++ b/src/libostree/ostree-bootloader-syslinux.c @@ -108,10 +108,11 @@ append_config_from_loader_entries (OstreeBootloaderSyslinux *self, } static gboolean -_ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader, - int bootversion, - GCancellable *cancellable, - GError **error) +_ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader, + int bootversion, + GPtrArray *new_deployments, + GCancellable *cancellable, + GError **error) { OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader); diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c index 531a3756..87a93806 100644 --- a/src/libostree/ostree-bootloader-uboot.c +++ b/src/libostree/ostree-bootloader-uboot.c @@ -158,10 +158,11 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self, } static gboolean -_ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader, - int bootversion, - GCancellable *cancellable, - GError **error) +_ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader, + int bootversion, + GPtrArray *new_deployments, + GCancellable *cancellable, + GError **error) { OstreeBootloaderUboot *self = OSTREE_BOOTLOADER_UBOOT (bootloader); diff --git a/src/libostree/ostree-bootloader.c b/src/libostree/ostree-bootloader.c index 87823f7e..5b8125dc 100644 --- a/src/libostree/ostree-bootloader.c +++ b/src/libostree/ostree-bootloader.c @@ -54,13 +54,15 @@ _ostree_bootloader_get_name (OstreeBootloader *self) gboolean _ostree_bootloader_write_config (OstreeBootloader *self, int bootversion, + GPtrArray *new_deployments, GCancellable *cancellable, GError **error) { g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE); - return OSTREE_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion, - cancellable, error); + return OSTREE_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion, + new_deployments, + cancellable, error); } gboolean diff --git a/src/libostree/ostree-bootloader.h b/src/libostree/ostree-bootloader.h index a4793b08..5af2dcc8 100644 --- a/src/libostree/ostree-bootloader.h +++ b/src/libostree/ostree-bootloader.h @@ -44,6 +44,7 @@ struct _OstreeBootloaderInterface const char * (* get_name) (OstreeBootloader *self); gboolean (* write_config) (OstreeBootloader *self, int bootversion, + GPtrArray *new_deployments, GCancellable *cancellable, GError **error); gboolean (* is_atomic) (OstreeBootloader *self); @@ -61,6 +62,7 @@ const char *_ostree_bootloader_get_name (OstreeBootloader *self); gboolean _ostree_bootloader_write_config (OstreeBootloader *self, int bootversion, + GPtrArray *new_deployments, GCancellable *cancellable, GError **error); diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index d37861b7..22aa4a43 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2122,7 +2122,8 @@ write_deployments_bootswap (OstreeSysroot *self, if (bootloader) { if (!_ostree_bootloader_write_config (bootloader, new_bootversion, - cancellable, error)) + new_deployments, cancellable, + error)) return glnx_prefix_error (error, "Bootloader write config"); } From 5464535205261308d020bbe0e2a08962f78ab27e Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Tue, 16 Apr 2019 17:06:01 -0400 Subject: [PATCH 46/50] lib: Add ot_journal_* helper macros Rather than wrapping each instance of `sd_journal_*` with `HAVE_SYSTEMD`, let's just add some convenience macros that are just no-op if we're not compiling with systemd. Closes: #1841 Approved by: cgwalters --- src/libostree/ostree-fetcher-util.c | 4 +--- src/libostree/ostree-repo-pull.c | 2 +- src/libostree/ostree-sysroot-deploy.c | 16 ++++------------ src/libotutil/otutil.h | 8 ++++++++ 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libostree/ostree-fetcher-util.c b/src/libostree/ostree-fetcher-util.c index 35e8c3c3..ef02ba1e 100644 --- a/src/libostree/ostree-fetcher-util.c +++ b/src/libostree/ostree-fetcher-util.c @@ -163,18 +163,16 @@ _ostree_fetcher_journal_failure (const char *remote_name, const char *url, const char *msg) { -#ifdef HAVE_LIBSYSTEMD /* Sanity - we don't want to log this when doing local/file pulls */ if (!remote_name) return; - sd_journal_send ("MESSAGE=libostree HTTP error from remote %s for <%s>: %s", + ot_journal_send ("MESSAGE=libostree HTTP error from remote %s for <%s>: %s", remote_name, url, msg, "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_HTTP_FAILURE_ID), "OSTREE_REMOTE=%s", remote_name, "OSTREE_URL=%s", url, "PRIORITY=%i", LOG_ERR, NULL); -#endif } /* Check whether a particular operation should be retried. This is entirely diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 5d77bc7e..48935523 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -4655,7 +4655,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_autofree char *formatted_xferred = g_format_size (bytes_transferred); g_string_append_printf (msg, "\ntransfer: secs: %u size: %s", n_seconds, formatted_xferred); - sd_journal_send ("MESSAGE=%s", msg->str, + ot_journal_send ("MESSAGE=%s", msg->str, "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_MESSAGE_FETCH_COMPLETE_ID), "OSTREE_REMOTE=%s", pull_data->remote_name, "OSTREE_GPG=%s", gpg_verify_state, diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 22aa4a43..d837f8ec 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -447,14 +447,12 @@ merge_configuration_from (OstreeSysroot *sysroot, { g_autofree char *msg = g_strdup_printf ("Copying /etc changes: %u modified, %u removed, %u added", modified->len, removed->len, added->len); -#ifdef HAVE_LIBSYSTEMD - sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_CONFIGMERGE_ID), + ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_CONFIGMERGE_ID), "MESSAGE=%s", msg, "ETC_N_MODIFIED=%u", modified->len, "ETC_N_REMOVED=%u", removed->len, "ETC_N_ADDED=%u", added->len, NULL); -#endif _ostree_sysroot_emit_journal_msg (sysroot, msg); } @@ -701,11 +699,9 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot, { { g_autofree char *msg = g_strdup_printf ("Relabeling /var (no stamp file '%s' found)", selabeled); -#ifdef HAVE_LIBSYSTEMD - sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_VARRELABEL_ID), + ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_VARRELABEL_ID), "MESSAGE=%s", msg, NULL); -#endif _ostree_sysroot_emit_journal_msg (sysroot, msg); } @@ -2387,8 +2383,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, (bootloader_is_atomic ? "Transaction complete" : "Bootloader updated"), requires_new_bootversion ? "yes" : "no", new_deployments->len - self->deployments->len); -#ifdef HAVE_LIBSYSTEMD - sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_COMPLETE_ID), + ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_COMPLETE_ID), "MESSAGE=%s", msg, "OSTREE_BOOTLOADER=%s", bootloader ? _ostree_bootloader_get_name (bootloader) : "none", "OSTREE_BOOTLOADER_CONFIG=%s", bootloader_config, @@ -2399,7 +2394,6 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, "OSTREE_SYNCFS_BOOT_MSEC=%" G_GUINT64_FORMAT, syncstats.boot_syncfs_msec, "OSTREE_SYNCFS_EXTRA_MSEC=%" G_GUINT64_FORMAT, syncstats.extra_syncfs_msec, NULL); -#endif _ostree_sysroot_emit_journal_msg (self, msg); } @@ -2891,8 +2885,7 @@ _ostree_sysroot_finalize_staged (OstreeSysroot *self, /* Notice we send this *after* the trivial `return TRUE` above; this msg implies we've * committed to finalizing the deployment. */ -#ifdef HAVE_LIBSYSTEMD - sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, + ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_FINALIZING_ID), "MESSAGE=Finalizing staged deployment", "OSTREE_OSNAME=%s", @@ -2902,7 +2895,6 @@ _ostree_sysroot_finalize_staged (OstreeSysroot *self, "OSTREE_DEPLOYSERIAL=%u", ostree_deployment_get_deployserial (self->staged_deployment), NULL); -#endif g_assert (self->staged_deployment_data); diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index d648932e..eced95f9 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -44,6 +44,14 @@ } \ } G_STMT_END; +#ifdef HAVE_LIBSYSTEMD +#define ot_journal_send(...) sd_journal_send(__VA_ARGS__) +#define ot_journal_print(...) sd_journal_print(__VA_ARGS__) +#else +#define ot_journal_send(...) {} +#define ot_journal_print(...) {} +#endif + #include #include #include From 405d9ef9e0bb66cf7f93f11f49244852b57ee270 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Tue, 16 Apr 2019 17:08:24 -0400 Subject: [PATCH 47/50] lib/deploy: Write to journal if nothing to finalize This can happen if a deployment was staged and later cleaned up. Though just as a helper when debugging issues, let's explicitly mention that case. Closes: #1841 Approved by: cgwalters --- src/libostree/ostree-sysroot-deploy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index d837f8ec..ce11fe67 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2881,7 +2881,10 @@ _ostree_sysroot_finalize_staged (OstreeSysroot *self, * service when a staged deployment is created. */ if (!self->staged_deployment) - return TRUE; + { + ot_journal_print (LOG_INFO, "No deployment staged for finalization"); + return TRUE; + } /* Notice we send this *after* the trivial `return TRUE` above; this msg implies we've * committed to finalizing the deployment. */ From 586cc2deee96ada367a6033f9062e8b0c24bc687 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Tue, 16 Apr 2019 17:12:08 -0400 Subject: [PATCH 48/50] lib/deploy: Support locking deployment finalization Teach `ostree-finalize-staged.service` to check for a file in `/run` to determine if it should do the finalization. This will be used in RPM-OSTree, where we want to be able to separate out "preparing updates" from "making update the default" for more fine-grained control. See: https://github.com/projectatomic/rpm-ostree/issues/1748 Closes: #1841 Approved by: cgwalters --- src/libostree/ostree-sysroot-deploy.c | 11 +++++++++++ src/libostree/ostree-sysroot-private.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index ce11fe67..3ca6c148 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2886,6 +2886,17 @@ _ostree_sysroot_finalize_staged (OstreeSysroot *self, return TRUE; } + /* Check if finalization is locked. */ + if (!glnx_fstatat_allow_noent (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED, + NULL, 0, error)) + return FALSE; + if (errno == 0) + { + ot_journal_print (LOG_INFO, "Not finalizing; found " + _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED); + return TRUE; + } + /* Notice we send this *after* the trivial `return TRUE` above; this msg implies we've * committed to finalizing the deployment. */ ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 9da6d4c9..e4b2039e 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -76,6 +76,7 @@ struct OstreeSysroot { #define OSTREE_SYSROOT_LOCKFILE "ostree/lock" /* We keep some transient state in /run */ #define _OSTREE_SYSROOT_RUNSTATE_STAGED "/run/ostree/staged-deployment" +#define _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED "/run/ostree/staged-deployment-locked" #define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_DIR "/run/ostree/deployment-state/" #define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_DEVELOPMENT "unlocked-development" From 304abee9eba964d945eacad9217dcd4f9c678d4a Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 25 Apr 2019 09:08:23 +0000 Subject: [PATCH 49/50] prepare-root: Fix compilation with --with-static-compiler Closes: https://github.com/ostreedev/ostree/issues/1845 Closes: #1846 Approved by: akiernan --- Makefile-switchroot.am | 2 +- src/switchroot/ostree-prepare-root.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile-switchroot.am b/Makefile-switchroot.am index 586a8cd5..ff44d4bc 100644 --- a/Makefile-switchroot.am +++ b/Makefile-switchroot.am @@ -45,7 +45,7 @@ if BUILDOPT_USE_STATIC_COMPILER ostree_boot_SCRIPTS = ostree-prepare-root ostree-prepare-root : $(ostree_prepare_root_SOURCES) - $(STATIC_COMPILER) -o $@ -static $(top_srcdir)/src/switchroot/ostree-prepare-root.c $(ostree_prepare_root_CPPFLAGS) $(AM_CFLAGS) $(DEFAULT_INCLUDES) + $(STATIC_COMPILER) -o $@ -static $(top_srcdir)/src/switchroot/ostree-prepare-root.c $(ostree_prepare_root_CPPFLAGS) $(AM_CFLAGS) $(DEFAULT_INCLUDES) -DOSTREE_PREPARE_ROOT_STATIC=1 else ostree_boot_PROGRAMS += ostree-prepare-root ostree_prepare_root_CFLAGS = $(AM_CFLAGS) -Isrc/switchroot diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index c4208750..15d49963 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -47,7 +47,11 @@ #include #include -#ifdef HAVE_LIBSYSTEMD +#if defined(HAVE_LIBSYSTEMD) && !defined(OSTREE_PREPARE_ROOT_STATIC) +#define USE_LIBSYSTEMD +#endif + +#ifdef USE_LIBSYSTEMD #include #define OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG SD_ID128_MAKE(71,70,33,6a,73,ba,46,01,ba,d3,1a,f8,88,aa,0d,f7) #endif @@ -79,7 +83,7 @@ resolve_deploy_path (const char * root_mountpoint) if (stat (deploy_path, &stbuf) < 0) err (EXIT_FAILURE, "stat(%s) failed", deploy_path); /* Quiet logs if there's no journal */ -#ifdef HAVE_LIBSYSTEMD +#ifdef USE_LIBSYSTEMD const char *resolved_path = deploy_path + strlen (root_mountpoint); sd_journal_send ("MESSAGE=Resolved OSTree target to: %s", deploy_path, "MESSAGE_ID=" SD_ID128_FORMAT_STR, From 80435e12a7ec055195d2355b60a0882b65d42a94 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 24 Apr 2019 16:12:31 -0400 Subject: [PATCH 50/50] Release 2019.2 Also add `ostree_repo_get_bootloader` to the public API, which was missed when it was initially merged. Closes: #1844 Approved by: rfairley --- apidoc/ostree-sections.txt | 1 + configure.ac | 2 +- src/libostree/libostree-devel.sym | 8 ++++---- src/libostree/libostree-released.sym | 7 +++++++ tests/test-symbols.sh | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 5dbafc5f..1a26e1eb 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -293,6 +293,7 @@ ostree_repo_is_system ostree_repo_is_writable ostree_repo_create_at ostree_repo_create +ostree_repo_get_bootloader ostree_repo_get_path ostree_repo_get_mode ostree_repo_get_min_free_space_bytes diff --git a/configure.ac b/configure.ac index 3a2b1362..e6e145db 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ m4_define([year_version], [2019]) m4_define([release_version], [2]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) -is_release_build=no +is_release_build=yes AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 4ff2b86f..8d9a7bfc 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -18,15 +18,15 @@ ***/ /* Add new symbols here. Release commits should copy this section into -released.sym. */ -LIBOSTREE_2018.10 { +LIBOSTREE_2019.3 { } LIBOSTREE_2018.9; /* Stub section for the stable release *after* this development one; don't - * edit this other than to update the last number. This is just a copy/paste + * edit this other than to update the year. This is just a copy/paste * source. Replace $LASTSTABLE with the last stable version, and $NEWVERSION * with whatever the next version with new symbols will be. -LIBOSTREE_2018.$NEWVERSION { +LIBOSTREE_2019.$NEWVERSION { global: someostree_symbol_deleteme; -} LIBOSTREE_2018.$LASTSTABLE; +} LIBOSTREE_2019.$LASTSTABLE; */ diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym index 90b363ca..a4daaf1c 100644 --- a/src/libostree/libostree-released.sym +++ b/src/libostree/libostree-released.sym @@ -542,6 +542,13 @@ LIBOSTREE_2018.9 { ostree_repo_get_default_repo_finders; } LIBOSTREE_2018.7; +/* No new symbols in 2019.1 */ + +LIBOSTREE_2019.2 { + ostree_repo_get_bootloader; +} LIBOSTREE_2018.9; + + /* NOTE: Only add more content here in release commits! See the * comments at the top of this file. */ diff --git a/tests/test-symbols.sh b/tests/test-symbols.sh index 47f3ad73..ac058fad 100755 --- a/tests/test-symbols.sh +++ b/tests/test-symbols.sh @@ -54,7 +54,7 @@ echo 'ok documented symbols' # ONLY update this checksum in release commits! cat > released-sha256.txt <