mirror of
https://github.com/davidallendj/gdpm.git
synced 2025-12-20 03:27:02 -07:00
Recfactored and simplified more code
- Added function to convert color string to ansi color string - Added `trim` and `join` utility functions - Added initial plugin test case - Implemented `config get` command to see config properties - Improved logging functionality and removed duplicate logging functions - Removed unused functions - Fixed more styling issues - Fixed some CLI commands not working correctly - Fixed CLI documentation format - Fixed some error handling issues
This commit is contained in:
parent
e48c54aa40
commit
02a4e879a8
21 changed files with 541 additions and 384 deletions
|
|
@ -50,7 +50,7 @@ The project uses the CMake or Meson build system and has been tested with GCC an
|
||||||
|
|
||||||
* doctest (optional; for tests, but still WIP)
|
* doctest (optional; for tests, but still WIP)
|
||||||
|
|
||||||
* cxxopts (header only)
|
* clipp (header only)
|
||||||
|
|
||||||
* SQLite 3
|
* SQLite 3
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "colors.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#if GDPM_ENABLE_COLORS == 1
|
#if GDPM_ENABLE_COLORS == 1
|
||||||
#define GDPM_COLOR_BLACK "\033[0;30m"
|
#define GDPM_COLOR_BLACK "\033[0;30m"
|
||||||
|
|
@ -16,24 +20,26 @@
|
||||||
#define GDPM_COLOR_LIGHT_PURPLE "\033[0;35m"
|
#define GDPM_COLOR_LIGHT_PURPLE "\033[0;35m"
|
||||||
#define GDPM_COLOR_YELLOW "\033[0;33m"
|
#define GDPM_COLOR_YELLOW "\033[0;33m"
|
||||||
#define GDPM_COLOR_WHITE "\033[0;37m"
|
#define GDPM_COLOR_WHITE "\033[0;37m"
|
||||||
|
#define GDPM_COLOR_RESET GDPM_COLOR_WHITE
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define GDPM_COLOR_BLACK
|
#define GDPM_COLOR_BLACK ""
|
||||||
#define GDPM_COLOR_BLUE
|
#define GDPM_COLOR_BLUE ""
|
||||||
#define GDPM_COLOR_GREEN
|
#define GDPM_COLOR_GREEN ""
|
||||||
#define GDPM_COLOR_CYAN
|
#define GDPM_COLOR_CYAN ""
|
||||||
#define GDPM_COLOR_RED
|
#define GDPM_COLOR_RED ""
|
||||||
#define GDPM_COLOR_PURPLE
|
#define GDPM_COLOR_PURPLE ""
|
||||||
#define GDPM_COLOR_BROWN
|
#define GDPM_COLOR_BROWN ""
|
||||||
#define GDPM_COLOR_GRAY
|
#define GDPM_COLOR_GRAY ""
|
||||||
#define GDPM_COLOR_DARK_GRAY
|
#define GDPM_COLOR_DARK_GRAY ""
|
||||||
#define GDPM_COLOR_LIGHT_BLUE
|
#define GDPM_COLOR_LIGHT_BLUE ""
|
||||||
#define GDPM_COLOR_LIGHT_GREEN
|
#define GDPM_COLOR_LIGHT_GREEN ""
|
||||||
#define GDPM_COLOR_LIGHT_CYAN
|
#define GDPM_COLOR_LIGHT_CYAN ""
|
||||||
#define GDPM_COLOR_LIGHT_RED
|
#define GDPM_COLOR_LIGHT_RED ""
|
||||||
#define GDPM_COLOR_LIGHT_PURPLE
|
#define GDPM_COLOR_LIGHT_PURPLE ""
|
||||||
#define GDPM_COLOR_YELLOW
|
#define GDPM_COLOR_YELLOW ""
|
||||||
#define GDPM_COLOR_WHITE
|
#define GDPM_COLOR_WHITE ""
|
||||||
|
#define GDPM_COLOR_RESET GDPM_COLOR_WHITE
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -43,3 +49,23 @@
|
||||||
#define GDPM_COLOR_LOG_ERROR GDPM_COLOR_RED
|
#define GDPM_COLOR_LOG_ERROR GDPM_COLOR_RED
|
||||||
#define GDPM_COLOR_LOG_DEBUG GDPM_COLOR_YELLOW
|
#define GDPM_COLOR_LOG_DEBUG GDPM_COLOR_YELLOW
|
||||||
#define GDPM_COLOR_LOG_WARNING GDPM_COLOR_YELLOW
|
#define GDPM_COLOR_LOG_WARNING GDPM_COLOR_YELLOW
|
||||||
|
|
||||||
|
namespace gdpm::color{
|
||||||
|
inline std::string from_string(const std::string& color_name){
|
||||||
|
if (color_name == "red"){ return GDPM_COLOR_RED; }
|
||||||
|
else if (color_name == "yellow"){ return GDPM_COLOR_YELLOW; }
|
||||||
|
else if (color_name == "green"){ return GDPM_COLOR_GREEN; }
|
||||||
|
else if (color_name == "blue"){ return GDPM_COLOR_BLUE; }
|
||||||
|
else if (color_name == "brown"){ return GDPM_COLOR_BROWN; }
|
||||||
|
else if (color_name == "gray"){ return GDPM_COLOR_GRAY; }
|
||||||
|
else if (color_name == "black"){ return GDPM_COLOR_BLACK; }
|
||||||
|
else if (color_name == "purple"){ return GDPM_COLOR_PURPLE; }
|
||||||
|
else if (color_name == "gray"){ return GDPM_COLOR_DARK_GRAY; }
|
||||||
|
else if (color_name == "light-blue"){ return GDPM_COLOR_LIGHT_BLUE; }
|
||||||
|
else if (color_name == "light-green"){ return GDPM_COLOR_LIGHT_GREEN; }
|
||||||
|
else if (color_name == "light-cyan"){ return GDPM_COLOR_LIGHT_CYAN; }
|
||||||
|
else if (color_name == "light-red"){ return GDPM_COLOR_LIGHT_RED; }
|
||||||
|
else if (color_name == "light-purple"){ return GDPM_COLOR_LIGHT_PURPLE; }
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,7 +43,8 @@ namespace gdpm::config{
|
||||||
error handle_config(config::context& config, const args_t& args, const var_opts& opts);
|
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);
|
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 validate(const rapidjson::Document& doc);
|
error validate(const rapidjson::Document& doc);
|
||||||
void print(const context& config);
|
void print_json(const context& config);
|
||||||
|
void print_properties(const context& config, const string_list& properties);
|
||||||
|
|
||||||
extern context config;
|
extern context config;
|
||||||
}
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ namespace gdpm::constants{
|
||||||
const std::string UserAgent("libcurl-agent/1.0 via GDPM (https://github.com/davidallendj/gdpm)");
|
const std::string UserAgent("libcurl-agent/1.0 via GDPM (https://github.com/davidallendj/gdpm)");
|
||||||
const std::string AssetRepo("https://godotengine.org/asset-library/api/asset");
|
const std::string AssetRepo("https://godotengine.org/asset-library/api/asset");
|
||||||
const std::string HostUrl("https://godotengine.org/asset-library/api");
|
const std::string HostUrl("https://godotengine.org/asset-library/api");
|
||||||
|
constexpr std::string WHITESPACE = " \n\r\t\f\v";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define default macros to set when building with -DGPM_* */
|
/* Define default macros to set when building with -DGPM_* */
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,10 @@ namespace gdpm::constants::error{
|
||||||
INVALID_ARG_COUNT,
|
INVALID_ARG_COUNT,
|
||||||
INVALID_CONFIG,
|
INVALID_CONFIG,
|
||||||
INVALID_KEY,
|
INVALID_KEY,
|
||||||
HTTP_RESPONSE_ERROR,
|
HTTP_RESPONSE_ERR,
|
||||||
STD_ERROR
|
SQLITE_ERR,
|
||||||
|
JSON_ERR,
|
||||||
|
STD_ERR
|
||||||
};
|
};
|
||||||
|
|
||||||
const string_list messages {
|
const string_list messages {
|
||||||
|
|
|
||||||
143
include/log.hpp
143
include/log.hpp
|
|
@ -1,10 +1,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "clipp.h"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include "colors.hpp"
|
#include "colors.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include <format>
|
#include <format>
|
||||||
|
#include <bitset>
|
||||||
// #include <fmt/core.h>
|
// #include <fmt/core.h>
|
||||||
|
|
||||||
#if __cplusplus > 201703L
|
#if __cplusplus > 201703L
|
||||||
|
|
@ -21,22 +23,51 @@ TODO: Write log information to file
|
||||||
namespace gdpm::log
|
namespace gdpm::log
|
||||||
{
|
{
|
||||||
|
|
||||||
enum level{
|
enum level_e : int{
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
INFO,
|
INFO = 1,
|
||||||
WARNING,
|
WARNING = 2,
|
||||||
DEBUG,
|
DEBUG = 3,
|
||||||
ERROR
|
ERROR = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
struct context {
|
enum flag_opt {
|
||||||
int level;
|
PRINT_STDOUT = 0b00000001,
|
||||||
string prefix;
|
PRINT_STDERR = 0b00000010
|
||||||
string path;
|
|
||||||
bool print_to_stdout;
|
|
||||||
bool print_to_stderr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int level = INFO;
|
||||||
|
static string prefix = "";
|
||||||
|
static string suffix = "";
|
||||||
|
static string path = "";
|
||||||
|
static std::bitset<8> flags = PRINT_STDOUT | PRINT_STDERR;
|
||||||
|
static bool print_to_stdout;
|
||||||
|
static bool print_to_stderr;
|
||||||
|
|
||||||
|
inline constexpr level_e to_level(int l){
|
||||||
|
return static_cast<level_e>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr int to_int(const level_e& l){
|
||||||
|
return static_cast<int>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void set_flag(uint8_t flag, bool value){
|
||||||
|
(value) ? flags.set(flag) : flags.reset(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool get_flag(uint8_t flag){
|
||||||
|
return flags.test(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void set_prefix_if(const std::string& v, bool predicate = !prefix.empty()){
|
||||||
|
prefix = (predicate) ? v : prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void set_suffix_if(const std::string& v, bool predicate = !suffix.empty()){
|
||||||
|
suffix = (predicate) ? v : suffix;
|
||||||
|
}
|
||||||
|
|
||||||
static void vlog(fmt::string_view format, fmt::format_args args){
|
static void vlog(fmt::string_view format, fmt::format_args args){
|
||||||
fmt::vprint(format, args);
|
fmt::vprint(format, args);
|
||||||
}
|
}
|
||||||
|
|
@ -47,30 +78,13 @@ namespace gdpm::log
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
template <typename S, typename...Args>
|
||||||
static constexpr void info(const S& format, Args&&...args){
|
static constexpr void info(const S& format, Args&&...args){
|
||||||
|
if(log::level < to_int(log::INFO))
|
||||||
|
return;
|
||||||
#if GDPM_LOG_LEVEL > NONE
|
#if GDPM_LOG_LEVEL > NONE
|
||||||
|
set_prefix_if(fmt::format("[INFO {}] ", utils::timestamp()));
|
||||||
|
set_suffix_if("\n");
|
||||||
vlog(
|
vlog(
|
||||||
fmt::format(GDPM_COLOR_LOG_INFO "[INFO {}] {}\n" GDPM_COLOR_LOG_RESET, utils::timestamp(), format),
|
fmt::format(GDPM_COLOR_LOG_INFO "{}{}{}" GDPM_COLOR_LOG_RESET, prefix, format, suffix),
|
||||||
// fmt::make_format_args<Args...>(args...)
|
|
||||||
fmt::make_format_args(args...)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
|
||||||
static constexpr void info(const S& prefix, const S& format, Args&&...args){
|
|
||||||
#if GDPM_LOG_LEVEL > INFO
|
|
||||||
vlog(
|
|
||||||
fmt::format(GDPM_COLOR_LOG_INFO + prefix + GDPM_COLOR_LOG_RESET, format),
|
|
||||||
fmt::make_format_args(args...)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
|
||||||
static constexpr void info(const context& context, const S& format, Args&&...args){
|
|
||||||
#if GDPM_LOG_LEVEL > INFO
|
|
||||||
vlog(
|
|
||||||
fmt::format(GDPM_COLOR_LOG_INFO + context.prefix + GDPM_COLOR_LOG_RESET, format),
|
|
||||||
fmt::make_format_args(args...)
|
fmt::make_format_args(args...)
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -78,10 +92,13 @@ namespace gdpm::log
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
template <typename S, typename...Args>
|
||||||
static constexpr void info_n(const S& format, Args&&...args){
|
static constexpr void info_n(const S& format, Args&&...args){
|
||||||
|
if(log::level < to_int(log::INFO))
|
||||||
|
return;
|
||||||
#if GDPM_LOG_LEVEL > INFO
|
#if GDPM_LOG_LEVEL > INFO
|
||||||
|
set_prefix_if(fmt::format("[INFO {}] ", utils::timestamp()));
|
||||||
|
set_suffix_if("");
|
||||||
vlog(
|
vlog(
|
||||||
fmt::format(GDPM_COLOR_LOG_INFO "[INFO {}] {}" GDPM_COLOR_LOG_RESET, utils::timestamp(), format),
|
fmt::format(GDPM_COLOR_LOG_INFO "{}{}{}" GDPM_COLOR_LOG_RESET, prefix, format, suffix),
|
||||||
// fmt::make_format_args<Args...>(args...)
|
|
||||||
fmt::make_format_args(args...)
|
fmt::make_format_args(args...)
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -89,30 +106,13 @@ namespace gdpm::log
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
template <typename S, typename...Args>
|
||||||
static constexpr void error(const S& format, Args&&...args){
|
static constexpr void error(const S& format, Args&&...args){
|
||||||
|
if(log::level < to_int(log::ERROR))
|
||||||
|
return;
|
||||||
#if GDPM_LOG_LEVEL > ERROR
|
#if GDPM_LOG_LEVEL > ERROR
|
||||||
|
set_prefix_if(std::format("[ERROR {}] ", utils::timestamp()));
|
||||||
|
set_suffix_if("\n");
|
||||||
vlog(
|
vlog(
|
||||||
fmt::format(GDPM_COLOR_LOG_ERROR "[ERROR {}] {}\n" GDPM_COLOR_LOG_RESET, utils::timestamp(), format),
|
fmt::format(GDPM_COLOR_LOG_ERROR "{}{}{}" GDPM_COLOR_LOG_RESET, prefix, format, suffix),
|
||||||
// fmt::make_format_args<Args...>(args...)
|
|
||||||
fmt::make_format_args(args...)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
|
||||||
static constexpr void error(const S& prefix, const S& format, Args&&...args){
|
|
||||||
#if GDPM_LOG_LEVEL > ERROR
|
|
||||||
vlog(
|
|
||||||
fmt::format(GDPM_COLOR_LOG_ERROR + prefix + GDPM_COLOR_LOG_RESET, format),
|
|
||||||
fmt::make_format_args(args...)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
|
||||||
static constexpr void error(const context& context, const S& format, Args&&...args){
|
|
||||||
#if GDPM_LOG_LEVEL > ERROR
|
|
||||||
vlog(
|
|
||||||
fmt::format(GDPM_COLOR_LOG_ERROR + context.prefix + GDPM_COLOR_LOG_RESET, format),
|
|
||||||
fmt::make_format_args(args...)
|
fmt::make_format_args(args...)
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -120,30 +120,13 @@ namespace gdpm::log
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
template <typename S, typename...Args>
|
||||||
static constexpr void debug(const S& format, Args&&...args){
|
static constexpr void debug(const S& format, Args&&...args){
|
||||||
|
if(log::level < to_int(log::DEBUG))
|
||||||
|
return;
|
||||||
#if GDPM_LOG_LEVEL > DEBUG
|
#if GDPM_LOG_LEVEL > DEBUG
|
||||||
|
set_prefix_if(std::format("[DEBUG {}] ", utils::timestamp()));
|
||||||
|
set_suffix_if("\n");
|
||||||
vlog(
|
vlog(
|
||||||
fmt::format(GDPM_COLOR_LOG_DEBUG "[DEBUG {}] {}\n" GDPM_COLOR_LOG_RESET, utils::timestamp(), format),
|
fmt::format(GDPM_COLOR_LOG_DEBUG "{}{}{}" GDPM_COLOR_LOG_RESET, prefix, format, suffix),
|
||||||
// fmt::make_format_args<Args...>(args...)
|
|
||||||
fmt::make_format_args(args...)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
|
||||||
static constexpr void debug(const S& prefix, const S& format, Args&&...args){
|
|
||||||
#if GDPM_LOG_LEVEL > DEBUG
|
|
||||||
vlog(
|
|
||||||
fmt::format(GDPM_COLOR_LOG_DEBUG + prefix + GDPM_COLOR_LOG_RESET, format),
|
|
||||||
fmt::make_format_args(args...)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename...Args>
|
|
||||||
static constexpr void debug(const context& context, const S& format, Args&&...args){
|
|
||||||
#if GDPM_LOG_LEVEL > DEBUG
|
|
||||||
vlog(
|
|
||||||
fmt::format(GDPM_COLOR_LOG_DEBUG + context.prefix + GDPM_COLOR_LOG_RESET, format),
|
|
||||||
fmt::make_format_args(args...)
|
fmt::make_format_args(args...)
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -153,7 +136,6 @@ namespace gdpm::log
|
||||||
static constexpr void print(const S& format, Args&&...args){
|
static constexpr void print(const S& format, Args&&...args){
|
||||||
vlog(
|
vlog(
|
||||||
fmt::format("{}", format),
|
fmt::format("{}", format),
|
||||||
// fmt::make_format_args<Args...>(args...)
|
|
||||||
fmt::make_format_args(args...)
|
fmt::make_format_args(args...)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +144,6 @@ namespace gdpm::log
|
||||||
static constexpr void println(const S& format, Args&&...args){
|
static constexpr void println(const S& format, Args&&...args){
|
||||||
vlog(
|
vlog(
|
||||||
fmt::format("{}\n", format),
|
fmt::format("{}\n", format),
|
||||||
// fmt::make_format_args<Args...>(args...)
|
|
||||||
fmt::make_format_args(args...)
|
fmt::make_format_args(args...)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "rest_api.hpp"
|
#include "rest_api.hpp"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
|
|
@ -48,7 +49,7 @@ namespace gdpm::package {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct params {
|
struct params {
|
||||||
args_t sub_commands;
|
args_t args;
|
||||||
var_opts opts;
|
var_opts opts;
|
||||||
string_list paths;
|
string_list paths;
|
||||||
string_list input_files;
|
string_list input_files;
|
||||||
|
|
@ -61,6 +62,7 @@ namespace gdpm::package {
|
||||||
using id_list = std::vector<size_t>;
|
using id_list = std::vector<size_t>;
|
||||||
using path = std::string;
|
using path = std::string;
|
||||||
using path_list = std::vector<path>;
|
using path_list = std::vector<path>;
|
||||||
|
using path_refs = std::vector<std::reference_wrapper<const path>>;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Install a Godot package from the Asset Library in the current project.
|
@brief Install a Godot package from the Asset Library in the current project.
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
namespace gdpm::package_manager {
|
namespace gdpm::package_manager {
|
||||||
extern remote::repository_map remote_sources;
|
|
||||||
extern CURL *curl;
|
extern CURL *curl;
|
||||||
extern CURLcode res;
|
extern CURLcode res;
|
||||||
extern config::context config;
|
extern config::context config;
|
||||||
|
|
@ -32,10 +31,13 @@ namespace gdpm::package_manager {
|
||||||
link,
|
link,
|
||||||
clone,
|
clone,
|
||||||
clean,
|
clean,
|
||||||
config,
|
config_get,
|
||||||
|
config_set,
|
||||||
fetch,
|
fetch,
|
||||||
sync,
|
sync,
|
||||||
remote,
|
remote_add,
|
||||||
|
remote_remove,
|
||||||
|
remote_list,
|
||||||
ui,
|
ui,
|
||||||
help,
|
help,
|
||||||
none
|
none
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace gdpm::plugin{
|
namespace gdpm::plugin{
|
||||||
struct info{
|
struct info{
|
||||||
|
|
@ -8,9 +9,11 @@ namespace gdpm::plugin{
|
||||||
string description;
|
string description;
|
||||||
string version;
|
string version;
|
||||||
};
|
};
|
||||||
extern int init(int argc, char **argv);
|
extern error initialize(int argc, char **argv);
|
||||||
extern int set_name(const char *name);
|
extern error set_name(const char *name);
|
||||||
extern int set_description(const char *description);
|
extern error set_description(const char *description);
|
||||||
extern int set_version(const char *version);
|
extern error set_version(const char *version);
|
||||||
extern int finalize();
|
extern error finalize();
|
||||||
|
|
||||||
|
error load(std::filesystem::path path);
|
||||||
}
|
}
|
||||||
|
|
@ -8,14 +8,8 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
namespace gdpm::remote{
|
namespace gdpm::remote{
|
||||||
using repo_names = string_list;
|
GDPM_DLL_EXPORT error add_repository(config::context& config, const args_t& args);
|
||||||
using repo_urls = string_list;
|
GDPM_DLL_EXPORT error remove_respositories(config::context& config, const args_t& names);
|
||||||
using repository_map = string_map;
|
GDPM_DLL_EXPORT void move_repository(config::context& config, int old_position, int new_position);
|
||||||
|
GDPM_DLL_EXPORT void print_repositories(const config::context& config);
|
||||||
GDPM_DLL_EXPORT error handle_remote(config::context& config, const args_t& args, const var_opts& opts);
|
|
||||||
GDPM_DLL_EXPORT void set_repositories(config::context& context, const repository_map& repos);
|
|
||||||
GDPM_DLL_EXPORT void add_repositories(config::context& context, const repository_map& repos);
|
|
||||||
GDPM_DLL_EXPORT void remove_respositories(config::context& context, const repo_names& names);
|
|
||||||
GDPM_DLL_EXPORT void move_repository(config::context& context, int old_position, int new_position);
|
|
||||||
GDPM_DLL_EXPORT void print_repositories(const config::context& context);
|
|
||||||
}
|
}
|
||||||
|
|
@ -101,5 +101,4 @@ namespace gdpm{
|
||||||
default: /*return*/ target = 0;
|
default: /*return*/ target = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +96,12 @@ namespace gdpm::utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string readfile(const std::string& path);
|
std::string readfile(const std::string& path);
|
||||||
void to_lower(std::string& s);
|
std::string to_lower(const std::string& s);
|
||||||
|
std::string trim(const std::string& s);
|
||||||
|
std::string trim_left(const std::string& s);
|
||||||
|
std::string trim_left(const std::string& s, const std::string& ref);
|
||||||
|
std::string trim_right(const std::string& s);
|
||||||
|
std::string trim_right(const std::string& s, const std::string& ref);
|
||||||
std::vector<std::string> parse_lines(const std::string& s);
|
std::vector<std::string> parse_lines(const std::string& s);
|
||||||
std::string replace_first(std::string& s, const std::string& from, const std::string& to);
|
std::string replace_first(std::string& s, const std::string& from, const std::string& to);
|
||||||
std::string replace_all(std::string& s, const std::string& from, const std::string& to);
|
std::string replace_all(std::string& s, const std::string& from, const std::string& to);
|
||||||
|
|
@ -105,7 +110,7 @@ namespace gdpm::utils {
|
||||||
bool prompt_user_yn(const char *message);
|
bool prompt_user_yn(const char *message);
|
||||||
void delay(std::chrono::milliseconds milliseconds = GDPM_REQUEST_DELAY);
|
void delay(std::chrono::milliseconds milliseconds = GDPM_REQUEST_DELAY);
|
||||||
std::string join(const std::vector<std::string>& target, const std::string& delimiter = ", ");
|
std::string join(const std::vector<std::string>& target, const std::string& delimiter = ", ");
|
||||||
|
std::string join(const std::unordered_map<std::string, std::string>& target, const std::string& prefix = "", const std::string& delimiter = "\n");
|
||||||
// TODO: Add function to get size of decompressed zip
|
// TODO: Add function to get size of decompressed zip
|
||||||
|
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
#include "cache.hpp"
|
#include "cache.hpp"
|
||||||
|
#include "error.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "package.hpp"
|
#include "package.hpp"
|
||||||
|
|
@ -12,7 +13,10 @@
|
||||||
|
|
||||||
|
|
||||||
namespace gdpm::cache{
|
namespace gdpm::cache{
|
||||||
error create_package_database(bool overwrite, const params& params){
|
error create_package_database(
|
||||||
|
bool overwrite,
|
||||||
|
const params& params
|
||||||
|
){
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
char *errmsg;
|
char *errmsg;
|
||||||
|
|
@ -77,7 +81,10 @@ namespace gdpm::cache{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error insert_package_info(const package::info_list& packages, const params& params){
|
error insert_package_info(
|
||||||
|
const package::info_list& packages,
|
||||||
|
const params& params
|
||||||
|
){
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
char *errmsg = nullptr;
|
char *errmsg = nullptr;
|
||||||
|
|
@ -115,7 +122,10 @@ namespace gdpm::cache{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result_t<package::info_list> get_package_info_by_id(const package::id_list& package_ids, const params& params){
|
result_t<package::info_list> get_package_info_by_id(
|
||||||
|
const package::id_list& package_ids,
|
||||||
|
const params& params
|
||||||
|
){
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
char *errmsg = nullptr;
|
char *errmsg = nullptr;
|
||||||
|
|
@ -179,7 +189,10 @@ namespace gdpm::cache{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result_t<package::info_list> get_package_info_by_title(const package::title_list& package_titles, const params& params){
|
result_t<package::info_list> get_package_info_by_title(
|
||||||
|
const package::title_list& package_titles,
|
||||||
|
const params& params
|
||||||
|
){
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
char *errmsg = nullptr;
|
char *errmsg = nullptr;
|
||||||
|
|
@ -306,17 +319,20 @@ namespace gdpm::cache{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error update_package_info(const package::info_list& packages, const params& params){
|
error update_package_info(
|
||||||
|
const package::info_list& packages,
|
||||||
|
const params& params
|
||||||
|
){
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
char *errmsg = nullptr;
|
char *errmsg = nullptr;
|
||||||
|
|
||||||
int rc = sqlite3_open(params.cache_path.c_str(), &db);
|
int rc = sqlite3_open(params.cache_path.c_str(), &db);
|
||||||
if(rc != SQLITE_OK){
|
if(rc != SQLITE_OK){
|
||||||
error error(rc, std::format(
|
error error(
|
||||||
|
constants::error::SQLITE_ERR, std::format(
|
||||||
"update_package_info.sqlite3_open(): {}", sqlite3_errmsg(db)
|
"update_package_info.sqlite3_open(): {}", sqlite3_errmsg(db)
|
||||||
));
|
));
|
||||||
log::error(error);
|
|
||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
@ -360,7 +376,10 @@ namespace gdpm::cache{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error delete_packages(const package::title_list& package_titles, const params& params){
|
error delete_packages(
|
||||||
|
const package::title_list& package_titles,
|
||||||
|
const params& params
|
||||||
|
){
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
char *errmsg = nullptr;
|
char *errmsg = nullptr;
|
||||||
|
|
@ -395,7 +414,10 @@ namespace gdpm::cache{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error delete_packages(const package::id_list& package_ids, const params& params){
|
error delete_packages(
|
||||||
|
const package::id_list& package_ids,
|
||||||
|
const params& params
|
||||||
|
){
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
char *errmsg = nullptr;
|
char *errmsg = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ namespace gdpm::config{
|
||||||
const context& config,
|
const context& config,
|
||||||
bool pretty_print
|
bool pretty_print
|
||||||
){
|
){
|
||||||
|
|
||||||
|
|
||||||
/* Build a JSON string to pass to document */
|
/* Build a JSON string to pass to document */
|
||||||
string prefix = (pretty_print) ? "\n\t" : "";
|
string prefix = (pretty_print) ? "\n\t" : "";
|
||||||
string spaces = (pretty_print) ? " " : "";
|
string spaces = (pretty_print) ? " " : "";
|
||||||
|
|
@ -232,6 +230,7 @@ namespace gdpm::config{
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
context make_context(
|
context make_context(
|
||||||
const string& username,
|
const string& username,
|
||||||
const string& password,
|
const string& password,
|
||||||
|
|
@ -286,8 +285,60 @@ namespace gdpm::config{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(const context& config){
|
void print_json(const context& config){
|
||||||
log::println("{}", to_json(config, true));
|
log::println("{}", to_json(config, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _print_property(
|
||||||
|
const context& config,
|
||||||
|
const string& property
|
||||||
|
){
|
||||||
|
if(property.empty()) return;
|
||||||
|
else if(property == "username") log::println("username: {}", config.username);
|
||||||
|
else if(property == "password") log::println("password: {}", config.password);
|
||||||
|
else if(property == "path") log::println("path: {}", config.path);
|
||||||
|
else if(property == "token") log::println("token: {}", config.token);
|
||||||
|
else if(property == "packages_dir") log::println("package directory: {}", config.packages_dir);
|
||||||
|
else if(property == "tmp_dir") log::println("temporary directory: {}", config.tmp_dir);
|
||||||
|
else if(property == "remote_sources") log::println("remote sources: \n{}", utils::join(config.remote_sources, "\t", "\n"));
|
||||||
|
else if(property == "jobs") log::println("parallel jobs: {}", config.jobs);
|
||||||
|
else if(property == "timeout") log::println("timeout: {}", config.timeout);
|
||||||
|
else if(property == "sync") log::println("enable sync: {}", config.enable_sync);
|
||||||
|
else if(property == "cache") log::println("enable cache: {}", config.enable_cache);
|
||||||
|
else if(property == "prompt") log::println("skip prompt: {}", config.skip_prompt);
|
||||||
|
else if(property == "logging") log::println("enable file logging: {}", config.enable_file_logging);
|
||||||
|
else if(property == "clean") log::println("clean temporary files: {}", config.clean_temporary);
|
||||||
|
else if(property == "verbose") log::println("verbose: {}", 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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "package_manager.hpp"
|
#include "package_manager.hpp"
|
||||||
#include "result.hpp"
|
#include "result.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
|
|
@ -14,5 +15,6 @@ int main(int argc, char **argv){
|
||||||
error error = initialize(argc, argv);
|
error error = initialize(argc, argv);
|
||||||
parse_arguments(argc, argv);
|
parse_arguments(argc, argv);
|
||||||
finalize();
|
finalize();
|
||||||
return 0;
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
116
src/package.cpp
116
src/package.cpp
|
|
@ -8,6 +8,8 @@
|
||||||
#include "http.hpp"
|
#include "http.hpp"
|
||||||
#include "remote.hpp"
|
#include "remote.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
#include <functional>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <rapidjson/ostreamwrapper.h>
|
#include <rapidjson/ostreamwrapper.h>
|
||||||
#include <rapidjson/prettywriter.h>
|
#include <rapidjson/prettywriter.h>
|
||||||
|
|
@ -31,6 +33,7 @@ namespace gdpm::package{
|
||||||
2. Check if the package is installed. If it is, make sure it is latest version.
|
2. Check if the package is installed. If it is, make sure it is latest version.
|
||||||
If not, download and update to the latest version.
|
If not, download and update to the latest version.
|
||||||
3. Extract package contents and copy/move to the correct install location.
|
3. Extract package contents and copy/move to the correct install location.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
result_t result = cache::get_package_info_by_title(package_titles);
|
result_t result = cache::get_package_info_by_title(package_titles);
|
||||||
|
|
@ -167,7 +170,7 @@ namespace gdpm::package{
|
||||||
log::println("Done.");
|
log::println("Done.");
|
||||||
}else{
|
}else{
|
||||||
error error(
|
error error(
|
||||||
constants::error::HTTP_RESPONSE_ERROR,
|
constants::error::HTTP_RESPONSE_ERR,
|
||||||
std::format("HTTP Error: {}", response.code)
|
std::format("HTTP Error: {}", response.code)
|
||||||
);
|
);
|
||||||
log::error(error);
|
log::error(error);
|
||||||
|
|
@ -186,7 +189,12 @@ namespace gdpm::package{
|
||||||
|
|
||||||
/* Update the cache data with information from */
|
/* Update the cache data with information from */
|
||||||
log::info_n("Updating local asset data...");
|
log::info_n("Updating local asset data...");
|
||||||
cache::update_package_info(p_found);
|
error error = cache::update_package_info(p_found);
|
||||||
|
if(error()){
|
||||||
|
log::error(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
log::println("done.");
|
log::println("done.");
|
||||||
// })
|
// })
|
||||||
// );
|
// );
|
||||||
|
|
@ -201,7 +209,8 @@ namespace gdpm::package{
|
||||||
const title_list& package_titles,
|
const title_list& package_titles,
|
||||||
const params& params
|
const params& params
|
||||||
){
|
){
|
||||||
|
/* Install packages in local project instead of package database.
|
||||||
|
This will not cache the package information in the cache database. */
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,7 +298,13 @@ namespace gdpm::package{
|
||||||
}
|
}
|
||||||
log::println("Done.");
|
log::println("Done.");
|
||||||
log::info_n("Updating local asset data...");
|
log::info_n("Updating local asset data...");
|
||||||
cache::update_package_info(p_cache);
|
{
|
||||||
|
error error = cache::update_package_info(p_cache);
|
||||||
|
if(error.has_occurred()){
|
||||||
|
log::error(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
log::println("done.");
|
log::println("done.");
|
||||||
|
|
||||||
return error();
|
return error();
|
||||||
|
|
@ -402,7 +417,7 @@ namespace gdpm::package{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info("{} package(s) found...", doc["total_items"].GetInt());
|
// log::info("{} package(s) found...", doc["total_items"].GetInt());
|
||||||
print_list(doc);
|
print_list(doc);
|
||||||
}
|
}
|
||||||
return error();
|
return error();
|
||||||
|
|
@ -416,16 +431,13 @@ namespace gdpm::package{
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
string show((!params.sub_commands.empty()) ? params.sub_commands[0] : "");
|
string show((!params.args.empty()) ? params.args[0] : "");
|
||||||
if(show.empty() || show == "packages"){
|
if(show.empty() || show == "packages"){
|
||||||
result_t r_installed = cache::get_installed_packages();
|
result_t r_installed = cache::get_installed_packages();
|
||||||
info_list p_installed = r_installed.unwrap_unsafe();
|
info_list p_installed = r_installed.unwrap_unsafe();
|
||||||
if(!p_installed.empty()){
|
if(!p_installed.empty()){
|
||||||
print_list(p_installed);
|
print_list(p_installed);
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
log::println("empty");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(show == "remote"){
|
else if(show == "remote"){
|
||||||
remote::print_repositories(config);
|
remote::print_repositories(config);
|
||||||
|
|
@ -476,30 +488,27 @@ namespace gdpm::package{
|
||||||
error link(
|
error link(
|
||||||
const config::context& config,
|
const config::context& config,
|
||||||
const title_list& package_titles,
|
const title_list& package_titles,
|
||||||
const package::params& params
|
const package::params& params /* path is last arg */
|
||||||
){
|
){
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
path_list paths = {};
|
if(params.args.empty()){
|
||||||
if(params.opts.contains("path")){
|
|
||||||
paths = get<path_list>(params.opts.at("path"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(paths.empty()){
|
|
||||||
error error(
|
error error(
|
||||||
constants::error::PATH_NOT_DEFINED,
|
constants::error::INVALID_ARG_COUNT,
|
||||||
"No path set. Use '--path' option to set a path."
|
"Must supply at least 2 arguments (package name and path)"
|
||||||
);
|
);
|
||||||
log::error(error);
|
log::error(error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for packages in cache to link */
|
||||||
result_t r_cache = cache::get_package_info_by_title(package_titles);
|
result_t r_cache = cache::get_package_info_by_title(package_titles);
|
||||||
info_list p_found = {};
|
info_list p_found = {};
|
||||||
info_list p_cache = r_cache.unwrap_unsafe();
|
info_list p_cache = r_cache.unwrap_unsafe();
|
||||||
if(p_cache.empty()){
|
if(p_cache.empty()){
|
||||||
error error(
|
error error(
|
||||||
constants::error::NOT_FOUND,
|
constants::error::NOT_FOUND,
|
||||||
"Could not find any packages to link."
|
"Could not find any packages to link in cache."
|
||||||
);
|
);
|
||||||
log::error(error);
|
log::error(error);
|
||||||
return error;
|
return error;
|
||||||
|
|
@ -522,20 +531,22 @@ namespace gdpm::package{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the storage paths for all packages to create symlinks */
|
/* 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};
|
const path package_dir{config.packages_dir};
|
||||||
for(const auto& p : p_found){
|
for(const auto& p : p_found){
|
||||||
for(const auto& path : paths){
|
for(const auto& path : paths){
|
||||||
log::info_n("Creating symlink for \"{}\" package to '{}'...", p.title, path + "/" + p.title);
|
const string _path = path;
|
||||||
|
log::info_n("link: \"{}\" -> '{}'...", p.title, _path + "/" + p.title);
|
||||||
// std::filesystem::path target{config.packages_dir + "/" + 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 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()))
|
if(!std::filesystem::exists(symlink_path.string()))
|
||||||
std::filesystem::create_directories(path + "/");
|
std::filesystem::create_directories(_path + "/");
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
std::filesystem::create_directory_symlink(target, symlink_path, ec);
|
std::filesystem::create_directory_symlink(target, symlink_path, ec);
|
||||||
if(ec){
|
if(ec){
|
||||||
error error(
|
error error(
|
||||||
constants::error::STD_ERROR,
|
constants::error::STD_ERR,
|
||||||
std::format("Could not create symlink: {}", ec.message())
|
std::format("Could not create symlink: {}", ec.message())
|
||||||
);
|
);
|
||||||
log::error(error);
|
log::error(error);
|
||||||
|
|
@ -554,10 +565,10 @@ namespace gdpm::package{
|
||||||
){
|
){
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
if(params.opts.empty()){
|
if(params.args.empty()){
|
||||||
error error(
|
error error(
|
||||||
constants::error::PATH_NOT_DEFINED,
|
constants::error::INVALID_ARG_COUNT,
|
||||||
"No path set. Use '--path' option to set a path."
|
"Must supply at least 2 arguments (package name and path)"
|
||||||
);
|
);
|
||||||
log::error(error);
|
log::error(error);
|
||||||
return error;
|
return error;
|
||||||
|
|
@ -566,17 +577,24 @@ namespace gdpm::package{
|
||||||
result_t r_cache = cache::get_package_info_by_title(package_titles);
|
result_t r_cache = cache::get_package_info_by_title(package_titles);
|
||||||
package::info_list p_found = {};
|
package::info_list p_found = {};
|
||||||
package::info_list p_cache = r_cache.unwrap_unsafe();
|
package::info_list p_cache = r_cache.unwrap_unsafe();
|
||||||
|
|
||||||
|
/* Check for installed packages to clone */
|
||||||
if(p_cache.empty()){
|
if(p_cache.empty()){
|
||||||
error error(
|
error error(
|
||||||
constants::error::NO_PACKAGE_FOUND,
|
constants::error::NO_PACKAGE_FOUND,
|
||||||
"Could not find any packages to clone."
|
"Could not find any packages to clone in cache."
|
||||||
);
|
);
|
||||||
log::error(error);
|
log::error(error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const auto& p_title : package_titles){
|
for(const auto& p_title : package_titles){
|
||||||
auto found = std::find_if(p_cache.begin(), p_cache.end(), [&p_title](const package::info& p){ return p.title == p_title; });
|
auto found = std::find_if(
|
||||||
|
p_cache.begin(),
|
||||||
|
p_cache.end(),
|
||||||
|
[&p_title](const package::info& p){
|
||||||
|
return p.title == p_title;
|
||||||
|
});
|
||||||
if(found != p_cache.end()){
|
if(found != p_cache.end()){
|
||||||
p_found.emplace_back(*found);
|
p_found.emplace_back(*found);
|
||||||
}
|
}
|
||||||
|
|
@ -592,15 +610,17 @@ namespace gdpm::package{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the storage paths for all packages to create clones */
|
/* Get the storage paths for all packages to create clones */
|
||||||
path_list paths = get<path_list>(params.opts.at("--path"));
|
path_refs paths = path_refs{params.args.back()};
|
||||||
|
// path_list paths = path_list({params.args.back()});
|
||||||
const path package_dir{config.packages_dir};
|
const path package_dir{config.packages_dir};
|
||||||
for(const auto& p : p_found){
|
for(const auto& p : p_found){
|
||||||
for(const auto& path : paths){
|
for(const auto& path : paths){
|
||||||
log::info("Cloning \"{}\" package to {}", p.title, path + "/" + p.title);
|
const string _path = string(path);
|
||||||
|
log::info("clone: \"{}\" -> {}", p.title, _path + "/" + p.title);
|
||||||
std::filesystem::path from{config.packages_dir + "/" + p.title};
|
std::filesystem::path from{config.packages_dir + "/" + p.title};
|
||||||
std::filesystem::path to{path + "/" + p.title};
|
std::filesystem::path to{_path + "/" + p.title};
|
||||||
if(!std::filesystem::exists(to.string()))
|
if(!std::filesystem::exists(to.string()))
|
||||||
std::filesystem::create_directories(to);
|
std::filesystem::create_directories(to); /* This should only occur if using a --force flag */
|
||||||
|
|
||||||
/* TODO: Add an option to force overwriting (i.e. --overwrite) */
|
/* TODO: Add an option to force overwriting (i.e. --overwrite) */
|
||||||
std::filesystem::copy(from, to, copy_options::update_existing | copy_options::recursive);
|
std::filesystem::copy(from, to, copy_options::update_existing | copy_options::recursive);
|
||||||
|
|
@ -609,19 +629,23 @@ namespace gdpm::package{
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void print_list(const info_list& packages){
|
void print_list(const info_list& packages){
|
||||||
for(const auto& p : packages){
|
for(const auto& p : packages){
|
||||||
log::println("{}/{}/{} {} id={}\n\tGodot {}, {}, {}, Last Modified: {}",
|
log::println(
|
||||||
|
GDPM_COLOR_BLUE"{}/"
|
||||||
|
GDPM_COLOR_RESET "{}/{}/{} "
|
||||||
|
GDPM_COLOR_GREEN "v{} "
|
||||||
|
GDPM_COLOR_CYAN "{} "
|
||||||
|
GDPM_COLOR_RESET "Godot {}, {}",
|
||||||
p.support_level,
|
p.support_level,
|
||||||
|
p.category,
|
||||||
p.author,
|
p.author,
|
||||||
p.title,
|
p.title,
|
||||||
p.version,
|
p.version,
|
||||||
p.asset_id,
|
p.modify_date,
|
||||||
|
// p.asset_id,
|
||||||
p.godot_version,
|
p.godot_version,
|
||||||
p.cost,
|
p.cost
|
||||||
p.category,
|
|
||||||
p.modify_date
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -629,16 +653,22 @@ namespace gdpm::package{
|
||||||
|
|
||||||
void print_list(const rapidjson::Document& json){
|
void print_list(const rapidjson::Document& json){
|
||||||
for(const auto& o : json["result"].GetArray()){
|
for(const auto& o : json["result"].GetArray()){
|
||||||
log::println("{}/{}/{} {} id={}\n\tGodot {}, {}, {}, Last Modified: {}",
|
log::println(
|
||||||
|
GDPM_COLOR_BLUE"{}/"
|
||||||
|
GDPM_COLOR_CYAN "{}/"
|
||||||
|
GDPM_COLOR_RESET "{}/{} "
|
||||||
|
GDPM_COLOR_GREEN "v{} "
|
||||||
|
GDPM_COLOR_CYAN "{} "
|
||||||
|
GDPM_COLOR_RESET "Godot {}, {}",
|
||||||
o["support_level"] .GetString(),
|
o["support_level"] .GetString(),
|
||||||
|
utils::to_lower(o["category"].GetString()),
|
||||||
o["author"] .GetString(),
|
o["author"] .GetString(),
|
||||||
o["title"] .GetString(),
|
o["title"] .GetString(),
|
||||||
o["version_string"] .GetString(),
|
o["version_string"] .GetString(),
|
||||||
o["asset_id"] .GetString(),
|
o["modify_date"] .GetString(),
|
||||||
|
// o["asset_id"] .GetString(),
|
||||||
o["godot_version"] .GetString(),
|
o["godot_version"] .GetString(),
|
||||||
o["cost"] .GetString(),
|
o["cost"] .GetString()
|
||||||
o["category"] .GetString(),
|
|
||||||
o["modify_date"] .GetString()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ namespace gdpm::package_manager{
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
config::context config;
|
config::context config;
|
||||||
remote::repository_map remote_sources;
|
|
||||||
action_e action;
|
action_e action;
|
||||||
|
|
||||||
// opts_t opts;
|
// opts_t opts;
|
||||||
|
|
@ -47,7 +46,6 @@ namespace gdpm::package_manager{
|
||||||
bool clean_tmp_dir = false;
|
bool clean_tmp_dir = false;
|
||||||
int priority = -1;
|
int priority = -1;
|
||||||
|
|
||||||
|
|
||||||
error initialize(int argc, char **argv){
|
error initialize(int argc, char **argv){
|
||||||
// curl_global_init(CURL_GLOBAL_ALL);
|
// curl_global_init(CURL_GLOBAL_ALL);
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
|
|
@ -83,166 +81,178 @@ namespace gdpm::package_manager{
|
||||||
|
|
||||||
|
|
||||||
error parse_arguments(int argc, char **argv){
|
error parse_arguments(int argc, char **argv){
|
||||||
|
using namespace clipp;
|
||||||
|
|
||||||
/* Replace cxxopts with clipp */
|
/* Replace cxxopts with clipp */
|
||||||
action_e action = action_e::none;
|
action_e action = action_e::none;
|
||||||
package::title_list package_titles;
|
package::title_list package_titles;
|
||||||
string_list input;
|
|
||||||
package::params params;
|
package::params params;
|
||||||
args_t args;
|
|
||||||
var_opts opts;
|
auto doc_format = clipp::doc_formatting{}
|
||||||
|
.first_column(7)
|
||||||
|
.doc_column(45)
|
||||||
|
.last_column(99);
|
||||||
|
|
||||||
/* Set global options */
|
/* Set global options */
|
||||||
auto configOpt = clipp::option("--config-path").set(config.path)% "set config path";
|
auto debugOpt = option("-d", "--debug").set(config.verbose, to_int(log::DEBUG)) % "show debug output";
|
||||||
auto fileOpt = clipp::option("--file", "-f").set(input) % "read file as input";
|
auto configOpt = option("--config-path").set(config.path) % "set config path";
|
||||||
auto pathOpt = clipp::option("--path").set(params.paths) % "specify a path to use with command";
|
auto fileOpt = repeatable(option("--file", "-f").set(params.args) % "read file as input");
|
||||||
auto typeOpt = clipp::option("--type").set(config.info.type) % "set package type (any|addon|project)";
|
auto pathOpt = option("--path").set(params.paths) % "specify a path to use with command";
|
||||||
auto sortOpt = clipp::option("--sort").set(config.api_params.sort) % "sort packages in order (rating|cost|name|updated)";
|
auto typeOpt = option("--type").set(config.info.type) % "set package type (any|addon|project)";
|
||||||
auto supportOpt = clipp::option("--support").set(config.api_params.support) % "set the support level for API (all|official|community|testing)";
|
auto sortOpt = option("--sort").set(config.api_params.sort) % "sort packages in order (rating|cost|name|updated)";
|
||||||
auto maxResultsOpt = clipp::option("--max-results").set(config.api_params.max_results) % "set the request max results";
|
auto supportOpt = option("--support").set(config.api_params.support) % "set the support level for API (all|official|community|testing)";
|
||||||
auto godotVersionOpt = clipp::option("--godot-version").set(config.api_params.godot_version) % "set the request Godot version";
|
auto maxResultsOpt = option("--max-results").set(config.api_params.max_results) % "set the request max results";
|
||||||
auto packageDirOpt = clipp::option("--package-dir").set(config.packages_dir) % "set the global package location";
|
auto godotVersionOpt = option("--godot-version").set(config.api_params.godot_version) % "set the request Godot version";
|
||||||
auto tmpDirOpt = clipp::option("--tmp-dir").set(config.tmp_dir) % "set the temporary download location";
|
auto packageDirOpt = option("--package-dir").set(config.packages_dir) % "set the global package location";
|
||||||
auto timeoutOpt = clipp::option("--timeout").set(config.timeout) % "set the request timeout";
|
auto tmpDirOpt = option("--tmp-dir").set(config.tmp_dir) % "set the temporary download location";
|
||||||
auto verboseOpt = clipp::option("--verbose", "-v").set(config.verbose) % "show verbose output";
|
auto timeoutOpt = option("--timeout").set(config.timeout) % "set the request timeout";
|
||||||
|
auto verboseOpt = repeatable(option("-v", "--verbose", "-v").call([]{ config.verbose += 1; })) % "show verbose output";
|
||||||
|
|
||||||
/* Set the options */
|
/* Set the options */
|
||||||
auto cleanOpt = clipp::option("--clean").set(config.clean_temporary) % "enable/disable cleaning temps";
|
auto cleanOpt = option("--clean").set(config.clean_temporary) % "enable/disable cleaning temps";
|
||||||
auto parallelOpt = clipp::option("--jobs").set(config.jobs) % "set number of parallel jobs";
|
auto parallelOpt = option("--jobs").set(config.jobs) % "set number of parallel jobs";
|
||||||
auto cacheOpt = clipp::option("--enable-cache").set(config.enable_cache) % "enable/disable local caching";
|
auto cacheOpt = option("--enable-cache").set(config.enable_cache) % "enable/disable local caching";
|
||||||
auto syncOpt = clipp::option("--enable-sync").set(config.enable_sync) % "enable/disable remote syncing";
|
auto syncOpt = option("--enable-sync").set(config.enable_sync) % "enable/disable remote syncing";
|
||||||
auto skipOpt = clipp::option("--skip-prompt").set(config.skip_prompt) % "skip the y/n prompt";
|
auto skipOpt = option("--skip-prompt").set(config.skip_prompt) % "skip the y/n prompt";
|
||||||
auto remoteOpt = clipp::option("--remote").set(params.remote_source) % "set remote source to use";
|
auto remoteOpt = option("--remote").set(params.remote_source) % "set remote source to use";
|
||||||
|
|
||||||
auto packageValues = clipp::values("packages", package_titles);
|
auto packageValues = values("packages", package_titles);
|
||||||
auto requiredPath = clipp::required("--path", input);
|
auto requiredPath = required("--path", params.args);
|
||||||
|
|
||||||
auto installCmd = (
|
|
||||||
clipp::command("install")
|
|
||||||
.set(action, action_e::install)
|
|
||||||
.doc("Install packages from asset library"),
|
|
||||||
clipp::values("packages", package_titles),
|
|
||||||
clipp::option("--godot-version") & clipp::value("version", config.info.godot_version),
|
|
||||||
cleanOpt, parallelOpt, syncOpt, skipOpt, remoteOpt
|
|
||||||
|
|
||||||
|
auto installCmd = "install" % (
|
||||||
|
command("install").set(action, action_e::install),
|
||||||
|
packageValues % "packages to install from asset library",
|
||||||
|
godotVersionOpt, cleanOpt, parallelOpt, syncOpt, skipOpt, remoteOpt
|
||||||
);
|
);
|
||||||
auto addCmd = (
|
auto addCmd = "add" % (
|
||||||
clipp::command("add").set(action, action_e::add)
|
command("add").set(action, action_e::add),
|
||||||
.doc("Add a package to a local project"),
|
packageValues % "package(s) to add to local project",
|
||||||
packageValues
|
parallelOpt, skipOpt, remoteOpt
|
||||||
);
|
);
|
||||||
auto removeCmd = (
|
auto removeCmd = "remove" % (
|
||||||
clipp::command("remove")
|
command("remove").set(action, action_e::remove),
|
||||||
.set(action, action_e::remove)
|
packageValues % "package(s) to remove from local project"
|
||||||
.doc("Remove a package from local project"),
|
|
||||||
packageValues
|
|
||||||
);
|
);
|
||||||
auto updateCmd = (
|
auto updateCmd = "update" % (
|
||||||
clipp::command("update")
|
command("update").set(action, action_e::update),
|
||||||
.set(action, action_e::update)
|
packageValues % "update package(s)"
|
||||||
.doc("Update package(s)"),
|
|
||||||
packageValues
|
|
||||||
);
|
);
|
||||||
auto searchCmd = (
|
auto searchCmd = "search" % (
|
||||||
clipp::command("search")
|
command("search").set(action, action_e::search),
|
||||||
.set(action, action_e::search)
|
packageValues % "package(s) to search for"
|
||||||
.doc("Search for package(s)"),
|
|
||||||
packageValues
|
|
||||||
);
|
);
|
||||||
auto exportCmd = (
|
auto exportCmd = "export" % (
|
||||||
clipp::command("export")
|
command("export").set(action, action_e::p_export),
|
||||||
.set(action, action_e::p_export)
|
values("paths", params.args) % "export installed package list to file"
|
||||||
.doc("Export package list"),
|
|
||||||
clipp::values("path", input)
|
|
||||||
);
|
);
|
||||||
auto listCmd = (
|
auto listCmd = "show installed packages" % (
|
||||||
clipp::command("list")
|
command("list").set(action, action_e::list)
|
||||||
.set(action, action_e::list)
|
|
||||||
.doc("Show installed packages")
|
|
||||||
);
|
);
|
||||||
auto linkCmd = (
|
auto linkCmd = "link" % (
|
||||||
clipp::command("link")
|
command("link").set(action, action_e::link),
|
||||||
.set(action, action_e::link)
|
value("package", package_titles) % "package name to link",
|
||||||
.doc("Create symlink packages to project"),
|
value("path", params.args) % "path to project"
|
||||||
packageValues,
|
|
||||||
requiredPath
|
|
||||||
);
|
);
|
||||||
auto cloneCmd = (
|
auto cloneCmd = "clone" % (
|
||||||
clipp::command("clone")
|
command("clone").set(action, action_e::clone),
|
||||||
.set(action, action_e::clone)
|
value("package", package_titles) % "packages to clone",
|
||||||
.doc("Clone packages to project"),
|
value("path", params.args) % "path to project"
|
||||||
packageValues,
|
|
||||||
requiredPath
|
|
||||||
);
|
);
|
||||||
auto cleanCmd = (
|
auto cleanCmd = "clean" % (
|
||||||
clipp::command("clean")
|
command("clean").set(action, action_e::clean),
|
||||||
.set(action, action_e::clean)
|
values("packages", package_titles) % "package temporary files to remove"
|
||||||
.doc("Clean temporary files"),
|
|
||||||
packageValues
|
|
||||||
);
|
);
|
||||||
auto configCmd = (
|
auto configCmd = "get/set config properties" % (
|
||||||
clipp::command("config")
|
command("config").set(action, action_e::config_get),
|
||||||
.set(action, action_e::config)
|
(
|
||||||
.doc("Set/get config properties")
|
( 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([]{}) % "config property",
|
||||||
|
value("value", params.args[2]).call([]{}) % "config value"
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
auto fetchCmd = (
|
auto fetchCmd = "fetch" % (
|
||||||
clipp::command("fetch")
|
command("fetch").set(action, action_e::fetch),
|
||||||
.set(action, action_e::fetch)
|
option(values("remote", params.args)) % "remote to fetch asset data"
|
||||||
.doc("Fetch asset metadata from remote source")
|
|
||||||
);
|
);
|
||||||
|
auto add_arg = [¶ms](string arg) { params.args.emplace_back(arg); };
|
||||||
auto remoteCmd = (
|
auto remoteCmd = (
|
||||||
clipp::command("remote")
|
command("remote").set(action, action_e::remote_list).if_missing(
|
||||||
.set(action, action_e::remote)
|
[]{
|
||||||
.doc("Manage remote sources")
|
remote::print_repositories(config);
|
||||||
.required("subcommand")
|
}
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"add a remote source" % ( command("add").set(action, action_e::remote_add),
|
||||||
|
word("name").call(add_arg) % "remote name",
|
||||||
|
value("url").call(add_arg) % "remote URL"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
"remove a remote source" % ( command("remove").set(action, action_e::remote_remove),
|
||||||
|
words("names", params.args) % "remote name(s)"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
"list remote sources" % ( command("list").set(action, action_e::remote_list))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
auto uiCmd = (
|
auto uiCmd = "start with UI" % (
|
||||||
clipp::command("ui")
|
command("ui").set(action, action_e::ui)
|
||||||
.set(action, action_e::ui)
|
|
||||||
.doc("Show the UI")
|
|
||||||
);
|
);
|
||||||
auto helpCmd = (
|
auto helpCmd = "show this message and exit" % (
|
||||||
clipp::command("help")
|
command("help").set(action, action_e::help)
|
||||||
.set(action, action_e::help)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
auto cli = (
|
auto cli = (
|
||||||
|
debugOpt, configOpt,
|
||||||
(installCmd | addCmd | removeCmd | updateCmd | searchCmd | exportCmd |
|
(installCmd | addCmd | removeCmd | updateCmd | searchCmd | exportCmd |
|
||||||
listCmd | linkCmd | cloneCmd | cleanCmd | configCmd | fetchCmd |
|
listCmd | linkCmd | cloneCmd | cleanCmd | configCmd | fetchCmd |
|
||||||
remoteCmd | uiCmd | helpCmd)
|
remoteCmd | uiCmd | helpCmd)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Make help output */
|
/* Make help output */
|
||||||
string map_page_format("");
|
string man_page_format("");
|
||||||
auto man_page = clipp::make_man_page(cli);
|
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(),
|
std::for_each(man_page.begin(), man_page.end(),
|
||||||
[&map_page_format](const clipp::man_page::section& s){
|
[&man_page_format](const man_page::section& s){
|
||||||
map_page_format += s.title() + "\n";
|
man_page_format += s.title() + "\n";
|
||||||
map_page_format += s.content() + "\n";
|
man_page_format += s.content() + "\n\n";
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// log::level = config.verbose;
|
||||||
if(clipp::parse(argc, argv, cli)){
|
if(clipp::parse(argc, argv, cli)){
|
||||||
|
log::level = config.verbose;
|
||||||
switch(action){
|
switch(action){
|
||||||
case action_e::install: package::install(config, package_titles, params); break;
|
case action_e::install: package::install(config, package_titles, params); break;
|
||||||
case action_e::add: break;
|
case action_e::add: package::add(config, package_titles);
|
||||||
case action_e::remove: package::remove(config, package_titles, params); break;
|
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::update: package::update(config, package_titles, params); break;
|
||||||
case action_e::search: package::search(config, package_titles, params); break;
|
case action_e::search: package::search(config, package_titles, params); break;
|
||||||
case action_e::p_export: package::export_to(input); break;
|
case action_e::p_export: package::export_to(params.args); break;
|
||||||
case action_e::list: package::list(config, params); break;
|
case action_e::list: package::list(config, params); break;
|
||||||
/* ...opts are the paths here */
|
/* ...opts are the paths here */
|
||||||
case action_e::link: package::link(config, package_titles, params); break;
|
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::clone: package::clone(config, package_titles, params); break;
|
||||||
case action_e::clean: package::clean_temporary(config, package_titles); break;
|
case action_e::clean: package::clean_temporary(config, package_titles); break;
|
||||||
case action_e::config: config::handle_config(config, package_titles, opts); 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::fetch: package::synchronize_database(config, package_titles); break;
|
||||||
case action_e::sync: package::synchronize_database(config, package_titles); break;
|
case action_e::sync: package::synchronize_database(config, package_titles); break;
|
||||||
case action_e::remote: remote::handle_remote(config, args, opts); break;
|
case action_e::remote_list: remote::print_repositories(config); break;
|
||||||
case action_e::ui: log::info("ui not implemented yet"); break;
|
case action_e::remote_add: remote::add_repository(config, params.args); break;
|
||||||
case action_e::help: log::println("{}", map_page_format); 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::none: /* ...here to run with no command */ break;
|
case action_e::none: /* ...here to run with no command */ break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::println("{}", map_page_format);
|
log::println("usage:\n{}", usage_lines(cli, argv[0]).str());
|
||||||
}
|
}
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,88 +6,48 @@
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
|
|
||||||
namespace gdpm::remote{
|
namespace gdpm::remote{
|
||||||
error handle_remote(
|
|
||||||
|
error add_repository(
|
||||||
config::context &config,
|
config::context &config,
|
||||||
const args_t& args,
|
const args_t &args
|
||||||
const var_opts& opts
|
|
||||||
){
|
){
|
||||||
/* Check if enough arguments are supplied */
|
/* Check if enough args were provided. */
|
||||||
size_t argc = args.size();
|
log::debug("arg count: {}\nargs: {}", args.size(), utils::join(args));
|
||||||
if (argc < 1){
|
if (args.size() < 2){
|
||||||
print_repositories(config);
|
return error(
|
||||||
return error();
|
constants::error::INVALID_ARG_COUNT,
|
||||||
|
"Requires a remote name and url argument"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check which subcommand is supplied */
|
/* Get the first two args */
|
||||||
string sub_command = args.front();
|
log::println("{}", args[0]);
|
||||||
if(sub_command == "add"){
|
config.remote_sources.insert({args[0], args[1]});
|
||||||
if(args.size() < 3 || args.empty()){
|
|
||||||
error error(
|
|
||||||
constants::error::INVALID_ARG_COUNT,
|
|
||||||
"Invalid number of args."
|
|
||||||
);
|
|
||||||
log::error(error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
string name = args[1];
|
|
||||||
string url = args[2];
|
|
||||||
add_repositories(config, {{name, url}});
|
|
||||||
}
|
|
||||||
else if (sub_command == "remove") {
|
|
||||||
if(args.size() < 2 || args.empty()){
|
|
||||||
error error(
|
|
||||||
constants::error::INVALID_ARG_COUNT,
|
|
||||||
"Invalid number of args."
|
|
||||||
);
|
|
||||||
log::error(error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
remove_respositories(config, {args.begin()+1, args.end()});
|
|
||||||
}
|
|
||||||
// else if (sub_command == "set") set_repositories(config::context &context, const repository_map &repos)
|
|
||||||
else if (sub_command == "list") print_repositories(config);
|
|
||||||
else{
|
|
||||||
error error(
|
|
||||||
constants::error::UNKNOWN,
|
|
||||||
"Unknown sub-command. Try 'gdpm help remote' for options."
|
|
||||||
);
|
|
||||||
log::error(error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_repositories(
|
error remove_respositories(
|
||||||
config::context& config,
|
config::context& config,
|
||||||
const repository_map &repos
|
const args_t& args
|
||||||
){
|
){
|
||||||
config.remote_sources = repos;
|
log::debug("arg count: {}\nargs: {}", args.size(), utils::join(args));
|
||||||
}
|
if(args.size() < 1){
|
||||||
|
return error(
|
||||||
|
constants::error::INVALID_ARG_COUNT,
|
||||||
void add_repositories(
|
"Requires at least one remote name argument"
|
||||||
config::context& config,
|
|
||||||
const repository_map &repos
|
|
||||||
){
|
|
||||||
std::for_each(repos.begin(), repos.end(),
|
|
||||||
[&config](const string_pair& p){
|
|
||||||
config.remote_sources.insert(p);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(auto it = args.begin(); it != args.end();){
|
||||||
void remove_respositories(
|
|
||||||
config::context& config,
|
|
||||||
const repo_names& names
|
|
||||||
){
|
|
||||||
for(auto it = names.begin(); it != names.end();){
|
|
||||||
if(config.remote_sources.contains(*it)){
|
if(config.remote_sources.contains(*it)){
|
||||||
|
log::println("{}", *it);
|
||||||
config.remote_sources.erase(*it);
|
config.remote_sources.erase(*it);
|
||||||
}
|
}
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include "constants.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,9 +14,12 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <rapidjson/ostreamwrapper.h>
|
#include <rapidjson/ostreamwrapper.h>
|
||||||
#include <rapidjson/writer.h>
|
#include <rapidjson/writer.h>
|
||||||
|
#include <readline/chardefs.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
#include <zip.h>
|
#include <zip.h>
|
||||||
|
|
||||||
namespace gdpm::utils{
|
namespace gdpm::utils{
|
||||||
|
|
@ -53,8 +57,38 @@ namespace gdpm::utils{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void to_lower(std::string& s){
|
std::string to_lower(const std::string& s){
|
||||||
std::transform(s.begin(), s.end(), s.begin(), tolower);
|
std::string copy = s;
|
||||||
|
std::transform(copy.begin(), copy.end(), copy.begin(), tolower);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string trim(const std::string& s){
|
||||||
|
return trim_right(trim_left(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string trim_left(const std::string& s){
|
||||||
|
return trim_left(s, constants::WHITESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string trim_left(
|
||||||
|
const std::string& s,
|
||||||
|
const std::string& ref
|
||||||
|
){
|
||||||
|
size_t start = s.find_first_not_of(ref);
|
||||||
|
return (start == std::string::npos) ? "" : s.substr(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string trim_right(const std::string& s){
|
||||||
|
return trim_right(s, constants::WHITESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string trim_right(
|
||||||
|
const std::string& s,
|
||||||
|
const std::string& ref
|
||||||
|
){
|
||||||
|
size_t end = s.find_last_not_of(ref);
|
||||||
|
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> parse_lines(const std::string &s){
|
std::vector<std::string> parse_lines(const std::string &s){
|
||||||
|
|
@ -97,7 +131,7 @@ namespace gdpm::utils{
|
||||||
const char *dest,
|
const char *dest,
|
||||||
int verbose
|
int verbose
|
||||||
){
|
){
|
||||||
const char *prog = "gpdm";
|
constexpr const char *prog = "gpdm";
|
||||||
struct zip *za;
|
struct zip *za;
|
||||||
struct zip_file *zf;
|
struct zip_file *zf;
|
||||||
struct zip_stat sb;
|
struct zip_stat sb;
|
||||||
|
|
@ -198,9 +232,31 @@ namespace gdpm::utils{
|
||||||
const std::string& delimiter
|
const std::string& delimiter
|
||||||
){
|
){
|
||||||
std::string o;
|
std::string o;
|
||||||
std::for_each(target.begin(), target.end(), [&o, &delimiter](const std::string& s){
|
std::for_each(
|
||||||
|
target.begin(),
|
||||||
|
target.end(),
|
||||||
|
[&o, &delimiter](const std::string& s){
|
||||||
o += s + delimiter;
|
o += s + delimiter;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
o = trim_right(o, delimiter);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string join(
|
||||||
|
const std::unordered_map<std::string, std::string>& target,
|
||||||
|
const std::string& prefix,
|
||||||
|
const std::string& delimiter
|
||||||
|
){
|
||||||
|
std::string o;
|
||||||
|
std::for_each(
|
||||||
|
target.begin(),
|
||||||
|
target.end(),
|
||||||
|
[&o, &prefix, &delimiter](const std::pair<std::string, std::string>& p){
|
||||||
|
o += prefix + p.first + ": " + p.second + delimiter;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
o = trim_right(o, delimiter);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
tests/plugin.cpp
Normal file
10
tests/plugin.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "plugin.hpp"
|
||||||
|
|
||||||
|
#include <doctest.h>
|
||||||
|
|
||||||
|
|
||||||
|
TEST_SUITE("Test example plugin"){
|
||||||
|
TEST_CASE("Test initialization"){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue