diff --git a/dnf5/context.cpp b/dnf5/context.cpp index c4415799b..50db645d4 100644 --- a/dnf5/context.cpp +++ b/dnf5/context.cpp @@ -255,7 +255,7 @@ void Context::Impl::apply_repository_setopts() { repo->get_config().opt_binds().at(key).new_string( libdnf5::Option::Priority::COMMANDLINE, setopt.second); } catch (const std::exception & ex) { - std::cerr << "setopt: \"" + setopt.first + "." + setopt.second + "\": " + ex.what() << std::endl; + print_error("setopt: \"" + setopt.first + "." + setopt.second + "\": " + ex.what()); } } } @@ -334,9 +334,9 @@ void Context::Impl::store_offline(libdnf5::base::Transaction & transaction) { auto & offline_data = state.get_data(); if (offline_data.get_status() != libdnf5::offline::STATUS_DOWNLOAD_INCOMPLETE) { - std::cerr << "There is already an offline transaction queued, initiated by the following command:" << std::endl - << "\t" << offline_data.get_cmd_line() << std::endl - << "Continuing will cancel the old offline transaction and replace it with this one." << std::endl; + print_error("There is already an offline transaction queued, initiated by the following command:"); + print_error(fmt::format("\t{}", offline_data.get_cmd_line())); + print_error("Continuing will cancel the old offline transaction and replace it with this one."); if (!libdnf5::cli::utils::userconfirm::userconfirm(base.get_config())) { throw libdnf5::cli::AbortedByUserError(); } @@ -365,19 +365,19 @@ void Context::Impl::store_offline(libdnf5::base::Transaction & transaction) { print_info("Testing offline transaction"); auto result = test_transaction.run(); if (result != libdnf5::base::Transaction::TransactionRunResult::SUCCESS) { - std::cerr << "Transaction failed: " << libdnf5::base::Transaction::transaction_result_to_string(result) - << std::endl; + print_error( + fmt::format("Transaction failed: {}", libdnf5::base::Transaction::transaction_result_to_string(result))); for (auto const & entry : transaction.get_gpg_signature_problems()) { - std::cerr << entry << std::endl; + print_error(entry); } for (auto & problem : test_transaction.get_transaction_problems()) { - std::cerr << " - " << problem << std::endl; + print_error(fmt::format(" - {}", problem)); } throw libdnf5::cli::SilentCommandExitError(1); } for (auto const & entry : test_transaction.get_gpg_signature_problems()) { - std::cerr << entry << std::endl; + print_error(entry); } // Download and transaction test complete. Fill out entries in offline @@ -415,9 +415,9 @@ void Context::Impl::download_and_run(libdnf5::base::Transaction & transaction) { constexpr const char * comps_in_trans_dir{"./comps"}; auto comps_location = transaction_store_path / comps_in_trans_dir; if (std::filesystem::exists(transaction_location)) { - std::cerr << libdnf5::utils::sformat( - _("Location \"{}\" already contains a stored transaction, it will be overwritten.\n"), - transaction_store_path.string()); + print_error(libdnf5::utils::sformat( + _("Location \"{}\" already contains a stored transaction, it will be overwritten."), + transaction_store_path.string())); if (libdnf5::cli::utils::userconfirm::userconfirm(base.get_config())) { std::filesystem::remove_all(packages_location); std::filesystem::remove_all(comps_location); @@ -452,10 +452,10 @@ void Context::Impl::download_and_run(libdnf5::base::Transaction & transaction) { if (should_store_offline) { store_offline(transaction); - std::cout << "Transaction stored to be performed offline. Run `dnf5 offline reboot` to reboot and run the " - "transaction. To cancel the transaction and delete the downloaded files, use `dnf5 " - "offline clean`." - << std::endl; + print_info( + "Transaction stored to be performed offline. Run `dnf5 offline reboot` to reboot and run the " + "transaction. To cancel the transaction and delete the downloaded files, use `dnf5 " + "offline clean`."); return; } @@ -487,19 +487,19 @@ void Context::Impl::download_and_run(libdnf5::base::Transaction & transaction) { auto result = transaction.run(); print_info(""); if (result != libdnf5::base::Transaction::TransactionRunResult::SUCCESS) { - std::cerr << "Transaction failed: " << libdnf5::base::Transaction::transaction_result_to_string(result) - << std::endl; + print_error( + fmt::format("Transaction failed: {}", libdnf5::base::Transaction::transaction_result_to_string(result))); for (auto const & entry : transaction.get_gpg_signature_problems()) { - std::cerr << entry << std::endl; + print_error(entry); } for (auto & problem : transaction.get_transaction_problems()) { - std::cerr << " - " << problem << std::endl; + print_error(problem); } throw libdnf5::cli::SilentCommandExitError(1); } for (auto const & entry : transaction.get_gpg_signature_problems()) { - std::cerr << entry << std::endl; + print_error(entry); } // TODO(mblaha): print a summary of successful transaction } @@ -655,9 +655,15 @@ Context::LoadAvailableRepos Context::get_load_available_repos() const noexcept { return p_impl->get_load_available_repos(); } +void Context::print_output(std::string_view msg) const { + p_impl->print_output(msg); +} void Context::print_info(std::string_view msg) const { p_impl->print_info(msg); } +void Context::print_error(std::string_view msg) const { + p_impl->print_error(msg); +} void Context::set_output_stream(std::ostream & new_output_stream) { p_impl->set_output_stream(new_output_stream); } diff --git a/dnf5/main.cpp b/dnf5/main.cpp index 267df75f7..69ffb07aa 100644 --- a/dnf5/main.cpp +++ b/dnf5/main.cpp @@ -187,11 +187,8 @@ void RootCommand::set_argument_parser() { try { cache.write_attribute(libdnf5::repo::RepoCache::ATTRIBUTE_EXPIRED); } catch (const std::exception & ex) { - std::cerr << libdnf5::utils::sformat( - _("Failed to expire repository cache in path \"{0}\": {1}"), - dir_entry.path().native(), - ex.what()) - << std::endl; + ctx.print_error(libdnf5::utils::sformat( + _("Failed to expire repository cache in path \"{0}\": {1}"), dir_entry.path().native(), ex.what())); } } return true; @@ -742,37 +739,34 @@ static void print_versions(Context & context) { constexpr const char * appl_name = "dnf5"; { const auto & version = get_application_version(); - std::cout - << fmt::format( - "{} version {}.{}.{}.{}", appl_name, version.prime, version.major, version.minor, version.micro) - << std::endl; + context.print_output(fmt::format( + "{} version {}.{}.{}.{}", appl_name, version.prime, version.major, version.minor, version.micro)); const auto & api_version = get_plugin_api_version(); - std::cout << fmt::format("{} plugin API version {}.{}", appl_name, api_version.major, api_version.minor) - << std::endl; + context.print_output( + fmt::format("{} plugin API version {}.{}", appl_name, api_version.major, api_version.minor)); } { const auto & version = libdnf5::get_library_version(); - std::cout << fmt::format( - "libdnf5 version {}.{}.{}.{}", version.prime, version.major, version.minor, version.micro) - << std::endl; + context.print_output( + fmt::format("libdnf5 version {}.{}.{}.{}", version.prime, version.major, version.minor, version.micro)); const auto & api_version = libdnf5::get_plugin_api_version(); - std::cout << fmt::format("libdnf5 plugin API version {}.{}", api_version.major, api_version.minor) << std::endl; + context.print_output(fmt::format("libdnf5 plugin API version {}.{}", api_version.major, api_version.minor)); } bool first{true}; for (const auto & plugin : context.get_plugins().get_plugins()) { if (first) { first = false; - std::cout << fmt::format("\nLoaded {} plugins:", appl_name) << std::endl; + context.print_output(fmt::format("\nLoaded {} plugins:", appl_name)); } else { - std::cout << std::endl; + context.print_output(""); } auto * iplugin = plugin->get_iplugin(); - std::cout << fmt::format(" name: {}", iplugin->get_name()) << std::endl; + context.print_output(fmt::format(" name: {}", iplugin->get_name())); const auto & version = iplugin->get_version(); - std::cout << fmt::format(" version: {}.{}.{}", version.major, version.minor, version.micro) << std::endl; + context.print_output(fmt::format(" version: {}.{}.{}", version.major, version.minor, version.micro)); const auto & api_version = iplugin->get_api_version(); - std::cout << fmt::format(" API version: {}.{}", api_version.major, api_version.minor) << std::endl; + context.print_output(fmt::format(" API version: {}.{}", api_version.major, api_version.minor)); } } @@ -835,7 +829,7 @@ static void print_transaction_size_stats(Context & context) { static void dump_main_configuration(Context & context) { libdnf5::Base & base = context.get_base(); - std::cout << _("======== Main configuration: ========") << std::endl; + context.print_output(_("======== Main configuration: ========")); for (const auto & option : base.get_config().opt_binds()) { const auto & val = option.second; std::string value; @@ -846,9 +840,9 @@ static void dump_main_configuration(Context & context) { } catch (const libdnf5::OptionError &) { } if (was_set) { - std::cout << fmt::format("{} = {}", option.first, value) << std::endl; + context.print_output(fmt::format("{} = {}", option.first, value)); } else { - std::cout << fmt::format("{}", option.first) << std::endl; + context.print_output(fmt::format("{}", option.first)); } } } @@ -876,8 +870,8 @@ static void dump_repository_configuration(Context & context, const std::vectorget_id()) - << std::endl; + context.print_output( + libdnf5::utils::sformat(_("======== \"{}\" repository configuration: ========"), repo->get_id())); for (const auto & option : repo->get_config().opt_binds()) { const auto & val = option.second; std::string value; @@ -888,19 +882,19 @@ static void dump_repository_configuration(Context & context, const std::vectorget_variables()) { const auto & val = var.second; - std::cout << fmt::format("{} = {}", var.first, val.value) << std::endl; + context.print_output(fmt::format("{} = {}", var.first, val.value)); } } @@ -937,11 +931,11 @@ static void print_new_leaves(Context & context) { } if (!new_leaves_na.empty()) { - std::cout << "New leaves:" << std::endl; + context.print_output("New leaves:"); for (const auto & leaf_pkg : new_leaves_na) { - std::cout << " " << leaf_pkg << std::endl; + context.print_output(fmt::format(" {}", leaf_pkg)); } - std::cout << std::endl; + context.print_output(""); } } @@ -1076,9 +1070,9 @@ static void print_resolve_hints(dnf5::Context & context) { } if (hints.size() > 0) { - std::cerr << _("You can try to add to command line:") << std::endl; + context.print_error(_("You can try to add to command line:")); for (const auto & hint : hints) { - std::cerr << " " << hint << std::endl; + context.print_error(fmt::format(" {}", hint)); } } } @@ -1112,7 +1106,7 @@ static void print_no_match_libdnf_plugin_patterns(dnf5::Context & context) { for (; it != no_match_pattern_set.end(); ++it) { patterns += ", " + *it; } - std::cerr << libdnf5::utils::sformat(TM_(no_match_message, 1), patterns) << std::endl; + context.print_error(libdnf5::utils::sformat(TM_(no_match_message, 1), patterns)); } } } @@ -1242,20 +1236,18 @@ int main(int argc, char * argv[]) try { } } if (help_printed) { - std::cerr << ex.what() << "." << std::endl; + context.print_error(fmt::format("{}.", ex.what())); } else { - std::cerr << ex.what() << _(". Add \"--help\" for more information about the arguments.") - << std::endl; + context.print_error(fmt::format( + "{}{}", ex.what(), _(". Add \"--help\" for more information about the arguments."))); } // If the error is an unknown top-level command, suggest // installing a package that provides the command if (auto * unknown_arg_ex = dynamic_cast(&ex)) { if (unknown_arg_ex->get_command() == "dnf5" && unknown_arg_ex->get_argument()[0] != '-') { - std::cerr - << fmt::format( - "It could be a command provided by a plugin, try: dnf5 install 'dnf5-command({})'", - unknown_arg_ex->get_argument()) - << std::endl; + context.print_error(fmt::format( + "It could be a command provided by a plugin, try: dnf5 install 'dnf5-command({})'", + unknown_arg_ex->get_argument())); } } return static_cast(libdnf5::cli::ExitCode::ARGPARSER_ERROR); @@ -1393,18 +1385,16 @@ int main(int argc, char * argv[]) try { if (auto transaction_store_path = context.get_transaction_store_path(); !transaction_store_path.empty()) { - std::cerr << "The operation will only store the transaction in " << transaction_store_path << "." - << std::endl; + context.print_error(fmt::format( + "The operation will only store the transaction in {}", transaction_store_path.string())); } else if (base.get_config().get_downloadonly_option().get_value()) { - std::cerr << "The operation will only download packages for the transaction." << std::endl; + context.print_error("The operation will only download packages for the transaction."); } else { for (const auto & tsflag : base.get_config().get_tsflags_option().get_value()) { if (tsflag == "test") { - std::cerr - << "Test mode enabled: Only package downloads, pgp key installations and transaction " - "checks " - "will be performed." - << std::endl; + context.print_error( + "Test mode enabled: Only package downloads, pgp key installations and transaction " + "checks will be performed."); } } } @@ -1416,13 +1406,12 @@ int main(int argc, char * argv[]) try { context.download_and_run(*context.get_transaction()); } } catch (libdnf5::cli::GoalResolveError & ex) { - std::cerr << ex.what() << std::endl; + context.print_error(ex.what()); if (!any_repos_from_system_configuration && base.get_config().get_installroot_option().get_value() != "/" && !base.get_config().get_use_host_config_option().get_value()) { - std::cerr - << "No repositories were loaded from the installroot. To use the configuration and repositories " - "of the host system, pass --use-host-config." - << std::endl; + context.print_error( + "No repositories were loaded from the installroot. To use the configuration and repositories " + "of the host system, pass --use-host-config."); } else { if (context.get_transaction() != nullptr) { // download command can throw GoalResolveError without context.transaction being set @@ -1431,10 +1420,11 @@ int main(int argc, char * argv[]) try { } return static_cast(libdnf5::cli::ExitCode::ERROR); } catch (libdnf5::cli::ArgumentParserError & ex) { - std::cerr << ex.what() << _(". Add \"--help\" for more information about the arguments.") << std::endl; + context.print_error( + fmt::format("{}{}", ex.what(), _(". Add \"--help\" for more information about the arguments."))); return static_cast(libdnf5::cli::ExitCode::ARGPARSER_ERROR); } catch (libdnf5::cli::CommandExitError & ex) { - std::cerr << ex.what() << std::endl; + context.print_error(ex.what()); return ex.get_exit_code(); } catch (libdnf5::cli::SilentCommandExitError & ex) { return ex.get_exit_code();