diff --git a/dnf5/commands/repo/repo_info.cpp b/dnf5/commands/repo/repo_info.cpp index 4e473789f..4cae2b7be 100644 --- a/dnf5/commands/repo/repo_info.cpp +++ b/dnf5/commands/repo/repo_info.cpp @@ -106,6 +106,7 @@ void RepoInfoCommand::print(const libdnf5::repo::RepoQuery & query, [[maybe_unus } std::sort(repos.begin(), repos.end(), [](const auto & l, const auto & r) { return l->get_id() < r->get_id(); }); + std::vector> repo_wrappers; for (auto & repo : repos) { libdnf5::rpm::PackageQuery pkgs(get_context().get_base(), libdnf5::sack::ExcludeFlags::IGNORE_EXCLUDES); pkgs.filter_repo_id({repo->get_id()}); @@ -118,11 +119,20 @@ void RepoInfoCommand::print(const libdnf5::repo::RepoQuery & query, [[maybe_unus repo_size += pkg.get_download_size(); } - libdnf5::cli::output::RepoInfo repo_info_table; - RepoInfoWrapper repo_wrapper(*repo, repo_size, pkgs.size(), available_pkgs.size()); - repo_info_table.add_repo(repo_wrapper); - repo_info_table.print(); - std::cout << std::endl; + repo_wrappers.emplace_back( + std::make_unique(*repo, repo_size, pkgs.size(), available_pkgs.size())); + } + + auto & context = get_context(); + if (context.get_json_output_requested()) { + libdnf5::cli::output::print_repoinfo_json(repo_wrappers); + } else { + for (auto & repo : repo_wrappers) { + libdnf5::cli::output::RepoInfo repo_info_table; + repo_info_table.add_repo(*repo); + repo_info_table.print(); + std::cout << std::endl; + } } } diff --git a/dnf5/context.cpp b/dnf5/context.cpp index 6415db577..9a6d42015 100644 --- a/dnf5/context.cpp +++ b/dnf5/context.cpp @@ -173,7 +173,12 @@ class Context::Impl { void set_should_store_offline(bool should_store_offline) { this->should_store_offline = should_store_offline; } bool get_should_store_offline() const { return should_store_offline; } - void set_json_output_requested(bool json_output) { this->json_output = json_output; } + void set_json_output_requested(bool json_output) { + this->json_output = json_output; + if (json_output) { + set_quiet(true); + } + } bool get_json_output_requested() const { return json_output; } libdnf5::Base & get_base() { return base; }; diff --git a/dnf5/main.cpp b/dnf5/main.cpp index 2f60569cc..c81da185d 100644 --- a/dnf5/main.cpp +++ b/dnf5/main.cpp @@ -1186,13 +1186,6 @@ int main(int argc, char * argv[]) try { return 0; } - auto download_callbacks_uptr = std::make_unique(); - auto * download_callbacks = download_callbacks_uptr.get(); - download_callbacks->set_show_total_bar_limit(static_cast(-1)); - if (!context.get_quiet()) { - base.set_download_callbacks(std::move(download_callbacks_uptr)); - } - // Parse command line arguments { auto & arg_parser = context.get_argument_parser(); @@ -1245,6 +1238,13 @@ int main(int argc, char * argv[]) try { } } + auto download_callbacks_uptr = std::make_unique(); + auto * download_callbacks = download_callbacks_uptr.get(); + download_callbacks->set_show_total_bar_limit(static_cast(-1)); + if (!context.get_quiet()) { + base.set_download_callbacks(std::move(download_callbacks_uptr)); + } + auto command = context.get_selected_command(); // Gets set to true when any repository is created from configuration or a diff --git a/include/libdnf5-cli/output/repo_info.hpp b/include/libdnf5-cli/output/repo_info.hpp index 5797406ae..4ef6d1369 100644 --- a/include/libdnf5-cli/output/repo_info.hpp +++ b/include/libdnf5-cli/output/repo_info.hpp @@ -40,6 +40,8 @@ class RepoInfo { std::unique_ptr p_impl; }; +void print_repoinfo_json(const std::vector> & repos); + } // namespace libdnf5::cli::output #endif // LIBDNF5_CLI_OUTPUT_REPO_INFO_HPP diff --git a/libdnf5-cli/output/repo_info.cpp b/libdnf5-cli/output/repo_info.cpp index d023f656c..a390801f4 100644 --- a/libdnf5-cli/output/repo_info.cpp +++ b/libdnf5-cli/output/repo_info.cpp @@ -24,8 +24,24 @@ along with libdnf. If not, see . #include "libdnf5-cli/utils/units.hpp" +#include + +#include + namespace libdnf5::cli::output { +namespace { + +std::vector flatten_distro_tags(const std::vector> & distro_tags) { + std::vector distro_tags_flat; + for (auto & key_value : distro_tags) { + distro_tags_flat.push_back(key_value.second + " (" + key_value.first + ")"); + } + return distro_tags_flat; +} + +} // namespace + class RepoInfo::Impl : public KeyValueTable { public: void add_repo(IRepoInfo & repo); @@ -155,13 +171,9 @@ void RepoInfo::Impl::add_repo(IRepoInfo & repo) { add_line("Content tags", content_tags, nullptr, group_repodata); } - auto distro_tags_flat = repo.get_distro_tags(); - if (!distro_tags_flat.empty()) { - std::vector distro_tags; - for (auto & key_value : distro_tags_flat) { - distro_tags.push_back(key_value.second + " (" + key_value.first + ")"); - } - add_line("Distro tags", distro_tags, nullptr, group_repodata); + auto distro_tags = repo.get_distro_tags(); + if (!distro_tags.empty()) { + add_line("Distro tags", flatten_distro_tags(distro_tags), nullptr, group_repodata); } add_line("Revision", repo.get_revision(), nullptr, group_repodata); @@ -195,4 +207,74 @@ void RepoInfo::print() { p_impl->print(); } +void print_repoinfo_json([[maybe_unused]] const std::vector> & repos) { + json_object * json_repos = json_object_new_array(); + for (const auto & repo : repos) { + json_object * json_repo = json_object_new_object(); + json_object_object_add(json_repo, "id", json_object_new_string(repo->get_id().c_str())); + json_object_object_add(json_repo, "name", json_object_new_string(repo->get_name().c_str())); + json_object_object_add(json_repo, "is_enabled", json_object_new_boolean(repo->is_enabled())); + json_object_object_add(json_repo, "priority", json_object_new_int(repo->get_priority())); + json_object_object_add(json_repo, "cost", json_object_new_int(repo->get_cost())); + json_object_object_add(json_repo, "type", json_object_new_string(repo->get_type().c_str())); + + json_object * json_exclude_pkgs = json_object_new_array(); + for (const auto & pkg : repo->get_excludepkgs()) { + json_object_array_add(json_exclude_pkgs, json_object_new_string(pkg.c_str())); + } + json_object_object_add(json_repo, "exclude_pkgs", json_exclude_pkgs); + + json_object * json_include_pkgs = json_object_new_array(); + for (const auto & pkg : repo->get_includepkgs()) { + json_object_array_add(json_include_pkgs, json_object_new_string(pkg.c_str())); + } + json_object_object_add(json_repo, "include_pkgs", json_include_pkgs); + + json_object_object_add(json_repo, "timestamp", json_object_new_int64(repo->get_timestamp())); + json_object_object_add(json_repo, "metadata_expire", json_object_new_int(repo->get_metadata_expire())); + json_object_object_add( + json_repo, "skip_if_unavailable", json_object_new_boolean(repo->get_skip_if_unavailable())); + json_object_object_add(json_repo, "repo_file_path", json_object_new_string(repo->get_repo_file_path().c_str())); + + json_object * json_baseurls = json_object_new_array(); + for (const auto & url : repo->get_baseurl()) { + json_object_array_add(json_baseurls, json_object_new_string(url.c_str())); + } + json_object_object_add(json_repo, "base_url", json_baseurls); + + json_object_object_add(json_repo, "metalink", json_object_new_string(repo->get_metalink().c_str())); + json_object_object_add(json_repo, "mirrorlist", json_object_new_string(repo->get_mirrorlist().c_str())); + + json_object * json_gpg_keys = json_object_new_array(); + for (const auto & key : repo->get_gpgkey()) { + json_object_array_add(json_gpg_keys, json_object_new_string(key.c_str())); + } + json_object_object_add(json_repo, "gpg_key", json_gpg_keys); + + json_object_object_add(json_repo, "repo_gpgcheck", json_object_new_boolean(repo->get_repo_gpgcheck())); + json_object_object_add(json_repo, "gpgcheck", json_object_new_boolean(repo->get_gpgcheck())); + json_object_object_add(json_repo, "available_pkgs", json_object_new_uint64(repo->get_available_pkgs())); + json_object_object_add(json_repo, "pkgs", json_object_new_uint64(repo->get_pkgs())); + json_object_object_add(json_repo, "size", json_object_new_uint64(repo->get_size())); + + json_object * json_content_tags = json_object_new_array(); + for (const auto & tag : repo->get_content_tags()) { + json_object_array_add(json_content_tags, json_object_new_string(tag.c_str())); + } + json_object_object_add(json_repo, "content_tags", json_content_tags); + + json_object * json_distro_tags = json_object_new_array(); + for (const auto & tag : flatten_distro_tags(repo->get_distro_tags())) { + json_object_array_add(json_distro_tags, json_object_new_string(tag.c_str())); + } + json_object_object_add(json_repo, "distro_tags", json_distro_tags); + + json_object_object_add(json_repo, "revision", json_object_new_string(repo->get_revision().c_str())); + json_object_object_add(json_repo, "max_timestamp", json_object_new_int(repo->get_max_timestamp())); + json_object_array_add(json_repos, json_repo); + } + std::cout << json_object_to_json_string_ext(json_repos, JSON_C_TO_STRING_PRETTY) << std::endl; + json_object_put(json_repos); +} + } // namespace libdnf5::cli::output