diff options
author | Phaedrus Leeds <mwleeds@protonmail.com> | 2021-10-14 15:47:06 -0700 |
---|---|---|
committer | Phaedrus Leeds <mwleeds@protonmail.com> | 2021-10-21 11:32:05 -0700 |
commit | ef059257001f7b2fbd6a52c56d5dab2df399d0f7 (patch) | |
tree | fcbd14ff4b84683e5331cc3a76706801bba0fe53 | |
parent | f6da902b3870a4427355e81f75b9b26728817172 (diff) | |
download | flatpak-ef059257001f7b2fbd6a52c56d5dab2df399d0f7.tar.gz |
dir: Don't mask the main ref of a noenumerate remote
When we create origin remotes for apps installed via .flatpakref files,
we set xa.noenumerate=true and
xa.main-ref=app/com.example.App/arch/branch so that the remote is only
used for the app it was intended for. This is implemented in
flatpak_dir_list_remote_refs() by only listing refs in the remote which
are already installed. This works fine after the ref is installed but in
the short timespan between when the origin remote is created and the app
is installed from it, it means that the remote appears as empty.
The use case where I ran into this is in attempting to use
flatpak_installation_fetch_remote_ref_sync() in the gnome-software
flatpak plugin, in the handling of flatpakref files, which is intended
to just display information to the user and let them decide whether to
install the app. But I was not able to create a FlatpakRemoteRef due to
the behavior described above; see #4453 for more details.
So, change the behavior so that the main ref for an origin remote is
visible even before it is installed. This technically could be a
breaking change for some consumer of libflatpak but that seems very
unlikely, and the new behavior makes more sense.
Also add a unit test for this behavior.
-rw-r--r-- | common/flatpak-dir.c | 11 | ||||
-rw-r--r-- | tests/testlibrary.c | 93 |
2 files changed, 103 insertions, 1 deletions
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index 5cba0f5d..30436e45 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -14351,9 +14351,10 @@ flatpak_dir_list_remote_refs (FlatpakDir *self, GHashTableIter hash_iter; gpointer key; g_autofree char *refspec_prefix = g_strconcat (state->remote_name, ":.", NULL); + g_autofree char *remote_main_ref = NULL; /* For noenumerate remotes, only return data for already locally - * available refs */ + * available refs or the ref set as xa.main-ref on the remote */ if (!ostree_repo_list_refs (self->repo, refspec_prefix, &local_refs, cancellable, error)) @@ -14368,6 +14369,14 @@ flatpak_dir_list_remote_refs (FlatpakDir *self, g_hash_table_insert (decomposed_local_refs, g_steal_pointer (&d), NULL); } + remote_main_ref = flatpak_dir_get_remote_main_ref (self, state->remote_name); + if (remote_main_ref != NULL && *remote_main_ref != '\0') + { + g_autoptr(FlatpakDecomposed) d = flatpak_decomposed_new_from_col_ref (remote_main_ref, state->collection_id, NULL); + if (d) + g_hash_table_insert (decomposed_local_refs, g_steal_pointer (&d), NULL); + } + /* Then we remove all remote refs not in the local refs set */ g_hash_table_foreach_remove (*refs, remove_unless_decomposed_in_hash, diff --git a/tests/testlibrary.c b/tests/testlibrary.c index 28d68050..3f7912fe 100644 --- a/tests/testlibrary.c +++ b/tests/testlibrary.c @@ -2845,6 +2845,9 @@ empty_installation (FlatpakInstallation *inst) flatpak_installation_prune_local_repo (inst, NULL, &error); g_assert_no_error (error); + + flatpak_installation_drop_caches (inst, NULL, &error); + g_assert_no_error (error); } static int ready_count; @@ -3542,6 +3545,95 @@ test_transaction_flatpakref_remote_creation (void) } static gboolean +ready_check_origin_remote (FlatpakTransaction *transaction) +{ + g_autoptr(FlatpakInstallation) installation = NULL; + g_autoptr(FlatpakRemoteRef) remote_ref = NULL; + g_autoptr(FlatpakRemote) remote = NULL; + g_autoptr(GError) error = NULL; + g_autofree char *app = NULL; + + installation = flatpak_transaction_get_installation (transaction); + app = g_strdup_printf ("app/org.test.Hello/%s/master", + flatpak_get_default_arch ()); + + /* The remote should return the ref set as xa.main-ref on it despite having xa.noenumerate set */ + remote = flatpak_installation_get_remote_by_name (installation, "hello-origin", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (remote); + g_assert_true (flatpak_remote_get_noenumerate (remote)); + g_assert_cmpstr (flatpak_remote_get_main_ref (remote), ==, app); + + remote_ref = flatpak_installation_fetch_remote_ref_sync (installation, + "hello-origin", + FLATPAK_REF_KIND_APP, + "org.test.Hello", + flatpak_get_default_arch (), + "master", + NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (remote_ref); + + return TRUE; +} + +/* Test that installing a flatpakref causes an origin remote to be created when + * the file has no SuggestRemoteName= option, and check the options set on the + * remote */ +static void +test_transaction_flatpakref_origin_remote_creation (void) +{ + g_autoptr(FlatpakInstallation) user_inst = NULL; + g_autoptr(FlatpakTransaction) transaction = NULL; + g_autoptr(GError) error = NULL; + g_autofree char *s = NULL; + g_autoptr(GBytes) data = NULL; + gboolean res; + + user_inst = flatpak_installation_new_user (NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (user_inst); + + empty_installation (user_inst); + + assert_remote_not_in_installation (user_inst, "hello-origin"); + assert_remote_not_in_installation (user_inst, "test-runtime-only-repo"); + + transaction = flatpak_transaction_new_for_installation (user_inst, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (transaction); + + s = g_strconcat ("[Flatpak Ref]\n" + "Title=Test App\n" + "Name=org.test.Hello\n" + "Branch=master\n" + "Url=http://127.0.0.1:", httpd_port, "/test-without-runtime\n" + "IsRuntime=False\n" + "RuntimeRepo=http://127.0.0.1:", httpd_port, "/test-runtime-only/test-runtime-only-repo.flatpakrepo\n", + NULL); + + data = g_bytes_new (s, strlen (s)); + res = flatpak_transaction_add_install_flatpakref (transaction, data, &error); + g_assert_no_error (error); + g_assert_true (res); + + g_signal_connect (transaction, "add-new-remote", G_CALLBACK (add_new_remote3), NULL); + g_signal_connect (transaction, "ready", G_CALLBACK (ready_check_origin_remote), NULL); + + res = flatpak_transaction_run (transaction, NULL, &error); + g_assert_no_error (error); + g_assert_true (res); + + assert_remote_in_installation (user_inst, "hello-origin"); + assert_remote_in_installation (user_inst, "test-runtime-only-repo"); + + empty_installation (user_inst); + /* note: the origin remote will be removed automatically in the above prune */ + assert_remote_not_in_installation (user_inst, "hello-origin"); + remove_remote_user ("test-runtime-only-repo"); +} + +static gboolean check_ready1_abort (FlatpakTransaction *transaction) { GList *ops; @@ -4675,6 +4767,7 @@ main (int argc, char *argv[]) g_test_add_func ("/library/transaction-install-uninstall", test_transaction_install_uninstall); g_test_add_func ("/library/transaction-install-flatpakref", test_transaction_install_flatpakref); g_test_add_func ("/library/transaction-flatpakref-remote-creation", test_transaction_flatpakref_remote_creation); + g_test_add_func ("/library/transaction-flatpakref-origin-remote-creation", test_transaction_flatpakref_origin_remote_creation); g_test_add_func ("/library/transaction-deps", test_transaction_deps); g_test_add_func ("/library/transaction-install-local", test_transaction_install_local); g_test_add_func ("/library/transaction-app-runtime-same-remote", test_transaction_app_runtime_same_remote); |