mirror of
https://github.com/flatpak/flatpak.git
synced 2026-05-06 23:18:40 -04:00
transaction: Move flatpakref installation to transaction code
This adds the flatpak_transaction_add_install_flatpakref method to easily install from flatpakref files. It additionally adds a new signal called add-new-remote which is called in two cases: To ask if the user wants to add a "normal" remote for the url specified by a flatpakref file. When a new remote is required for the runtimes the application depends on. Closes: #1868 Approved by: alexlarsson
This commit is contained in:
committed by
Atomic Bot
parent
1ecca029a8
commit
c0ebd3a121
@@ -155,6 +155,8 @@ handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error)
|
||||
g_autoptr(GBytes) gpg_key = NULL;
|
||||
g_autofree char *group = NULL;
|
||||
g_autofree char *runtime_collection_id = NULL;
|
||||
g_autoptr(GKeyFile) dep_keyfile = g_key_file_new ();
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
char *t;
|
||||
int i;
|
||||
|
||||
@@ -168,6 +170,12 @@ handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_key_file_load_from_data (dep_keyfile,
|
||||
g_bytes_get_data (dep_data, NULL),
|
||||
g_bytes_get_size (dep_data),
|
||||
0, error))
|
||||
return flatpak_fail (error, "Invalid .flatpakrepo: %s", local_error->message);
|
||||
|
||||
uri = soup_uri_new (dep_url);
|
||||
basename = g_path_get_basename (soup_uri_get_path (uri));
|
||||
/* Strip suffix */
|
||||
@@ -190,7 +198,7 @@ handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error)
|
||||
}
|
||||
while (remotes != NULL && g_strv_contains ((const char * const*)remotes, new_remote));
|
||||
|
||||
config = flatpak_dir_parse_repofile (dir, new_remote, FALSE, dep_data, &gpg_key, NULL, error);
|
||||
config = flatpak_dir_parse_repofile (dir, new_remote, FALSE, dep_keyfile, &gpg_key, NULL, error);
|
||||
if (config == NULL)
|
||||
{
|
||||
g_prefix_error (error, "Can't parse dependent file %s: ", dep_url);
|
||||
@@ -305,81 +313,6 @@ install_bundle (FlatpakDir *dir,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_suggested_remote_name (FlatpakDir *dir, GBytes *data, GError **error)
|
||||
{
|
||||
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
||||
g_autofree char *suggested_name = NULL;
|
||||
g_autofree char *url = NULL;
|
||||
g_autofree char *collection_id = NULL;
|
||||
g_autoptr(GKeyFile) config = NULL;
|
||||
g_autoptr(GBytes) gpg_key = NULL;
|
||||
|
||||
if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (data, NULL), g_bytes_get_size (data),
|
||||
0, error))
|
||||
return FALSE;
|
||||
|
||||
suggested_name = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
|
||||
FLATPAK_REF_SUGGEST_REMOTE_NAME_KEY, NULL);
|
||||
if (suggested_name == NULL)
|
||||
return TRUE;
|
||||
|
||||
url = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
|
||||
FLATPAK_REF_URL_KEY, NULL);
|
||||
if (url == NULL)
|
||||
return TRUE;
|
||||
|
||||
collection_id = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP, FLATPAK_REF_COLLECTION_ID_KEY, NULL);
|
||||
|
||||
if (remote_is_already_configured (dir, url, collection_id))
|
||||
return TRUE;
|
||||
|
||||
/* The name is already used, ignore */
|
||||
if (ostree_repo_remote_get_url (flatpak_dir_get_repo (dir), suggested_name, NULL, NULL))
|
||||
return TRUE;
|
||||
|
||||
if (opt_yes ||
|
||||
flatpak_yes_no_prompt (_("The remote '%s', at location %s contains additional applications.\nShould the remote be kept for future installations?"),
|
||||
suggested_name, url))
|
||||
{
|
||||
if (opt_yes)
|
||||
g_print (_("Configuring %s as new remote '%s'"), url, suggested_name);
|
||||
|
||||
config = flatpak_dir_parse_repofile (dir, suggested_name, TRUE, data, &gpg_key, NULL, error);
|
||||
if (config == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_modify_remote (dir, suggested_name, config, gpg_key, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_recreate_repo (dir, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_runtime_repo_deps_from_keyfile (FlatpakDir *dir, GBytes *data, GError **error)
|
||||
{
|
||||
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
||||
g_autofree char *dep_url = NULL;
|
||||
|
||||
if (opt_no_deps)
|
||||
return TRUE;
|
||||
|
||||
if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (data, NULL), g_bytes_get_size (data),
|
||||
0, error))
|
||||
return FALSE;
|
||||
|
||||
dep_url = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
|
||||
FLATPAK_REF_RUNTIME_REPO_KEY, NULL);
|
||||
if (dep_url == NULL)
|
||||
return TRUE;
|
||||
|
||||
return handle_runtime_repo_deps (dir, dep_url, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
install_from (FlatpakDir *dir,
|
||||
GOptionContext *context,
|
||||
@@ -392,10 +325,6 @@ install_from (FlatpakDir *dir,
|
||||
g_autofree char *data = NULL;
|
||||
gsize data_len;
|
||||
const char *filename;
|
||||
g_autofree char *remote = NULL;
|
||||
g_autofree char *ref = NULL;
|
||||
const char *slash;
|
||||
FlatpakDir *clone;
|
||||
g_autoptr(FlatpakTransaction) transaction = NULL;
|
||||
|
||||
if (argc < 2)
|
||||
@@ -427,25 +356,7 @@ install_from (FlatpakDir *dir,
|
||||
file_data = g_bytes_new_take (g_steal_pointer (&data), data_len);
|
||||
}
|
||||
|
||||
/* Handle this before the runtime deps, because they might be the same */
|
||||
if (!handle_suggested_remote_name (dir, file_data, error))
|
||||
return FALSE;
|
||||
|
||||
if (!handle_runtime_repo_deps_from_keyfile (dir, file_data, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_create_remote_for_ref_file (dir, file_data, opt_arch, &remote, NULL, &ref, error))
|
||||
return FALSE;
|
||||
|
||||
/* Need to pick up the new config, in case it was applied in the system helper. */
|
||||
clone = flatpak_dir_clone (dir);
|
||||
if (!flatpak_dir_ensure_repo (clone, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
slash = strchr (ref, '/');
|
||||
g_print (_("Installing: %s\n"), slash + 1);
|
||||
|
||||
transaction = flatpak_cli_transaction_new (clone, opt_yes, TRUE, error);
|
||||
transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, error);
|
||||
if (transaction == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -455,8 +366,9 @@ install_from (FlatpakDir *dir,
|
||||
flatpak_transaction_set_disable_dependencies (transaction, opt_no_deps);
|
||||
flatpak_transaction_set_disable_related (transaction, opt_no_related);
|
||||
flatpak_transaction_set_reinstall (transaction, opt_reinstall);
|
||||
flatpak_transaction_set_default_arch (transaction, opt_arch);
|
||||
|
||||
if (!flatpak_cli_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error))
|
||||
if (!flatpak_transaction_add_install_flatpakref (transaction, file_data, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_cli_transaction_run (transaction, cancellable, error))
|
||||
|
||||
@@ -94,6 +94,39 @@ choose_remote_for_ref (FlatpakTransaction *transaction,
|
||||
return chosen;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
add_new_remote (FlatpakTransaction *transaction,
|
||||
FlatpakTransactionRemoteReason reason,
|
||||
const char *from_id,
|
||||
const char *remote_name,
|
||||
const char *url)
|
||||
{
|
||||
FlatpakCliTransaction *self = FLATPAK_CLI_TRANSACTION (transaction);
|
||||
|
||||
if (self->disable_interaction)
|
||||
{
|
||||
g_print (_("Configuring %s as new remote '%s'"), url, remote_name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (reason == FLATPAK_TRANSACTION_REMOTE_GENERIC_REPO)
|
||||
{
|
||||
if (flatpak_yes_no_prompt (_("The remote '%s', refered to by '%s' at location %s contains additional applications.\n"
|
||||
"Should the remote be kept for future installations?"),
|
||||
remote_name, from_id, url))
|
||||
return TRUE;
|
||||
}
|
||||
else if (reason == FLATPAK_TRANSACTION_REMOTE_RUNTIME_DEPS)
|
||||
{
|
||||
if (flatpak_yes_no_prompt (_("The application %s depends on runtimes from:\n %s\n"
|
||||
"Configure this as new remote '%s'"),
|
||||
from_id, url, remote_name))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static char *
|
||||
op_type_to_string (FlatpakTransactionOperationType operation_type)
|
||||
{
|
||||
@@ -602,6 +635,7 @@ flatpak_cli_transaction_class_init (FlatpakCliTransactionClass *klass)
|
||||
FlatpakTransactionClass *transaction_class = FLATPAK_TRANSACTION_CLASS (klass);
|
||||
|
||||
object_class->finalize = flatpak_cli_transaction_finalize;
|
||||
transaction_class->add_new_remote = add_new_remote;
|
||||
transaction_class->ready = transaction_ready;
|
||||
transaction_class->new_operation = new_operation;
|
||||
transaction_class->operation_done = operation_done;
|
||||
|
||||
@@ -615,7 +615,7 @@ char *flatpak_dir_create_origin_remote (FlatpakDir *self,
|
||||
void flatpak_dir_prune_origin_remote (FlatpakDir *self,
|
||||
const char *remote);
|
||||
gboolean flatpak_dir_create_remote_for_ref_file (FlatpakDir *self,
|
||||
GBytes *data,
|
||||
GKeyFile *keyfile,
|
||||
const char *default_arch,
|
||||
char **remote_name_out,
|
||||
char **collection_id_out,
|
||||
@@ -627,7 +627,7 @@ gboolean flatpak_dir_create_suggested_remote_for_ref_file (FlatpakDir *self,
|
||||
GKeyFile * flatpak_dir_parse_repofile (FlatpakDir *self,
|
||||
const char *remote_name,
|
||||
gboolean from_ref,
|
||||
GBytes *data,
|
||||
GKeyFile *keyfile,
|
||||
GBytes **gpg_data_out,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
@@ -10072,13 +10072,11 @@ GKeyFile *
|
||||
flatpak_dir_parse_repofile (FlatpakDir *self,
|
||||
const char *remote_name,
|
||||
gboolean from_ref,
|
||||
GBytes *data,
|
||||
GKeyFile *keyfile,
|
||||
GBytes **gpg_data_out,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
g_autoptr(GBytes) gpg_data = NULL;
|
||||
g_autofree char *uri = NULL;
|
||||
g_autofree char *title = NULL;
|
||||
@@ -10096,15 +10094,6 @@ flatpak_dir_parse_repofile (FlatpakDir *self,
|
||||
GKeyFile *config = g_key_file_new ();
|
||||
g_autofree char *group = g_strdup_printf ("remote \"%s\"", remote_name);
|
||||
|
||||
if (!g_key_file_load_from_data (keyfile,
|
||||
g_bytes_get_data (data, NULL),
|
||||
g_bytes_get_size (data),
|
||||
0, &local_error))
|
||||
{
|
||||
flatpak_fail (error, "Invalid .flatpakref: %s", local_error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_key_file_has_group (keyfile, source_group))
|
||||
{
|
||||
flatpak_fail (error, "Invalid .flatpakref");
|
||||
@@ -10179,7 +10168,7 @@ flatpak_dir_parse_repofile (FlatpakDir *self,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_ref_file (GBytes *data,
|
||||
parse_ref_file (GKeyFile *keyfile,
|
||||
char **name_out,
|
||||
char **branch_out,
|
||||
char **url_out,
|
||||
@@ -10189,7 +10178,6 @@ parse_ref_file (GBytes *data,
|
||||
char **collection_id_out,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
||||
g_autofree char *url = NULL;
|
||||
g_autofree char *title = NULL;
|
||||
g_autofree char *name = NULL;
|
||||
@@ -10207,10 +10195,6 @@ parse_ref_file (GBytes *data,
|
||||
*gpg_data_out = NULL;
|
||||
*is_runtime_out = FALSE;
|
||||
|
||||
if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (data, NULL), g_bytes_get_size (data),
|
||||
0, error))
|
||||
return FALSE;
|
||||
|
||||
if (!g_key_file_has_group (keyfile, FLATPAK_REF_GROUP))
|
||||
return flatpak_fail (error, "Invalid file format, no %s group", FLATPAK_REF_GROUP);
|
||||
|
||||
@@ -10273,7 +10257,7 @@ parse_ref_file (GBytes *data,
|
||||
|
||||
gboolean
|
||||
flatpak_dir_create_remote_for_ref_file (FlatpakDir *self,
|
||||
GBytes *data,
|
||||
GKeyFile *keyfile,
|
||||
const char *default_arch,
|
||||
char **remote_name_out,
|
||||
char **collection_id_out,
|
||||
@@ -10291,7 +10275,7 @@ flatpak_dir_create_remote_for_ref_file (FlatpakDir *self,
|
||||
g_autofree char *collection_id = NULL;
|
||||
g_autoptr(GFile) deploy_dir = NULL;
|
||||
|
||||
if (!parse_ref_file (data, &name, &branch, &url, &title, &gpg_data, &is_runtime, &collection_id, error))
|
||||
if (!parse_ref_file (keyfile, &name, &branch, &url, &title, &gpg_data, &is_runtime, &collection_id, error))
|
||||
return FALSE;
|
||||
|
||||
ref = flatpak_compose_ref (!is_runtime, name, branch, default_arch, error);
|
||||
|
||||
@@ -1638,12 +1638,19 @@ flatpak_installation_install_ref_file (FlatpakInstallation *self,
|
||||
g_autofree char *ref = NULL;
|
||||
g_autofree char *collection_id = NULL;
|
||||
g_autoptr(FlatpakCollectionRef) coll_ref = NULL;
|
||||
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
||||
|
||||
dir = flatpak_installation_get_dir (self, error);
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!flatpak_dir_create_remote_for_ref_file (dir, ref_file_data, NULL, &remote, &collection_id, &ref, error))
|
||||
if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (ref_file_data, NULL),
|
||||
g_bytes_get_size (ref_file_data),
|
||||
0, error))
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (!flatpak_dir_create_remote_for_ref_file (dir, keyfile, NULL, &remote, &collection_id, &ref, error))
|
||||
return NULL;
|
||||
|
||||
if (!flatpak_installation_drop_caches (self, cancellable, error))
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <libsoup/soup.h>
|
||||
|
||||
#include "flatpak-transaction-private.h"
|
||||
#include "flatpak-installation-private.h"
|
||||
@@ -88,6 +89,8 @@ struct _FlatpakTransactionPrivate {
|
||||
GList *ops;
|
||||
GPtrArray *added_origin_remotes;
|
||||
|
||||
GList *flatpakrefs; /* GKeyFiles */
|
||||
|
||||
FlatpakTransactionOperation *current_op;
|
||||
|
||||
gboolean no_pull;
|
||||
@@ -108,6 +111,7 @@ enum {
|
||||
CHOOSE_REMOTE_FOR_REF,
|
||||
END_OF_LIFED,
|
||||
READY,
|
||||
ADD_NEW_REMOTE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@@ -487,6 +491,7 @@ flatpak_transaction_finalize (GObject *object)
|
||||
|
||||
g_clear_object (&priv->installation);
|
||||
|
||||
g_list_free_full (priv->flatpakrefs, (GDestroyNotify)g_key_file_unref);
|
||||
g_free (priv->default_arch);
|
||||
g_hash_table_unref (priv->last_op_for_ref);
|
||||
g_hash_table_unref (priv->remote_states);
|
||||
@@ -565,12 +570,23 @@ flatpak_transaction_ready (FlatpakTransaction *transaction)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
flatpak_transaction_add_new_remote (FlatpakTransaction *transaction,
|
||||
FlatpakTransactionRemoteReason reason,
|
||||
const char *from_id,
|
||||
const char *suggested_remote_name,
|
||||
const char *url)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_transaction_class_init (FlatpakTransactionClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->ready = flatpak_transaction_ready;
|
||||
klass->add_new_remote = flatpak_transaction_add_new_remote;
|
||||
object_class->finalize = flatpak_transaction_finalize;
|
||||
object_class->get_property = flatpak_transaction_get_property;
|
||||
object_class->set_property = flatpak_transaction_set_property;
|
||||
@@ -689,6 +705,26 @@ flatpak_transaction_class_init (FlatpakTransactionClass *klass)
|
||||
signal_accumulator_false_abort, NULL,
|
||||
NULL,
|
||||
G_TYPE_BOOLEAN, 0);
|
||||
/**
|
||||
* FlatpakTransaction::add-new-remote:
|
||||
* @object: A #FlatpakTransaction
|
||||
* @reason: The reason for the new remote is needed
|
||||
* @from_id: The id of the app/runtime
|
||||
* @suggested_remote_name: The suggested remote name
|
||||
* @url: The repo url
|
||||
*
|
||||
* As part of the transaction, it is required or recommended
|
||||
* that a new remote is added, for the reason described in @reason.
|
||||
* Return %TRUE to add it.
|
||||
*/
|
||||
signals[ADD_NEW_REMOTE] =
|
||||
g_signal_new ("add-new-remote",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (FlatpakTransactionClass, add_new_remote),
|
||||
g_signal_accumulator_first_wins, NULL,
|
||||
NULL,
|
||||
G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1324,6 +1360,25 @@ flatpak_transaction_add_install_bundle (FlatpakTransaction *self,
|
||||
return flatpak_transaction_add_ref (self, remote, ref, NULL, commit, FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE, file, metadata, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_transaction_add_install_flatpakref (FlatpakTransaction *self,
|
||||
GBytes *flatpakref_data,
|
||||
GError **error)
|
||||
{
|
||||
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
|
||||
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
|
||||
if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (flatpakref_data, NULL),
|
||||
g_bytes_get_size (flatpakref_data),
|
||||
0, error))
|
||||
return flatpak_fail (error, "Invalid .flatpakref: %s", local_error->message);
|
||||
|
||||
priv->flatpakrefs = g_list_append (priv->flatpakrefs, g_steal_pointer (&keyfile));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_transaction_add_update (FlatpakTransaction *self,
|
||||
const char *ref,
|
||||
@@ -1760,6 +1815,262 @@ flatpak_transaction_get_installation (FlatpakTransaction *self)
|
||||
return g_object_ref (priv->installation);
|
||||
}
|
||||
|
||||
|
||||
static GBytes *
|
||||
download_uri (const char *url,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(SoupSession) session = NULL;
|
||||
g_autoptr(SoupRequest) req = NULL;
|
||||
g_autoptr(GInputStream) input = NULL;
|
||||
g_autoptr(GOutputStream) out = NULL;
|
||||
|
||||
session = flatpak_create_soup_session (PACKAGE_STRING);
|
||||
|
||||
req = soup_session_request (session, url, error);
|
||||
if (req == NULL)
|
||||
return NULL;
|
||||
|
||||
input = soup_request_send (req, NULL, error);
|
||||
if (input == NULL)
|
||||
return NULL;
|
||||
|
||||
out = g_memory_output_stream_new_resizable ();
|
||||
if (!g_output_stream_splice (out,
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET | G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
|
||||
NULL,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
return g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (out));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
remote_is_already_configured (FlatpakTransaction *self,
|
||||
const char *url,
|
||||
const char *collection_id)
|
||||
{
|
||||
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
|
||||
g_autofree char *old_remote = NULL;
|
||||
int i;
|
||||
|
||||
old_remote = flatpak_dir_find_remote_by_uri (priv->dir, url, collection_id);
|
||||
if (old_remote == NULL)
|
||||
{
|
||||
for (i = 0; i < priv->extra_dependency_dirs->len; i++)
|
||||
{
|
||||
FlatpakDir *dependency_dir = g_ptr_array_index (priv->extra_dependency_dirs, i);
|
||||
|
||||
old_remote = flatpak_dir_find_remote_by_uri (dependency_dir, url, collection_id);
|
||||
if (old_remote != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return old_remote != NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_suggested_remote_name (FlatpakTransaction *self, GKeyFile *keyfile, GError **error)
|
||||
{
|
||||
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
|
||||
g_autofree char *suggested_name = NULL;
|
||||
g_autofree char *name = NULL;
|
||||
g_autofree char *url = NULL;
|
||||
g_autofree char *collection_id = NULL;
|
||||
g_autoptr(GKeyFile) config = NULL;
|
||||
g_autoptr(GBytes) gpg_key = NULL;
|
||||
gboolean res;
|
||||
|
||||
suggested_name = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
|
||||
FLATPAK_REF_SUGGEST_REMOTE_NAME_KEY, NULL);
|
||||
if (suggested_name == NULL)
|
||||
return TRUE;
|
||||
|
||||
name = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP, FLATPAK_REF_NAME_KEY, NULL);
|
||||
if (name == NULL)
|
||||
return TRUE;
|
||||
|
||||
url = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP, FLATPAK_REF_URL_KEY, NULL);
|
||||
if (url == NULL)
|
||||
return TRUE;
|
||||
|
||||
collection_id = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP, FLATPAK_REF_COLLECTION_ID_KEY, NULL);
|
||||
|
||||
if (remote_is_already_configured (self, url, collection_id))
|
||||
return TRUE;
|
||||
|
||||
/* The name is already used, ignore */
|
||||
if (ostree_repo_remote_get_url (flatpak_dir_get_repo (priv->dir), suggested_name, NULL, NULL))
|
||||
return TRUE;
|
||||
|
||||
res = FALSE;
|
||||
g_signal_emit (self, signals[ADD_NEW_REMOTE], 0, FLATPAK_TRANSACTION_REMOTE_GENERIC_REPO,
|
||||
name, suggested_name, url, &res);
|
||||
if (res)
|
||||
{
|
||||
config = flatpak_dir_parse_repofile (priv->dir, suggested_name, TRUE, keyfile, &gpg_key, NULL, error);
|
||||
if (config == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_modify_remote (priv->dir, suggested_name, config, gpg_key, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_recreate_repo (priv->dir, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_runtime_repo_deps (FlatpakTransaction *self, const char *id, const char *dep_url, GError **error)
|
||||
{
|
||||
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
|
||||
g_autoptr(GBytes) dep_data = NULL;
|
||||
g_autofree char *runtime_url = NULL;
|
||||
g_autofree char *new_remote = NULL;
|
||||
g_autofree char *basename = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
g_auto(GStrv) remotes = NULL;
|
||||
g_autoptr(GKeyFile) config = NULL;
|
||||
g_autoptr(GKeyFile) dep_keyfile = g_key_file_new ();
|
||||
g_autoptr(GBytes) gpg_key = NULL;
|
||||
g_autofree char *group = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
g_autofree char *runtime_collection_id = NULL;
|
||||
char *t;
|
||||
int i;
|
||||
gboolean res;
|
||||
|
||||
if (priv->disable_deps)
|
||||
return TRUE;
|
||||
|
||||
dep_data = download_uri (dep_url, error);
|
||||
if (dep_data == NULL)
|
||||
{
|
||||
g_prefix_error (error, "Can't load dependent file %s", dep_url);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_key_file_load_from_data (dep_keyfile,
|
||||
g_bytes_get_data (dep_data, NULL),
|
||||
g_bytes_get_size (dep_data),
|
||||
0, error))
|
||||
return flatpak_fail (error, "Invalid .flatpakrepo: %s", local_error->message);
|
||||
|
||||
uri = soup_uri_new (dep_url);
|
||||
basename = g_path_get_basename (soup_uri_get_path (uri));
|
||||
/* Strip suffix */
|
||||
t = strchr (basename, '.');
|
||||
if (t != NULL)
|
||||
*t = 0;
|
||||
|
||||
/* Find a free remote name */
|
||||
remotes = flatpak_dir_list_remotes (priv->dir, NULL, NULL);
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
g_clear_pointer (&new_remote, g_free);
|
||||
|
||||
if (i == 0)
|
||||
new_remote = g_strdup (basename);
|
||||
else
|
||||
new_remote = g_strdup_printf ("%s-%d", basename, i);
|
||||
i++;
|
||||
}
|
||||
while (remotes != NULL && g_strv_contains ((const char * const*)remotes, new_remote));
|
||||
|
||||
config = flatpak_dir_parse_repofile (priv->dir, new_remote, FALSE, dep_keyfile, &gpg_key, NULL, error);
|
||||
if (config == NULL)
|
||||
{
|
||||
g_prefix_error (error, "Can't parse dependent file %s: ", dep_url);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* See if it already exists */
|
||||
group = g_strdup_printf ("remote \"%s\"", new_remote);
|
||||
runtime_url = g_key_file_get_string (config, group, "url", NULL);
|
||||
g_assert (runtime_url != NULL);
|
||||
runtime_collection_id = g_key_file_get_string (config, group, "collection-id", NULL);
|
||||
|
||||
if (remote_is_already_configured (self, runtime_url, runtime_collection_id))
|
||||
return TRUE;
|
||||
|
||||
res = FALSE;
|
||||
g_signal_emit (self, signals[ADD_NEW_REMOTE], 0, FLATPAK_TRANSACTION_REMOTE_RUNTIME_DEPS,
|
||||
id, new_remote, runtime_url, &res);
|
||||
if (res)
|
||||
{
|
||||
if (!flatpak_dir_modify_remote (priv->dir, new_remote, config, gpg_key, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_recreate_repo (priv->dir, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_runtime_repo_deps_from_keyfile (FlatpakTransaction *self, GKeyFile *keyfile, GError **error)
|
||||
{
|
||||
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
|
||||
g_autofree char *dep_url = NULL;
|
||||
g_autofree char *name = NULL;
|
||||
|
||||
if (priv->disable_deps)
|
||||
return TRUE;
|
||||
|
||||
dep_url = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
|
||||
FLATPAK_REF_RUNTIME_REPO_KEY, NULL);
|
||||
if (dep_url == NULL)
|
||||
return TRUE;
|
||||
|
||||
name = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP, FLATPAK_REF_NAME_KEY, NULL);
|
||||
if (name == NULL)
|
||||
return TRUE;
|
||||
|
||||
return handle_runtime_repo_deps (self, name, dep_url, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
flatpak_transaction_resolve_flatpakrefs (FlatpakTransaction *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->flatpakrefs; l != NULL; l = l->next)
|
||||
{
|
||||
GKeyFile *flatpakref = l->data;
|
||||
g_autofree char *remote = NULL;
|
||||
g_autofree char *ref = NULL;
|
||||
|
||||
/* Handle this before the runtime deps, because they might be the same */
|
||||
if (!handle_suggested_remote_name (self, flatpakref, error))
|
||||
return FALSE;
|
||||
|
||||
if (!handle_runtime_repo_deps_from_keyfile (self, flatpakref, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_create_remote_for_ref_file (priv->dir, flatpakref, priv->default_arch,
|
||||
&remote, NULL, &ref, error))
|
||||
return FALSE;
|
||||
|
||||
/* Need to pick up the new config, in case it was applied in the system helper. */
|
||||
if (!flatpak_dir_recreate_repo (priv->dir, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_transaction_add_install (self, remote, ref, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_transaction_run (FlatpakTransaction *self,
|
||||
GCancellable *cancellable,
|
||||
@@ -1783,6 +2094,9 @@ flatpak_transaction_run (FlatpakTransaction *self,
|
||||
/* Work around ostree-pull spinning the default main context for the sync calls */
|
||||
main_context = flatpak_main_context_new_default ();
|
||||
|
||||
if (!flatpak_transaction_resolve_flatpakrefs (self, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
/* Resolve initial ops */
|
||||
if (!resolve_ops (self, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
@@ -68,6 +68,16 @@ typedef enum {
|
||||
FLATPAK_TRANSACTION_RESULT_NO_CHANGE = 1 << 0,
|
||||
} FlatpakTransactionResult;
|
||||
|
||||
/**
|
||||
* FlatpakTransactionRemoteReason
|
||||
* @FLATPAK_TRANSACTION_REMOTE_GENERIC_REPO: The remote specified in the flatpakref has other apps too
|
||||
* @FLATPAK_TRANSACTION_REMOTE_RUNTIME_DEPS: The remote has runtimes needed for the app
|
||||
*/
|
||||
typedef enum {
|
||||
FLATPAK_TRANSACTION_REMOTE_GENERIC_REPO,
|
||||
FLATPAK_TRANSACTION_REMOTE_RUNTIME_DEPS,
|
||||
} FlatpakTransactionRemoteReason;
|
||||
|
||||
FLATPAK_EXTERN
|
||||
G_DECLARE_FINAL_TYPE (FlatpakTransactionProgress, flatpak_transaction_progress, FLATPAK, TRANSACTION_PROGRESS, GObject)
|
||||
|
||||
@@ -101,7 +111,12 @@ struct _FlatpakTransactionClass
|
||||
const char *rebase);
|
||||
gboolean (*ready) (FlatpakTransaction *transaction);
|
||||
|
||||
gpointer padding[11];
|
||||
gboolean (*add_new_remote) (FlatpakTransaction *transaction,
|
||||
FlatpakTransactionRemoteReason reason,
|
||||
const char *from_id,
|
||||
const char *remote_name,
|
||||
const char *url);
|
||||
gpointer padding[10];
|
||||
};
|
||||
|
||||
FLATPAK_EXTERN
|
||||
@@ -190,6 +205,10 @@ gboolean flatpak_transaction_add_install_bundle (FlatpakTransa
|
||||
GBytes *gpg_data,
|
||||
GError **error);
|
||||
FLATPAK_EXTERN
|
||||
gboolean flatpak_transaction_add_install_flatpakref (FlatpakTransaction *self,
|
||||
GBytes *flatpakref_data,
|
||||
GError **error);
|
||||
FLATPAK_EXTERN
|
||||
gboolean flatpak_transaction_add_update (FlatpakTransaction *self,
|
||||
const char *ref,
|
||||
const char **subpaths,
|
||||
|
||||
@@ -238,6 +238,7 @@ flatpak_transaction_set_no_pull
|
||||
flatpak_transaction_set_reinstall
|
||||
flatpak_transaction_set_force_uninstall
|
||||
flatpak_transaction_set_default_arch
|
||||
flatpak_transaction_add_install_flatpakref
|
||||
<SUBSECTION Standard>
|
||||
FlatpakTransactionClass
|
||||
FLATPAK_IS_TRANSACTION
|
||||
|
||||
Reference in New Issue
Block a user