transaction: Move the handling of bundle runtime remote from cli code

This allows libflatpak users to also add runtime remotes
as needed by bundles.

Closes: #1868
Approved by: alexlarsson
This commit is contained in:
Alexander Larsson
2018-07-07 15:27:26 +02:00
committed by Atomic Bot
parent c0ebd3a121
commit 98fd052695
2 changed files with 107 additions and 161 deletions

View File

@@ -113,147 +113,6 @@ read_gpg_data (GCancellable *cancellable,
return flatpak_read_stream (source_stream, FALSE, error);
}
static gboolean
remote_is_already_configured (FlatpakDir *dir,
const char *url,
const char *collection_id)
{
g_autofree char *old_remote = NULL;
old_remote = flatpak_dir_find_remote_by_uri (dir, url, collection_id);
if (old_remote == NULL && flatpak_dir_is_user (dir))
{
g_autoptr(GPtrArray) system_dirs = NULL;
int i;
system_dirs = flatpak_dir_get_system_list (NULL, NULL);
if (system_dirs == NULL)
return FALSE;
for (i = 0; i < system_dirs->len; i++)
{
FlatpakDir *system_dir = g_ptr_array_index (system_dirs, i);
old_remote = flatpak_dir_find_remote_by_uri (system_dir, url, collection_id);
if (old_remote != NULL)
break;
}
}
return old_remote != NULL;
}
static gboolean
handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error)
{
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(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;
if (opt_no_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 (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 (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 (dir, runtime_url, runtime_collection_id))
return TRUE;
if (opt_yes ||
flatpak_yes_no_prompt (_("This application depends on runtimes from:\n %s\nConfigure this as new remote '%s'"),
runtime_url, new_remote))
{
if (opt_yes)
g_print (_("Configuring %s as new remote '%s'"), runtime_url, new_remote);
if (!flatpak_dir_modify_remote (dir, new_remote, 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_bundle (FlatpakDir *dir, GFile *file, GError **error)
{
g_autofree char *dep_url = NULL;
g_autoptr(GVariant) metadata = NULL;
if (opt_no_deps)
return TRUE;
metadata = flatpak_bundle_load (file, NULL,
NULL,
NULL,
&dep_url,
NULL,
NULL,
NULL,
NULL,
NULL);
if (metadata == NULL || dep_url == NULL)
return TRUE;
return handle_runtime_repo_deps (dir, dep_url, error);
}
static gboolean
install_bundle (FlatpakDir *dir,
GOptionContext *context,
@@ -287,12 +146,6 @@ install_bundle (FlatpakDir *dir,
return FALSE;
}
if (!handle_runtime_repo_deps_from_bundle (dir, file, error))
return FALSE;
if (!flatpak_dir_ensure_repo (dir, cancellable, error))
return FALSE;
transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, error);
if (transaction == NULL)
return FALSE;

View File

@@ -78,6 +78,13 @@ struct _FlatpakTransactionOperation {
typedef struct _FlatpakTransactionPrivate FlatpakTransactionPrivate;
typedef struct _BundleData BundleData;
struct _BundleData {
GFile *file;
GBytes *gpg_data;
};
struct _FlatpakTransactionPrivate {
GObject parent;
@@ -90,6 +97,7 @@ struct _FlatpakTransactionPrivate {
GPtrArray *added_origin_remotes;
GList *flatpakrefs; /* GKeyFiles */
GList *bundles; /* BundleData */
FlatpakTransactionOperation *current_op;
@@ -136,6 +144,27 @@ enum {
LAST_PROGRESS_SIGNAL
};
static BundleData *
bundle_data_new (GFile *file,
GBytes *gpg_data)
{
BundleData *data = g_new0 (BundleData, 1);
data->file = g_object_ref (file);
if (gpg_data)
data->gpg_data = g_object_ref (gpg_data);
return data;
}
static void
bundle_data_free (BundleData *data)
{
g_clear_object (&data->file);
g_clear_object (&data->gpg_data);
g_free (data);
}
static guint progress_signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (FlatpakTransactionProgress, flatpak_transaction_progress, G_TYPE_OBJECT)
@@ -492,6 +521,7 @@ flatpak_transaction_finalize (GObject *object)
g_clear_object (&priv->installation);
g_list_free_full (priv->flatpakrefs, (GDestroyNotify)g_key_file_unref);
g_list_free_full (priv->bundles, (GDestroyNotify)bundle_data_free);
g_free (priv->default_arch);
g_hash_table_unref (priv->last_op_for_ref);
g_hash_table_unref (priv->remote_states);
@@ -1342,22 +1372,10 @@ flatpak_transaction_add_install_bundle (FlatpakTransaction *self,
GError **error)
{
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
g_autofree char *remote = NULL;
g_autofree char *ref = NULL;
g_autofree char *commit = NULL;
g_autofree char *metadata = NULL;
gboolean created_remote;
remote = flatpak_dir_ensure_bundle_remote (priv->dir, file, gpg_data,
&ref, &commit, &metadata, &created_remote,
NULL, error);
if (remote == NULL)
return FALSE;
priv->bundles = g_list_append (priv->flatpakrefs, bundle_data_new (file, gpg_data));
if (!flatpak_dir_recreate_repo (priv->dir, NULL, error))
return FALSE;
return flatpak_transaction_add_ref (self, remote, ref, NULL, commit, FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE, file, metadata, error);
return TRUE;
}
gboolean
@@ -2071,6 +2089,78 @@ flatpak_transaction_resolve_flatpakrefs (FlatpakTransaction *self,
return TRUE;
}
static gboolean
handle_runtime_repo_deps_from_bundle (FlatpakTransaction *self,
GFile *file,
GError **error)
{
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
g_autofree char *dep_url = NULL;
g_autofree char *ref = NULL;
g_auto(GStrv) ref_parts = NULL;
g_autoptr(GVariant) metadata = NULL;
if (priv->disable_deps)
return TRUE;
metadata = flatpak_bundle_load (file, NULL,
NULL,
&ref,
&dep_url,
NULL,
NULL,
NULL,
NULL,
NULL);
if (metadata == NULL || dep_url == NULL || ref == NULL)
return TRUE;
ref_parts = g_strsplit (ref, "/", -1);
return handle_runtime_repo_deps (self, ref_parts[1], dep_url, error);
}
static gboolean
flatpak_transaction_resolve_bundles (FlatpakTransaction *self,
GCancellable *cancellable,
GError **error)
{
FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self);
GList *l;
for (l = priv->bundles; l != NULL; l = l->next)
{
BundleData *data = l->data;
g_autofree char *remote = NULL;
g_autofree char *ref = NULL;
g_autofree char *commit = NULL;
g_autofree char *metadata = NULL;
gboolean created_remote;
if (!handle_runtime_repo_deps_from_bundle (self, data->file, error))
return FALSE;
if (!flatpak_dir_ensure_repo (priv->dir, cancellable, error))
return FALSE;
remote = flatpak_dir_ensure_bundle_remote (priv->dir, data->file, data->gpg_data,
&ref, &commit, &metadata, &created_remote,
NULL, error);
if (remote == NULL)
return FALSE;
if (!flatpak_dir_recreate_repo (priv->dir, NULL, error))
return FALSE;
if (!flatpak_transaction_add_ref (self, remote, ref, NULL, commit,
FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE, data->file, metadata, error))
return FALSE;
}
return TRUE;
}
gboolean
flatpak_transaction_run (FlatpakTransaction *self,
GCancellable *cancellable,
@@ -2097,6 +2187,9 @@ flatpak_transaction_run (FlatpakTransaction *self,
if (!flatpak_transaction_resolve_flatpakrefs (self, cancellable, error))
return FALSE;
if (!flatpak_transaction_resolve_bundles (self, cancellable, error))
return FALSE;
/* Resolve initial ops */
if (!resolve_ops (self, cancellable, error))
return FALSE;