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:
Alexander Larsson
2018-07-05 14:12:17 +02:00
committed by Atomic Bot
parent 1ecca029a8
commit c0ebd3a121
8 changed files with 395 additions and 124 deletions

View File

@@ -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))

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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))

View File

@@ -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;

View File

@@ -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,

View File

@@ -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