diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c index 6a8fe108..446224e6 100644 --- a/app/flatpak-builtins-install.c +++ b/app/flatpak-builtins-install.c @@ -287,7 +287,10 @@ install_bundle (FlatpakDir *dir, if (!flatpak_dir_ensure_repo (dir, cancellable, error)) return FALSE; - transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE); + transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, error); + if (transaction == NULL) + return FALSE; + flatpak_transaction_set_no_pull (transaction, opt_no_pull); flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); @@ -446,7 +449,10 @@ install_from (FlatpakDir *dir, slash = strchr (ref, '/'); g_print (_("Installing: %s\n"), slash + 1); - transaction = flatpak_cli_transaction_new (clone, opt_yes, TRUE); + transaction = flatpak_cli_transaction_new (clone, opt_yes, TRUE, error); + if (transaction == NULL) + return FALSE; + flatpak_transaction_set_no_pull (transaction, opt_no_pull); flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); @@ -527,7 +533,10 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro default_branch = flatpak_dir_get_remote_default_branch (dir, remote); kinds = flatpak_kinds_from_bools (opt_app, opt_runtime); - transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE); + transaction = flatpak_cli_transaction_new (dir, opt_yes, TRUE, error); + if (transaction == NULL) + return FALSE; + flatpak_transaction_set_no_pull (transaction, opt_no_pull); flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); diff --git a/app/flatpak-builtins-update.c b/app/flatpak-builtins-update.c index 37dbcf16..22e7937d 100644 --- a/app/flatpak-builtins-update.c +++ b/app/flatpak-builtins-update.c @@ -110,7 +110,10 @@ flatpak_builtin_update (int argc, for (k = 0; k < dirs->len; k++) { - FlatpakTransaction *transaction = flatpak_cli_transaction_new (g_ptr_array_index (dirs, k), opt_yes, FALSE); + FlatpakTransaction *transaction = flatpak_cli_transaction_new (g_ptr_array_index (dirs, k), opt_yes, FALSE, error); + if (transaction == NULL) + return FALSE; + flatpak_transaction_set_no_pull (transaction, opt_no_pull); flatpak_transaction_set_no_deploy (transaction, opt_no_deploy); flatpak_transaction_set_disable_static_deltas (transaction, opt_no_static_deltas); diff --git a/app/flatpak-cli-transaction.c b/app/flatpak-cli-transaction.c index 47cfa3df..d1e4a081 100644 --- a/app/flatpak-cli-transaction.c +++ b/app/flatpak-cli-transaction.c @@ -22,6 +22,7 @@ #include "flatpak-cli-transaction.h" #include "flatpak-transaction-private.h" +#include "flatpak-installation-private.h" #include "flatpak-utils-private.h" #include "flatpak-error.h" #include @@ -303,11 +304,22 @@ flatpak_cli_transaction_free (FlatpakCliTransaction *cli) FlatpakTransaction * flatpak_cli_transaction_new (FlatpakDir *dir, gboolean disable_interaction, - gboolean stop_on_first_error) + gboolean stop_on_first_error, + GError **error) { - FlatpakTransaction *transaction = flatpak_transaction_new (dir); - FlatpakCliTransaction *cli = g_new0 (FlatpakCliTransaction, 1); + g_autoptr(FlatpakInstallation) installation = NULL; + g_autoptr(FlatpakTransaction) transaction = NULL; + FlatpakCliTransaction *cli = NULL; + installation = flatpak_installation_new_for_dir (dir, NULL, error); + if (installation == NULL) + return NULL; + + transaction = flatpak_transaction_new_for_installation (installation, NULL, error); + if (transaction == NULL) + return NULL; + + cli = g_new0 (FlatpakCliTransaction, 1); cli->transaction = transaction; cli->disable_interaction = disable_interaction; cli->stop_on_first_error = stop_on_first_error; @@ -320,7 +332,7 @@ flatpak_cli_transaction_new (FlatpakDir *dir, g_signal_connect (transaction, "operation-error", G_CALLBACK (operation_error), cli); g_signal_connect (transaction, "end-of-lifed", G_CALLBACK (end_of_lifed), cli); - return transaction; + return g_steal_pointer (&transaction); } gboolean diff --git a/app/flatpak-cli-transaction.h b/app/flatpak-cli-transaction.h index 114d3f70..34c28d5e 100644 --- a/app/flatpak-cli-transaction.h +++ b/app/flatpak-cli-transaction.h @@ -26,7 +26,8 @@ FlatpakTransaction *flatpak_cli_transaction_new (FlatpakDir *dir, gboolean disable_interaction, - gboolean stop_on_first_error); + gboolean stop_on_first_error, + GError **error); gboolean flatpak_cli_transaction_add_install (FlatpakTransaction *self, const char *remote, diff --git a/common/Makefile.am.inc b/common/Makefile.am.inc index 95f51143..cea3dae6 100644 --- a/common/Makefile.am.inc +++ b/common/Makefile.am.inc @@ -114,6 +114,7 @@ libflatpak_common_la_SOURCES = \ common/flatpak-remote-private.h \ common/flatpak-remote.c \ common/flatpak-error.c \ + common/flatpak-installation-private.h \ common/flatpak-installation.c \ common/valgrind-private.h \ $(NULL) diff --git a/common/flatpak-installation-private.h b/common/flatpak-installation-private.h new file mode 100644 index 00000000..bf0b2c57 --- /dev/null +++ b/common/flatpak-installation-private.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2018 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __FLATPAK_INSTALLATION_PRIVATE_H__ +#define __FLATPAK_INSTALLATION_PRIVATE_H__ + +#include "flatpak-installation.h" + +#include "flatpak-dir-private.h" + +FlatpakDir * +flatpak_installation_clone_dir (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error); + +FlatpakInstallation * +flatpak_installation_new_for_dir (FlatpakDir *dir, + GCancellable *cancellable, + GError **error); + +#endif /* __FLATPAK_INSTALLATION_PRIVATE_H__ */ diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index 6ee9e910..76f0139d 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -27,6 +27,7 @@ #include #endif /* FLATPAK_ENABLE_P2P */ +#include "flatpak-installation-private.h" #include "flatpak-utils-private.h" #include "flatpak-installation.h" #include "flatpak-installed-ref-private.h" @@ -138,9 +139,9 @@ flatpak_installation_init (FlatpakInstallation *self) } static FlatpakInstallation * -flatpak_installation_new_for_dir (FlatpakDir *dir, - GCancellable *cancellable, - GError **error) +flatpak_installation_new_steal_dir (FlatpakDir *dir, + GCancellable *cancellable, + GError **error) { FlatpakInstallation *self; FlatpakInstallationPrivate *priv; @@ -158,6 +159,17 @@ flatpak_installation_new_for_dir (FlatpakDir *dir, return self; } + +FlatpakInstallation * +flatpak_installation_new_for_dir (FlatpakDir *dir, + GCancellable *cancellable, + GError **error) +{ + return flatpak_installation_new_steal_dir (g_object_ref (dir), + cancellable, + error); +} + /** * flatpak_get_default_arch: * @@ -218,7 +230,7 @@ flatpak_get_system_installations (GCancellable *cancellable, FlatpakDir *install_dir = g_ptr_array_index (system_dirs, i); g_autoptr(FlatpakInstallation) installation = NULL; - installation = flatpak_installation_new_for_dir (g_object_ref (install_dir), + installation = flatpak_installation_new_for_dir (install_dir, cancellable, &local_error); if (installation != NULL) @@ -257,7 +269,7 @@ FlatpakInstallation * flatpak_installation_new_system (GCancellable *cancellable, GError **error) { - return flatpak_installation_new_for_dir (flatpak_dir_get_system_default (), cancellable, error); + return flatpak_installation_new_steal_dir (flatpak_dir_get_system_default (), cancellable, error); } /** @@ -285,7 +297,7 @@ flatpak_installation_new_system_with_id (const char *id, if (install_dir == NULL) return NULL; - installation = flatpak_installation_new_for_dir (g_object_ref (install_dir), + installation = flatpak_installation_new_for_dir (install_dir, cancellable, &local_error); if (installation == NULL) @@ -313,7 +325,7 @@ flatpak_installation_new_user (GCancellable *cancellable, { flatpak_migrate_from_xdg_app (); - return flatpak_installation_new_for_dir (flatpak_dir_get_user (), cancellable, error); + return flatpak_installation_new_steal_dir (flatpak_dir_get_user (), cancellable, error); } /** @@ -334,7 +346,7 @@ flatpak_installation_new_for_path (GFile *path, gboolean user, { flatpak_migrate_from_xdg_app (); - return flatpak_installation_new_for_dir (flatpak_dir_new (path, user), cancellable, error); + return flatpak_installation_new_steal_dir (flatpak_dir_new (path, user), cancellable, error); } static FlatpakDir * @@ -373,6 +385,26 @@ flatpak_installation_get_dir_maybe_no_repo (FlatpakInstallation *self) return _flatpak_installation_get_dir (self, FALSE, NULL); } +FlatpakDir * +flatpak_installation_clone_dir (FlatpakInstallation *self, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(FlatpakDir) dir_clone = NULL; + g_autoptr(FlatpakDir) dir = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + /* Pull, prune, etc are not threadsafe, so we work on a copy */ + dir_clone = flatpak_dir_clone (dir); + if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) + return NULL; + + return g_steal_pointer (&dir_clone); +} + /** * flatpak_installation_drop_caches: * @self: a #FlatpakInstallation @@ -1624,41 +1656,6 @@ flatpak_installation_install_ref_file (FlatpakInstallation *self, return flatpak_remote_ref_new (coll_ref, NULL, remote, NULL); } - -/** - * flatpak_installation_create_transaction: - * @self: a #FlatpakInstallation - * @cancellable: (nullable): a #GCancellable - * @error: return location for a #GError - * - * Creates a new #FlatpakTransaction object that can be used to do installation - * and updates of multiple refs, as well as their dependencies, in a single - * operation. Set the options you want on the transaction and add the - * refs you want to install/update, then start the transaction with - * flatpak_transaction_run (). - * - * Returns: (transfer full): a #FlatpakTransaction, or %NULL on failure. - */ -FlatpakTransaction * -flatpak_installation_create_transaction (FlatpakInstallation *self, - GCancellable *cancellable, - GError **error) -{ - g_autoptr(FlatpakDir) dir = NULL; - g_autoptr(FlatpakDir) dir_clone = NULL; - - dir = flatpak_installation_get_dir (self, error); - if (dir == NULL) - return NULL; - - /* Pull, prune, etc are not threadsafe, so we work on a copy */ - dir_clone = flatpak_dir_clone (dir); - if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error)) - return NULL; - - return flatpak_transaction_new (dir); -} - /** * flatpak_installation_install_full: * @self: a #FlatpakInstallation diff --git a/common/flatpak-installation.h b/common/flatpak-installation.h index ad773b0e..3c47950e 100644 --- a/common/flatpak-installation.h +++ b/common/flatpak-installation.h @@ -30,7 +30,6 @@ typedef struct _FlatpakInstallation FlatpakInstallation; #include #include #include -#include #define FLATPAK_TYPE_INSTALLATION flatpak_installation_get_type () #define FLATPAK_INSTALLATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_INSTALLATION, FlatpakInstallation)) @@ -235,9 +234,6 @@ FLATPAK_EXTERN char * flatpak_installation_load_app_overrides (Flat const char *app_id, GCancellable *cancellable, GError **error); -FLATPAK_EXTERN FlatpakTransaction *flatpak_installation_create_transaction (FlatpakInstallation *self, - GCancellable *cancellable, - GError **error); FLATPAK_EXTERN FlatpakInstalledRef * flatpak_installation_install (FlatpakInstallation *self, const char *remote_name, FlatpakRefKind kind, diff --git a/common/flatpak-transaction-private.h b/common/flatpak-transaction-private.h index 66dadbbd..5f591df7 100644 --- a/common/flatpak-transaction-private.h +++ b/common/flatpak-transaction-private.h @@ -25,6 +25,4 @@ #include "flatpak-dir-private.h" -FlatpakTransaction *flatpak_transaction_new (FlatpakDir *dir); - #endif /* __FLATPAK_TRANSACTION_PRIVATE_H__ */ diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c index e74c36c7..5b2097bf 100644 --- a/common/flatpak-transaction.c +++ b/common/flatpak-transaction.c @@ -24,6 +24,7 @@ #include #include "flatpak-transaction-private.h" +#include "flatpak-installation-private.h" #include "flatpak-utils-private.h" #include "flatpak-error.h" @@ -33,7 +34,7 @@ * @Short_description: Transaction information * * FlatpakTransaction is an object representing an install/update - * transaction. You create an object like this using flatpak_installation_create_transaction() + * transaction. You create an object like this using flatpak_transaction_new_for_installation() * and then you add all the operations (installs, updates, etc) you wish to do. Then * you start the transaction with flatpak_transaction_run() which will resolve all kinds * of dependencies and report progress and status while downloading and installing these. @@ -71,6 +72,7 @@ typedef struct _FlatpakTransactionPrivate FlatpakTransactionPrivate; struct _FlatpakTransactionPrivate { GObject parent; + FlatpakInstallation *installation; FlatpakDir *dir; GHashTable *refs; GHashTable *remote_states; /* (element-type utf8 FlatpakRemoteState) */ @@ -96,6 +98,11 @@ enum { LAST_SIGNAL }; +enum { + PROP_0, + PROP_INSTALLATION, +}; + struct _FlatpakTransactionProgress { GObject parent; @@ -216,7 +223,11 @@ flatpak_transaction_progress_new (void) static guint signals[LAST_SIGNAL] = { 0 }; -G_DEFINE_TYPE_WITH_PRIVATE (FlatpakTransaction, flatpak_transaction, G_TYPE_OBJECT) +static void initable_iface_init (GInitableIface *initable_iface); + +G_DEFINE_TYPE_WITH_CODE (FlatpakTransaction, flatpak_transaction, G_TYPE_OBJECT, + G_ADD_PRIVATE(FlatpakTransaction) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)) static FlatpakTransactionOperationType op_type_from_resolved_kind (FlatpakTransactionOpKind kind) @@ -352,6 +363,8 @@ flatpak_transaction_finalize (GObject *object) FlatpakTransaction *self = (FlatpakTransaction *) object; FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_clear_object (&priv->installation); + g_hash_table_unref (priv->refs); g_hash_table_unref (priv->remote_states); g_list_free_full (priv->ops, (GDestroyNotify)flatpak_transaction_operation_free); @@ -365,12 +378,65 @@ flatpak_transaction_finalize (GObject *object) G_OBJECT_CLASS (flatpak_transaction_parent_class)->finalize (object); } +static void +flatpak_transaction_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FlatpakTransaction *self = FLATPAK_TRANSACTION (object); + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + switch (prop_id) + { + case PROP_INSTALLATION: + g_clear_object (&priv->installation); + priv->installation = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +flatpak_transaction_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FlatpakTransaction *self = FLATPAK_TRANSACTION (object); + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + + switch (prop_id) + { + case PROP_INSTALLATION: + g_value_set_object (value, priv->installation); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void flatpak_transaction_class_init (FlatpakTransactionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = flatpak_transaction_finalize; + object_class->get_property = flatpak_transaction_get_property; + object_class->set_property = flatpak_transaction_set_property; + + g_object_class_install_property (object_class, + PROP_INSTALLATION, + g_param_spec_object ("installation", + "Installation", + "The installation instance", + FLATPAK_TYPE_INSTALLATION, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS)); /** * FlatpakTransaction::new-operation: @@ -471,21 +537,60 @@ flatpak_transaction_init (FlatpakTransaction *self) priv->refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); priv->remote_states = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)flatpak_remote_state_free); priv->added_origin_remotes = g_ptr_array_new_with_free_func (g_free); - } -FlatpakTransaction * -flatpak_transaction_new (FlatpakDir *dir) + +static gboolean +initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) { - FlatpakTransaction *t; - FlatpakTransactionPrivate *priv; + FlatpakTransaction *self = FLATPAK_TRANSACTION (initable); + FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); + g_autoptr(FlatpakDir) dir_clone = NULL; + g_autoptr(FlatpakDir) dir = NULL; - t = g_object_new (FLATPAK_TYPE_TRANSACTION, NULL); - priv = flatpak_transaction_get_instance_private (t); + if (priv->installation == NULL) + return flatpak_fail (error, "No installation specified"); - priv->dir = g_object_ref (dir); + dir = flatpak_installation_clone_dir (priv->installation, cancellable, error); + if (dir == NULL) + return FALSE; - return t; + priv->dir = g_steal_pointer (&dir); + + return TRUE; +} + +static void +initable_iface_init (GInitableIface *initable_iface) +{ + initable_iface->init = initable_init; +} + +/** + * flatpak_transaction_new_for_installation: + * @installation: a #FlatpakInstallation + * @cancellable: (nullable): a #GCancellable + * @error: return location for a #GError + * + * Creates a new #FlatpakTransaction object that can be used to do installation + * and updates of multiple refs, as well as their dependencies, in a single + * operation. Set the options you want on the transaction and add the + * refs you want to install/update, then start the transaction with + * flatpak_transaction_run (). + * + * Returns: (transfer full): a #FlatpakTransaction, or %NULL on failure. + */ +FlatpakTransaction * +flatpak_transaction_new_for_installation (FlatpakInstallation *installation, + GCancellable *cancellable, + GError **error) +{ + return g_initable_new (FLATPAK_TYPE_TRANSACTION, + cancellable, error, + "installation", installation, + NULL); } void diff --git a/common/flatpak-transaction.h b/common/flatpak-transaction.h index 644506ff..475750d0 100644 --- a/common/flatpak-transaction.h +++ b/common/flatpak-transaction.h @@ -26,6 +26,7 @@ #define __FLATPAK_TRANSACTION_H__ #include +#include #define FLATPAK_TYPE_TRANSACTION flatpak_transaction_get_type () #define FLATPAK_TYPE_TRANSACTION_PROGRESS flatpak_transaction_progress_get_type () @@ -75,6 +76,11 @@ struct _FlatpakTransactionClass gpointer padding[12]; }; +FLATPAK_EXTERN +FlatpakTransaction *flatpak_transaction_new_for_installation (FlatpakInstallation *installation, + GCancellable *cancellable, + GError **error); + FLATPAK_EXTERN void flatpak_transaction_progress_set_update_frequency (FlatpakTransactionProgress *self, guint update_frequency);