From 7e2b96467eadb977293081a30794ac8d4d206f31 Mon Sep 17 00:00:00 2001 From: Derick Diaz Date: Tue, 23 Jan 2024 09:14:45 -0600 Subject: [PATCH] Add --urlprotocol option to download command --- dnf5/commands/download/download.cpp | 32 ++++++++++++++++++++++++++--- dnf5/commands/download/download.hpp | 3 +++ doc/commands/download.8.rst | 13 +++++++++++- libdnf5/rpm/package.cpp | 4 ++-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/dnf5/commands/download/download.cpp b/dnf5/commands/download/download.cpp index ced34949f..8d0178ac5 100644 --- a/dnf5/commands/download/download.cpp +++ b/dnf5/commands/download/download.cpp @@ -82,15 +82,34 @@ void DownloadCommand::set_argument_parser() { auto url = parser.add_new_named_arg("url"); url->set_long_name("url"); - url->set_description("Print the list of urls where the rpms can be downloaded instead of downloading"); + url->set_description("Print a URL where the rpms can be downloaded instead of downloading"); url->set_const_value("true"); url->link_value(url_option); + urlprotocol_valid_options = {"http", "https", "ftp", "file"}; + urlprotocol_option = {}; + auto urlprotocol = parser.add_new_named_arg("urlprotocol"); + urlprotocol->set_long_name("urlprotocol"); + urlprotocol->set_description("When running with --url, limit to specific protocols"); + urlprotocol->set_has_value(true); + urlprotocol->set_arg_value_help("{http|https|ftp|file},..."); + urlprotocol->set_parse_hook_func( + [this]( + [[maybe_unused]] ArgumentParser::NamedArg * arg, [[maybe_unused]] const char * option, const char * value) { + if (urlprotocol_valid_options.find(value) == urlprotocol_valid_options.end()) { + throw libdnf5::cli::ArgumentParserInvalidValueError( + M_("Invalid urlprotocol option: {}"), std::string(value)); + } + urlprotocol_option.emplace(value); + return true; + }); + cmd.register_named_arg(alldeps); create_destdir_option(*this); cmd.register_named_arg(resolve); cmd.register_positional_arg(keys); cmd.register_named_arg(url); + cmd.register_named_arg(urlprotocol); } void DownloadCommand::configure() { @@ -161,9 +180,16 @@ void DownloadCommand::run() { } if (url_option->get_value()) { + // If no urlprotocols are specified, all values within the urlprotocol_valid_options will be used + if (urlprotocol_option.empty()) { + urlprotocol_option = urlprotocol_valid_options; + } for (auto & [nerva, pkg] : download_pkgs) { - auto urls = pkg.get_remote_locations(); - libdnf_assert(!urls.empty(), "Failed to get mirror for package: \"{}\"", pkg.get_name()); + auto urls = pkg.get_remote_locations(urlprotocol_option); + if (urls.empty()) { + ctx.base.get_logger()->warning("Failed to get mirror for package: \"{}\"", pkg.get_name()); + continue; + } std::cout << urls[0] << std::endl; } return; diff --git a/dnf5/commands/download/download.hpp b/dnf5/commands/download/download.hpp index be9805f80..9c787587f 100644 --- a/dnf5/commands/download/download.hpp +++ b/dnf5/commands/download/download.hpp @@ -25,6 +25,7 @@ along with libdnf. If not, see . #include #include +#include #include @@ -40,6 +41,8 @@ class DownloadCommand : public Command { void run() override; private: + std::set urlprotocol_valid_options; + std::set urlprotocol_option; libdnf5::OptionBool * resolve_option{nullptr}; libdnf5::OptionBool * alldeps_option{nullptr}; libdnf5::OptionBool * url_option{nullptr}; diff --git a/doc/commands/download.8.rst b/doc/commands/download.8.rst index 8c2cbec45..4d97f4d8f 100644 --- a/doc/commands/download.8.rst +++ b/doc/commands/download.8.rst @@ -45,7 +45,14 @@ Options | To be used together with ``--resolve``, it downloads all dependencies, not skipping the already installed ones. ``--destdir=`` - Set directory used for downloading packages to. Default location is to the current working directory. + | Set directory used for downloading packages to. Default location is to the current working directory. + +``--url`` + | Prints the list of URLs where the rpms can be downloaded instead of downloading. + +``--urlprotocol`` + | To be used together with ``--url``. It filters out the URLs to the specified protocols: ``http``, ``https``, ``ftp``, or ``file``. This option can be used multiple times. + Examples @@ -63,6 +70,10 @@ Examples ``dnf5 download --destdir /tmp/my_packages maven-compiler-plugin`` | Download the ``maven-compiler-plugin`` package to ``/tmp/my_packages`` directory. +``dnf5 download --url --urlprotocol http python`` + | List the http URL to download the python package + + See Also ======== diff --git a/libdnf5/rpm/package.cpp b/libdnf5/rpm/package.cpp index f6ecd2db6..a4454e0a4 100644 --- a/libdnf5/rpm/package.cpp +++ b/libdnf5/rpm/package.cpp @@ -329,7 +329,7 @@ std::vector Package::get_remote_locations(const std::setget_mirrors(); for (const auto & mirror : repo_mirrors) { for (const auto & protocol : protocols) { - if (utils::string::starts_with(mirror, protocol)) { + if (utils::string::starts_with(mirror, protocol + ":")) { auto path = lr_pathconcat(mirror.c_str(), location.c_str(), NULL); remote_locations.emplace_back(path); lr_free(path); @@ -341,7 +341,7 @@ std::vector Package::get_remote_locations(const std::setget_config().get_baseurl_option().get_value(); for (const auto & baseurl : repo_baseurls) { for (const auto & protocol : protocols) { - if (utils::string::starts_with(baseurl, protocol)) { + if (utils::string::starts_with(baseurl, protocol + ":")) { auto path = lr_pathconcat(baseurl.c_str(), location.c_str(), NULL); remote_locations.emplace_back(path); lr_free(path);