From 7e57a929d4f32dc8367614573ab80099aeb6212d Mon Sep 17 00:00:00 2001 From: Jan Kolarik Date: Tue, 4 Jun 2024 08:51:12 +0000 Subject: [PATCH] repoinfo: Implement json output --- dnf5/commands/repo/repo_info.cpp | 20 +++-- include/libdnf5-cli/output/repo_info.hpp | 2 + libdnf5-cli/output/repo_info.cpp | 96 ++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 12 deletions(-) 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/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