/* vi:set et sw=2 sts=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e-s: * Copyright © 2019 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: * Matthias Clasen */ #include "config.h" #include "flatpak-quiet-transaction.h" #include "flatpak-transaction-private.h" #include "flatpak-installation-private.h" #include "flatpak-run-private.h" #include "flatpak-table-printer.h" #include "flatpak-utils-private.h" #include "flatpak-error.h" #include struct _FlatpakQuietTransaction { FlatpakTransaction parent; gboolean got_error; }; struct _FlatpakQuietTransactionClass { FlatpakTransactionClass parent_class; }; G_DEFINE_TYPE (FlatpakQuietTransaction, flatpak_quiet_transaction, FLATPAK_TYPE_TRANSACTION); static int choose_remote_for_ref (FlatpakTransaction *transaction, const char *for_ref, const char *runtime_ref, const char * const *remotes) { return 0; } static gboolean add_new_remote (FlatpakTransaction *transaction, FlatpakTransactionRemoteReason reason, const char *from_id, const char *remote_name, const char *url) { return TRUE; } static void new_operation (FlatpakTransaction *transaction, FlatpakTransactionOperation *op, FlatpakTransactionProgress *progress) { FlatpakTransactionOperationType op_type = flatpak_transaction_operation_get_operation_type (op); const char *ref = flatpak_transaction_operation_get_ref (op); switch (op_type) { case FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE: case FLATPAK_TRANSACTION_OPERATION_INSTALL: g_print (_("Installing %s\n"), ref); break; case FLATPAK_TRANSACTION_OPERATION_UPDATE: g_print (_("Updating %s\n"), ref); break; case FLATPAK_TRANSACTION_OPERATION_UNINSTALL: g_print (_("Uninstalling %s\n"), ref); break; default: g_assert_not_reached (); break; } } static void print_op_error_msg (FlatpakTransactionOperationType operation_type, FlatpakRef *rref, const char *msg, gboolean non_fatal) { /* Here we go to great lengths not to split the sentences. See * https://wiki.gnome.org/TranslationProject/DevGuidelines/Never%20split%20sentences */ switch (operation_type) { case FLATPAK_TRANSACTION_OPERATION_INSTALL: if (non_fatal) g_printerr (_("Warning: Failed to install %s: %s\n"), flatpak_ref_get_name (rref), msg); else g_printerr (_("Error: Failed to install %s: %s\n"), flatpak_ref_get_name (rref), msg); break; case FLATPAK_TRANSACTION_OPERATION_UPDATE: if (non_fatal) g_printerr (_("Warning: Failed to update %s: %s\n"), flatpak_ref_get_name (rref), msg); else g_printerr (_("Error: Failed to update %s: %s\n"), flatpak_ref_get_name (rref), msg); break; case FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE: if (non_fatal) g_printerr (_("Warning: Failed to install bundle %s: %s\n"), flatpak_ref_get_name (rref), msg); else g_printerr (_("Error: Failed to install bundle %s: %s\n"), flatpak_ref_get_name (rref), msg); break; case FLATPAK_TRANSACTION_OPERATION_UNINSTALL: if (non_fatal) g_printerr (_("Warning: Failed to uninstall %s: %s\n"), flatpak_ref_get_name (rref), msg); else g_printerr (_("Error: Failed to uninstall %s: %s\n"), flatpak_ref_get_name (rref), msg); break; default: g_assert_not_reached (); } } static gboolean operation_error (FlatpakTransaction *transaction, FlatpakTransactionOperation *op, const GError *error, FlatpakTransactionErrorDetails detail) { FlatpakQuietTransaction *self = FLATPAK_QUIET_TRANSACTION (transaction); FlatpakTransactionOperationType op_type = flatpak_transaction_operation_get_operation_type (op); const char *ref = flatpak_transaction_operation_get_ref (op); g_autoptr(FlatpakRef) rref = flatpak_ref_parse (ref, NULL); g_autofree char *msg = NULL; gboolean non_fatal = (detail & FLATPAK_TRANSACTION_ERROR_DETAILS_NON_FATAL) != 0; if (g_error_matches (error, FLATPAK_ERROR, FLATPAK_ERROR_SKIPPED)) { g_print (_("Info: %s was skipped"), flatpak_ref_get_name (rref)); return TRUE; } if (g_error_matches (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) msg = g_strdup_printf (_("%s already installed"), flatpak_ref_get_name (rref)); else if (g_error_matches (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED)) msg = g_strdup_printf (_("%s not installed"), flatpak_ref_get_name (rref)); else if (g_error_matches (error, FLATPAK_ERROR, FLATPAK_ERROR_NEED_NEW_FLATPAK)) msg = g_strdup_printf (_("%s needs a later flatpak version"), flatpak_ref_get_name (rref)); else if (g_error_matches (error, FLATPAK_ERROR, FLATPAK_ERROR_OUT_OF_SPACE)) msg = g_strdup (_("Not enough disk space to complete this operation")); else msg = g_strdup (error->message); print_op_error_msg (op_type, rref, msg, non_fatal); if (non_fatal) return TRUE; /* Continue */ self->got_error = TRUE; return non_fatal; /* Continue if non-fatal */ } static void install_authenticator (FlatpakTransaction *old_transaction, const char *remote, const char *ref) { g_autoptr(FlatpakTransaction) transaction2 = NULL; g_autoptr(GError) local_error = NULL; FlatpakInstallation *installation = flatpak_transaction_get_installation (old_transaction); FlatpakDir *dir = flatpak_installation_get_dir (installation, NULL); if (dir == NULL) { /* This should not happen */ g_warning ("No dir in install_authenticator"); return; } transaction2 = flatpak_quiet_transaction_new (dir, &local_error); if (transaction2 == NULL) { g_printerr ("Unable to install authenticator: %s\n", local_error->message); return; } if (!flatpak_transaction_add_install (transaction2, remote, ref, NULL, &local_error)) { if (!g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED)) g_printerr ("Unable to install authenticator: %s\n", local_error->message); return; } if (!flatpak_transaction_run (transaction2, NULL, &local_error)) { if (!g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED)) g_printerr ("Unable to install authenticator: %s\n", local_error->message); return; } return; } static gboolean end_of_lifed_with_rebase (FlatpakTransaction *transaction, const char *remote, const char *ref, const char *reason, const char *rebased_to_ref, const char **previous_ids) { FlatpakQuietTransaction *self = FLATPAK_QUIET_TRANSACTION (transaction); g_autoptr(FlatpakRef) rref = flatpak_ref_parse (ref, NULL); if (rebased_to_ref) g_print (_("Info: %s is end-of-life, in favor of %s\n"), flatpak_ref_get_name (rref), rebased_to_ref); else if (reason) g_print (_("Info: %s is end-of-life, with reason: %s\n"), flatpak_ref_get_name (rref), reason); if (rebased_to_ref && remote) { g_autoptr(GError) error = NULL; g_print (_("Updating to rebased version\n")); if (!flatpak_transaction_add_rebase_and_uninstall (transaction, remote, rebased_to_ref, ref, NULL, previous_ids, &error)) { g_printerr (_("Failed to rebase %s to %s: %s\n"), flatpak_ref_get_name (rref), rebased_to_ref, error->message); self->got_error = TRUE; return FALSE; } return TRUE; } return FALSE; } static gboolean flatpak_quiet_transaction_run (FlatpakTransaction *transaction, GCancellable *cancellable, GError **error) { FlatpakQuietTransaction *self = FLATPAK_QUIET_TRANSACTION (transaction); gboolean res; res = FLATPAK_TRANSACTION_CLASS (flatpak_quiet_transaction_parent_class)->run (transaction, cancellable, error); if (self->got_error) { g_clear_error (error); return FALSE; /* Don't report on stderr, we already reported */ } if (!res) return FALSE; return TRUE; } static void flatpak_quiet_transaction_init (FlatpakQuietTransaction *transaction) { } static void flatpak_quiet_transaction_class_init (FlatpakQuietTransactionClass *class) { FlatpakTransactionClass *transaction_class = FLATPAK_TRANSACTION_CLASS (class); transaction_class->choose_remote_for_ref = choose_remote_for_ref; transaction_class->add_new_remote = add_new_remote; transaction_class->new_operation = new_operation; transaction_class->operation_error = operation_error; transaction_class->end_of_lifed_with_rebase = end_of_lifed_with_rebase; transaction_class->run = flatpak_quiet_transaction_run; transaction_class->install_authenticator = install_authenticator; } FlatpakTransaction * flatpak_quiet_transaction_new (FlatpakDir *dir, GError **error) { g_autoptr(FlatpakQuietTransaction) self = NULL; g_autoptr(FlatpakInstallation) installation = NULL; installation = flatpak_installation_new_for_dir (dir, NULL, error); if (installation == NULL) return NULL; self = g_initable_new (FLATPAK_TYPE_QUIET_TRANSACTION, NULL, error, "installation", installation, NULL); if (self == NULL) return NULL; flatpak_transaction_set_no_interaction (FLATPAK_TRANSACTION (self), TRUE); flatpak_transaction_add_default_dependency_sources (FLATPAK_TRANSACTION (self)); return FLATPAK_TRANSACTION (g_steal_pointer (&self)); }