From b3828eea46ceaee61b58bbc38a637214632fa64e Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Mon, 11 Dec 2017 21:08:20 -0800 Subject: [PATCH] app: Make remote commands smarter wrt installations Currently "flatpak remotes" shows remotes across user and system installations, but other remote commands (remote-delete, remote-modify, remote-ls, remote-info) only work on one installation: the system one unless overridden using --user or --installation. This commit changes each command to infer the correct installation by checking which has the specified remote. In case multiple installations have remotes by the same name, the user is prompted to decide which to use. This commit also adds unit tests and updates the man pages for the aforementioned commands. Fixes https://github.com/flatpak/flatpak/issues/787 Closes: #1205 Approved by: alexlarsson --- app/flatpak-builtins-add-remote.c | 42 ++++---- app/flatpak-builtins-delete-remote.c | 35 +++--- app/flatpak-builtins-info-remote.c | 50 +++++---- app/flatpak-builtins-ls-remote.c | 118 +++++++++++++------- app/flatpak-builtins-utils.c | 62 +++++++++++ app/flatpak-builtins-utils.h | 6 ++ doc/flatpak-remote-delete.xml | 6 +- doc/flatpak-remote-info.xml | 6 +- doc/flatpak-remote-ls.xml | 6 +- doc/flatpak-remote-modify.xml | 6 +- tests/test-repo.sh | 156 ++++++++++++++++++++++++++- 11 files changed, 386 insertions(+), 107 deletions(-) diff --git a/app/flatpak-builtins-add-remote.c b/app/flatpak-builtins-add-remote.c index 7f692f73..92193441 100644 --- a/app/flatpak-builtins-add-remote.c +++ b/app/flatpak-builtins-add-remote.c @@ -455,7 +455,7 @@ flatpak_builtin_modify_remote (int argc, char **argv, GCancellable *cancellable, { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; + g_autoptr(FlatpakDir) preferred_dir = NULL; g_autoptr(GKeyFile) config = NULL; g_autoptr(GBytes) gpg_data = NULL; const char *remote_name; @@ -467,18 +467,18 @@ flatpak_builtin_modify_remote (int argc, char **argv, GCancellable *cancellable, g_option_context_add_main_entries (context, common_options, NULL); if (!flatpak_option_context_parse (context, modify_options, &argc, &argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, - &dirs, cancellable, error)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, cancellable, error)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - if (argc < 2) return usage_error (context, _("Remote NAME must be specified"), error); remote_name = argv[1]; - if (!ostree_repo_remote_get_url (flatpak_dir_get_repo (dir), remote_name, NULL, NULL)) + if (!flatpak_resolve_duplicate_remotes (dirs, remote_name, &preferred_dir, cancellable, error)) + return FALSE; + + if (!ostree_repo_remote_get_url (flatpak_dir_get_repo (preferred_dir), remote_name, NULL, NULL)) return flatpak_fail (error, _("No remote %s"), remote_name); if (opt_update_metadata) @@ -486,18 +486,18 @@ flatpak_builtin_modify_remote (int argc, char **argv, GCancellable *cancellable, g_autoptr(GError) local_error = NULL; g_print (_("Updating extra metadata from remote summary for %s\n"), remote_name); - if (!flatpak_dir_update_remote_configuration (dir, remote_name, cancellable, &local_error)) + if (!flatpak_dir_update_remote_configuration (preferred_dir, remote_name, cancellable, &local_error)) { g_printerr (_("Error updating extra metadata for '%s': %s\n"), remote_name, local_error->message); return flatpak_fail (error, _("Could not update extra metadata for %s"), remote_name); } /* Reload changed configuration */ - if (!flatpak_dir_recreate_repo (dir, cancellable, error)) + if (!flatpak_dir_recreate_repo (preferred_dir, cancellable, error)) return FALSE; } - config = get_config_from_opts (dir, remote_name, &changed); + config = get_config_from_opts (preferred_dir, remote_name, &changed); if (opt_gpg_import != NULL) { @@ -510,7 +510,7 @@ flatpak_builtin_modify_remote (int argc, char **argv, GCancellable *cancellable, if (!changed) return TRUE; - return flatpak_dir_modify_remote (dir, remote_name, config, gpg_data, cancellable, error); + return flatpak_dir_modify_remote (preferred_dir, remote_name, config, gpg_data, cancellable, error); } gboolean @@ -518,17 +518,14 @@ flatpak_complete_modify_remote (FlatpakCompletion *completion) { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; int i; context = g_option_context_new (""); g_option_context_add_main_entries (context, common_options, NULL); if (!flatpak_option_context_parse (context, modify_options, &completion->argc, &completion->argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, &dirs, NULL, NULL)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, NULL, NULL)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - switch (completion->argc) { case 0: @@ -538,13 +535,16 @@ flatpak_complete_modify_remote (FlatpakCompletion *completion) flatpak_complete_options (completion, modify_options); flatpak_complete_options (completion, user_entries); - { - g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); - if (remotes == NULL) - return FALSE; - for (i = 0; remotes[i] != NULL; i++) - flatpak_complete_word (completion, "%s ", remotes[i]); - } + for (i = 0; i < dirs->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, i); + int j; + g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); + if (remotes == NULL) + return FALSE; + for (j = 0; remotes[j] != NULL; j++) + flatpak_complete_word (completion, "%s ", remotes[j]); + } break; } diff --git a/app/flatpak-builtins-delete-remote.c b/app/flatpak-builtins-delete-remote.c index c84ea27e..f23470ff 100644 --- a/app/flatpak-builtins-delete-remote.c +++ b/app/flatpak-builtins-delete-remote.c @@ -30,6 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" +#include "flatpak-builtins-utils.h" static gboolean opt_force; @@ -44,7 +45,7 @@ flatpak_builtin_delete_remote (int argc, char **argv, GCancellable *cancellable, { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; + g_autoptr(FlatpakDir) preferred_dir = NULL; const char *remote_name; context = g_option_context_new (_("NAME - Delete a remote repository")); @@ -53,12 +54,9 @@ flatpak_builtin_delete_remote (int argc, char **argv, GCancellable *cancellable, g_option_context_add_main_entries (context, delete_options, NULL); if (!flatpak_option_context_parse (context, NULL, &argc, &argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, - &dirs, cancellable, error)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, cancellable, error)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - if (argc < 2) return usage_error (context, _("NAME must be specified"), error); @@ -67,7 +65,10 @@ flatpak_builtin_delete_remote (int argc, char **argv, GCancellable *cancellable, if (argc > 2) return usage_error (context, _("Too many arguments"), error); - if (!flatpak_dir_remove_remote (dir, opt_force, remote_name, + if (!flatpak_resolve_duplicate_remotes (dirs, remote_name, &preferred_dir, cancellable, error)) + return FALSE; + + if (!flatpak_dir_remove_remote (preferred_dir, opt_force, remote_name, cancellable, error)) return FALSE; @@ -79,16 +80,13 @@ flatpak_complete_delete_remote (FlatpakCompletion *completion) { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; int i; context = g_option_context_new (""); if (!flatpak_option_context_parse (context, delete_options, &completion->argc, &completion->argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, &dirs, NULL, NULL)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, NULL, NULL)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - switch (completion->argc) { case 0: @@ -97,13 +95,16 @@ flatpak_complete_delete_remote (FlatpakCompletion *completion) flatpak_complete_options (completion, delete_options); flatpak_complete_options (completion, user_entries); - { - g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); - if (remotes == NULL) - return FALSE; - for (i = 0; remotes[i] != NULL; i++) - flatpak_complete_word (completion, "%s ", remotes[i]); - } + for (i = 0; i < dirs->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, i); + int j; + g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); + if (remotes == NULL) + return FALSE; + for (j = 0; remotes[j] != NULL; j++) + flatpak_complete_word (completion, "%s ", remotes[j]); + } break; } diff --git a/app/flatpak-builtins-info-remote.c b/app/flatpak-builtins-info-remote.c index 56a147ba..93168623 100644 --- a/app/flatpak-builtins-info-remote.c +++ b/app/flatpak-builtins-info-remote.c @@ -30,6 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" +#include "flatpak-builtins-utils.h" #include "flatpak-utils.h" #include "flatpak-table-printer.h" @@ -87,7 +88,7 @@ flatpak_builtin_info_remote (int argc, char **argv, GCancellable *cancellable, G { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; + g_autoptr(FlatpakDir) preferred_dir = NULL; g_autoptr(GVariant) commit_v = NULL; g_autoptr(GVariant) commit_metadata = NULL; const char *remote; @@ -121,12 +122,9 @@ flatpak_builtin_info_remote (int argc, char **argv, GCancellable *cancellable, G g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); if (!flatpak_option_context_parse (context, options, &argc, &argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, - &dirs, cancellable, error)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, cancellable, error)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - if (!opt_app && !opt_runtime) opt_app = opt_runtime = TRUE; @@ -136,19 +134,22 @@ flatpak_builtin_info_remote (int argc, char **argv, GCancellable *cancellable, G remote = argv[1]; pref = argv[2]; - default_branch = flatpak_dir_get_remote_default_branch (dir, remote); + if (!flatpak_resolve_duplicate_remotes (dirs, remote, &preferred_dir, cancellable, error)) + return FALSE; + + default_branch = flatpak_dir_get_remote_default_branch (preferred_dir, remote); kinds = flatpak_kinds_from_bools (opt_app, opt_runtime); if (!flatpak_split_partial_ref_arg (pref, kinds, opt_arch, NULL, &matched_kinds, &id, &arch, &branch, error)) return FALSE; - ref = flatpak_dir_find_remote_ref (dir, remote, id, branch, default_branch, arch, + ref = flatpak_dir_find_remote_ref (preferred_dir, remote, id, branch, default_branch, arch, matched_kinds, &kind, cancellable, error); if (ref == NULL) return FALSE; - commit_v = flatpak_dir_fetch_remote_commit (dir, remote, ref, opt_commit, &commit, cancellable, error); + commit_v = flatpak_dir_fetch_remote_commit (preferred_dir, remote, ref, opt_commit, &commit, cancellable, error); if (commit_v == NULL) return FALSE; @@ -220,7 +221,7 @@ flatpak_builtin_info_remote (int argc, char **argv, GCancellable *cancellable, G g_autofree char *p_formatted_timestamp = NULL; g_autoptr(GVariant) p_commit_v = NULL; - p_commit_v = flatpak_dir_fetch_remote_commit (dir, remote, ref, p, NULL, cancellable, NULL); + p_commit_v = flatpak_dir_fetch_remote_commit (preferred_dir, remote, ref, p, NULL, cancellable, NULL); if (p_commit_v == NULL) break; @@ -282,7 +283,7 @@ flatpak_builtin_info_remote (int argc, char **argv, GCancellable *cancellable, G c_v = NULL; if (c && opt_log) - c_v = flatpak_dir_fetch_remote_commit (dir, remote, ref, c, NULL, cancellable, NULL); + c_v = flatpak_dir_fetch_remote_commit (preferred_dir, remote, ref, c, NULL, cancellable, NULL); } while (c_v != NULL); } @@ -295,18 +296,15 @@ flatpak_complete_info_remote (FlatpakCompletion *completion) { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; FlatpakKinds kinds; int i; context = g_option_context_new (""); if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, &dirs, NULL, NULL)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, NULL, NULL)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - kinds = flatpak_kinds_from_bools (opt_app, opt_runtime); switch (completion->argc) @@ -317,18 +315,26 @@ flatpak_complete_info_remote (FlatpakCompletion *completion) flatpak_complete_options (completion, options); flatpak_complete_options (completion, user_entries); - { - g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); - if (remotes == NULL) - return FALSE; - for (i = 0; remotes[i] != NULL; i++) - flatpak_complete_word (completion, "%s ", remotes[i]); - } + for (i = 0; i < dirs->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, i); + int j; + g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); + if (remotes == NULL) + return FALSE; + for (j = 0; remotes[j] != NULL; j++) + flatpak_complete_word (completion, "%s ", remotes[j]); + } break; default: /* REF */ - flatpak_complete_partial_ref (completion, kinds, opt_arch, dir, completion->argv[1]); + for (i = 0; i < dirs->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, i); + flatpak_complete_partial_ref (completion, kinds, opt_arch, dir, completion->argv[1]); + } + break; } diff --git a/app/flatpak-builtins-ls-remote.c b/app/flatpak-builtins-ls-remote.c index f59fc43e..c1614a50 100644 --- a/app/flatpak-builtins-ls-remote.c +++ b/app/flatpak-builtins-ls-remote.c @@ -30,6 +30,7 @@ #include "libglnx/libglnx.h" #include "flatpak-builtins.h" +#include "flatpak-builtins-utils.h" #include "flatpak-utils.h" #include "flatpak-table-printer.h" @@ -50,12 +51,33 @@ static GOptionEntry options[] = { { NULL } }; +typedef struct RemoteDirPair { + gchar *remote_name; + FlatpakDir *dir; +} RemoteDirPair; + +static void +remote_dir_pair_free (RemoteDirPair *pair) +{ + g_free (pair->remote_name); + g_object_unref (pair->dir); + g_free (pair); +} + +static RemoteDirPair * +remote_dir_pair_new (const char *remote_name, FlatpakDir *dir) +{ + RemoteDirPair *pair = g_new (RemoteDirPair, 1); + pair->remote_name = g_strdup (remote_name); + pair->dir = g_object_ref (dir); + return pair; +} + gboolean flatpak_builtin_ls_remote (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; GHashTableIter refs_iter; GHashTableIter iter; gpointer refs_key; @@ -67,54 +89,72 @@ flatpak_builtin_ls_remote (int argc, char **argv, GCancellable *cancellable, GEr int i; const char **arches = flatpak_get_arches (); const char *opt_arches[] = {NULL, NULL}; - g_auto(GStrv) remotes = NULL; gboolean has_remote; g_autoptr(GHashTable) pref_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_autoptr(GHashTable) refs_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, (GDestroyNotify)g_hash_table_unref, g_free); + g_autoptr(GHashTable) refs_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, (GDestroyNotify)g_hash_table_unref, (GDestroyNotify)remote_dir_pair_free); context = g_option_context_new (_(" [REMOTE] - Show available runtimes and applications")); g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); if (!flatpak_option_context_parse (context, options, &argc, &argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, - &dirs, cancellable, error)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, cancellable, error)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - if (!opt_app && !opt_runtime) opt_app = opt_runtime = TRUE; if (argc > 2) return usage_error (context, _("Too many arguments"), error); - if (argc < 2) - { - has_remote = FALSE; - remotes = flatpak_dir_list_remotes (dir, cancellable, error); - if (remotes == NULL) - return FALSE; - } - else - { - has_remote = TRUE; - remotes = g_new (char *, 2); - remotes[0] = g_strdup(argv[1]); - remotes[1] = NULL; - } + has_remote = (argc == 2); - for (i = 0; remotes[i] != NULL; i++) + if (has_remote) { + g_autoptr(FlatpakDir) preferred_dir = NULL; g_autoptr(GHashTable) refs = NULL; - const char *remote_name = remotes[i]; + RemoteDirPair *remote_dir_pair = NULL; - if (!flatpak_dir_list_remote_refs (dir, - remote_name, + if (!flatpak_resolve_duplicate_remotes (dirs, argv[1], &preferred_dir, cancellable, error)) + return FALSE; + + if (!flatpak_dir_list_remote_refs (preferred_dir, + argv[1], &refs, cancellable, error)) return FALSE; - g_hash_table_insert (refs_hash, g_steal_pointer (&refs), g_strdup (remote_name)); + remote_dir_pair = remote_dir_pair_new (argv[1], preferred_dir); + g_hash_table_insert (refs_hash, g_steal_pointer (&refs), remote_dir_pair); + } + else + { + int i; + for (i = 0; i < dirs->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, i); + g_auto(GStrv) remotes = NULL; + int j; + + remotes = flatpak_dir_list_remotes (dir, cancellable, error); + if (remotes == NULL) + return FALSE; + + for (j = 0; remotes[j] != NULL; j++) + { + g_autoptr(GHashTable) refs = NULL; + RemoteDirPair *remote_dir_pair = NULL; + const char *remote_name = remotes[j]; + + if (!flatpak_dir_list_remote_refs (dir, + remote_name, + &refs, + cancellable, error)) + return FALSE; + + remote_dir_pair = remote_dir_pair_new (remote_name, dir); + g_hash_table_insert (refs_hash, g_steal_pointer (&refs), remote_dir_pair); + } + } } if (opt_arch != NULL) @@ -142,7 +182,9 @@ flatpak_builtin_ls_remote (int argc, char **argv, GCancellable *cancellable, GEr while (g_hash_table_iter_next (&refs_iter, &refs_key, &refs_value)) { GHashTable *refs = refs_key; - char *remote = refs_value; + RemoteDirPair *remote_dir_pair = refs_value; + const char *remote = remote_dir_pair->remote_name; + FlatpakDir *dir = remote_dir_pair->dir; g_autoptr(GHashTable) names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_hash_table_iter_init (&iter, refs); @@ -285,17 +327,14 @@ flatpak_complete_ls_remote (FlatpakCompletion *completion) { g_autoptr(GOptionContext) context = NULL; g_autoptr(GPtrArray) dirs = NULL; - FlatpakDir *dir; int i; context = g_option_context_new (""); if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, - FLATPAK_BUILTIN_FLAG_ONE_DIR, &dirs, NULL, NULL)) + FLATPAK_BUILTIN_FLAG_STANDARD_DIRS, &dirs, NULL, NULL)) return FALSE; - dir = g_ptr_array_index (dirs, 0); - switch (completion->argc) { case 0: @@ -304,13 +343,16 @@ flatpak_complete_ls_remote (FlatpakCompletion *completion) flatpak_complete_options (completion, options); flatpak_complete_options (completion, user_entries); - { - g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); - if (remotes == NULL) - return FALSE; - for (i = 0; remotes[i] != NULL; i++) - flatpak_complete_word (completion, "%s ", remotes[i]); - } + for (i = 0; i < dirs->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, i); + int j; + g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL); + if (remotes == NULL) + return FALSE; + for (j = 0; remotes[j] != NULL; j++) + flatpak_complete_word (completion, "%s ", remotes[j]); + } break; } diff --git a/app/flatpak-builtins-utils.c b/app/flatpak-builtins-utils.c index 56eeb3ea..0c874912 100644 --- a/app/flatpak-builtins-utils.c +++ b/app/flatpak-builtins-utils.c @@ -326,3 +326,65 @@ flatpak_load_gpg_keys (char **gpg_import, return g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output_stream)); } + +gboolean +flatpak_resolve_duplicate_remotes (GPtrArray *dirs, + const char *remote_name, + FlatpakDir **out_dir, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GPtrArray) dirs_with_remote = NULL; + int chosen = 0; + int i; + + dirs_with_remote = g_ptr_array_new (); + for (i = 0; i < dirs->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs, i); + g_auto(GStrv) remotes = NULL; + int j = 0; + + remotes = flatpak_dir_list_remotes (dir, cancellable, error); + if (remotes == NULL) + return FALSE; + + for (j = 0; remotes[j] != NULL; j++) + { + const char *this_remote = remotes[j]; + + if (g_strcmp0 (remote_name, this_remote) == 0) + g_ptr_array_add (dirs_with_remote, dir); + } + } + + if (dirs_with_remote->len == 1) + chosen = 1; + else if (dirs_with_remote->len > 1) + { + g_print (_("Remote ā€˜%s’ found in multiple installations:\n"), remote_name); + for (i = 0; i < dirs_with_remote->len; i++) + { + FlatpakDir *dir = g_ptr_array_index (dirs_with_remote, i); + g_autofree char *dir_name = flatpak_dir_get_name (dir); + g_print("%d) %s\n", i + 1, dir_name); + } + chosen = flatpak_number_prompt (1, dirs_with_remote->len, _("Which do you want to use (0 to abort)?")); + if (chosen == 0) + return flatpak_fail (error, _("No remote chosen to resolve ā€˜%s’ which exists in multiple installations"), remote_name); + } + + if (out_dir) + { + if (dirs_with_remote->len == 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Remote \"%s\" not found", remote_name); + return FALSE; + } + else + *out_dir = g_object_ref (g_ptr_array_index (dirs_with_remote, chosen - 1)); + } + + return TRUE; +} diff --git a/app/flatpak-builtins-utils.h b/app/flatpak-builtins-utils.h index 6d66c931..1ce4aaf7 100644 --- a/app/flatpak-builtins-utils.h +++ b/app/flatpak-builtins-utils.h @@ -46,4 +46,10 @@ FlatpakDir * flatpak_find_installed_pref (const char *pref, GCancellable *cancellable, GError **error); +gboolean flatpak_resolve_duplicate_remotes (GPtrArray *dirs, + const char *remote_name, + FlatpakDir **out_dir, + GCancellable *cancellable, + GError **error); + #endif /* __FLATPAK_BUILTINS_UTILS_H__ */ diff --git a/doc/flatpak-remote-delete.xml b/doc/flatpak-remote-delete.xml index 6c8ec652..5c2d2540 100644 --- a/doc/flatpak-remote-delete.xml +++ b/doc/flatpak-remote-delete.xml @@ -44,8 +44,10 @@ NAME is the name of an existing remote. - Unless overridden with the --user or --installation options, this command - changes the default system-wide installation. + Unless overridden with the --system, --user, or --installation options, + this command uses either the default system-wide installation or the + per-user one, depending on which has the specified + REMOTE. diff --git a/doc/flatpak-remote-info.xml b/doc/flatpak-remote-info.xml index 1f482d81..ffd9bb56 100644 --- a/doc/flatpak-remote-info.xml +++ b/doc/flatpak-remote-info.xml @@ -52,8 +52,10 @@ in a machine-readable format. - Unless overridden with the --user or --installation options, this command - uses the default system-wide configuration. + Unless overridden with the --system, --user, or --installation options, + this command uses either the default system-wide installation or the + per-user one, depending on which has the specified + REMOTE. diff --git a/doc/flatpak-remote-ls.xml b/doc/flatpak-remote-ls.xml index 7e4ce778..33bcc294 100644 --- a/doc/flatpak-remote-ls.xml +++ b/doc/flatpak-remote-ls.xml @@ -46,8 +46,10 @@ remote repositories with flatpak-remotes1. - Unless overridden with the --user or --installation options, this command - uses the default system-wide configuration. + Unless overridden with the --system, --user, or --installation options, + this command uses either the default system-wide installation or the + per-user one, depending on which has the specified + REMOTE. diff --git a/doc/flatpak-remote-modify.xml b/doc/flatpak-remote-modify.xml index 3f5b58bc..9e961435 100644 --- a/doc/flatpak-remote-modify.xml +++ b/doc/flatpak-remote-modify.xml @@ -44,8 +44,10 @@ NAME is the name for the remote. - Unless overridden with the --user or --installation options, this command - changes the default system-wide installation. + Unless overridden with the --system, --user, or --installation options, + this command uses either the default system-wide installation or the + per-user one, depending on which has the specified + REMOTE. diff --git a/tests/test-repo.sh b/tests/test-repo.sh index 76371955..f588ce5b 100755 --- a/tests/test-repo.sh +++ b/tests/test-repo.sh @@ -28,7 +28,7 @@ if [ x${USE_COLLECTIONS_IN_CLIENT-} == xyes ] || [ x${USE_COLLECTIONS_IN_SERVER- skip_without_p2p fi -echo "1..6" +echo "1..10" #Regular repo setup_repo @@ -131,4 +131,158 @@ update_repo test-gpg3 org.test.Collection.test ${FLATPAK} ${U} install test-repo org.test.Hello assert_file_has_content $FL_DIR/app/org.test.Hello/$ARCH/master/active/files/bin/hello.sh UPDATED +${FLATPAK} ${U} uninstall org.test.Platform org.test.Hello + echo "ok redirect url and gpg key" + +# Test that remote-ls works in all of the following cases: +# * system remote, and --system is used +# * system remote, and --system is omitted +# * user remote, and --user is used +# * user remote, and --user is omitted +# and fails in the following cases: +# * system remote, and --user is used +# * user remote, and --system is used +if [ x${USE_SYSTEMDIR-} == xyes ]; then + ${FLATPAK} --system remote-ls test-repo > repo-list + assert_file_has_content repo-list "org.test.Hello" + + ${FLATPAK} remote-ls test-repo > repo-list + assert_file_has_content repo-list "org.test.Hello" + + if ${FLATPAK} --user remote-ls test-repo 2> remote-ls-error-log; then + assert_not_reached "flatpak --user remote-ls should not work for system remotes" + fi + assert_file_has_content remote-ls-error-log "Remote \"test-repo\" not found" +else + ${FLATPAK} --user remote-ls test-repo > repo-list + assert_file_has_content repo-list "org.test.Hello" + + ${FLATPAK} remote-ls test-repo > repo-list + assert_file_has_content repo-list "org.test.Hello" + + if ${FLATPAK} --system remote-ls test-repo 2> remote-ls-error-log; then + assert_not_reached "flatpak --system remote-ls should not work for user remotes" + fi + assert_file_has_content remote-ls-error-log "Remote \"test-repo\" not found" +fi + +echo "ok remote-ls" + +# Test that remote-modify works in all of the following cases: +# * system remote, and --system is used +# * system remote, and --system is omitted +# * user remote, and --user is used +# * user remote, and --user is omitted +# and fails in the following cases: +# * system remote, and --user is used +# * user remote, and --system is used +if [ x${USE_SYSTEMDIR-} == xyes ]; then + ${FLATPAK} --system remote-modify --title=NewTitle test-repo + ${FLATPAK} remotes -d | grep ^test-repo > repo-info + assert_file_has_content repo-info "NewTitle" + ${FLATPAK} --system remote-modify --title=OldTitle test-repo + + ${FLATPAK} remote-modify --title=NewTitle test-repo + ${FLATPAK} remotes -d | grep ^test-repo > repo-info + assert_file_has_content repo-info "NewTitle" + ${FLATPAK} --system remote-modify --title=OldTitle test-repo + + if ${FLATPAK} --user remote-modify --title=NewTitle test-repo 2> remote-modify-error-log; then + assert_not_reached "flatpak --user remote-modify should not work for system remotes" + fi + assert_file_has_content remote-modify-error-log "Remote \"test-repo\" not found" +else + ${FLATPAK} --user remote-modify --title=NewTitle test-repo + ${FLATPAK} remotes -d | grep ^test-repo > repo-info + assert_file_has_content repo-info "NewTitle" + ${FLATPAK} --user remote-modify --title=OldTitle test-repo + + ${FLATPAK} remote-modify --title=NewTitle test-repo + ${FLATPAK} remotes -d | grep ^test-repo > repo-info + assert_file_has_content repo-info "NewTitle" + ${FLATPAK} remote-modify --title=OldTitle test-repo + + if ${FLATPAK} --system remote-modify --title=NewTitle test-repo 2> remote-modify-error-log; then + assert_not_reached "flatpak --system remote-modify should not work for user remotes" + fi + assert_file_has_content remote-modify-error-log "Remote \"test-repo\" not found" +fi + +echo "ok remote-modify" + +# Test that remote-delete works in all of the following cases: +# * system remote, and --system is used +# * system remote, and --system is omitted +# * user remote, and --user is used +# * user remote, and --user is omitted +# and fails in the following cases: +# * system remote, and --user is used +# * user remote, and --system is used +if [ x${USE_SYSTEMDIR-} == xyes ]; then + ${FLATPAK} --system remote-delete test-repo + ${FLATPAK} remotes > repo-info + assert_not_file_has_content repo-info "test-repo" + setup_repo + + ${FLATPAK} remote-delete test-repo + ${FLATPAK} remotes > repo-list + assert_not_file_has_content repo-info "test-repo" + setup_repo + + if ${FLATPAK} --user remote-delete test-repo 2> remote-delete-error-log; then + assert_not_reached "flatpak --user remote-delete should not work for system remotes" + fi + assert_file_has_content remote-delete-error-log "Remote \"test-repo\" not found" +else + ${FLATPAK} --user remote-delete test-repo + ${FLATPAK} remotes > repo-info + assert_not_file_has_content repo-info "test-repo" + setup_repo + + ${FLATPAK} remote-delete test-repo + ${FLATPAK} remotes > repo-info + assert_not_file_has_content repo-info "test-repo" + setup_repo + + if ${FLATPAK} --system remote-delete test-repo 2> remote-delete-error-log; then + assert_not_reached "flatpak --system remote-delete should not work for user remotes" + fi + assert_file_has_content remote-delete-error-log "Remote \"test-repo\" not found" +fi + +echo "ok remote-delete" + +# Test that remote-info works in all of the following cases: +# * system remote, and --system is used +# * system remote, and --system is omitted +# * user remote, and --user is used +# * user remote, and --user is omitted +# and fails in the following cases: +# * system remote, and --user is used +# * user remote, and --system is used +if [ x${USE_SYSTEMDIR-} == xyes ]; then + ${FLATPAK} --system remote-info test-repo org.test.Hello > remote-ref-info + assert_file_has_content remote-ref-info "ID: org.test.Hello" + + ${FLATPAK} remote-info test-repo org.test.Hello > remote-ref-info + assert_file_has_content remote-ref-info "ID: org.test.Hello" + + if ${FLATPAK} --user remote-info test-repo org.test.Hello 2> remote-info-error-log; then + assert_not_reached "flatpak --user remote-info should not work for system remotes" + fi + assert_file_has_content remote-info-error-log "Remote \"test-repo\" not found" +else + ${FLATPAK} --user remote-info test-repo org.test.Hello > remote-ref-info + assert_file_has_content remote-ref-info "ID: org.test.Hello" + + ${FLATPAK} remote-info test-repo org.test.Hello > remote-ref-info + assert_file_has_content remote-ref-info "ID: org.test.Hello" + + if ${FLATPAK} --system remote-info test-repo org.test.Hello 2> remote-info-error-log; then + assert_not_reached "flatpak --system remote-info should not work for user remotes" + fi + assert_file_has_content remote-info-error-log "Remote \"test-repo\" not found" +fi + +echo "ok remote-info"