From ce9a1c4f6c97a72c48a837ed45d705d09709d50f Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 4 May 2021 10:19:17 +0200 Subject: [PATCH 1/5] Add FLATPAK_QUERY_FLAGS_ALL_ARCHES for list_remote_refs() This allows flatpak_installation_list_remote_refs_sync_full() to list refs for all arches on remotes that use the new subsummary format. Fixes #4252 --- common/flatpak-dir-private.h | 5 +++++ common/flatpak-dir.c | 29 +++++++++++++++++++++++++++++ common/flatpak-installation.c | 25 +++++++++++++++++++------ common/flatpak-installation.h | 2 ++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/common/flatpak-dir-private.h b/common/flatpak-dir-private.h index accfe061..3c69928c 100644 --- a/common/flatpak-dir-private.h +++ b/common/flatpak-dir-private.h @@ -155,6 +155,11 @@ gboolean flatpak_remote_state_ensure_subsummary (FlatpakRemoteState *self, gboolean only_cached, GCancellable *cancellable, GError **error); +gboolean flatpak_remote_state_ensure_subsummary_all_arches (FlatpakRemoteState *self, + FlatpakDir *dir, + gboolean only_cached, + GCancellable *cancellable, + GError **error); gboolean flatpak_remote_state_allow_ref (FlatpakRemoteState *self, const char *ref); gboolean flatpak_remote_state_lookup_ref (FlatpakRemoteState *self, diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index d4f5e5c5..1c331907 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -497,6 +497,35 @@ flatpak_remote_state_ensure_subsummary (FlatpakRemoteState *self, return TRUE; } +gboolean +flatpak_remote_state_ensure_subsummary_all_arches (FlatpakRemoteState *self, + FlatpakDir *dir, + gboolean only_cached, + GCancellable *cancellable, + GError **error) +{ + if (self->index_ht == NULL) + return TRUE; /* No subsummaries, got all arches anyway */ + + GLNX_HASH_TABLE_FOREACH (self->index_ht, const char *, arch) + { + g_autoptr(GError) local_error = NULL; + + if (!flatpak_remote_state_ensure_subsummary (self, dir, arch, only_cached, cancellable, &local_error)) + { + /* Don't error on non-cached subsummaries */ + if (only_cached && g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_CACHED)) + continue; + + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + } + + return TRUE; +} + + gboolean flatpak_remote_state_allow_ref (FlatpakRemoteState *self, const char *ref) diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index 62e23a25..0daf3d66 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -2418,22 +2418,35 @@ flatpak_installation_list_remote_refs_sync_full (FlatpakInstallation *self, GHashTableIter iter; gpointer key; gpointer value; + gboolean only_sideloaded = (flags & FLATPAK_QUERY_FLAGS_ONLY_SIDELOADED) != 0; + gboolean only_cached = (flags & FLATPAK_QUERY_FLAGS_ONLY_CACHED) != 0; + gboolean all_arches = (flags & FLATPAK_QUERY_FLAGS_ALL_ARCHES) != 0; dir = flatpak_installation_get_dir (self, error); if (dir == NULL) return NULL; - if (flags & FLATPAK_QUERY_FLAGS_ONLY_SIDELOADED) - state = flatpak_dir_get_remote_state_local_only (dir, remote_or_uri, cancellable, error); + if (only_sideloaded) + { + state = flatpak_dir_get_remote_state_local_only (dir, remote_or_uri, cancellable, error); + if (state == NULL) + return NULL; + } else - state = flatpak_dir_get_remote_state (dir, remote_or_uri, (flags & FLATPAK_QUERY_FLAGS_ONLY_CACHED) != 0, cancellable, error); - if (state == NULL) - return NULL; + { + state = flatpak_dir_get_remote_state (dir, remote_or_uri, only_cached, cancellable, error); + if (state == NULL) + return NULL; + + if (all_arches && + !flatpak_remote_state_ensure_subsummary_all_arches (state, dir, only_cached, cancellable, error)) + return NULL; + } if (!flatpak_dir_list_remote_refs (dir, state, &ht, cancellable, &local_error)) { - if (flags & FLATPAK_QUERY_FLAGS_ONLY_SIDELOADED) + if (only_sideloaded) { /* Just return no sideloaded refs rather than a summary download failed error if there are none */ return g_steal_pointer (&refs); diff --git a/common/flatpak-installation.h b/common/flatpak-installation.h index 899163e5..2fb0fd59 100644 --- a/common/flatpak-installation.h +++ b/common/flatpak-installation.h @@ -131,6 +131,7 @@ typedef enum { * lot more efficient if you're doing many requests. * @FLATPAK_QUERY_FLAGS_ONLY_SIDELOADED: Only list refs available from sideload * repos; see flatpak(1). (Snce: 1.7) + * @FLATPAK_QUERY_FLAGS_ALL_ARCHES: Include refs from all arches, not just the primary ones. (Snce: 1.11.2) * * Flags to alter the behavior of e.g flatpak_installation_list_remote_refs_sync_full(). * @@ -140,6 +141,7 @@ typedef enum { FLATPAK_QUERY_FLAGS_NONE = 0, FLATPAK_QUERY_FLAGS_ONLY_CACHED = (1 << 0), FLATPAK_QUERY_FLAGS_ONLY_SIDELOADED = (1 << 1), + FLATPAK_QUERY_FLAGS_ALL_ARCHES = (1 << 2), } FlatpakQueryFlags; /** From 540bcda3bd70c5bc2e0506d65db2462407fa9cb3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 6 May 2021 11:16:33 +0200 Subject: [PATCH 2/5] Transaction: Ensure we download the subsummary for the arch of added refs By default we only download the main arch subsummary, so if you added a ref for some other arch it failed to find the ref. This works with the CLI, because it explicilty loads the subsummary when its trying to expand the parial ref to the full ref. However apps using libflatpak don't do that so they failed. --- app/flatpak-builtins-install.c | 6 +--- common/flatpak-transaction-private.h | 1 + common/flatpak-transaction.c | 41 +++++++++++++++++----------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c index ee74fb1f..f4328f25 100644 --- a/app/flatpak-builtins-install.c +++ b/app/flatpak-builtins-install.c @@ -513,14 +513,10 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro g_autoptr(FlatpakRemoteState) state = NULL; state = flatpak_transaction_ensure_remote_state (transaction, FLATPAK_TRANSACTION_OPERATION_INSTALL, - remote, error); + remote, arch, error); if (state == NULL) return FALSE; - if (arch != NULL && - !flatpak_remote_state_ensure_subsummary (state, dir, arch, FALSE, cancellable, error)) - return FALSE; - refs = flatpak_dir_find_remote_refs (dir, state, id, branch, default_branch, arch, flatpak_get_default_arch (), matched_kinds, FIND_MATCHING_REFS_FLAGS_FUZZY, diff --git a/common/flatpak-transaction-private.h b/common/flatpak-transaction-private.h index 2ebd5d69..d4971515 100644 --- a/common/flatpak-transaction-private.h +++ b/common/flatpak-transaction-private.h @@ -27,6 +27,7 @@ FlatpakRemoteState *flatpak_transaction_ensure_remote_state (FlatpakTransaction *self, FlatpakTransactionOperationType kind, const char *remote, + const char *opt_arch, GError **error); FlatpakDecomposed * flatpak_transaction_operation_get_decomposed (FlatpakTransactionOperation *self); diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c index 3678fc19..95da9d5e 100644 --- a/common/flatpak-transaction.c +++ b/common/flatpak-transaction.c @@ -1904,23 +1904,26 @@ FlatpakRemoteState * flatpak_transaction_ensure_remote_state (FlatpakTransaction *self, FlatpakTransactionOperationType kind, const char *remote, + const char *opt_arch, GError **error) { FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); - FlatpakRemoteState *state; + g_autoptr(FlatpakRemoteState) state = NULL; + FlatpakRemoteState *cached_state; /* We don't cache local-only states, as we might later need the same state with non-local state */ if (transaction_is_local_only (self, kind)) return flatpak_dir_get_remote_state_local_only (priv->dir, remote, NULL, error); - state = g_hash_table_lookup (priv->remote_states, remote); - if (state) - return flatpak_remote_state_ref (state); - - state = flatpak_dir_get_remote_state_optional (priv->dir, remote, FALSE, NULL, error); - - if (state) + cached_state = g_hash_table_lookup (priv->remote_states, remote); + if (cached_state) + state = flatpak_remote_state_ref (cached_state); + else { + state = flatpak_dir_get_remote_state_optional (priv->dir, remote, FALSE, NULL, error); + if (state == NULL) + return NULL; + g_hash_table_insert (priv->remote_states, state->remote_name, flatpak_remote_state_ref (state)); for (int i = 0; i < priv->extra_sideload_repos->len; i++) @@ -1931,7 +1934,11 @@ flatpak_transaction_ensure_remote_state (FlatpakTransaction *self, } } - return state; + if (opt_arch != NULL && + !flatpak_remote_state_ensure_subsummary (state, priv->dir, opt_arch, FALSE, NULL, error)) + return FALSE; + + return g_steal_pointer (&state); } static gboolean @@ -2042,7 +2049,7 @@ op_get_related (FlatpakTransaction *self, if (op->kind != FLATPAK_TRANSACTION_OPERATION_UNINSTALL) { - state = flatpak_transaction_ensure_remote_state (self, op->kind, op->remote, error); + state = flatpak_transaction_ensure_remote_state (self, op->kind, op->remote, NULL, error); if (state == NULL) return FALSE; } @@ -2189,7 +2196,7 @@ search_for_dependency (FlatpakTransaction *self, g_autoptr(GError) local_error = NULL; g_autoptr(FlatpakRemoteState) state = NULL; - state = flatpak_transaction_ensure_remote_state (self, FLATPAK_TRANSACTION_OPERATION_INSTALL, remote, &local_error); + state = flatpak_transaction_ensure_remote_state (self, FLATPAK_TRANSACTION_OPERATION_INSTALL, remote, NULL, &local_error); if (state == NULL) { g_debug ("Can't get state for remote %s: %s", remote, local_error->message); @@ -2510,7 +2517,9 @@ flatpak_transaction_add_ref (FlatpakTransaction *self, * remote to be fatal */ if (kind != FLATPAK_TRANSACTION_OPERATION_UNINSTALL) { - state = flatpak_transaction_ensure_remote_state (self, kind, remote, error); + g_autofree char *arch = flatpak_decomposed_dup_arch (ref); + + state = flatpak_transaction_ensure_remote_state (self, kind, remote, arch, error); if (state == NULL) return FALSE; } @@ -2793,7 +2802,7 @@ flatpak_transaction_update_metadata (FlatpakTransaction *self, char *remote = remotes[i]; gboolean updated = FALSE; g_autoptr(GError) my_error = NULL; - g_autoptr(FlatpakRemoteState) state = flatpak_transaction_ensure_remote_state (self, FLATPAK_TRANSACTION_OPERATION_UPDATE, remote, NULL); + g_autoptr(FlatpakRemoteState) state = flatpak_transaction_ensure_remote_state (self, FLATPAK_TRANSACTION_OPERATION_UPDATE, remote, NULL, NULL); g_debug ("Looking for remote metadata updates for %s", remote); if (!flatpak_dir_update_remote_configuration (priv->dir, remote, state, &updated, cancellable, &my_error)) @@ -2854,7 +2863,7 @@ flatpak_transaction_add_auto_install (FlatpakTransaction *self, deploy = flatpak_dir_get_if_deployed (priv->dir, auto_install_ref, NULL, cancellable); if (deploy == NULL) { - g_autoptr(FlatpakRemoteState) state = flatpak_transaction_ensure_remote_state (self, FLATPAK_TRANSACTION_OPERATION_UPDATE, remote, NULL); + g_autoptr(FlatpakRemoteState) state = flatpak_transaction_ensure_remote_state (self, FLATPAK_TRANSACTION_OPERATION_UPDATE, remote, NULL, NULL); if (state != NULL && flatpak_remote_state_lookup_ref (state, flatpak_decomposed_get_ref (auto_install_ref), NULL, NULL, NULL, NULL, NULL)) @@ -3175,7 +3184,7 @@ resolve_ops (FlatpakTransaction *self, priv->max_op = MAX (priv->max_op, RUNTIME_INSTALL); } - state = flatpak_transaction_ensure_remote_state (self, op->kind, op->remote, error); + state = flatpak_transaction_ensure_remote_state (self, op->kind, op->remote, NULL, error); if (state == NULL) return FALSE; @@ -4749,7 +4758,7 @@ flatpak_transaction_real_run (FlatpakTransaction *self, res = FALSE; } else if (op->kind != FLATPAK_TRANSACTION_OPERATION_UNINSTALL && - (state = flatpak_transaction_ensure_remote_state (self, op->kind, op->remote, &local_error)) == NULL) + (state = flatpak_transaction_ensure_remote_state (self, op->kind, op->remote, NULL, &local_error)) == NULL) { res = FALSE; } From 51ac8e159039425c3be9bb9f9556051f912312b3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 17 May 2021 10:22:43 +0200 Subject: [PATCH 3/5] builtin-utils: Use shared helper This uses the new flatpak_remote_state_ensure_subsummary_all_arches() helper in ensure_remote_state_all_arches(). --- app/flatpak-builtins-utils.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/flatpak-builtins-utils.c b/app/flatpak-builtins-utils.c index e3de1f8f..bec64a2e 100644 --- a/app/flatpak-builtins-utils.c +++ b/app/flatpak-builtins-utils.c @@ -1388,6 +1388,7 @@ get_remote_state (FlatpakDir *dir, return state; } +/* Note: cached == TRUE here means prefer-cache, not only-cache */ gboolean ensure_remote_state_arch (FlatpakDir *dir, FlatpakRemoteState *state, @@ -1427,6 +1428,7 @@ ensure_remote_state_arch_for_ref (FlatpakDir *dir, return ensure_remote_state_arch (dir, state, ref_arch, cached, only_sideloaded,cancellable, error); } +/* Note: cached == TRUE here means prefer-cache, not only-cache */ gboolean ensure_remote_state_all_arches (FlatpakDir *dir, FlatpakRemoteState *state, @@ -1435,15 +1437,19 @@ ensure_remote_state_all_arches (FlatpakDir *dir, GCancellable *cancellable, GError **error) { - if (state->index_ht == NULL) + if (only_sideloaded) return TRUE; - GLNX_HASH_TABLE_FOREACH (state->index_ht, const char *, arch) + if (cached) { - if (!ensure_remote_state_arch (dir, state, arch, - cached, only_sideloaded, - cancellable, error)) + /* First try cached, this will not error on uncached arches */ + if (!flatpak_remote_state_ensure_subsummary_all_arches (state, dir, TRUE, cancellable, error)) return FALSE; } + + /* Then download rest */ + if (!flatpak_remote_state_ensure_subsummary_all_arches (state, dir, FALSE, cancellable, error)) + return FALSE; + return TRUE; } From 0a9d5ac7f2e0e3f9d49a4c498bcde3d69abed097 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 17 May 2021 13:48:42 +0200 Subject: [PATCH 4/5] Include more architectures when listing installed refs. It turns out that we can't currently uninstall a ref from a non-standard arch without specifying the arch even if there is no similar ref installed for the main arch. (#4264) The fundamental reason for this that `flatpak_dir_find_installed_ref(s)` currently only returns refs with standard arches unless you explicitly specify an arch. This changes flatpak_dir_find_installed_refs() to always return all the refs for all installed arches. This is generally what we want anyway, except in the case of "flatpak run org.some.Platform" where we don't want to prompt if there are multiple arches installed, so that is manually changed. This changes find_matching_ref() to look for refs in all arches, but always prefer (without prompting) the default arch if that is installed. This also matches what all current callers want. Fixes #4264 --- app/flatpak-builtins-run.c | 8 +- common/flatpak-dir.c | 174 +++++++++++++++++++++++++------------ 2 files changed, 125 insertions(+), 57 deletions(-) diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c index df2713bf..d30a4a72 100644 --- a/app/flatpak-builtins-run.c +++ b/app/flatpak-builtins-run.c @@ -198,6 +198,12 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError ** g_autoptr(GError) local_error2 = NULL; g_autoptr(GPtrArray) ref_dir_pairs = NULL; RefDirPair *chosen_pair = NULL; + const char *runtime_arch = arch; + + /* If arch is not specified, only run the default arch to avoid asking for prompts for non-primary arches, + still asks for prompts if there are multiple branches though */ + if (runtime_arch == NULL) + runtime_arch = flatpak_get_arch (); /* Whereas for apps we want to default to using the "current" one (see * flatpak-make-current(1)) runtimes don't have a concept of currentness. @@ -208,7 +214,7 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError ** FlatpakDir *dir = g_ptr_array_index (dirs, i); g_autoptr(GPtrArray) refs = NULL; - refs = flatpak_dir_find_installed_refs (dir, id, branch, arch, FLATPAK_KINDS_RUNTIME, + refs = flatpak_dir_find_installed_refs (dir, id, branch, runtime_arch, FLATPAK_KINDS_RUNTIME, FIND_MATCHING_REFS_FLAGS_NONE, error); if (refs == NULL) return FALSE; diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index 1c331907..4294cd48 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -12346,23 +12346,18 @@ find_matching_refs (GHashTable *refs, const char *opt_name, const char *opt_branch, const char *opt_default_branch, - const char *opt_arch, + const char **valid_arches, /* NULL => any arch */ const char *opt_default_arch, FlatpakKinds kinds, FindMatchingRefsFlags flags, GError **error) { g_autoptr(GPtrArray) matched_refs = NULL; - const char **arches = flatpak_get_arches (); - const char *opt_arches[] = {opt_arch, NULL}; g_autoptr(GError) local_error = NULL; gboolean found_exact_name_match = FALSE; gboolean found_default_branch_match = FALSE; gboolean found_default_arch_match = FALSE; - if (opt_arch != NULL) - arches = opt_arches; - if (opt_name && !(flags & FIND_MATCHING_REFS_FLAGS_FUZZY) && !flatpak_is_valid_name (opt_name, -1, &local_error)) { @@ -12397,7 +12392,8 @@ find_matching_refs (GHashTable *refs, } } - if (!flatpak_decomposed_is_arches (ref, -1, arches)) + if (valid_arches != NULL && + !flatpak_decomposed_is_arches (ref, -1, valid_arches)) continue; if (opt_branch != NULL && !flatpak_decomposed_is_branch (ref, opt_branch)) @@ -12438,66 +12434,91 @@ find_matching_refs (GHashTable *refs, return g_steal_pointer (&matched_refs); } +static GPtrArray * +get_refs_for_arch (GPtrArray *refs, const char *arch) +{ + g_autoptr(GPtrArray) arched_refs = g_ptr_array_new_with_free_func ((GDestroyNotify)flatpak_decomposed_unref); + + for (int i = 0; i < refs->len; i++) + { + FlatpakDecomposed *ref = g_ptr_array_index (refs, i); + if (flatpak_decomposed_is_arch (ref, arch)) + g_ptr_array_add (arched_refs, flatpak_decomposed_ref (ref)); + } + + return g_steal_pointer (&arched_refs); +} + +static gpointer +fail_multiple_refs (GError **error, + const char *name, + GPtrArray *refs) +{ + g_autoptr(GString) err = g_string_new (""); + + g_string_printf (err, _("Multiple branches available for %s, you must specify one of: "), name); + g_ptr_array_sort (refs, flatpak_strcmp0_ptr); + + for (int i = 0; i < refs->len; i++) + { + FlatpakDecomposed *ref = g_ptr_array_index (refs, i); + if (i != 0) + g_string_append (err, ", "); + + g_string_append (err, flatpak_decomposed_get_pref (ref)); + } + flatpak_fail (error, "%s", err->str); + + return NULL; +} + static FlatpakDecomposed * find_matching_ref (GHashTable *refs, const char *name, const char *opt_branch, const char *opt_default_branch, - const char *opt_arch, + const char **valid_arches, /* NULL => any arch */ + const char *opt_default_arch, FlatpakKinds kinds, GError **error) { - const char **arches = flatpak_get_arches (); - const char *opt_arches[] = {opt_arch, NULL}; - int i; + g_autoptr(GPtrArray) matched_refs = NULL; - if (opt_arch != NULL) - arches = opt_arches; + matched_refs = find_matching_refs (refs, + name, + opt_branch, + opt_default_branch, + valid_arches, + opt_default_arch, + kinds, + FIND_MATCHING_REFS_FLAGS_NONE, + error); + if (matched_refs == NULL) + return NULL; - /* We stop at the first arch (in prio order) that has a match */ - for (i = 0; arches[i] != NULL; i++) + if (valid_arches != NULL) { - g_autoptr(GPtrArray) matched_refs = NULL; - int j; + /* Filter by valid, arch. We stop at the first arch (in prio order) that has a match */ + for (int i = 0; valid_arches[i] != NULL; i++) + { + const char *arch = valid_arches[i]; - matched_refs = find_matching_refs (refs, - name, - opt_branch, - opt_default_branch, - arches[i], - NULL, - kinds, - FIND_MATCHING_REFS_FLAGS_NONE, - error); - if (matched_refs == NULL) - return NULL; + g_autoptr(GPtrArray) arched_refs = get_refs_for_arch (matched_refs, arch); - if (matched_refs->len == 0) - continue; + if (arched_refs->len == 1) + return flatpak_decomposed_ref (g_ptr_array_index (arched_refs, 0)); + if (arched_refs->len > 1) + return fail_multiple_refs (error, name, arched_refs); + } + } + else + { if (matched_refs->len == 1) return flatpak_decomposed_ref (g_ptr_array_index (matched_refs, 0)); - /* Nothing to do other than reporting the different choices */ - g_autoptr(GString) err = g_string_new (""); - g_string_printf (err, _("Multiple branches available for %s, you must specify one of: "), name); - g_ptr_array_sort (matched_refs, flatpak_strcmp0_ptr); - for (j = 0; j < matched_refs->len; j++) - { - FlatpakDecomposed *ref = g_ptr_array_index (matched_refs, j); - if (j != 0) - g_string_append (err, ", "); - - const char *branch = flatpak_decomposed_get_branch (ref); - g_string_append_printf (err, - "%s/%s/%s", - name, - opt_arch ? opt_arch : "", - branch); - } - - flatpak_fail (error, "%s", err->str); - return NULL; + if (matched_refs->len > 1) + return fail_multiple_refs (error, name, matched_refs); } g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, @@ -12519,6 +12540,9 @@ flatpak_dir_get_remote_collection_id (FlatpakDir *self, return collection_id; } +/* This tries to find all available refs based on the specified name/branch/arch + * triplet from a remote. If arch is not specified, matches only on compatible arches. +*/ GPtrArray * flatpak_dir_find_remote_refs (FlatpakDir *self, FlatpakRemoteState *state, @@ -12534,17 +12558,21 @@ flatpak_dir_find_remote_refs (FlatpakDir *self, { g_autoptr(GHashTable) remote_refs = NULL; g_autoptr(GPtrArray) matched_refs = NULL; + const char **valid_arches = flatpak_get_arches (); + const char *opt_arches[] = {opt_arch, NULL}; + + if (opt_arch != NULL) + valid_arches = opt_arches; if (!flatpak_dir_list_all_remote_refs (self, state, &remote_refs, cancellable, error)) return NULL; - matched_refs = find_matching_refs (remote_refs, name, opt_branch, opt_default_branch, - opt_arch, + valid_arches, opt_default_arch, kinds, flags, @@ -12571,12 +12599,19 @@ find_ref_for_refs_set (GHashTable *refs, FlatpakKinds kinds, GError **error) { + const char **valid_arches = flatpak_get_arches (); + const char *opt_arches[] = {opt_arch, NULL}; + + if (opt_arch != NULL) + valid_arches = opt_arches; + g_autoptr(GError) my_error = NULL; g_autoptr(FlatpakDecomposed) ref = find_matching_ref (refs, name, opt_branch, opt_default_branch, - opt_arch, + valid_arches, + NULL, kinds, &my_error); if (ref == NULL) @@ -12604,6 +12639,9 @@ find_ref_for_refs_set (GHashTable *refs, return NULL; } +/* This tries to find a single ref based on the specfied name/branch/arch + * triplet from a remote. If arch is not specified, matches only on compatible arches. +*/ FlatpakDecomposed * flatpak_dir_find_remote_ref (FlatpakDir *self, FlatpakRemoteState *state, @@ -12702,6 +12740,11 @@ flatpak_dir_find_local_refs (FlatpakDir *self, g_autoptr(GError) my_error = NULL; g_autofree char *refspec_prefix = g_strconcat (remote, ":.", NULL); g_autoptr(GPtrArray) matched_refs = NULL; + const char **valid_arches = flatpak_get_arches (); + const char *opt_arches[] = {opt_arch, NULL}; + + if (opt_arch != NULL) + valid_arches = opt_arches; if (!flatpak_dir_ensure_repo (self, NULL, error)) return NULL; @@ -12717,7 +12760,7 @@ flatpak_dir_find_local_refs (FlatpakDir *self, name, opt_branch, opt_default_branch, - opt_arch, + valid_arches, opt_default_arch, kinds, flags, @@ -12780,6 +12823,9 @@ flatpak_dir_get_all_installed_refs (FlatpakDir *self, return g_steal_pointer (&local_refs); } +/* This tries to find a all installed refs based on the specfied name/branch/arch + * triplet. Matches on all arches. +*/ GPtrArray * flatpak_dir_find_installed_refs (FlatpakDir *self, const char *opt_name, @@ -12791,6 +12837,11 @@ flatpak_dir_find_installed_refs (FlatpakDir *self, { g_autoptr(GHashTable) local_refs = NULL; g_autoptr(GPtrArray) matched_refs = NULL; + const char **valid_arches = NULL; /* List all installed arches if unspecified */ + const char *opt_arches[] = {opt_arch, NULL}; + + if (opt_arch != NULL) + valid_arches = opt_arches; local_refs = flatpak_dir_get_all_installed_refs (self, kinds, error); if (local_refs == NULL) @@ -12800,7 +12851,7 @@ flatpak_dir_find_installed_refs (FlatpakDir *self, opt_name, opt_branch, NULL, /* default branch */ - opt_arch, + valid_arches, NULL, /* default arch */ kinds, flags, @@ -12811,6 +12862,10 @@ flatpak_dir_find_installed_refs (FlatpakDir *self, return g_steal_pointer (&matched_refs); } +/* This tries to find a single ref based on the specfied name/branch/arch + * triplet. This matches on all (installed) arches, but defaults to the primary + * arch if that is installed. Otherwise, ambiguity is an error. +*/ FlatpakDecomposed * flatpak_dir_find_installed_ref (FlatpakDir *self, const char *opt_name, @@ -12822,13 +12877,20 @@ flatpak_dir_find_installed_ref (FlatpakDir *self, g_autoptr(FlatpakDecomposed) local_ref = NULL; g_autoptr(GHashTable) local_refs = NULL; g_autoptr(GError) my_error = NULL; + const char **valid_arches = NULL; /* All are valid unless specified in opt_arch */ + const char *default_arch = flatpak_get_arch (); + const char *opt_arches[] = {opt_arch, NULL}; + + if (opt_arch != NULL) + valid_arches = opt_arches; local_refs = flatpak_dir_get_all_installed_refs (self, kinds, error); if (local_refs == NULL) return NULL; local_ref = find_matching_ref (local_refs, opt_name, opt_branch, NULL, - opt_arch, kinds, &my_error); + valid_arches, default_arch, + kinds, &my_error); if (local_ref == NULL) { if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) From 515ae5e5df8a9248210c4acb9b9dbe791990bace Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 17 May 2021 14:01:12 +0200 Subject: [PATCH 5/5] CLI: List arch if it is not the primary arch (even if unique) Currenly we only list arch in the list of things to install from a transaction if not all the refs are the same arch. It makes more sense to show the arch even if its unique if they are not the primary arch. --- app/flatpak-cli-transaction.c | 5 ++++- app/flatpak-table-printer.c | 25 +++++++++++++++++++++++-- app/flatpak-table-printer.h | 4 ++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/flatpak-cli-transaction.c b/app/flatpak-cli-transaction.c index 32a5b7e6..a19a6a41 100644 --- a/app/flatpak-cli-transaction.c +++ b/app/flatpak-cli-transaction.c @@ -1125,7 +1125,10 @@ transaction_ready_pre_auth (FlatpakTransaction *transaction) flatpak_table_printer_set_column_expand (printer, i, TRUE); if (!self->non_default_arch) - flatpak_table_printer_set_column_skip_unique (printer, i, TRUE); + { + flatpak_table_printer_set_column_skip_unique (printer, i, TRUE); + flatpak_table_printer_set_column_skip_unique_string (printer, i, flatpak_get_arch ()); + } flatpak_table_printer_set_column_title (printer, i++, _("Arch")); flatpak_table_printer_set_column_expand (printer, i, TRUE); diff --git a/app/flatpak-table-printer.c b/app/flatpak-table-printer.c index 8ea60ff7..a1e9d727 100644 --- a/app/flatpak-table-printer.c +++ b/app/flatpak-table-printer.c @@ -69,6 +69,7 @@ typedef struct gboolean expand; FlatpakEllipsizeMode ellipsize; gboolean skip_unique; + char *skip_unique_str; gboolean skip; } TableColumn; @@ -78,6 +79,7 @@ free_column (gpointer data) TableColumn *column = data; g_free (column->title); + g_free (column->skip_unique_str); g_free (column); } @@ -391,7 +393,8 @@ string_add_spaces (GString *str, int count) static gboolean column_is_unique (FlatpakTablePrinter *printer, int col) { - char *first_row = NULL; + TableColumn *column = get_table_column (printer, col); + char *first_row = column->skip_unique_str; int i; for (i = 0; i < printer->rows->len; i++) @@ -402,7 +405,7 @@ column_is_unique (FlatpakTablePrinter *printer, int col) Cell *cell = g_ptr_array_index (row->cells, col); - if (i == 0) + if (i == 0 && first_row == NULL) first_row = cell->text; else { @@ -853,6 +856,7 @@ flatpak_table_printer_set_column_ellipsize (FlatpakTablePrinter *printer, col->ellipsize = mode; } +/* Specifies that the column should be skipped if all values are the same */ void flatpak_table_printer_set_column_skip_unique (FlatpakTablePrinter *printer, int column, @@ -862,3 +866,20 @@ flatpak_table_printer_set_column_skip_unique (FlatpakTablePrinter *printer, col->skip_unique = skip_unique; } + +/* This modifies set_column_skip_unique to also require that the + * unique value of the column must be this particular string. Useful if you + * want to e.g. skip the arch list if everything is for the primary arch, but + * not if everything is for a non-standard arch. + */ +void +flatpak_table_printer_set_column_skip_unique_string (FlatpakTablePrinter *printer, + int column, + const char *str) +{ + TableColumn *col = get_table_column (printer, column); + + g_assert (col->skip_unique_str == NULL); + + col->skip_unique_str = g_strdup (str); +} diff --git a/app/flatpak-table-printer.h b/app/flatpak-table-printer.h index 55a546a8..dad03345 100644 --- a/app/flatpak-table-printer.h +++ b/app/flatpak-table-printer.h @@ -96,6 +96,10 @@ void flatpak_table_printer_set_column_ellipsize (FlatpakTablePrint void flatpak_table_printer_set_column_skip_unique (FlatpakTablePrinter *printer, int column, gboolean skip_unique); +void flatpak_table_printer_set_column_skip_unique_string (FlatpakTablePrinter *printer, + int column, + const char *str); + G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakTablePrinter, flatpak_table_printer_free)