summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhaedrus Leeds <mwleeds@protonmail.com>2021-10-14 15:47:06 -0700
committerPhaedrus Leeds <mwleeds@protonmail.com>2021-10-21 11:32:05 -0700
commitef059257001f7b2fbd6a52c56d5dab2df399d0f7 (patch)
treefcbd14ff4b84683e5331cc3a76706801bba0fe53
parentf6da902b3870a4427355e81f75b9b26728817172 (diff)
downloadflatpak-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.c11
-rw-r--r--tests/testlibrary.c93
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);