From c8e1ba41e1c5f98028fecb153cc93bd886b9ade3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 10 Oct 2019 17:41:47 +0200 Subject: [PATCH] Transaction: non-p2p support for tokens We extract the need-token key from the summary and if set we calculate a token to use for the operation, which we then pass to install/update. For now the actual token just comes from the FLATPAK_TEST_TOKEN environment var. The details of this will be fleshed out later. Additionally, this does not support the p2p case, because there we need the token in order to request the commit during the resolve. This will also be added later. --- common/flatpak-transaction.c | 103 ++++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c index 2c00d868..0c9c92a1 100644 --- a/common/flatpak-transaction.c +++ b/common/flatpak-transaction.c @@ -111,10 +111,13 @@ struct _FlatpakTransactionOperation GKeyFile *resolved_metakey; GBytes *resolved_old_metadata; GKeyFile *resolved_old_metakey; + char *resolved_token; + gboolean requested_token; /* TRUE if we requested a token. value in resolved_token, but may be NULL if token not needed. */ guint64 download_size; guint64 installed_size; char *eol; char *eol_rebase; + gint32 token_type; int run_after_count; int run_after_prio; /* Higher => run later (when it becomes runnable). Used to run related ops (runtime extensions) before deps (apps using the runtime) */ GList *run_before_ops; @@ -567,6 +570,7 @@ flatpak_transaction_operation_finalize (GObject *object) g_bytes_unref (self->resolved_old_metadata); if (self->resolved_old_metakey) g_key_file_unref (self->resolved_old_metakey); + g_free (self->resolved_token); g_list_free (self->run_before_ops); G_OBJECT_CLASS (flatpak_transaction_operation_parent_class)->finalize (object); @@ -2282,11 +2286,22 @@ resolve_op_from_metadata (FlatpakTransaction *self, { g_variant_lookup (sparse_cache, FLATPAK_SPARSE_CACHE_KEY_ENDOFLINE, "s", &op->eol); g_variant_lookup (sparse_cache, FLATPAK_SPARSE_CACHE_KEY_ENDOFLINE_REBASE, "s", &op->eol_rebase); + g_variant_lookup (sparse_cache, FLATPAK_SPARSE_CACHE_KEY_TOKEN_TYPE, "i", &op->token_type); } resolve_op_end (self, op, checksum, metadata_bytes); } +static gboolean +op_may_need_token (FlatpakTransactionOperation *op) +{ + return + !op->skip && + (op->kind == FLATPAK_TRANSACTION_OPERATION_INSTALL || + op->kind == FLATPAK_TRANSACTION_OPERATION_UPDATE || + op->kind == FLATPAK_TRANSACTION_OPERATION_INSTALL_OR_UPDATE); +} + static gboolean resolve_p2p_ops (FlatpakTransaction *self, GList *p2p_ops, @@ -2355,7 +2370,6 @@ resolve_ops (FlatpakTransaction *self, GList *l; g_autoptr(GList) collection_id_ops = NULL; - for (l = priv->ops; l != NULL; l = l->next) { FlatpakTransactionOperation *op = l->data; @@ -2470,6 +2484,85 @@ resolve_all_ops (FlatpakTransaction *self, return TRUE; } + +static gboolean +request_tokens_for_remote (FlatpakTransaction *self, + const char *remote, + GList *ops, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GString) refs_as_str = g_string_new (""); + GList *l; + const char *token; + + for (l = ops; l != NULL; l = l->next) + { + FlatpakTransactionOperation *op = l->data; + + if (l != ops) + g_string_append (refs_as_str, ", "); + g_string_append (refs_as_str, op->ref); + } + + g_debug ("Requesting tokens for remote %s, refs: %s", remote, refs_as_str->str); + + /* FIXME: This is just some temporary testing code and will be + replaces with a callout later. */ + token = g_getenv ("FLATPAK_TEST_TOKEN"); + if (token == NULL) + token = "default-token"; + + g_debug ("Got token %s", token); + + for (l = ops; l != NULL; l = l->next) + { + FlatpakTransactionOperation *op = l->data; + + op->resolved_token = g_strdup (token); + op->requested_token = TRUE; + } + + return TRUE; +} + +static gboolean +request_required_tokens (FlatpakTransaction *self, + const char *optional_remote, /* else all remotes */ + GCancellable *cancellable, + GError **error) +{ + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + GList *l; + g_autoptr(GHashTable) need_token_ht = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_list_free); /* remote name -> list of op */ + + for (l = priv->ops; l != NULL; l = l->next) + { + FlatpakTransactionOperation *op = l->data; + GList *old; + + if (!op_may_need_token (op) || op->token_type == 0 || op->requested_token) + continue; + + if (optional_remote != NULL && g_strcmp0 (op->remote, optional_remote) != 0) + continue; + + old = g_hash_table_lookup (need_token_ht, op->remote); + if (old == NULL) + g_hash_table_insert (need_token_ht, op->remote, g_list_append (NULL, op)); + else + old = g_list_append (old, op); + } + + GLNX_HASH_TABLE_FOREACH_KV(need_token_ht, const char *, remote, GList *, remote_ops) + { + if (!request_tokens_for_remote (self, remote, remote_ops, cancellable, error)) + return FALSE; + } + + return TRUE; +} + static int compare_op_ref (FlatpakTransactionOperation *a, FlatpakTransactionOperation *b) { @@ -3007,7 +3100,7 @@ _run_op_kind (FlatpakTransaction *self, remote_state, op->ref, op->resolved_commit, (const char **) op->subpaths, (const char **) op->previous_ids, - NULL, + op->resolved_token, progress->ostree_progress, cancellable, error); @@ -3057,7 +3150,7 @@ _run_op_kind (FlatpakTransaction *self, NULL, (const char **) op->subpaths, (const char **) op->previous_ids, - NULL, + op->resolved_token, progress->ostree_progress, cancellable, &local_error); flatpak_transaction_progress_done (progress); @@ -3218,6 +3311,10 @@ flatpak_transaction_real_run (FlatpakTransaction *self, if (!resolve_all_ops (self, cancellable, error)) return FALSE; + /* Ensure we have all required tokens */ + if (!request_required_tokens (self, NULL, cancellable, error)) + return FALSE; + sort_ops (self); /* Ensure the operation kind is normalized and not no-op */