From fb7efdd7a4b6deb5617ba7bf5ada27dcbeb1f60e Mon Sep 17 00:00:00 2001 From: "David J. Allen" Date: Sun, 2 Jul 2023 17:28:18 -0600 Subject: [PATCH] Fixed `search` command not working properly --- README.md | 2 - include/config.hpp | 13 ++--- include/constants.hpp | 7 +++ include/package.hpp | 1 + include/rest_api.hpp | 23 +++++--- src/config.cpp | 18 +++---- src/package.cpp | 54 +++++++++++++++---- src/package_manager.cpp | 28 ++++++---- src/remote.cpp | 4 +- src/rest_api.cpp | 113 +++++++++++++++------------------------- 10 files changed, 143 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index 1c6fdf7..660cb2a 100644 --- a/README.md +++ b/README.md @@ -344,8 +344,6 @@ gdpm config set username towk * The code is currently changing so new issues will pop up often. -* Searching is broken. - * Logging doesn't write to file. ## License diff --git a/include/config.hpp b/include/config.hpp index bdfd0c5..3d2a135 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -17,12 +17,7 @@ namespace gdpm::package{ } namespace gdpm::config{ - enum class print_style{ - list = 0, - table = 1, - }; - - + struct context{ string username; string password; @@ -40,13 +35,13 @@ namespace gdpm::config{ bool clean_temporary; int verbose = log::INFO; - print_style style = print_style::list; + print::style style = print::style::list; package::info info; rest_api::request_params rest_api_params; }; - string from_style(const print_style& style); - print_style to_style(const string& s); + string from_style(const print::style& style); + print::style to_style(const string& s); string to_json(const context& config, bool pretty_print = false); error load(std::filesystem::path path, context& config); error save(std::filesystem::path path, const context& config); diff --git a/include/constants.hpp b/include/constants.hpp index c817a8c..a1f7dec 100644 --- a/include/constants.hpp +++ b/include/constants.hpp @@ -18,6 +18,13 @@ namespace gdpm::constants{ constexpr std::string WHITESPACE = " \n\r\t\f\v"; } +namespace gdpm::print{ + enum class style{ + list = 0, + table = 1, + }; +} + /* Define default macros to set when building with -DGPM_* */ #define GDPM_CONFIG_USERNAME "" #define GDPM_CONFIG_PASSWORD "" diff --git a/include/package.hpp b/include/package.hpp index 465026d..022af9a 100644 --- a/include/package.hpp +++ b/include/package.hpp @@ -117,6 +117,7 @@ namespace gdpm::package { GDPM_DLL_EXPORT void print_list(const rapidjson::Document& json); GDPM_DLL_EXPORT void print_list(const info_list& packages); GDPM_DLL_EXPORT void print_table(const info_list& packages); + GDPM_DLL_EXPORT void print_table(const rapidjson::Document& json); GDPM_DLL_EXPORT result_t get_package_info(const opts_t& opts); GDPM_DLL_EXPORT result_t get_package_titles(const info_list& packages); GDPM_DLL_EXPORT void clean_temporary(const config::context& config, const title_list& package_titles); diff --git a/include/rest_api.hpp b/include/rest_api.hpp index c18ef2a..0847069 100644 --- a/include/rest_api.hpp +++ b/include/rest_api.hpp @@ -39,28 +39,36 @@ namespace gdpm::rest_api{ enum type_e: int { any = 0, addon, project }; enum support_e: int { all = 0, official, community, testing }; enum sort_e: int { none = 0, rating, cost, name, updated }; + /* TODO: Include all information with categories and not just type*/ + struct category{ + int id; + int type; + string name; + }; + using categories = std::vector; struct request_params{ - int type ; + int type; int category; int support; - string user; - string godot_version; - int max_results; + string user = ""; + string cost = ""; + string godot_version = "4.0"; + int max_results = 500; int page; + int offset; int sort; bool reverse; int verbose; }; request_params make_from_config(const config::context& config); - request_params make_request_params(type_e type = GDPM_DEFAULT_ASSET_TYPE, int category = GDPM_DEFAULT_ASSET_CATEGORY, support_e support = GDPM_DEFAULT_ASSET_SUPPORT, const string& user = GDPM_DEFAULT_ASSET_USER, const string& godot_version = GDPM_DEFAULT_ASSET_GODOT_VERSION, int max_results = GDPM_DEFAULT_ASSET_MAX_RESULTS, int page = GDPM_DEFAULT_ASSET_PAGE, sort_e sort = GDPM_DEFAULT_ASSET_SORT, bool reverse = GDPM_DEFAULT_ASSET_REVERSE, int verbose = GDPM_DEFAULT_ASSET_VERBOSE); - string to_json(const rapidjson::Document& doc); string to_string(type_e type); string to_string(support_e support); string to_string(sort_e sort); - void _print_params(const request_params& params, const string& filter); + error print_params(const request_params& params, const string& filter = ""); + error print_asset(const request_params& params, const string& filter = "", const print::style& style = print::style::list); rapidjson::Document _parse_json(const string& r, int verbose = 0); string _prepare_request(const string& url, const request_params& context, const string& filter); @@ -69,7 +77,6 @@ namespace gdpm::rest_api{ bool logout(); rapidjson::Document configure(const string& url = constants::HostUrl, type_e type = any, int verbose = 0); - rapidjson::Document get_assets_list(const string& url = constants::HostUrl, type_e type = GDPM_DEFAULT_ASSET_TYPE, int category = GDPM_DEFAULT_ASSET_CATEGORY, support_e support = GDPM_DEFAULT_ASSET_SUPPORT, const string& filter = GDPM_DEFAULT_ASSET_FILTER, const std::string& user = GDPM_DEFAULT_ASSET_USER, const std::string& godot_version = GDPM_DEFAULT_ASSET_GODOT_VERSION, int max_results = GDPM_DEFAULT_ASSET_MAX_RESULTS, int page = GDPM_DEFAULT_ASSET_PAGE, sort_e sort = GDPM_DEFAULT_ASSET_SORT, bool reverse = GDPM_DEFAULT_ASSET_REVERSE, int verbose = GDPM_DEFAULT_ASSET_VERBOSE); rapidjson::Document get_assets_list(const string& url, const request_params& params = {}, const string& filter = ""); rapidjson::Document get_asset(const string& url, int asset_id, const request_params& params = {}, const string& filter = ""); bool delete_asset(int asset_id); // ...for moderators diff --git a/src/config.cpp b/src/config.cpp index 3174021..665a02c 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -35,16 +35,16 @@ namespace gdpm::config{ context config; - string from_style(const print_style& style){ - if(style == print_style::list) return "list"; - else if(style == print_style::table) return "table"; + string from_style(const print::style& style){ + if(style == print::style::list) return "list"; + else if(style == print::style::table) return "table"; return "list"; } - print_style to_style(const string& s){ - if(s == "list") return print_style::list; - else if(s == "table") return print_style::table; - else return print_style::list; + print::style to_style(const string& s){ + if(s == "list") return print::style::list; + else if(s == "table") return print::style::table; + else return print::style::list; } string to_json( @@ -413,7 +413,7 @@ namespace gdpm::config{ ){ using namespace tabulate; - if(config.style == config::print_style::list){ + if(config.style == print::style::list){ if(properties.empty()){ _print_property(config, "username"); _print_property(config, "password"); @@ -442,7 +442,7 @@ namespace gdpm::config{ ); } } - else if(config.style == config::print_style::table){ + else if(config.style == print::style::table){ Table table; table.add_row({"Property", "Value"}); if(properties.empty()){ diff --git a/src/package.cpp b/src/package.cpp index fde5b0b..d3a9b33 100644 --- a/src/package.cpp +++ b/src/package.cpp @@ -406,6 +406,8 @@ namespace gdpm::package{ return error(); } + + error search( const config::context& config, @@ -420,18 +422,19 @@ namespace gdpm::package{ return error(); } + /* Do a generic query with no filter */ rest_api::request_params rest_api_params = rest_api::make_from_config(config); + if(package_titles.empty()){ + return print_asset(rest_api_params); + } + + /* Query each package title supplied as input */ for(const auto& p_title : package_titles){ - using namespace rapidjson; - string request_url{constants::HostUrl + rest_api::endpoints::GET_Asset}; - Document doc = rest_api::get_assets_list(request_url, rest_api_params, p_title); - if(doc.IsNull()){ - return log::error_rc(error( - constants::error::HOST_UNREACHABLE, - "Could not fetch metadata. Aborting." - )); + error error = print_asset(rest_api_params, p_title, config.style); + if(error.has_occurred()){ + log::error(error); + continue; } - print_list(doc); } return error(); } @@ -449,9 +452,9 @@ namespace gdpm::package{ result_t r_installed = cache::get_installed_packages(); info_list p_installed = r_installed.unwrap_unsafe(); if(!p_installed.empty()){ - if(config.style == config::print_style::list) + if(config.style == print::style::list) print_list(p_installed); - else if(config.style == config::print_style::table){ + else if(config.style == print::style::table){ print_table(p_installed); } } @@ -705,6 +708,35 @@ namespace gdpm::package{ } + void print_table(const rapidjson::Document& json){ + using namespace tabulate; + Table table; + table.add_row({ + "Asset Name", + "Author", + "Category", + "Version", + "Godot Version", + "License/Cost", + "Last Modified", + "Support" + }); + for(const auto& o : json["result"].GetArray()){ + table.add_row({ + o["title"] .GetString(), + o["author"] .GetString(), + o["category"] .GetString(), + o["version_string"] .GetString(), + o["godot_version"] .GetString(), + o["cost"] .GetString(), + o["modify_date"] .GetString(), + o["support_level"] .GetString() + }); + } + table.print(std::cout); + } + + result_t get_package_info(const title_list& package_titles){ return cache::get_package_info_by_title(package_titles); } diff --git a/src/package_manager.cpp b/src/package_manager.cpp index 426f584..9ca5aa9 100644 --- a/src/package_manager.cpp +++ b/src/package_manager.cpp @@ -241,11 +241,14 @@ namespace gdpm::package_manager{ search_command.add_argument("--support") .help("set the support level") .nargs(1); - search_command.add_argument("-f", "--file") .help("set the file(s) to read as input") .append() .nargs(nargs_pattern::at_least_one); + search_command.add_argument("--style") + .help("set how to print output") + .nargs(1) + .default_value("list"); ui_command.add_description("show user interface (WIP)"); version_command.add_description("show version and exit"); @@ -422,6 +425,13 @@ namespace gdpm::package_manager{ set_if_used(search_command, config.rest_api_params.godot_version, "godot-version"); set_if_used(search_command, params.remote_source, "remote"); set_if_used(search_command, params.input_files, "file"); + if(search_command.is_used("style")){ + string style = search_command.get("style"); + if(!style.compare("list")) + config.style = print::style::list; + else if(!style.compare("table")) + config.style = print::style::table; + } } else if(program.is_subcommand_used(export_command)){ action = action_e::p_export; @@ -434,9 +444,9 @@ namespace gdpm::package_manager{ if(list_command.is_used("style")){ string style = list_command.get("style"); if(!style.compare("list")) - config.style = config::print_style::list; + config.style = print::style::list; else if(!style.compare("table")) - config.style = config::print_style::table; + config.style = print::style::table; } } else if(program.is_subcommand_used(link_command)){ @@ -469,9 +479,9 @@ namespace gdpm::package_manager{ if(config_command.is_used("style")){ string style = config_command.get("style"); if(!style.compare("list")) - config.style = config::print_style::list; + config.style = print::style::list; else if(!style.compare("table")) - config.style = config::print_style::table; + config.style = print::style::table; } if(config_command.is_subcommand_used(config_get)){ action = action_e::config_get; @@ -480,9 +490,9 @@ namespace gdpm::package_manager{ if(config_get.is_used("style")){ string style = config_get.get("style"); if(!style.compare("list")) - config.style = config::print_style::list; + config.style = print::style::list; else if(!style.compare("table")) - config.style = config::print_style::table; + config.style = print::style::table; } } else if(config_command.is_subcommand_used(config_set)){ @@ -521,9 +531,9 @@ namespace gdpm::package_manager{ action = action_e::remote_list; string style = remote_list.get("style"); if(!style.compare("list")) - config.style = config::print_style::list; + config.style = print::style::list; else if(!style.compare("table")) - config.style = config::print_style::table; + config.style = print::style::table; } } else if(program.is_subcommand_used("ui")){ diff --git a/src/remote.cpp b/src/remote.cpp index c16d5a1..62589ea 100644 --- a/src/remote.cpp +++ b/src/remote.cpp @@ -63,12 +63,12 @@ namespace gdpm::remote{ void print_repositories(const config::context& config){ const auto &rs = config.remote_sources; - if(config.style == config::print_style::list){ + if(config.style == print::style::list){ std::for_each(rs.begin(), rs.end(), [](const string_pair& p){ log::println("{}: {}", p.first, p.second); }); } - else if(config.style == config::print_style::table){ + else if(config.style == print::style::table){ using namespace tabulate; Table table; table.add_row({"Name", "URL"}); diff --git a/src/rest_api.cpp b/src/rest_api.cpp index c6a66d9..11ca39f 100644 --- a/src/rest_api.cpp +++ b/src/rest_api.cpp @@ -1,5 +1,7 @@ #include "config.hpp" +#include "error.hpp" +#include "package.hpp" #include "rest_api.hpp" #include "constants.hpp" #include "http.hpp" @@ -23,31 +25,6 @@ namespace gdpm::rest_api{ return rp; } - request_params make_request_params( - type_e type, - int category, - support_e support, - const string& user, - const string& godot_version, - int max_results, - int page, - sort_e sort, - bool reverse, - int verbose - ){ - return request_params{ - .type = type, - .category = category, - .support = support, - .user = user, - .godot_version = godot_version, - .max_results = max_results, - .page = page, - .sort = sort, - .reverse = reverse, - .verbose = verbose - }; - } bool register_account( const string& username, @@ -124,23 +101,25 @@ namespace gdpm::rest_api{ string _prepare_request( const string& url, - const request_params &c, + const request_params& c, const string& filter ){ string request_url{url}; - request_url += to_string(static_cast(c.type)); - request_url += (c.category <= 0) ? "&category=" : "&category="+std::to_string(c.category); - request_url += "&" + to_string(static_cast(c.support)); - request_url += "&" + to_string(static_cast(c.sort)); + request_url += to_string(static_cast(std::clamp(c.type, 0, 2))); + request_url += (c.category <= 0) ? "" : "&category="+std::to_string(c.category); + request_url += "&" + to_string(static_cast(std::clamp(c.support, 0, 3))); + request_url += (c.sort <= 0) ? "" : "&" + to_string(static_cast(std::clamp(c.sort, 1, 4))); request_url += (!filter.empty()) ? "&filter="+filter : ""; + request_url += (!c.user.empty()) ? "&user="+c.user : ""; + request_url += (!c.cost.empty()) ? "&cost="+c.cost : ""; request_url += (!c.godot_version.empty()) ? "&godot_version="+c.godot_version : ""; - request_url += "&max_results=" + std::to_string(c.max_results); - request_url += "&page=" + std::to_string(c.page); + request_url += (c.max_results <= 0 || c.max_results > 500) ? "" : "&max_results=" + std::to_string(c.max_results); + request_url += (c.page <= 0) ? "" : "&page=" + std::to_string(c.page); request_url += (c.reverse) ? "&reverse" : ""; return request_url; } - void _print_params(const request_params& params, const string& filter){ + error print_params(const request_params& params, const string& filter){ log::println("params: \n" "\ttype: {}\n" "\tcategory: {}\n" @@ -155,6 +134,28 @@ namespace gdpm::rest_api{ params.godot_version, params.max_results ); + return error(); + } + + error print_asset( + const rest_api::request_params& rest_api_params, + const string& filter, + const print::style& style + ){ + using namespace rapidjson; + string request_url{constants::HostUrl + rest_api::endpoints::GET_Asset}; + Document doc = rest_api::get_assets_list(request_url, rest_api_params); + if(doc.IsNull()){ + return log::error_rc(error( + constants::error::HOST_UNREACHABLE, + "Could not fetch metadata. Aborting." + )); + } + if(style == print::style::list) + package::print_list(doc); + if(style == print::style::table) + package::print_table(doc); + return error(); } rapidjson::Document configure( @@ -171,34 +172,6 @@ namespace gdpm::rest_api{ return _parse_json(r.body); } - rapidjson::Document get_assets_list( - const string& url, - type_e type, - int category, - support_e support, - const string& filter, - const string& user, - const string& godot_version, - int max_results, - int page, - sort_e sort, - bool reverse, - int verbose - ){ - request_params c{ - .type = type, - .category = category, - .support = support, - .user = user, - .godot_version = godot_version, - .max_results = max_results, - .page = page, - .sort = sort, - .reverse = reverse, - .verbose = verbose - }; - return get_assets_list(url, c); - } rapidjson::Document get_assets_list( const string& url, @@ -207,14 +180,14 @@ namespace gdpm::rest_api{ ){ http::context http; http::request_params http_params; - // http_params.headers.insert(http::header("Accept", "*/*")); - // http_params.headers.insert(http::header("Accept-Encoding", "application/gzip")); - // http_params.headers.insert(http::header("Content-Encoding", "application/gzip")); - // http_params.headers.insert(http::header("Connection", "keep-alive")); + http_params.headers.insert(http::header("Accept", "*/*")); + http_params.headers.insert(http::header("Accept-Encoding", "application/gzip")); + http_params.headers.insert(http::header("Content-Encoding", "application/gzip")); + http_params.headers.insert(http::header("Connection", "keep-alive")); string request_url = _prepare_request(url, c, http.url_escape(filter)); http::response r = http.request_get(request_url, http_params); if(c.verbose >= log::INFO) - log::info("get_asset().URL: {}", request_url); + log::info("rest_api::get_asset_list()::URL: {}", request_url); return _parse_json(r.body, c.verbose); } @@ -228,10 +201,10 @@ namespace gdpm::rest_api{ /* Set up HTTP request */ http::context http; http::request_params http_params; - // http_params.headers.insert(http::header("Accept", "*/*")); - // http_params.headers.insert(http::header("Accept-Encoding", "application/gzip")); - // http_params.headers.insert(http::header("Content-Encoding", "application/gzip")); - // http_params.headers.insert(http::header("Connection", "keep-alive")); + http_params.headers.insert(http::header("Accept", "*/*")); + http_params.headers.insert(http::header("Accept-Encoding", "application/gzip")); + http_params.headers.insert(http::header("Content-Encoding", "application/gzip")); + http_params.headers.insert(http::header("Connection", "keep-alive")); string request_url = utils::replace_all(_prepare_request(url, api_params, http.url_escape(filter)), "{id}", std::to_string(asset_id)); http::response r = http.request_get(request_url.c_str(), http_params); if(api_params.verbose >= log::INFO)