summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <53172+pwithnall@users.noreply.github.com>2021-11-02 11:14:37 +0000
committerGitHub <noreply@github.com>2021-11-02 11:14:37 +0000
commitcd2f796ba9e05e47c3dcd36fb7a2518447520ace (patch)
tree82c1d9a246868de6c83579aa00272d6b44434b7c
parent4da815f3b915e39e0c46af7292331f63070817b5 (diff)
parentdf3d85e7539281de6810ea93ba81b161e3e71774 (diff)
downloadflatpak-cd2f796ba9e05e47c3dcd36fb7a2518447520ace.tar.gz
Merge pull request #4487 from flatpak/dont-mask-noenumerate-main-refs
dir: Don't mask the main ref of a noenumerate remote
-rw-r--r--common/flatpak-dir.c57
-rw-r--r--tests/testlibrary.c273
2 files changed, 312 insertions, 18 deletions
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 5cba0f5d..c5b03d3e 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -12283,7 +12283,7 @@ flatpak_dir_list_all_remote_refs (FlatpakDir *self,
{
summary = var_summary_from_gvariant (subsummary);
ref_map = var_summary_get_ref_map (summary);
- populate_hash_table_from_refs_map (ret_all_refs, NULL, ref_map, NULL, state);
+ populate_hash_table_from_refs_map (ret_all_refs, NULL, ref_map, state->collection_id, state);
}
}
else if (state->summary != NULL)
@@ -14316,17 +14316,6 @@ flatpak_dir_modify_remote (FlatpakDir *self,
return TRUE;
}
-static gboolean
-remove_unless_decomposed_in_hash (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- GHashTable *table = user_data;
- const FlatpakDecomposed *d = key;
-
- return !g_hash_table_contains (table, d);
-}
-
gboolean
flatpak_dir_list_remote_refs (FlatpakDir *self,
FlatpakRemoteState *state,
@@ -14348,12 +14337,15 @@ flatpak_dir_list_remote_refs (FlatpakDir *self,
g_autoptr(GHashTable) decomposed_local_refs =
g_hash_table_new_full ((GHashFunc)flatpak_decomposed_hash, (GEqualFunc)flatpak_decomposed_equal, (GDestroyNotify)flatpak_decomposed_unref, NULL);
g_autoptr(GHashTable) local_refs = NULL;
+ g_autoptr(FlatpakDecomposed) decomposed_main_ref = NULL;
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, or
+ * extensions of that main ref */
if (!ostree_repo_list_refs (self->repo, refspec_prefix, &local_refs,
cancellable, error))
@@ -14363,15 +14355,44 @@ flatpak_dir_list_remote_refs (FlatpakDir *self,
while (g_hash_table_iter_next (&hash_iter, &key, NULL))
{
const char *refspec = key;
- g_autoptr(FlatpakDecomposed) d = flatpak_decomposed_new_from_refspec (refspec, NULL);
+ g_autofree char *ref = NULL;
+ g_autoptr(FlatpakDecomposed) d = NULL;
+
+ if (!ostree_parse_refspec (refspec, NULL, &ref, error))
+ return FALSE;
+
+ d = flatpak_decomposed_new_from_col_ref (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,
- decomposed_local_refs);
+ remote_main_ref = flatpak_dir_get_remote_main_ref (self, state->remote_name);
+ if (remote_main_ref != NULL && *remote_main_ref != '\0')
+ decomposed_main_ref = flatpak_decomposed_new_from_col_ref (remote_main_ref, state->collection_id, NULL);
+
+ /* Then we remove all remote refs not in the local refs set, not the main
+ * ref, and not an extension of the main ref */
+ GLNX_HASH_TABLE_FOREACH_IT (*refs, it, FlatpakDecomposed *, d, void *, v)
+ {
+ if (g_hash_table_contains (decomposed_local_refs, d))
+ continue;
+
+ if (decomposed_main_ref != NULL)
+ {
+ g_autofree char *main_ref_id = NULL;
+ g_autofree char *main_ref_prefix = NULL;
+
+ if (flatpak_decomposed_equal (decomposed_main_ref, d))
+ continue;
+
+ main_ref_id = flatpak_decomposed_dup_id (decomposed_main_ref);
+ main_ref_prefix = g_strconcat (main_ref_id, ".", NULL);
+ if (flatpak_decomposed_id_has_prefix (d, main_ref_prefix))
+ continue;
+ }
+
+ g_hash_table_iter_remove (&it);
+ }
}
return TRUE;
diff --git a/tests/testlibrary.c b/tests/testlibrary.c
index 28d68050..cac8a893 100644
--- a/tests/testlibrary.c
+++ b/tests/testlibrary.c
@@ -1129,6 +1129,63 @@ test_list_remote_refs (void)
}
}
+/* Test the xa.noenumerate option on a remote, which should mask non-installed refs */
+static void
+test_list_remote_refs_noenumerate (void)
+{
+ g_autoptr(FlatpakInstallation) inst = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) refs = NULL;
+ g_autoptr(FlatpakRemote) remote = NULL;
+ g_autoptr(FlatpakInstalledRef) runtime_ref = NULL;
+ gboolean res;
+
+ inst = flatpak_installation_new_user (NULL, &error);
+ g_assert_no_error (error);
+
+ empty_installation (inst);
+
+ refs = flatpak_installation_list_remote_refs_sync (inst, repo_name, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (refs);
+ g_assert_cmpint (refs->len, ==, 4);
+
+ /* Install a runtime */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ runtime_ref = flatpak_installation_install (inst,
+ repo_name,
+ FLATPAK_REF_KIND_RUNTIME,
+ "org.test.Platform",
+ NULL, "master", NULL, NULL, NULL,
+ &error);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ g_assert_no_error (error);
+ g_assert_true (FLATPAK_IS_INSTALLED_REF (runtime_ref));
+
+ /* Set xa.noenumerate=true */
+ remote = flatpak_installation_get_remote_by_name (inst, repo_name, NULL, &error);
+ g_assert_no_error (error);
+ flatpak_remote_set_noenumerate (remote, TRUE);
+ res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ /* Only the platform should be visible */
+ g_clear_pointer (&refs, g_ptr_array_unref);
+ refs = flatpak_installation_list_remote_refs_sync (inst, repo_name, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (refs);
+ g_assert_cmpint (refs->len, ==, 1);
+
+ empty_installation (inst);
+
+ /* Set xa.noenumerate=false */
+ flatpak_remote_set_noenumerate (remote, FALSE);
+ res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+}
+
static void
test_update_installed_ref_if_missing_runtime (void)
{
@@ -2845,6 +2902,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 +3602,107 @@ 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);
+
+ /* An extension with the main ref as a prefix should also be visible */
+ g_clear_object (&remote_ref);
+ remote_ref = flatpak_installation_fetch_remote_ref_sync (installation,
+ "hello-origin",
+ FLATPAK_REF_KIND_RUNTIME,
+ "org.test.Hello.Plugin.fun",
+ flatpak_get_default_arch (),
+ "v1",
+ 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;
@@ -3760,6 +3921,115 @@ test_transaction_app_runtime_same_remote (void)
remove_remote_user ("aaatest-runtime-only-repo");
}
+static gboolean
+ready_set_nodeps_on_remote (FlatpakTransaction *transaction)
+{
+ g_autoptr(FlatpakInstallation) installation = NULL;
+ g_autoptr(FlatpakRemote) remote = NULL;
+ g_autoptr(GError) error = NULL;
+ gboolean res;
+
+ installation = flatpak_transaction_get_installation (transaction);
+
+ /* Set the nodeps option on the runtime remote */
+ remote = flatpak_installation_get_remote_by_name (installation, "test-runtime-only-repo", NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (remote);
+ g_assert_false (flatpak_remote_get_nodeps (remote));
+
+ flatpak_remote_set_nodeps (remote, TRUE);
+ res = flatpak_installation_modify_remote (installation, remote, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ /* Abort since this transaction is already resolved; we need a new one */
+ return FALSE;
+}
+
+/* Test that setting xa.nodeps=true on the remote providing the runtime causes
+ * app installation to fail */
+static void
+test_remote_nodeps_option (void)
+{
+ g_autoptr(FlatpakInstallation) user_inst = NULL;
+ g_autoptr(FlatpakRemote) remote = 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");
+
+ /* Set the nodeps option on the test-repo remote */
+ remote = flatpak_installation_get_remote_by_name (user_inst, "test-repo", NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (remote);
+ g_assert_false (flatpak_remote_get_nodeps (remote));
+ flatpak_remote_set_nodeps (remote, TRUE);
+ res = flatpak_installation_modify_remote (user_inst, remote, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ 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_set_nodeps_on_remote), NULL);
+
+ res = flatpak_transaction_run (transaction, NULL, &error);
+ g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED);
+ g_assert_false (res);
+ g_clear_error (&error);
+
+ /* Make a new transaction so the runtime resolution happens again */
+ g_clear_object (&transaction);
+ transaction = flatpak_transaction_new_for_installation (user_inst, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (transaction);
+ 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);
+
+ res = flatpak_transaction_run (transaction, NULL, &error);
+ g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_RUNTIME_NOT_FOUND);
+ g_assert_false (res);
+ g_clear_error (&error);
+
+ /* Set nodeps back to false */
+ flatpak_remote_set_nodeps (remote, FALSE);
+ res = flatpak_installation_modify_remote (user_inst, remote, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ empty_installation (user_inst);
+ remove_remote_user ("hello-origin");
+ remove_remote_user ("test-runtime-only-repo");
+}
+
typedef struct
{
GMainLoop *loop;
@@ -4662,6 +4932,7 @@ main (int argc, char *argv[])
g_test_add_func ("/library/remote-new", test_remote_new);
g_test_add_func ("/library/remote-new-from-file", test_remote_new_from_file);
g_test_add_func ("/library/list-remote-refs", test_list_remote_refs);
+ g_test_add_func ("/library/list-remote-refs-noenumerate", test_list_remote_refs_noenumerate);
g_test_add_func ("/library/list-remote-related-refs", test_list_remote_related_refs);
g_test_add_func ("/library/list-remote-related-refs-for-installed", test_list_remote_related_refs_for_installed);
g_test_add_func ("/library/list-refs", test_list_refs);
@@ -4675,9 +4946,11 @@ 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);
+ g_test_add_func ("/library/remote-nodeps-option", test_remote_nodeps_option);
g_test_add_func ("/library/instance", test_instance);
g_test_add_func ("/library/update-subpaths", test_update_subpaths);
g_test_add_func ("/library/overrides", test_overrides);