mirror of
https://github.com/davidallendj/gdpm.git
synced 2025-12-20 03:27:02 -07:00
Change command-line parsing (again...)
- Added formatted table with `--style` option - Added `warning` log level - Fixed bugs and cleaned up API - Removed some extra debugging output
This commit is contained in:
parent
0238dfd510
commit
b36d55ceee
15 changed files with 685 additions and 255 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -13,3 +13,6 @@
|
|||
[submodule "modules/csv2"]
|
||||
path = modules/csv2
|
||||
url = https://github.com/p-ranav/csv2
|
||||
[submodule "modules/argparse"]
|
||||
path = modules/argparse
|
||||
url = https://github.com/p-ranav/argparse
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ find_package(SQLiteCpp CONFIG REQUIRED)
|
|||
set(CMAKE_CXX_COMPILER "clang++")
|
||||
set(CMAKE_BUILD_RPATH "build/cmake")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -std=c++20 -Ofast -fPIC -fPIE -fpermissive -Wall -Wno-switch -Wno-unused-variable -Wno-unused-function -Wno-sign-conversion -pedantic-errors"
|
||||
"${CMAKE_CXX_FLAGS} -std=c++20 -Ofast -fPIC -fPIE -fpermissive -Wall -Wno-switch -Wno-unused-variable -Wno-unused-function -Wno-sign-conversion -Wno-deprecated-declarations -pedantic-errors"
|
||||
)
|
||||
set(INCLUDE_DIRS
|
||||
"include"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ namespace gdpm::package{
|
|||
}
|
||||
|
||||
namespace gdpm::config{
|
||||
enum class print_style{
|
||||
list = 0,
|
||||
table = 1,
|
||||
};
|
||||
|
||||
struct context{
|
||||
string username;
|
||||
string password;
|
||||
|
|
@ -25,24 +30,28 @@ namespace gdpm::config{
|
|||
string packages_dir;
|
||||
string tmp_dir;
|
||||
string_map remote_sources;
|
||||
size_t jobs = 1;
|
||||
size_t timeout = 3000;
|
||||
size_t max_results = 200;
|
||||
int jobs = 1;
|
||||
int timeout = 3000;
|
||||
bool enable_sync = true;
|
||||
bool enable_cache = true;
|
||||
bool skip_prompt = false;
|
||||
bool enable_file_logging;
|
||||
bool clean_temporary;
|
||||
int verbose;
|
||||
|
||||
int verbose = log::INFO;
|
||||
print_style style = print_style::list;
|
||||
package::info info;
|
||||
rest_api::request_params api_params;
|
||||
rest_api::request_params rest_api_params;
|
||||
};
|
||||
|
||||
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);
|
||||
error handle_config(config::context& config, const args_t& args, const var_opts& opts);
|
||||
context make_context(const string& username = GDPM_CONFIG_USERNAME, const string& password = GDPM_CONFIG_PASSWORD, const string& path = GDPM_CONFIG_PATH, const string& token = GDPM_CONFIG_TOKEN, const string& godot_version = GDPM_CONFIG_GODOT_VERSION, const string& packages_dir = GDPM_CONFIG_LOCAL_PACKAGES_DIR, const string& tmp_dir = GDPM_CONFIG_LOCAL_TMP_DIR, const string_map& remote_sources = {GDPM_CONFIG_REMOTE_SOURCES}, size_t threads = GDPM_CONFIG_THREADS, size_t timeout = 0, bool enable_sync = GDPM_CONFIG_ENABLE_SYNC, bool enable_file_logging = GDPM_CONFIG_ENABLE_FILE_LOGGING, int verbose = GDPM_CONFIG_VERBOSE);
|
||||
error set_property(config::context& config, const string& property, const any& value);
|
||||
template <typename T = any>
|
||||
T& get_property(const config::context& config, const string& property);
|
||||
context make_context(const string& username = GDPM_CONFIG_USERNAME, const string& password = GDPM_CONFIG_PASSWORD, const string& path = GDPM_CONFIG_PATH, const string& token = GDPM_CONFIG_TOKEN, const string& godot_version = GDPM_CONFIG_GODOT_VERSION, const string& packages_dir = GDPM_CONFIG_LOCAL_PACKAGES_DIR, const string& tmp_dir = GDPM_CONFIG_LOCAL_TMP_DIR, const string_map& remote_sources = {GDPM_CONFIG_REMOTE_SOURCES}, int jobs = GDPM_CONFIG_THREADS, int timeout = 0, bool enable_sync = GDPM_CONFIG_ENABLE_SYNC, bool enable_file_logging = GDPM_CONFIG_ENABLE_FILE_LOGGING, int verbose = GDPM_CONFIG_VERBOSE);
|
||||
error validate(const rapidjson::Document& doc);
|
||||
void print_json(const context& config);
|
||||
void print_properties(const context& config, const string_list& properties);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ namespace gdpm::constants::error{
|
|||
NONE = 0,
|
||||
UNKNOWN,
|
||||
UNKNOWN_COMMAND,
|
||||
UNKNOWN_ARGUMENT,
|
||||
ARGPARSE_ERROR,
|
||||
NOT_FOUND,
|
||||
NOT_DEFINED,
|
||||
NOT_IMPLEMENTED,
|
||||
|
|
@ -102,6 +104,11 @@ namespace gdpm{
|
|||
#endif
|
||||
}
|
||||
|
||||
static constexpr gdpm::error error_rc(const gdpm::error& e){
|
||||
error(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
static void error(const char *p, const gdpm::error& e){
|
||||
println("{}{}{}", p, prefix.contents, e.get_message());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ namespace gdpm::log
|
|||
inline constexpr const char* get_info_prefix() { return "[INFO {}] "; }
|
||||
inline constexpr const char* get_error_prefix() { return "[ERROR {}] "; }
|
||||
inline constexpr const char* get_debug_prefix() { return "[DEBUG {}] "; }
|
||||
inline constexpr const char* get_warning_prefix() { return "[WARN {}] "; }
|
||||
|
||||
static void vlog(fmt::string_view format, fmt::format_args args){
|
||||
fmt::vprint(format, args);
|
||||
|
|
@ -142,6 +143,21 @@ namespace gdpm::log
|
|||
#endif
|
||||
}
|
||||
|
||||
template <typename S, typename...Args>
|
||||
static constexpr void warn(const S& format, Args&&...args){
|
||||
if(log::level < to_int(log::WARNING))
|
||||
return;
|
||||
#if GDPM_LOG_LEVEL > WARN
|
||||
set_prefix_if(std::format(get_warning_prefix(), utils::timestamp()), true);
|
||||
set_suffix_if("\n");
|
||||
vlog(
|
||||
fmt::format(GDPM_COLOR_LOG_WARNING "{}{}{}" GDPM_COLOR_LOG_RESET, prefix.contents, format, suffix),
|
||||
fmt::make_format_args(args...)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <typename S, typename...Args>
|
||||
static constexpr void print(const S& format, Args&&...args){
|
||||
vlog(
|
||||
|
|
|
|||
|
|
@ -116,6 +116,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 result_t<info_list> get_package_info(const opts_t& opts);
|
||||
GDPM_DLL_EXPORT result_t<title_list> get_package_titles(const info_list& packages);
|
||||
GDPM_DLL_EXPORT void clean_temporary(const config::context& config, const title_list& package_titles);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "clipp.h"
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <future>
|
||||
#include <any>
|
||||
|
||||
namespace gdpm{
|
||||
class error;
|
||||
|
|
@ -47,6 +49,7 @@ namespace gdpm{
|
|||
using string_list = std::vector<string>;
|
||||
using string_map = std::unordered_map<string, string>;
|
||||
using string_pair = std::pair<string, string>;
|
||||
using any = std::any;
|
||||
using var = std::variant<int, float, bool, string, string_list, string_map, size_t>;
|
||||
template <typename T = var>
|
||||
using _args_t = std::vector<T>;
|
||||
|
|
|
|||
1
modules/argparse
Submodule
1
modules/argparse
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 557948f1236db9e27089959de837cc23de6c6bbd
|
||||
167
src/config.cpp
167
src/config.cpp
|
|
@ -7,6 +7,7 @@
|
|||
#include "types.hpp"
|
||||
|
||||
// RapidJSON
|
||||
#include <any>
|
||||
#include <rapidjson/ostreamwrapper.h>
|
||||
#include <rapidjson/rapidjson.h>
|
||||
#include <rapidjson/writer.h>
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
#include <rapidjson/prettywriter.h>
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/error/en.h>
|
||||
#include <tabulate/table.hpp>
|
||||
|
||||
|
||||
// fmt
|
||||
|
|
@ -67,7 +69,7 @@ namespace gdpm::config{
|
|||
file.open(path, std::ios::in);
|
||||
if(!file){
|
||||
if(config.verbose)
|
||||
log::info("No configuration file found. Creating a new one.");
|
||||
log::warn("No configuration file found. Creating a new one.");
|
||||
config = make_context();
|
||||
save(config.path, config);
|
||||
return error();
|
||||
|
|
@ -230,6 +232,46 @@ namespace gdpm::config{
|
|||
return error();
|
||||
}
|
||||
|
||||
error set_property(
|
||||
config::context& config,
|
||||
const string& property,
|
||||
const any& value
|
||||
){
|
||||
log::println("config::set_property() called");
|
||||
if(property == "username") config.username = std::any_cast<string>(value);
|
||||
else if(property == "password") config.password = std::any_cast<string>(value);
|
||||
else if(property == "path") config.path = std::any_cast<string>(value);
|
||||
else if(property == "token") config.token = std::any_cast<string>(value);
|
||||
else if(property == "packages_dir") config.packages_dir = std::any_cast<string>(value);
|
||||
else if(property == "tmp_dir") config.tmp_dir = std::any_cast<string>(value);
|
||||
else if(property == "remote_sources") config.remote_sources = std::any_cast<string_map>(value);
|
||||
else if(property == "jobs") config.jobs = std::any_cast<int>(value);
|
||||
else if(property == "timeout") config.timeout = std::any_cast<int>(value);
|
||||
else if(property == "enable_sync") config.enable_sync = std::any_cast<bool>(value);
|
||||
else if(property == "enable_cache") config.enable_cache = std::any_cast<bool>(value);
|
||||
else if(property == "skip_prompt") config.skip_prompt = std::any_cast<bool>(value);
|
||||
else if(property == "enable_file_logging") config.enable_file_logging = std::any_cast<bool>(value);
|
||||
else if(property == "clean_temporary") config.clean_temporary = std::any_cast<bool>(value);
|
||||
else{
|
||||
return log::error_rc(error(
|
||||
constants::error::INVALID_CONFIG,
|
||||
"Could not find property"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& get_property(
|
||||
const config::context& config,
|
||||
const string& property
|
||||
){
|
||||
log::println("config::get_property() called");
|
||||
if(property == "username") return config.username;
|
||||
else if(property == "password") return config.password;
|
||||
else if(property == "path") return config.path;
|
||||
else if(property == "token") return config.token;
|
||||
else if(property == "package_dir") return config.packages_dir;
|
||||
}
|
||||
|
||||
context make_context(
|
||||
const string& username,
|
||||
|
|
@ -240,8 +282,8 @@ namespace gdpm::config{
|
|||
const string& packages_dir,
|
||||
const string& tmp_dir,
|
||||
const string_map& remote_sources,
|
||||
size_t threads,
|
||||
size_t timeout,
|
||||
int jobs,
|
||||
int timeout,
|
||||
bool enable_sync,
|
||||
bool enable_file_logging,
|
||||
int verbose
|
||||
|
|
@ -254,7 +296,7 @@ namespace gdpm::config{
|
|||
.packages_dir = (packages_dir.empty()) ? string(getenv("HOME")) + ".gdpm" : packages_dir,
|
||||
.tmp_dir = tmp_dir,
|
||||
.remote_sources = remote_sources,
|
||||
.jobs = threads,
|
||||
.jobs = jobs,
|
||||
.timeout = timeout,
|
||||
.enable_sync = enable_sync,
|
||||
.enable_file_logging = enable_file_logging,
|
||||
|
|
@ -293,6 +335,8 @@ namespace gdpm::config{
|
|||
const context& config,
|
||||
const string& property
|
||||
){
|
||||
using namespace tabulate;
|
||||
|
||||
if(property.empty()) return;
|
||||
else if(property == "username") log::println("username: {}", config.username);
|
||||
else if(property == "password") log::println("password: {}", config.password);
|
||||
|
|
@ -311,34 +355,103 @@ namespace gdpm::config{
|
|||
else if(property == "verbose") log::println("verbose: {}", config.verbose);
|
||||
}
|
||||
|
||||
|
||||
void add_row(
|
||||
tabulate::Table& table,
|
||||
const context& config,
|
||||
const string property
|
||||
){
|
||||
if(property.empty()) return;
|
||||
else if(property == "username") table.add_row({"Username", config.username});
|
||||
else if(property == "password") table.add_row({"Password", config.password});
|
||||
else if(property == "path") table.add_row({"Path", config.path});
|
||||
else if(property == "token") table.add_row({"Token", config.token});
|
||||
else if(property == "packages_dir") table.add_row({"Package Directory", config.packages_dir});
|
||||
else if(property == "tmp_dir") table.add_row({"Temp Directory", config.tmp_dir});
|
||||
else if(property == "remote_sources") table.add_row({"Remotes", utils::join(config.remote_sources, "\t", "\n")});
|
||||
else if(property == "jobs") table.add_row({"Threads", std::to_string(config.jobs)});
|
||||
else if(property == "timeout") table.add_row({"Timeout", std::to_string(config.timeout)});
|
||||
else if(property == "sync") table.add_row({"Fetch Assets", std::to_string(config.enable_sync)});
|
||||
else if(property == "cache") table.add_row({"Cache", std::to_string(config.enable_cache)});
|
||||
else if(property == "prompt") table.add_row({"Skip Prompt", std::to_string(config.skip_prompt)});
|
||||
else if(property == "logging") table.add_row({"File Logging", std::to_string(config.enable_file_logging)});
|
||||
else if(property == "clean") table.add_row({"Clean Temporary", std::to_string(config.clean_temporary)});
|
||||
else if(property == "verbose") table.add_row({"Verbosity", std::to_string(config.verbose)});
|
||||
}
|
||||
|
||||
void print_properties(
|
||||
const context& config,
|
||||
const string_list& properties
|
||||
){
|
||||
if(properties.empty()){
|
||||
_print_property(config, "username");
|
||||
_print_property(config, "password");
|
||||
_print_property(config, "path");
|
||||
_print_property(config, "token");
|
||||
_print_property(config, "packages_dir");
|
||||
_print_property(config, "tmp_dir");
|
||||
_print_property(config, "remote_sources");
|
||||
_print_property(config, "jobs");
|
||||
_print_property(config, "timeout");
|
||||
_print_property(config, "sync");
|
||||
_print_property(config, "cache");
|
||||
_print_property(config, "prompt");
|
||||
_print_property(config, "logging");
|
||||
_print_property(config, "clean");
|
||||
_print_property(config, "verbose");
|
||||
}
|
||||
std::for_each(
|
||||
properties.begin(),
|
||||
properties.end(),
|
||||
[&config](const string& property){
|
||||
_print_property(config, property);
|
||||
using namespace tabulate;
|
||||
|
||||
if(config.style == config::print_style::list){
|
||||
if(properties.empty()){
|
||||
_print_property(config, "username");
|
||||
_print_property(config, "password");
|
||||
_print_property(config, "path");
|
||||
_print_property(config, "token");
|
||||
_print_property(config, "packages_dir");
|
||||
_print_property(config, "tmp_dir");
|
||||
_print_property(config, "remote_sources");
|
||||
_print_property(config, "jobs");
|
||||
_print_property(config, "timeout");
|
||||
_print_property(config, "sync");
|
||||
_print_property(config, "cache");
|
||||
_print_property(config, "prompt");
|
||||
_print_property(config, "logging");
|
||||
_print_property(config, "clean");
|
||||
_print_property(config, "verbose");
|
||||
}
|
||||
);
|
||||
else {
|
||||
std::for_each(
|
||||
properties.begin(),
|
||||
properties.end(),
|
||||
[&config](const string& property){
|
||||
_print_property(config, property);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(config.style == config::print_style::table){
|
||||
Table table;
|
||||
if(properties.empty()){
|
||||
table.add_row({"Property", "Value"});
|
||||
table.add_row({"Username", config.username});
|
||||
table.add_row({"Password", config.password});
|
||||
table.add_row({"Path", config.path});
|
||||
table.add_row({"Token", config.token});
|
||||
table.add_row({"Package Directory", config.token});
|
||||
table.add_row({"Temp Directory", config.tmp_dir});
|
||||
table.add_row({"Remotes", utils::join(config.remote_sources)});
|
||||
table.add_row({"Threads", std::to_string(config.jobs)});
|
||||
table.add_row({"Timeout", std::to_string(config.timeout)});
|
||||
table.add_row({"Fetch Data", std::to_string(config.enable_sync)});
|
||||
table.add_row({"Use Cache", std::to_string(config.enable_cache)});
|
||||
table.add_row({"Logging", std::to_string(config.enable_file_logging)});
|
||||
table.add_row({"Clean", std::to_string(config.clean_temporary)});
|
||||
table.add_row({"Verbosity", std::to_string(config.verbose)});
|
||||
}
|
||||
else{
|
||||
std::for_each(
|
||||
properties.begin(),
|
||||
properties.end(),
|
||||
[&table, &config](const string& property){
|
||||
add_row(table, config, property);
|
||||
}
|
||||
);
|
||||
}
|
||||
table[0].format()
|
||||
.padding_top(1)
|
||||
.padding_bottom(1)
|
||||
.font_background_color(Color::red)
|
||||
.font_style({FontStyle::bold});
|
||||
table.column(1).format()
|
||||
.font_color(Color::yellow);
|
||||
table[0][1].format()
|
||||
.font_background_color(Color::blue);
|
||||
table.print(std::cout);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
104
src/package.cpp
104
src/package.cpp
|
|
@ -15,6 +15,7 @@
|
|||
#include <rapidjson/error/en.h>
|
||||
#include <rapidjson/ostreamwrapper.h>
|
||||
#include <rapidjson/prettywriter.h>
|
||||
#include <tabulate/table.hpp>
|
||||
|
||||
namespace gdpm::package{
|
||||
|
||||
|
|
@ -39,8 +40,7 @@ namespace gdpm::package{
|
|||
*/
|
||||
|
||||
/* Append files from --file option */
|
||||
if(!params.input_files.empty()){
|
||||
log::print("input files");
|
||||
// if(!params.input_files.empty()){
|
||||
for(const auto& filepath : params.input_files){
|
||||
string contents = utils::readfile(filepath);
|
||||
log::print("contents: {}", contents);
|
||||
|
|
@ -51,7 +51,7 @@ namespace gdpm::package{
|
|||
std::end(input_titles)
|
||||
);
|
||||
}
|
||||
}
|
||||
// }
|
||||
result_t result = cache::get_package_info_by_title(package_titles);
|
||||
package::info_list p_found = {};
|
||||
package::info_list p_cache = result.unwrap_unsafe();
|
||||
|
|
@ -445,16 +445,14 @@ namespace gdpm::package{
|
|||
|
||||
rest_api_params.filter = http.url_escape(p_title);
|
||||
|
||||
std::string request_url{constants::HostUrl};
|
||||
string request_url{constants::HostUrl};
|
||||
request_url += rest_api::endpoints::GET_Asset;
|
||||
Document doc = rest_api::get_assets_list(request_url, rest_api_params);
|
||||
if(doc.IsNull()){
|
||||
error error(
|
||||
return log::error_rc(error(
|
||||
constants::error::HOST_UNREACHABLE,
|
||||
"Could not fetch metadata."
|
||||
);
|
||||
log::error(error);
|
||||
return error;
|
||||
));
|
||||
}
|
||||
|
||||
// log::info("{} package(s) found...", doc["total_items"].GetInt());
|
||||
|
|
@ -476,18 +474,21 @@ namespace gdpm::package{
|
|||
result_t r_installed = cache::get_installed_packages();
|
||||
info_list p_installed = r_installed.unwrap_unsafe();
|
||||
if(!p_installed.empty()){
|
||||
print_list(p_installed);
|
||||
if(config.style == config::print_style::list)
|
||||
print_list(p_installed);
|
||||
else if(config.style == config::print_style::table){
|
||||
print_table(p_installed);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(show == "remote"){
|
||||
remote::print_repositories(config);
|
||||
}
|
||||
else{
|
||||
error error(
|
||||
log::error(error(
|
||||
constants::error::UNKNOWN_COMMAND,
|
||||
"Unrecognized subcommand. Try either 'packages' or 'remote' instead."
|
||||
);
|
||||
log::error(error);
|
||||
));
|
||||
}
|
||||
return error();
|
||||
}
|
||||
|
|
@ -520,7 +521,7 @@ namespace gdpm::package{
|
|||
}
|
||||
}
|
||||
std::ofstream of(path);
|
||||
log::println("writing contents to file");
|
||||
log::println("export: {}", path);
|
||||
of << output;
|
||||
of.close();
|
||||
}
|
||||
|
|
@ -532,17 +533,15 @@ namespace gdpm::package{
|
|||
error link(
|
||||
const config::context& config,
|
||||
const title_list& package_titles,
|
||||
const package::params& params /* path is last arg */
|
||||
const package::params& params
|
||||
){
|
||||
using namespace std::filesystem;
|
||||
|
||||
if(params.args.empty()){
|
||||
error error(
|
||||
constants::error::INVALID_ARG_COUNT,
|
||||
"Must supply at least 2 arguments (package name and path)"
|
||||
);
|
||||
log::error(error);
|
||||
return error;
|
||||
if(params.paths.empty()){
|
||||
return log::error_rc(error(
|
||||
constants::error::PATH_NOT_DEFINED,
|
||||
"Path is required"
|
||||
));
|
||||
}
|
||||
|
||||
/* Check for packages in cache to link */
|
||||
|
|
@ -550,12 +549,10 @@ namespace gdpm::package{
|
|||
info_list p_found = {};
|
||||
info_list p_cache = r_cache.unwrap_unsafe();
|
||||
if(p_cache.empty()){
|
||||
error error(
|
||||
return log::error_rc(error(
|
||||
constants::error::NOT_FOUND,
|
||||
"Could not find any packages to link in cache."
|
||||
);
|
||||
log::error(error);
|
||||
return error;
|
||||
));
|
||||
}
|
||||
|
||||
for(const auto& p_title : package_titles){
|
||||
|
|
@ -575,17 +572,15 @@ namespace gdpm::package{
|
|||
}
|
||||
|
||||
/* Get the storage paths for all packages to create symlinks */
|
||||
path_refs paths = path_refs({params.args.back()});
|
||||
const path package_dir{config.packages_dir};
|
||||
for(const auto& p : p_found){
|
||||
for(const auto& path : paths){
|
||||
const string _path = path;
|
||||
log::info_n("link: \"{}\" -> '{}'...", p.title, _path + "/" + p.title);
|
||||
for(const auto& path : params.paths){
|
||||
log::info_n("link: \"{}\" -> '{}'...", p.title, path + "/" + p.title);
|
||||
// std::filesystem::path target{config.packages_dir + "/" + p.title};
|
||||
std::filesystem::path target = {current_path().string() + "/" + config.packages_dir + "/" + p.title};
|
||||
std::filesystem::path symlink_path{_path + "/" + p.title};
|
||||
std::filesystem::path symlink_path{path + "/" + p.title};
|
||||
if(!std::filesystem::exists(symlink_path.string()))
|
||||
std::filesystem::create_directories(_path + "/");
|
||||
std::filesystem::create_directories(path + "/");
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directory_symlink(target, symlink_path, ec);
|
||||
if(ec){
|
||||
|
|
@ -609,13 +604,11 @@ namespace gdpm::package{
|
|||
){
|
||||
using namespace std::filesystem;
|
||||
|
||||
if(params.args.empty()){
|
||||
error error(
|
||||
constants::error::INVALID_ARG_COUNT,
|
||||
"Must supply at least 2 arguments (package name and path)"
|
||||
);
|
||||
log::error(error);
|
||||
return error;
|
||||
if(params.paths.empty()){
|
||||
return log::error_rc(error(
|
||||
constants::error::PATH_NOT_DEFINED,
|
||||
"Path is required"
|
||||
));
|
||||
}
|
||||
|
||||
result_t r_cache = cache::get_package_info_by_title(package_titles);
|
||||
|
|
@ -624,12 +617,10 @@ namespace gdpm::package{
|
|||
|
||||
/* Check for installed packages to clone */
|
||||
if(p_cache.empty()){
|
||||
error error(
|
||||
return log::error_rc(error(
|
||||
constants::error::NO_PACKAGE_FOUND,
|
||||
"Could not find any packages to clone in cache."
|
||||
);
|
||||
log::error(error);
|
||||
return error;
|
||||
));
|
||||
}
|
||||
|
||||
for(const auto& p_title : package_titles){
|
||||
|
|
@ -694,7 +685,6 @@ namespace gdpm::package{
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void print_list(const rapidjson::Document& json){
|
||||
for(const auto& o : json["result"].GetArray()){
|
||||
log::println(
|
||||
|
|
@ -717,6 +707,34 @@ namespace gdpm::package{
|
|||
}
|
||||
}
|
||||
|
||||
void print_table(const info_list& packages){
|
||||
using namespace tabulate;
|
||||
Table table;
|
||||
table.add_row({
|
||||
"Asset Name",
|
||||
"Author",
|
||||
"Category",
|
||||
"Version",
|
||||
"Godot Version",
|
||||
"License/Cost",
|
||||
"Last Modified",
|
||||
"Support"
|
||||
});
|
||||
for(const auto& p : packages){
|
||||
table.add_row({
|
||||
p.title,
|
||||
p.author,
|
||||
p.category,
|
||||
p.version,
|
||||
p.godot_version,
|
||||
p.cost,
|
||||
p.modify_date,
|
||||
p.support_level
|
||||
});
|
||||
}
|
||||
table.print(std::cout);
|
||||
}
|
||||
|
||||
|
||||
result_t<info_list> get_package_info(const title_list& package_titles){
|
||||
return cache::get_package_info_by_title(package_titles);
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@
|
|||
#include <rapidjson/document.h>
|
||||
#include <cxxopts.hpp>
|
||||
#include "clipp.h"
|
||||
#include "argparse/argparse.hpp"
|
||||
|
||||
#include <rapidjson/ostreamwrapper.h>
|
||||
#include <rapidjson/prettywriter.h>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <future>
|
||||
|
||||
|
|
@ -79,185 +81,426 @@ namespace gdpm::package_manager{
|
|||
return error;
|
||||
}
|
||||
|
||||
template <typename T, typename String = string>
|
||||
auto set_if_used(
|
||||
const argparse::ArgumentParser& cmd,
|
||||
T& value,
|
||||
const String& arg
|
||||
){
|
||||
using namespace argparse;
|
||||
if(cmd.is_used(arg)){
|
||||
value = cmd.get<T>(arg);
|
||||
}
|
||||
};
|
||||
|
||||
string_list get_packages_from_parser(
|
||||
const argparse::ArgumentParser& cmd,
|
||||
const std::string& arg = "packages"
|
||||
){
|
||||
if(cmd.is_used(arg))
|
||||
return cmd.get<string_list>(arg);
|
||||
return string_list();
|
||||
}
|
||||
|
||||
|
||||
error parse_arguments(int argc, char **argv){
|
||||
using namespace clipp;
|
||||
using namespace argparse;
|
||||
|
||||
/* Replace cxxopts with clipp */
|
||||
action_e action = action_e::none;
|
||||
package::title_list package_titles;
|
||||
package::params params;
|
||||
|
||||
auto doc_format = clipp::doc_formatting{}
|
||||
.first_column(7)
|
||||
.doc_column(45)
|
||||
.last_column(99);
|
||||
ArgumentParser program(argv[0], "0.0.1", argparse::default_arguments::help);
|
||||
ArgumentParser install_command("install");
|
||||
ArgumentParser add_command("add");
|
||||
ArgumentParser remove_command("remove");
|
||||
ArgumentParser update_command("update");
|
||||
ArgumentParser search_command("search");
|
||||
ArgumentParser export_command("export");
|
||||
ArgumentParser list_command("list");
|
||||
ArgumentParser link_command("link");
|
||||
ArgumentParser clone_command("clone");
|
||||
ArgumentParser clean_command("clean");
|
||||
ArgumentParser config_command("config");
|
||||
ArgumentParser fetch_command("fetch");
|
||||
ArgumentParser version_command("version");
|
||||
ArgumentParser remote_command("remote");
|
||||
ArgumentParser ui_command("ui");
|
||||
ArgumentParser help_command("help");
|
||||
|
||||
/* Set global options */
|
||||
auto debugOpt = option("-d", "--debug").set(config.verbose, to_int(log::DEBUG)) % "show debug output";
|
||||
auto configOpt = option("--config-path").set(config.path) % "set config path";
|
||||
auto pathOpt = option("--path").set(params.paths) % "specify a path to use with command";
|
||||
auto typeOpt = option("--type").set(config.info.type) % "set package type (any|addon|project)";
|
||||
auto sortOpt = option("--sort").set(config.rest_api_params.sort) % "sort packages in order (rating|cost|name|updated)";
|
||||
auto supportOpt = option("--support").set(config.rest_api_params.support) % "set the support level for API (all|official|community|testing)";
|
||||
auto maxResultsOpt = option("--max-results").set(config.rest_api_params.max_results) % "set the request max results";
|
||||
auto godotVersionOpt = option("--godot-version").set(config.rest_api_params.godot_version) % "set the request Godot version";
|
||||
auto packageDirOpt = option("--package-dir").set(config.packages_dir) % "set the global package location";
|
||||
auto tmpDirOpt = option("--tmp-dir").set(config.tmp_dir) % "set the temporary download location";
|
||||
auto timeoutOpt = option("--timeout").set(config.timeout) % "set the request timeout";
|
||||
auto verboseOpt = joinable(repeatable(option("-v", "--verbose").call([]{ config.verbose += 1; }))) % "show verbose output";
|
||||
ArgumentParser config_get("get");
|
||||
ArgumentParser config_set("set");
|
||||
|
||||
/* Set the options */
|
||||
// auto fileOpt = repeatable(option("--file", "-f").set(params.input_files) % "read file as input");
|
||||
auto fileOpt = repeatable(option("--file", "-f") & values("input", params.input_files)) % "read file as input";
|
||||
auto cleanOpt = option("--clean").set(config.clean_temporary) % "enable/disable cleaning temps";
|
||||
auto parallelOpt = option("--jobs").set(config.jobs) % "set number of parallel jobs";
|
||||
auto cacheOpt = option("--enable-cache").set(config.enable_cache) % "enable/disable local caching";
|
||||
auto syncOpt = option("--enable-sync").set(config.enable_sync) % "enable/disable remote syncing";
|
||||
auto skipOpt = option("-y", "--skip-prompt").set(config.skip_prompt, true) % "skip the y/n prompt";
|
||||
auto remoteOpt = option("--remote").set(params.remote_source) % "set remote source to use";
|
||||
ArgumentParser remote_add("add");
|
||||
ArgumentParser remote_remove("remove");
|
||||
ArgumentParser remote_list("list");
|
||||
|
||||
auto packageValues = values("packages", package_titles);
|
||||
auto requiredPath = required("--path", params.args);
|
||||
program.add_description("Manage Godot engine assets from CLI");
|
||||
program.add_argument("-v", "--verbose")
|
||||
.action([&](const auto&){ config.verbose += 1; })
|
||||
.default_value(false)
|
||||
.implicit_value(true)
|
||||
.help("set verbosity level")
|
||||
.nargs(0);
|
||||
|
||||
auto installCmd = "install" % (
|
||||
command("install").set(action, action_e::install),
|
||||
packageValues % "package(s) to install from asset library",
|
||||
godotVersionOpt, cleanOpt, parallelOpt, syncOpt, skipOpt, remoteOpt, fileOpt
|
||||
);
|
||||
auto addCmd = "add" % (
|
||||
command("add").set(action, action_e::add),
|
||||
packageValues % "package(s) to add to project",
|
||||
parallelOpt, skipOpt, remoteOpt, fileOpt
|
||||
);
|
||||
auto removeCmd = "remove" % (
|
||||
command("remove").set(action, action_e::remove),
|
||||
packageValues % "packages(s) to remove from project",
|
||||
fileOpt, skipOpt, cleanOpt
|
||||
);
|
||||
auto updateCmd = "update package(s)" % (
|
||||
command("update").set(action, action_e::update),
|
||||
packageValues % ""
|
||||
);
|
||||
auto searchCmd = "search for package(s)" % (
|
||||
command("search").set(action, action_e::search),
|
||||
packageValues % "",
|
||||
godotVersionOpt, fileOpt, remoteOpt, configOpt
|
||||
);
|
||||
auto exportCmd = "export installed package list to file" % (
|
||||
command("export").set(action, action_e::p_export),
|
||||
values("paths", params.args) % ""
|
||||
);
|
||||
auto listCmd = "show installed packages" % (
|
||||
command("list").set(action, action_e::list)
|
||||
);
|
||||
auto linkCmd = "create link from package to project" % (
|
||||
command("link").set(action, action_e::link),
|
||||
value("package", package_titles) % "",
|
||||
value("path", params.args) % ""
|
||||
);
|
||||
auto cloneCmd = "clone package to project" % (
|
||||
command("clone").set(action, action_e::clone),
|
||||
value("package", package_titles) % "",
|
||||
value("path", params.args) % ""
|
||||
);
|
||||
auto cleanCmd = "clean temporary download files" % (
|
||||
command("clean").set(action, action_e::clean),
|
||||
values("packages", package_titles) % ""
|
||||
);
|
||||
auto configCmd = "manage config properties" % (
|
||||
command("config").set(action, action_e::config_get) ,
|
||||
(
|
||||
( greedy(command("get")).set(action, action_e::config_get),
|
||||
option(repeatable(values("properties", params.args)))
|
||||
) % "get config properties"
|
||||
|
|
||||
( command("set").set(action, action_e::config_set) ,
|
||||
value("property", params.args[1]).call([]{}),
|
||||
value("value", params.args[2]).call([]{})
|
||||
) % "set config properties"
|
||||
)
|
||||
);
|
||||
auto fetchCmd = "fetch asset data from remote" % (
|
||||
command("fetch").set(action, action_e::fetch),
|
||||
option(values("remote", params.args)) % ""
|
||||
);
|
||||
auto versionCmd = "show the version and exit" %(
|
||||
command("version").set(action, action_e::version)
|
||||
);
|
||||
auto add_arg = [¶ms](string arg) { params.args.emplace_back(arg); };
|
||||
auto remoteCmd = "manage remote sources" % (
|
||||
command("remote").set(action, action_e::remote_list).if_missing(
|
||||
[]{ remote::print_repositories(config); }
|
||||
),
|
||||
(
|
||||
"add" % ( command("add").set(action, action_e::remote_add),
|
||||
word("name").call(add_arg) % "",
|
||||
value("url").call(add_arg) % ""
|
||||
)
|
||||
|
|
||||
"remove a remote source" % ( command("remove").set(action, action_e::remote_remove),
|
||||
words("names", params.args) % ""
|
||||
)
|
||||
|
|
||||
"list remote sources" % ( command("list").set(action, action_e::remote_list))
|
||||
)
|
||||
);
|
||||
auto uiCmd = "start with UI" % (
|
||||
command("ui").set(action, action_e::ui)
|
||||
);
|
||||
auto helpCmd = "show this message and exit" % (
|
||||
command("help").set(action, action_e::help)
|
||||
);
|
||||
install_command.add_description("install package(s)");
|
||||
install_command.add_argument("packages")
|
||||
.required()
|
||||
.nargs(nargs_pattern::at_least_one)
|
||||
.help("packages to install");
|
||||
install_command.add_argument("--godot-version")
|
||||
.help("set Godot version for request");
|
||||
install_command.add_argument("--clean")
|
||||
.help("clean temporary files")
|
||||
.implicit_value(true)
|
||||
.default_value(false)
|
||||
.nargs(0);
|
||||
install_command.add_argument("--disable-sync")
|
||||
.help("enable syncing with remote before installing")
|
||||
.implicit_value(true)
|
||||
.default_value(false)
|
||||
.nargs(0);
|
||||
install_command.add_argument("--disable-cache")
|
||||
.help("disable caching asset data")
|
||||
.implicit_value(true)
|
||||
.default_value(false)
|
||||
.nargs(0);
|
||||
install_command.add_argument("--remote")
|
||||
.help("set the remote to use")
|
||||
.nargs(1);
|
||||
install_command.add_argument("-j", "--jobs")
|
||||
.help("set the number of parallel downloads")
|
||||
.default_value(1)
|
||||
.nargs(1)
|
||||
.scan<'i', int>();
|
||||
install_command.add_argument("-y", "--skip-prompt")
|
||||
.help("skip the yes/no prompt")
|
||||
.implicit_value(true)
|
||||
.default_value(false)
|
||||
.nargs(0);
|
||||
install_command.add_argument("-f", "--file")
|
||||
.help("set the file(s) to read as input")
|
||||
.append()
|
||||
.nargs(1);
|
||||
install_command.add_argument("-t", "--timeout")
|
||||
.help("set the request timeout")
|
||||
.default_value(30)
|
||||
.nargs(0);
|
||||
|
||||
auto cli = (
|
||||
debugOpt, verboseOpt, configOpt,
|
||||
(installCmd | addCmd | removeCmd | updateCmd | searchCmd | exportCmd |
|
||||
listCmd | linkCmd | cloneCmd | cleanCmd | configCmd | fetchCmd |
|
||||
remoteCmd | uiCmd | helpCmd | versionCmd)
|
||||
);
|
||||
add_command.add_description("add package to project");
|
||||
add_command.add_argument("packages").nargs(nargs_pattern::at_least_one);
|
||||
add_command.add_argument("--remote");
|
||||
add_command.add_argument("-j", "--jobs")
|
||||
.help("")
|
||||
.nargs(1)
|
||||
.default_value(1)
|
||||
.nargs(1)
|
||||
.scan<'i', int>();
|
||||
add_command.add_argument("-y", "--skip-prompt");
|
||||
add_command.add_argument("-f", "--file")
|
||||
.help("set the file(s) to read as input")
|
||||
.append()
|
||||
.nargs(nargs_pattern::at_least_one);
|
||||
|
||||
/* Make help output */
|
||||
string man_page_format("");
|
||||
auto man_page = make_man_page(cli, argv[0], doc_format)
|
||||
.prepend_section("DESCRIPTION", "\tManage Godot Game Engine assets from the command-line.")
|
||||
.append_section("LICENSE", "\tSee the 'LICENSE.md' file for more details.");
|
||||
std::for_each(man_page.begin(), man_page.end(),
|
||||
[&man_page_format](const man_page::section& s){
|
||||
man_page_format += s.title() + "\n";
|
||||
man_page_format += s.content() + "\n\n";
|
||||
remove_command.add_description("remove package(s)");
|
||||
remove_command.add_argument("packages").nargs(nargs_pattern::at_least_one);
|
||||
remove_command.add_argument("--clean");
|
||||
remove_command.add_argument("-y", "--skip-prompt");
|
||||
remove_command.add_argument("-f", "--file")
|
||||
.help("set the file(s) to read as input")
|
||||
.append()
|
||||
.nargs(nargs_pattern::at_least_one);
|
||||
|
||||
update_command.add_description("update package(s)");
|
||||
update_command.add_argument("packages").nargs(nargs_pattern::at_least_one);
|
||||
update_command.add_argument("--clean");
|
||||
update_command.add_argument("--remote");
|
||||
update_command.add_argument("-f", "--file")
|
||||
.help("set the file(s) to read as input")
|
||||
.append()
|
||||
.nargs(nargs_pattern::at_least_one);
|
||||
|
||||
search_command.add_description("search for package(s)");
|
||||
search_command.add_argument("packages").nargs(nargs_pattern::at_least_one);
|
||||
search_command.add_argument("--godot-version");
|
||||
search_command.add_argument("--remote");
|
||||
search_command.add_argument("-f", "--file")
|
||||
.help("set the file(s) to read as input")
|
||||
.append()
|
||||
.nargs(nargs_pattern::at_least_one);
|
||||
|
||||
ui_command.add_description("show user interface (WIP)");
|
||||
version_command.add_description("show version and exit");
|
||||
help_command.add_description("show help message and exit");
|
||||
|
||||
export_command.add_description("export install package(s) list");
|
||||
export_command.add_argument("paths")
|
||||
.help("export list of installed packages")
|
||||
.required()
|
||||
.nargs(nargs_pattern::at_least_one);
|
||||
|
||||
list_command.add_description("show install package(s) and remotes");
|
||||
list_command.add_argument("show")
|
||||
.help("show installed packages or remote")
|
||||
.nargs(nargs_pattern::any)
|
||||
.default_value("packages");
|
||||
list_command.add_argument("--style")
|
||||
.help("set how to print output")
|
||||
.nargs(1)
|
||||
.default_value("list");
|
||||
|
||||
link_command.add_description("link package(s) to path");
|
||||
link_command.add_argument("packages")
|
||||
.help("package(s) to link")
|
||||
.required()
|
||||
.nargs(1);
|
||||
link_command.add_argument("path")
|
||||
.help("path to link")
|
||||
.required()
|
||||
.nargs(1);
|
||||
|
||||
clone_command.add_description("clone package(s) to path");
|
||||
clone_command.add_argument("packages")
|
||||
.help("package(s) to clone")
|
||||
.required()
|
||||
.nargs(1);;
|
||||
clone_command.add_argument("path")
|
||||
.help("path to clone")
|
||||
.required()
|
||||
.nargs(1);
|
||||
|
||||
clean_command.add_description("clean package(s) temporary files");
|
||||
clean_command.add_argument("packages")
|
||||
.help("package(s) to clean")
|
||||
.required()
|
||||
.nargs(nargs_pattern::at_least_one);
|
||||
|
||||
fetch_command.add_description("fetch and sync asset data");
|
||||
fetch_command.add_argument("remote")
|
||||
.help("remote to fetch")
|
||||
.required()
|
||||
.nargs(1);
|
||||
|
||||
config_get.add_argument("properties")
|
||||
.help("get config properties")
|
||||
.nargs(nargs_pattern::any);
|
||||
config_get.add_description("get config properties");
|
||||
config_set.add_argument("property")
|
||||
.help("property name")
|
||||
.required()
|
||||
.nargs(1);
|
||||
config_set.add_argument("value")
|
||||
.help("property value")
|
||||
.required()
|
||||
.nargs(1);
|
||||
config_set.add_description("set config property");
|
||||
|
||||
config_command.add_description("manage config properties");
|
||||
config_command.add_subparser(config_get);
|
||||
config_command.add_subparser(config_set);
|
||||
|
||||
remote_add.add_argument("name")
|
||||
.help("remote name")
|
||||
.nargs(1);
|
||||
remote_add.add_argument("url")
|
||||
.help("remote url")
|
||||
.nargs(1);
|
||||
remote_remove.add_argument("names")
|
||||
.help("remote name")
|
||||
.nargs(nargs_pattern::at_least_one);
|
||||
remote_list.add_argument("--style")
|
||||
.help("set print style")
|
||||
.nargs(1);
|
||||
|
||||
remote_command.add_description("manage remote(s)");
|
||||
remote_command.add_subparser(remote_add);
|
||||
remote_command.add_subparser(remote_remove);
|
||||
remote_command.add_subparser(remote_list);
|
||||
|
||||
// version_command.add_argument(Targs f_args...)
|
||||
|
||||
program.add_subparser(install_command);
|
||||
program.add_subparser(add_command);
|
||||
program.add_subparser(remove_command);
|
||||
program.add_subparser(update_command);
|
||||
program.add_subparser(search_command);
|
||||
program.add_subparser(export_command);
|
||||
program.add_subparser(list_command);
|
||||
program.add_subparser(link_command);
|
||||
program.add_subparser(clone_command);
|
||||
program.add_subparser(clean_command);
|
||||
program.add_subparser(config_command);
|
||||
program.add_subparser(fetch_command);
|
||||
program.add_subparser(remote_command);
|
||||
program.add_subparser(version_command);
|
||||
program.add_subparser(ui_command);
|
||||
program.add_subparser(help_command);
|
||||
|
||||
try{
|
||||
program.parse_args(argc, argv);
|
||||
// program.parse_known_args(argc, argv);
|
||||
} catch(const std::runtime_error& e){
|
||||
return log::error_rc(error(
|
||||
constants::error::ARGPARSE_ERROR,
|
||||
e.what())
|
||||
);
|
||||
}
|
||||
|
||||
if(program.is_subcommand_used(install_command)){
|
||||
action = action_e::install;
|
||||
if(install_command.is_used("packages"))
|
||||
package_titles = install_command.get<string_list>("packages");
|
||||
set_if_used(install_command, config.rest_api_params.godot_version, "godot-version");
|
||||
set_if_used(install_command, config.clean_temporary, "clean");
|
||||
set_if_used(install_command, config.enable_sync, "disable-sync");
|
||||
set_if_used(install_command, config.enable_cache, "disable-cache");
|
||||
set_if_used(install_command, params.remote_source, "remote");
|
||||
set_if_used(install_command, config.jobs, "jobs");
|
||||
set_if_used(install_command, config.skip_prompt, "skip-prompt");
|
||||
set_if_used(install_command, params.input_files, "file");
|
||||
set_if_used(install_command, config.timeout, "timeout");
|
||||
}
|
||||
else if(program.is_subcommand_used(add_command)){
|
||||
action = action_e::add;
|
||||
package_titles = get_packages_from_parser(add_command);
|
||||
set_if_used(add_command, params.remote_source, "remote");
|
||||
set_if_used(add_command, config.jobs, "jobs");
|
||||
set_if_used(add_command, config.skip_prompt, "skip-prompt");
|
||||
set_if_used(add_command, params.input_files, "files");
|
||||
}
|
||||
else if(program.is_subcommand_used(remove_command)){
|
||||
action = action_e::remove;
|
||||
package_titles = get_packages_from_parser(remove_command);
|
||||
set_if_used(remove_command, config.clean_temporary, "clean");
|
||||
set_if_used(remove_command, config.skip_prompt, "skip-prompt");
|
||||
set_if_used(remove_command, params.input_files, "file");
|
||||
}
|
||||
else if(program.is_subcommand_used(update_command)){
|
||||
action = action_e::update;
|
||||
package_titles = get_packages_from_parser(program);
|
||||
set_if_used(update_command, config.clean_temporary, "clean");
|
||||
set_if_used(update_command, params.remote_source, "remote");
|
||||
set_if_used(update_command, params.input_files, "file");
|
||||
}
|
||||
else if(program.is_subcommand_used(search_command)){
|
||||
action = action_e::search;
|
||||
package_titles = get_packages_from_parser(search_command);
|
||||
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");
|
||||
}
|
||||
else if(program.is_subcommand_used(export_command)){
|
||||
action = action_e::p_export;
|
||||
params.paths = export_command.get<string_list>("paths");
|
||||
}
|
||||
else if(program.is_subcommand_used(list_command)){
|
||||
action = action_e::list;
|
||||
// auto list = get_parser(program, "list");
|
||||
if(list_command.is_used("show"))
|
||||
params.args = list_command.get<string_list>("show");
|
||||
if(list_command.is_used("style")){
|
||||
string style = list_command.get<string>("style");
|
||||
if(!style.compare("list"))
|
||||
config.style = config::print_style::list;
|
||||
else if(!style.compare("table"))
|
||||
config.style = config::print_style::table;
|
||||
}
|
||||
);
|
||||
|
||||
// log::level = config.verbose;
|
||||
if(clipp::parse(argc, argv, cli)){
|
||||
log::level = config.verbose;
|
||||
switch(action){
|
||||
case action_e::install: package::install(config, package_titles, params); break;
|
||||
case action_e::add: package::add(config, package_titles);
|
||||
case action_e::remove: package::remove(config, package_titles, params); break;
|
||||
case action_e::update: package::update(config, package_titles, params); break;
|
||||
case action_e::search: package::search(config, package_titles, params); break;
|
||||
case action_e::p_export: package::export_to(params.args); break;
|
||||
case action_e::list: package::list(config, params); break;
|
||||
/* ...opts are the paths here */
|
||||
case action_e::link: package::link(config, package_titles, params); break;
|
||||
case action_e::clone: package::clone(config, package_titles, params); break;
|
||||
case action_e::clean: package::clean_temporary(config, package_titles); break;
|
||||
case action_e::config_get: config::print_properties(config, params.args); break;
|
||||
case action_e::config_set: config::handle_config(config, package_titles, params.opts); break;
|
||||
case action_e::fetch: package::synchronize_database(config, package_titles); break;
|
||||
case action_e::sync: package::synchronize_database(config, package_titles); break;
|
||||
case action_e::remote_list: remote::print_repositories(config); break;
|
||||
case action_e::remote_add: remote::add_repository(config, params.args); break;
|
||||
case action_e::remote_remove: remote::remove_respositories(config, params.args); break;
|
||||
case action_e::ui: log::println("UI not implemented yet"); break;
|
||||
case action_e::help: log::println("{}", man_page_format); break;
|
||||
case action_e::version: break;
|
||||
case action_e::none: /* ...here to run with no command */ break;
|
||||
}
|
||||
else if(program.is_subcommand_used(link_command)){
|
||||
action = action_e::link;
|
||||
package_titles = get_packages_from_parser(link_command);
|
||||
set_if_used(link_command, params.paths, "path");
|
||||
}
|
||||
else if(program.is_subcommand_used(clone_command)){
|
||||
action = action_e::clone;
|
||||
package_titles = get_packages_from_parser(clone_command);
|
||||
set_if_used(clone_command, params.paths, "path");
|
||||
}
|
||||
else if(program.is_subcommand_used(clean_command)){
|
||||
action = action_e::clean;
|
||||
package_titles = get_packages_from_parser(clean_command);
|
||||
}
|
||||
else if(program.is_subcommand_used(config_command)){
|
||||
if(config_command.is_subcommand_used(config_get)){
|
||||
action = action_e::config_get;
|
||||
if(config_get.is_used("properties"))
|
||||
params.args = config_get.get<string_list>("properties");
|
||||
}
|
||||
} else {
|
||||
log::println("usage:\n{}", usage_lines(cli, argv[0]).str());
|
||||
else if(config_command.is_subcommand_used(config_set)){
|
||||
action = action_e::config_set;
|
||||
if(config_set.is_used("property"))
|
||||
params.args.emplace_back(config_set.get<string>("property"));
|
||||
if(config_set.is_used("value"))
|
||||
params.args.emplace_back(config_set.get<string>("value"));
|
||||
}
|
||||
// else{
|
||||
// action = action_e::config_get;
|
||||
// }
|
||||
}
|
||||
else if(program.is_subcommand_used(fetch_command)){
|
||||
action = action_e::fetch;
|
||||
params.remote_source = fetch_command.get("remote");
|
||||
}
|
||||
else if(program.is_subcommand_used(version_command)){
|
||||
action = action_e::version;
|
||||
}
|
||||
else if(program.is_subcommand_used(remote_command)){
|
||||
if(remote_command.is_subcommand_used(remote_add)){
|
||||
action = action_e::remote_add;
|
||||
if(remote_add.is_used("name"))
|
||||
params.args.emplace_back(remote_add.get<string>("name"));
|
||||
if(remote_add.is_used("url"))
|
||||
params.args.emplace_back(remote_add.get<string>("url"));
|
||||
for(const auto& arg: params.args){
|
||||
log::println("{}: {}", params.args[0], params.args[1]);
|
||||
}
|
||||
}
|
||||
if(remote_command.is_subcommand_used(remote_remove)){
|
||||
action = action_e::remote_remove;
|
||||
if(remote_remove.is_used("names"))
|
||||
params.args = remote_remove.get<string_list>("names");
|
||||
}
|
||||
if(remote_command.is_subcommand_used(remote_list)){
|
||||
action = action_e::remote_list;
|
||||
string style = remote_list.get<string>("style");
|
||||
if(!style.compare("list"))
|
||||
config.style = config::print_style::list;
|
||||
else if(!style.compare("table"))
|
||||
config.style = config::print_style::table;
|
||||
}
|
||||
}
|
||||
else if(program.is_subcommand_used("ui")){
|
||||
action = action_e::ui;
|
||||
}
|
||||
else if(program.is_subcommand_used("help")){
|
||||
action = action_e::help;
|
||||
}
|
||||
|
||||
switch(action){
|
||||
case action_e::install: package::install(config, package_titles, params); break;
|
||||
case action_e::add: package::add(config, package_titles, params);
|
||||
case action_e::remove: package::remove(config, package_titles, params); break;
|
||||
case action_e::update: package::update(config, package_titles, params); break;
|
||||
case action_e::search: package::search(config, package_titles, params); break;
|
||||
case action_e::p_export: package::export_to(params.paths); break;
|
||||
case action_e::list: package::list(config, params); break;
|
||||
/* ...opts are the paths here */
|
||||
case action_e::link: package::link(config, package_titles, params); break;
|
||||
case action_e::clone: package::clone(config, package_titles, params); break;
|
||||
case action_e::clean: package::clean_temporary(config, package_titles); break;
|
||||
case action_e::config_get: config::print_properties(config, params.args); break;
|
||||
case action_e::config_set: config::set_property(config, params.args[0], params.args[1]); break;
|
||||
case action_e::fetch: package::synchronize_database(config, package_titles); break;
|
||||
case action_e::sync: package::synchronize_database(config, package_titles); break;
|
||||
case action_e::remote_list: remote::print_repositories(config); break;
|
||||
case action_e::remote_add: remote::add_repository(config, params.args); break;
|
||||
case action_e::remote_remove: remote::remove_respositories(config, params.args); break;
|
||||
case action_e::ui: log::println("UI not implemented"); break;
|
||||
case action_e::help: program.print_help(); break;
|
||||
case action_e::version: break;
|
||||
case action_e::none: program.usage(); break;/* ...here to run with no command */ break;
|
||||
}
|
||||
return error();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
|
||||
#include "remote.hpp"
|
||||
#include "config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "log.hpp"
|
||||
#include "types.hpp"
|
||||
#include <readline/readline.h>
|
||||
#include <tabulate/table.hpp>
|
||||
|
||||
namespace gdpm::remote{
|
||||
|
||||
|
|
@ -12,7 +14,7 @@ namespace gdpm::remote{
|
|||
const args_t &args
|
||||
){
|
||||
/* Check if enough args were provided. */
|
||||
log::debug("arg count: {}\nargs: {}", args.size(), utils::join(args));
|
||||
log::println("arg count: {}\nargs: {}", args.size(), utils::join(args));
|
||||
if (args.size() < 2){
|
||||
return error(
|
||||
constants::error::INVALID_ARG_COUNT,
|
||||
|
|
@ -31,7 +33,7 @@ namespace gdpm::remote{
|
|||
config::context& config,
|
||||
const args_t& args
|
||||
){
|
||||
log::debug("arg count: {}\nargs: {}", args.size(), utils::join(args));
|
||||
log::println("arg count: {}\nargs: {}", args.size(), utils::join(args));
|
||||
if(args.size() < 1){
|
||||
return error(
|
||||
constants::error::INVALID_ARG_COUNT,
|
||||
|
|
@ -61,8 +63,19 @@ namespace gdpm::remote{
|
|||
|
||||
void print_repositories(const config::context& config){
|
||||
const auto &rs = config.remote_sources;
|
||||
std::for_each(rs.begin(), rs.end(), [](const string_pair& p){
|
||||
log::println("{}: {}", p.first, p.second);
|
||||
});
|
||||
if(config.style == config::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){
|
||||
using namespace tabulate;
|
||||
Table table;
|
||||
table.add_row({"Name", "URL"});
|
||||
std::for_each(rs.begin(), rs.end(), [&table](const string_pair& p){
|
||||
table.add_row({p.first, p.second});
|
||||
});
|
||||
table.print(std::cout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,9 @@
|
|||
namespace gdpm::rest_api{
|
||||
|
||||
request_params make_from_config(const config::context& config){
|
||||
return config.rest_api_params;
|
||||
request_params rp = config.rest_api_params;
|
||||
rp.verbose = config.verbose;
|
||||
return rp;
|
||||
}
|
||||
|
||||
request_params make_request_params(
|
||||
|
|
@ -212,7 +214,7 @@ namespace gdpm::rest_api{
|
|||
http_params.headers.insert(http::header("Connection", "keep-alive"));
|
||||
string request_url = _prepare_request(url, c);
|
||||
http::response r = http.request_get(request_url, http_params);
|
||||
if(c.verbose > 0)
|
||||
if(c.verbose >= log::INFO)
|
||||
log::info("get_asset().URL: {}", request_url);
|
||||
return _parse_json(r.body, c.verbose);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ namespace gdpm::utils{
|
|||
int verbose
|
||||
){
|
||||
constexpr const char *prog = "gpdm";
|
||||
struct zip *za;
|
||||
struct zip *zip;
|
||||
struct zip_file *zf;
|
||||
struct zip_stat sb;
|
||||
char buf[100];
|
||||
|
|
@ -196,14 +196,14 @@ namespace gdpm::utils{
|
|||
|
||||
// log::info_n("Extracting package contents to '{}'...", dest);
|
||||
log::info_n("Extracting package contents...");
|
||||
if((za = zip_open(archive, 0, &err)) == nullptr){
|
||||
if((zip = zip_open(archive, 0, &err)) == nullptr){
|
||||
zip_error_to_str(buf, sizeof(buf), err, errno);
|
||||
log::error("{}: can't open zip archive {}: {}", prog, archive, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(i = 0; i < zip_get_num_entries(za, 0); i++){
|
||||
if(zip_stat_index(za, i, 0, &sb) == 0){
|
||||
for(i = 0; i < zip_get_num_entries(zip, 0); i++){
|
||||
if(zip_stat_index(zip, i, 0, &sb) == 0){
|
||||
len = strlen(sb.name);
|
||||
if(verbose > 1){
|
||||
log::print("{}, ", sb.name);
|
||||
|
|
@ -215,7 +215,7 @@ namespace gdpm::utils{
|
|||
// safe_create_dir(sb.name);
|
||||
std::filesystem::create_directory(path);
|
||||
} else {
|
||||
zf = zip_fopen_index(za, i, 0);
|
||||
zf = zip_fopen_index(zip, i, 0);
|
||||
if(!zf){
|
||||
log::error("extract_zip: zip_fopen_index() failed.");
|
||||
return 100;
|
||||
|
|
@ -248,7 +248,7 @@ namespace gdpm::utils{
|
|||
}
|
||||
}
|
||||
|
||||
if(zip_close(za) == -1){
|
||||
if(zip_close(zip) == -1){
|
||||
log::error("{}: can't close zip archive '{}'", prog, archive);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ TEST_SUITE("Command functions"){
|
|||
using namespace gdpm::package_manager;
|
||||
|
||||
package::params params = package::params{
|
||||
.remote_source = "test"
|
||||
.remote_source = "test",
|
||||
};
|
||||
config::context config = config::context{
|
||||
.username = "",
|
||||
|
|
@ -33,9 +33,10 @@ TEST_SUITE("Command functions"){
|
|||
.remote_sources = {
|
||||
{"test", "http://godotengine.org/asset-library/api"}
|
||||
},
|
||||
.skip_prompt = true,
|
||||
.info {
|
||||
.godot_version = "latest",
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
package::title_list package_titles{"ResolutionManagerPlugin","godot-hmac", "Godot"};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue