mirror of
https://github.com/davidallendj/gdpm.git
synced 2025-12-20 03:27:02 -07:00
Refactored, simplified, and removed code; replaced cli header lib
- Reinitialized submodules - Slightly restructed project - Added more options to `compile.sh` script - Added more utility functions
This commit is contained in:
parent
d34243db74
commit
e48c54aa40
27 changed files with 564 additions and 3232 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -13,3 +13,4 @@ vgcore.*
|
||||||
.vscode
|
.vscode
|
||||||
config.json
|
config.json
|
||||||
*.txt
|
*.txt
|
||||||
|
actions-runner/
|
||||||
|
|
|
||||||
8
.gitmodules
vendored
8
.gitmodules
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
[submodule "modules/doxygen-awesome-css"]
|
|
||||||
path = modules/doxygen-awesome-css
|
|
||||||
url = https://github.com/jothepro/doxygen-awesome-css.git
|
|
||||||
[submodule "modules/clipp"]
|
[submodule "modules/clipp"]
|
||||||
path = modules/clipp
|
path = modules/clipp
|
||||||
url = https://github.com/GerHobbelt/clipp.git
|
url = https://github.com/GerHobbelt/clipp
|
||||||
|
[submodule "modules/doxygen-awesome-css"]
|
||||||
|
path = modules/doxygen-awesome-css
|
||||||
|
url = https://github.com/jothepro/doxygen-awesome-css/
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ exe=gdpm
|
||||||
static=gdpm.static
|
static=gdpm.static
|
||||||
tests=gdpm.tests
|
tests=gdpm.tests
|
||||||
|
|
||||||
|
|
||||||
function link_exe(){
|
function link_exe(){
|
||||||
path=$1
|
path=$1
|
||||||
link=$2
|
link=$2
|
||||||
|
|
@ -19,6 +20,7 @@ function link_exe(){
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function strip(){
|
function strip(){
|
||||||
path=$1
|
path=$1
|
||||||
if test -f "$path"
|
if test -f "$path"
|
||||||
|
|
@ -28,11 +30,6 @@ function strip(){
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function generate_docs(){
|
|
||||||
# Generate documentation using `doxygen`
|
|
||||||
cd ${script_dir}/..
|
|
||||||
doxygen
|
|
||||||
}
|
|
||||||
|
|
||||||
function strip_all(){
|
function strip_all(){
|
||||||
# Strip debug symbols
|
# Strip debug symbols
|
||||||
|
|
@ -41,6 +38,7 @@ function strip_all(){
|
||||||
strip ${script_dir}/../build/gdpm.tests
|
strip ${script_dir}/../build/gdpm.tests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function link_all(){
|
function link_all(){
|
||||||
# Create symlinks to executables in build folder if necessary
|
# Create symlinks to executables in build folder if necessary
|
||||||
link_exe $script_dir/../build/gdpm $script_dir/../bin/$exe
|
link_exe $script_dir/../build/gdpm $script_dir/../bin/$exe
|
||||||
|
|
@ -48,6 +46,7 @@ function link_all(){
|
||||||
link_exe $script_dir/../build/gdpm.tests $script_dir/../bin/$tests
|
link_exe $script_dir/../build/gdpm.tests $script_dir/../bin/$tests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function clean(){
|
function clean(){
|
||||||
rm ${script_dir}/../bin/$exe
|
rm ${script_dir}/../bin/$exe
|
||||||
rm ${script_dir}/../bin/$static
|
rm ${script_dir}/../bin/$static
|
||||||
|
|
@ -58,12 +57,49 @@ function clean(){
|
||||||
#meson configure build
|
#meson configure build
|
||||||
#CXX=clang++ meson compile -C build -j$(proc)
|
#CXX=clang++ meson compile -C build -j$(proc)
|
||||||
|
|
||||||
|
PROCS=$(nproc)
|
||||||
|
CMAKE_COMMAND="cmake -B build -S . -D CMAKE_EXPORT_COMPILE_COMMANDS=1 -D CMAKE_BUILD_TYPE=Debug -G Ninja"
|
||||||
|
NINJA_COMMAND="ninja -C build -j ${PROCS}"
|
||||||
|
|
||||||
# CMake/ninja build system
|
# CMake/ninja build system
|
||||||
function build_binaries(){
|
function build_all(){
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cmake -B build -S . -D CMAKE_EXPORT_COMPILE_COMMANDS=1 -D CMAKE_BUILD_TYPE=Debug -G Ninja
|
$CMAKE_COMMAND
|
||||||
ninja -C build -j $(nproc)
|
$NINJA_COMMAND
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function build_exe(){
|
||||||
|
mkdir -p build
|
||||||
|
$CMAKE_COMMAND \
|
||||||
|
--target gdpm \
|
||||||
|
--target gdpm.static
|
||||||
|
$NINJA_COMMAND
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function build_libs(){
|
||||||
|
mkdir -p build
|
||||||
|
$CMAKE_COMMAND \\
|
||||||
|
--target gdpm-static \
|
||||||
|
--target gdpm-shared \
|
||||||
|
--target gdpm-http \
|
||||||
|
--target gdpm-restapi
|
||||||
|
$NINJA_COMMAND
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_tests(){
|
||||||
|
mkdir -p build
|
||||||
|
$CMAKE_COMMAND --target gdpm.tests
|
||||||
|
$NINJA_COMMAND
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function build_docs(){
|
||||||
|
# Generate documentation using `doxygen`
|
||||||
|
pushd ${script_dir}/docs/doxygen
|
||||||
|
doxygen
|
||||||
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -78,12 +114,16 @@ i=$(($#-1))
|
||||||
while [ $i -ge 0 ];
|
while [ $i -ge 0 ];
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-a|--all) build_binaries shift;;
|
-a|--all) build_all shift;;
|
||||||
|
--exe) build_exe shift;;
|
||||||
|
--libs) build_libs shift;;
|
||||||
|
--tests) build_tests shift;;
|
||||||
|
-d|--docs) build_docs shift;;
|
||||||
-c|--clean) clean shift;;
|
-c|--clean) clean shift;;
|
||||||
-d|--docs) generate_docs shift;;
|
|
||||||
-s|--strip) strip_all shift;;
|
-s|--strip) strip_all shift;;
|
||||||
-l|--link) link_all shift;;
|
-l|--link) link_all shift;;
|
||||||
--*) echo "Bad option: $1"
|
--procs=*) PROCS="${i#*=}" shift;;
|
||||||
|
-*|--*) echo "Bad option: $1"
|
||||||
esac
|
esac
|
||||||
i=$((i-1))
|
i=$((i-1))
|
||||||
done
|
done
|
||||||
|
|
|
||||||
0
Jenkinsfile → ci/Jenkinsfile
vendored
0
Jenkinsfile → ci/Jenkinsfile
vendored
|
|
@ -31,8 +31,8 @@ jobs:
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run:
|
run:
|
||||||
echo -e "Building executable and libraries...\n$PWD"
|
echo -e "Building executable, libraries, documentation, and symlinks...\n$PWD"
|
||||||
./bin/compile.sh
|
./bin/compile.sh --all --docs --link --strip
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run:
|
run:
|
||||||
1
include/clipp.h
Symbolic link
1
include/clipp.h
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../modules/clipp/include/clipp.h
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "package.hpp"
|
||||||
|
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -9,27 +10,40 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
namespace gdpm::package{
|
||||||
|
struct info;
|
||||||
|
struct params;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gdpm::config{
|
namespace gdpm::config{
|
||||||
struct context{
|
struct context{
|
||||||
string username;
|
string username;
|
||||||
string password;
|
string password;
|
||||||
string path;
|
string path;
|
||||||
string token;
|
string token;
|
||||||
string godot_version;
|
|
||||||
string packages_dir;
|
string packages_dir;
|
||||||
string tmp_dir;
|
string tmp_dir;
|
||||||
string_map remote_sources;
|
string_map remote_sources;
|
||||||
size_t threads;
|
size_t jobs = 1;
|
||||||
size_t timeout;
|
size_t timeout = 3000;
|
||||||
bool enable_sync;
|
bool enable_sync = true;
|
||||||
|
bool enable_cache = true;
|
||||||
|
bool skip_prompt = false;
|
||||||
bool enable_file_logging;
|
bool enable_file_logging;
|
||||||
|
bool clean_temporary;
|
||||||
int verbose;
|
int verbose;
|
||||||
|
package::info info;
|
||||||
|
rest_api::request_params api_params;
|
||||||
};
|
};
|
||||||
string to_json(const context& params);
|
|
||||||
error load(std::filesystem::path path, context& config, int verbose = 0);
|
string to_json(const context& config, bool pretty_print = false);
|
||||||
error save(std::filesystem::path path, const context& config, int verbose = 0);
|
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);
|
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);
|
||||||
|
|
||||||
extern context config;
|
extern context config;
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ namespace gdpm::constants{
|
||||||
const std::string LockfilePath(HomePath + ".config/gdpm/gdpm.lck");
|
const std::string LockfilePath(HomePath + ".config/gdpm/gdpm.lck");
|
||||||
const std::string LocalPackagesDir(HomePath + ".config/gdpm/packages");
|
const std::string LocalPackagesDir(HomePath + ".config/gdpm/packages");
|
||||||
const std::string TemporaryPath(HomePath + ".config/gdpm/tmp");
|
const std::string TemporaryPath(HomePath + ".config/gdpm/tmp");
|
||||||
const std::string UserAgent("libcurl-agent/1.0");
|
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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
#include "package.hpp"
|
#include "package.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "result.hpp"
|
#include "result.hpp"
|
||||||
#include "config.hpp"
|
#include "rest_api.hpp"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace gdpm::config{
|
||||||
|
struct context;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gdpm::package {
|
namespace gdpm::package {
|
||||||
|
|
||||||
struct info {
|
struct info {
|
||||||
|
|
@ -42,11 +46,12 @@ namespace gdpm::package {
|
||||||
GLOBAL_ONLY = 2,
|
GLOBAL_ONLY = 2,
|
||||||
LOCAL_ONLY = 3
|
LOCAL_ONLY = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
struct params {
|
struct params {
|
||||||
int parallel_jobs = 1;
|
args_t sub_commands;
|
||||||
bool enable_cache = true;
|
var_opts opts;
|
||||||
bool enable_sync = true;
|
string_list paths;
|
||||||
bool skip_prompt = false;
|
string_list input_files;
|
||||||
string remote_source = "origin";
|
string remote_source = "origin";
|
||||||
install_method_e install_method = GLOBAL_LINK_LOCAL;
|
install_method_e install_method = GLOBAL_LINK_LOCAL;
|
||||||
};
|
};
|
||||||
|
|
@ -101,10 +106,10 @@ namespace gdpm::package {
|
||||||
GDPM_DLL_EXPORT error remove_all(const config::context& config, const params& params = package::params());
|
GDPM_DLL_EXPORT error remove_all(const config::context& config, const params& params = package::params());
|
||||||
GDPM_DLL_EXPORT error update(const config::context& config, const title_list& package_titles, const params& params = package::params());
|
GDPM_DLL_EXPORT error update(const config::context& config, const title_list& package_titles, const params& params = package::params());
|
||||||
GDPM_DLL_EXPORT error search(const config::context& config, const title_list& package_titles, const params& params = package::params());
|
GDPM_DLL_EXPORT error search(const config::context& config, const title_list& package_titles, const params& params = package::params());
|
||||||
GDPM_DLL_EXPORT error list(const config::context& config, const args_t& args, const opts_t& opts);
|
GDPM_DLL_EXPORT error list(const config::context& config, const params& params = package::params());
|
||||||
GDPM_DLL_EXPORT error export_to(const path_list& paths);
|
GDPM_DLL_EXPORT error export_to(const path_list& paths);
|
||||||
GDPM_DLL_EXPORT error link(const config::context& config, const title_list& package_titles, const opts_t& opts);
|
GDPM_DLL_EXPORT error link(const config::context& config, const title_list& package_titles, const params& params = package::params());
|
||||||
GDPM_DLL_EXPORT error clone(const config::context& config, const title_list& package_titles, const opts_t& opts);
|
GDPM_DLL_EXPORT error clone(const config::context& config, const title_list& package_titles, const params& params = package::params());
|
||||||
|
|
||||||
|
|
||||||
GDPM_DLL_EXPORT void print_list(const rapidjson::Document& json);
|
GDPM_DLL_EXPORT void print_list(const rapidjson::Document& json);
|
||||||
|
|
@ -117,4 +122,6 @@ namespace gdpm::package {
|
||||||
/* Dependency Management API */
|
/* Dependency Management API */
|
||||||
GDPM_DLL_EXPORT result_t<info_list> synchronize_database(const config::context& config, const title_list& package_titles);
|
GDPM_DLL_EXPORT result_t<info_list> synchronize_database(const config::context& config, const title_list& package_titles);
|
||||||
GDPM_DLL_EXPORT result_t<info_list> resolve_dependencies(const config::context& config, const title_list& package_titles);
|
GDPM_DLL_EXPORT result_t<info_list> resolve_dependencies(const config::context& config, const title_list& package_titles);
|
||||||
|
|
||||||
|
GDPM_DLL_EXPORT string to_json(const info& info, bool pretty_print = false);
|
||||||
}
|
}
|
||||||
|
|
@ -21,16 +21,6 @@ namespace gdpm::package_manager {
|
||||||
extern CURLcode res;
|
extern CURLcode res;
|
||||||
extern config::context config;
|
extern config::context config;
|
||||||
|
|
||||||
struct cxxargs{
|
|
||||||
cxxopts::ParseResult result;
|
|
||||||
cxxopts::Options options;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exec_args{
|
|
||||||
var_args args;
|
|
||||||
var_opts opts;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class action_e{
|
enum class action_e{
|
||||||
install,
|
install,
|
||||||
add,
|
add,
|
||||||
|
|
@ -42,18 +32,17 @@ namespace gdpm::package_manager {
|
||||||
link,
|
link,
|
||||||
clone,
|
clone,
|
||||||
clean,
|
clean,
|
||||||
|
config,
|
||||||
|
fetch,
|
||||||
sync,
|
sync,
|
||||||
remote,
|
remote,
|
||||||
|
ui,
|
||||||
help,
|
help,
|
||||||
none
|
none
|
||||||
};
|
};
|
||||||
|
|
||||||
GDPM_DLL_EXPORT result_t<exec_args> initialize(int argc, char **argv);
|
GDPM_DLL_EXPORT error initialize(int argc, char **argv);
|
||||||
GDPM_DLL_EXPORT int execute(const exec_args& in);
|
GDPM_DLL_EXPORT error parse_arguments(int argc, char **argv);
|
||||||
GDPM_DLL_EXPORT void finalize();
|
GDPM_DLL_EXPORT error finalize();
|
||||||
|
|
||||||
/* Auxiliary Functions */
|
|
||||||
GDPM_DLL_EXPORT cxxargs _parse_arguments(int argc, char **argv);
|
|
||||||
GDPM_DLL_EXPORT result_t<exec_args> _handle_arguments(const cxxargs& args);
|
|
||||||
GDPM_DLL_EXPORT void run_command(action_e command, const var_args& args, const var_opts& opts);
|
GDPM_DLL_EXPORT void run_command(action_e command, const var_args& args, const var_opts& opts);
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ namespace gdpm::remote{
|
||||||
using repo_urls = string_list;
|
using repo_urls = string_list;
|
||||||
using repository_map = string_map;
|
using repository_map = string_map;
|
||||||
|
|
||||||
GDPM_DLL_EXPORT error _handle_remote(config::context& config, const args_t& args, const opts_t& opts);
|
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 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 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 remove_respositories(config::context& context, const repo_names& names);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "config.hpp"
|
#include "types.hpp"
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <rapidjson/writer.h>
|
#include <rapidjson/writer.h>
|
||||||
#include <rapidjson/stringbuffer.h>
|
#include <rapidjson/stringbuffer.h>
|
||||||
#include <rapidjson/prettywriter.h>
|
#include <rapidjson/prettywriter.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace gdpm::config{
|
||||||
|
struct context;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gdpm::rest_api{
|
namespace gdpm::rest_api{
|
||||||
// See GitHub reference: https://github.com/godotengine/godot-asset-library/blob/master/API.md
|
// See GitHub reference: https://github.com/godotengine/godot-asset-library/blob/master/API.md
|
||||||
namespace endpoints{
|
namespace endpoints{
|
||||||
|
|
@ -30,33 +36,34 @@ namespace gdpm::rest_api{
|
||||||
bool logout();
|
bool logout();
|
||||||
// bool change_password()
|
// bool change_password()
|
||||||
|
|
||||||
enum type_e { any, addon, project };
|
enum type_e: int { any = 0, addon, project };
|
||||||
enum support_e { all, official, community, testing };
|
enum support_e: int { all = 0, official, community, testing };
|
||||||
enum sort_e { none, rating, cost, name, updated };
|
enum sort_e: int { none = 0, rating, cost, name, updated };
|
||||||
|
|
||||||
struct context{
|
struct request_params{
|
||||||
type_e type;
|
int type ;
|
||||||
int category;
|
int category;
|
||||||
support_e support;
|
int support;
|
||||||
string filter;
|
string filter;
|
||||||
string user;
|
string user;
|
||||||
string godot_version;
|
string godot_version;
|
||||||
int max_results;
|
int max_results;
|
||||||
int page;
|
int page;
|
||||||
sort_e sort;
|
int sort;
|
||||||
bool reverse;
|
bool reverse;
|
||||||
int verbose;
|
int verbose;
|
||||||
};
|
};
|
||||||
|
|
||||||
context make_from_config(const config::context& config);
|
request_params make_from_config(const config::context& config);
|
||||||
context make_context(type_e type = GDPM_DEFAULT_ASSET_TYPE, int category = GDPM_DEFAULT_ASSET_CATEGORY, support_e support = GDPM_DEFAULT_ASSET_SUPPORT, const std::string& filter = GDPM_DEFAULT_ASSET_FILTER, const std::string& user = GDPM_DEFAULT_ASSET_USER, const std::string& godot_version = GDPM_DEFAULT_ASSET_GODOT_VERSION, int max_results = GDPM_DEFAULT_ASSET_MAX_RESULTS, int page = GDPM_DEFAULT_ASSET_PAGE, sort_e sort = GDPM_DEFAULT_ASSET_SORT, bool reverse = GDPM_DEFAULT_ASSET_REVERSE, int verbose = GDPM_DEFAULT_ASSET_VERBOSE);
|
request_params make_request_params(type_e type = GDPM_DEFAULT_ASSET_TYPE, int category = GDPM_DEFAULT_ASSET_CATEGORY, support_e support = GDPM_DEFAULT_ASSET_SUPPORT, const std::string& filter = GDPM_DEFAULT_ASSET_FILTER, const std::string& user = GDPM_DEFAULT_ASSET_USER, const std::string& godot_version = GDPM_DEFAULT_ASSET_GODOT_VERSION, int max_results = GDPM_DEFAULT_ASSET_MAX_RESULTS, int page = GDPM_DEFAULT_ASSET_PAGE, sort_e sort = GDPM_DEFAULT_ASSET_SORT, bool reverse = GDPM_DEFAULT_ASSET_REVERSE, int verbose = GDPM_DEFAULT_ASSET_VERBOSE);
|
||||||
|
|
||||||
|
string to_json(const rapidjson::Document& doc);
|
||||||
string to_string(type_e type);
|
string to_string(type_e type);
|
||||||
string to_string(support_e support);
|
string to_string(support_e support);
|
||||||
string to_string(sort_e sort);
|
string to_string(sort_e sort);
|
||||||
void _print_params(const context& params);
|
void _print_params(const request_params& params);
|
||||||
rapidjson::Document _parse_json(const string& r, int verbose = 0);
|
rapidjson::Document _parse_json(const string& r, int verbose = 0);
|
||||||
string _prepare_request(const string& url, const context& context);
|
string _prepare_request(const string& url, const request_params& context);
|
||||||
|
|
||||||
bool register_account(const string& username, const string& password, const string& email);
|
bool register_account(const string& username, const string& password, const string& email);
|
||||||
bool login(const string& username, const string& password);
|
bool login(const string& username, const string& password);
|
||||||
|
|
@ -64,8 +71,8 @@ namespace gdpm::rest_api{
|
||||||
|
|
||||||
rapidjson::Document configure(const string& url = constants::HostUrl, type_e type = any, int verbose = 0);
|
rapidjson::Document configure(const string& url = constants::HostUrl, type_e type = any, int verbose = 0);
|
||||||
rapidjson::Document get_assets_list(const string& url = constants::HostUrl, type_e type = GDPM_DEFAULT_ASSET_TYPE, int category = GDPM_DEFAULT_ASSET_CATEGORY, support_e support = GDPM_DEFAULT_ASSET_SUPPORT, const string& filter = GDPM_DEFAULT_ASSET_FILTER, const std::string& user = GDPM_DEFAULT_ASSET_USER, const std::string& godot_version = GDPM_DEFAULT_ASSET_GODOT_VERSION, int max_results = GDPM_DEFAULT_ASSET_MAX_RESULTS, int page = GDPM_DEFAULT_ASSET_PAGE, sort_e sort = GDPM_DEFAULT_ASSET_SORT, bool reverse = GDPM_DEFAULT_ASSET_REVERSE, int verbose = GDPM_DEFAULT_ASSET_VERBOSE);
|
rapidjson::Document get_assets_list(const string& url = constants::HostUrl, type_e type = GDPM_DEFAULT_ASSET_TYPE, int category = GDPM_DEFAULT_ASSET_CATEGORY, support_e support = GDPM_DEFAULT_ASSET_SUPPORT, const string& filter = GDPM_DEFAULT_ASSET_FILTER, const std::string& user = GDPM_DEFAULT_ASSET_USER, const std::string& godot_version = GDPM_DEFAULT_ASSET_GODOT_VERSION, int max_results = GDPM_DEFAULT_ASSET_MAX_RESULTS, int page = GDPM_DEFAULT_ASSET_PAGE, sort_e sort = GDPM_DEFAULT_ASSET_SORT, bool reverse = GDPM_DEFAULT_ASSET_REVERSE, int verbose = GDPM_DEFAULT_ASSET_VERBOSE);
|
||||||
rapidjson::Document get_assets_list(const string& url, const context& params = {});
|
rapidjson::Document get_assets_list(const string& url, const request_params& params = {});
|
||||||
rapidjson::Document get_asset(const string& url, int asset_id, const context& params = {});
|
rapidjson::Document get_asset(const string& url, int asset_id, const request_params& params = {});
|
||||||
bool delete_asset(int asset_id); // ...for moderators
|
bool delete_asset(int asset_id); // ...for moderators
|
||||||
bool undelete_asset(int asset_id); // ...for moderators
|
bool undelete_asset(int asset_id); // ...for moderators
|
||||||
bool set_support_level(int asset_id); // ...for moderators
|
bool set_support_level(int asset_id); // ...for moderators
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ namespace gdpm{
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr void get(const var& v, T& target){
|
constexpr void get(const var& v, T& target){
|
||||||
switch(v.index()){
|
switch(v.index()){
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
|
|
@ -103,5 +105,11 @@ 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 = ", ");
|
||||||
|
|
||||||
// TODO: Add function to get size of decompressed zip
|
// TODO: Add function to get size of decompressed zip
|
||||||
|
|
||||||
|
namespace json {
|
||||||
|
std::string from_array(const std::set<std::string>& a, const std::string& prefix);
|
||||||
|
std::string from_object(const std::unordered_map<std::string, std::string>& m, const std::string& prefix, const std::string& spaces);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2c32b2f1f7cc530b1ec1f62c92f698643bb368db
|
Subproject commit 02783b6782ebedbb2bebc2e6ceda738ee51c7df2
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit a7f7891706c656903326f79baf74beb2b711688d
|
Subproject commit df83fbf22cfff76b875c13d324baf584c74e96d0
|
||||||
130
src/config.cpp
130
src/config.cpp
|
|
@ -4,6 +4,7 @@
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
// RapidJSON
|
// RapidJSON
|
||||||
#include <rapidjson/ostreamwrapper.h>
|
#include <rapidjson/ostreamwrapper.h>
|
||||||
|
|
@ -31,43 +32,30 @@
|
||||||
|
|
||||||
namespace gdpm::config{
|
namespace gdpm::config{
|
||||||
context config;
|
context config;
|
||||||
std::string to_json(const context& params){
|
|
||||||
auto _build_json_array = [](std::set<std::string> a){
|
|
||||||
std::string o{"["};
|
|
||||||
for(const std::string& src : a)
|
|
||||||
o += "\"" + src + "\",";
|
|
||||||
if(o.back() == ',')
|
|
||||||
o.pop_back();
|
|
||||||
o += "]";
|
|
||||||
return o;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto _build_json_object = [](const string_map& m){
|
string to_json(
|
||||||
string o{"{"};
|
const context& config,
|
||||||
std::for_each(m.begin(), m.end(), [&o](const string_pair& p){
|
bool pretty_print
|
||||||
o += std::format("\n\"{}\": \"{}\",", p.first, p.second);
|
){
|
||||||
});
|
|
||||||
if(o.back() == ',')
|
|
||||||
o.pop_back();
|
|
||||||
o += "}";
|
|
||||||
return o;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Build a JSON string to pass to document */
|
/* Build a JSON string to pass to document */
|
||||||
|
string prefix = (pretty_print) ? "\n\t" : "";
|
||||||
|
string spaces = (pretty_print) ? " " : "";
|
||||||
string json{
|
string json{
|
||||||
"{\"username\":\"" + params.username + "\","
|
"{" + prefix + "\"username\":" + spaces + "\"" + config.username + "\","
|
||||||
+ "\"password\":\"" + params.password + "\","
|
+ prefix + "\"password\":" + spaces + "\"" + config.password + "\","
|
||||||
+ "\"path\":\"" + params.path + "\","
|
+ prefix + "\"path\":"+ spaces + "\"" + config.path + "\","
|
||||||
+ "\"token\":\"" + params.token + "\","
|
+ prefix + "\"token\":" + spaces + "\"" + config.token + "\","
|
||||||
+ "\"godot_version\":\"" + params.godot_version + "\","
|
+ prefix + "\"godot_version\":" + spaces + "\"" + config.info.godot_version + "\","
|
||||||
+ "\"packages_dir\":\"" + params.packages_dir + "\","
|
+ prefix + "\"packages_dir\":" + spaces + "\"" + config.packages_dir + "\","
|
||||||
+ "\"tmp_dir\":\"" + params.tmp_dir + "\","
|
+ prefix + "\"tmp_dir\":" + spaces + "\"" + config.tmp_dir + "\","
|
||||||
+ "\"remote_sources\":" + _build_json_object(params.remote_sources) + ","
|
+ prefix + "\"remote_sources\":" + spaces + utils::json::from_object(config.remote_sources, prefix, spaces) + ","
|
||||||
+ "\"threads\":" + fmt::to_string(params.threads) + ","
|
+ prefix + "\"threads\":" + spaces + fmt::to_string(config.jobs) + ","
|
||||||
+ "\"timeout\":" + fmt::to_string(params.timeout) + ","
|
+ prefix + "\"timeout\":" + spaces + fmt::to_string(config.timeout) + ","
|
||||||
+ "\"enable_sync\":" + fmt::to_string(params.enable_sync) + ","
|
+ prefix + "\"enable_sync\":" + spaces + fmt::to_string(config.enable_sync) + ","
|
||||||
+ "\"enable_file_logging\":" + fmt::to_string(params.enable_file_logging)
|
+ prefix + "\"enable_file_logging\":" + spaces + fmt::to_string(config.enable_file_logging)
|
||||||
+ "}"
|
+ "\n}"
|
||||||
};
|
};
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
@ -75,16 +63,15 @@ namespace gdpm::config{
|
||||||
|
|
||||||
error load(
|
error load(
|
||||||
std::filesystem::path path,
|
std::filesystem::path path,
|
||||||
context& config,
|
context& config
|
||||||
int verbose
|
|
||||||
){
|
){
|
||||||
std::fstream file;
|
std::fstream file;
|
||||||
file.open(path, std::ios::in);
|
file.open(path, std::ios::in);
|
||||||
if(!file){
|
if(!file){
|
||||||
if(verbose)
|
if(config.verbose)
|
||||||
log::info("No configuration file found. Creating a new one.");
|
log::info("No configuration file found. Creating a new one.");
|
||||||
config = make_context();
|
config = make_context();
|
||||||
save(config.path, config, verbose);
|
save(config.path, config);
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
else if(file.is_open()){
|
else if(file.is_open()){
|
||||||
|
|
@ -100,7 +87,7 @@ namespace gdpm::config{
|
||||||
while(std::getline(file, line))
|
while(std::getline(file, line))
|
||||||
contents += line + "\n";
|
contents += line + "\n";
|
||||||
|
|
||||||
if(verbose > 0)
|
if(config.verbose > 0)
|
||||||
log::info("Loading configuration file...\n{}", contents.c_str());
|
log::info("Loading configuration file...\n{}", contents.c_str());
|
||||||
|
|
||||||
Document doc;
|
Document doc;
|
||||||
|
|
@ -164,10 +151,10 @@ namespace gdpm::config{
|
||||||
config.password = _get_value_string(doc, "password");
|
config.password = _get_value_string(doc, "password");
|
||||||
config.path = _get_value_string(doc, "path");
|
config.path = _get_value_string(doc, "path");
|
||||||
config.token = _get_value_string(doc, "token");
|
config.token = _get_value_string(doc, "token");
|
||||||
config.godot_version = _get_value_string(doc, "godot_version");
|
config.info.godot_version = _get_value_string(doc, "godot_version");
|
||||||
config.packages_dir = _get_value_string(doc, "packages_dir");
|
config.packages_dir = _get_value_string(doc, "packages_dir");
|
||||||
config.tmp_dir = _get_value_string(doc, "tmp_dir");
|
config.tmp_dir = _get_value_string(doc, "tmp_dir");
|
||||||
config.threads = _get_value_int(doc, "threads");
|
config.jobs = _get_value_int(doc, "threads");
|
||||||
config.enable_sync = _get_value_int(doc, "enable_sync");
|
config.enable_sync = _get_value_int(doc, "enable_sync");
|
||||||
config.enable_file_logging = _get_value_int(doc, "enable_file_logging");
|
config.enable_file_logging = _get_value_int(doc, "enable_file_logging");
|
||||||
}
|
}
|
||||||
|
|
@ -177,14 +164,13 @@ namespace gdpm::config{
|
||||||
|
|
||||||
error save(
|
error save(
|
||||||
std::filesystem::path path,
|
std::filesystem::path path,
|
||||||
const context& config,
|
const context& config
|
||||||
int verbose
|
|
||||||
){
|
){
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
/* Build a JSON string to pass to document */
|
/* Build a JSON string to pass to document */
|
||||||
string json = to_json(config);
|
string json = to_json(config);
|
||||||
if(verbose > 0)
|
if(config.verbose > 0)
|
||||||
log::info("Saving configuration file...\n{}", json.c_str());
|
log::info("Saving configuration file...\n{}", json.c_str());
|
||||||
|
|
||||||
/* Dump JSON config to file */
|
/* Dump JSON config to file */
|
||||||
|
|
@ -200,6 +186,52 @@ namespace gdpm::config{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
error handle_config(
|
||||||
|
config::context& config,
|
||||||
|
const args_t& args,
|
||||||
|
const var_opts& opts
|
||||||
|
){
|
||||||
|
std::for_each(opts.begin(), opts.end(), [](const var_opt& p){
|
||||||
|
log::println("opt: {}", p.first);
|
||||||
|
|
||||||
|
if (p.second.index() == STRING_LIST){
|
||||||
|
string_list p_list = get<string_list>(p.second);
|
||||||
|
std::for_each(p_list.begin(), p_list.end(), [](const string& o){
|
||||||
|
log::println("\t{}", o);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
log::println("opts count: {}", opts.size());
|
||||||
|
if(opts.contains("--username")){
|
||||||
|
string_list v = get<string_list>(opts.at("--username"));
|
||||||
|
log::println("username: {}", v[0]);
|
||||||
|
if(v.empty()){
|
||||||
|
log::println("username: {}", v[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
config.username = v[0];
|
||||||
|
}
|
||||||
|
if(opts.contains("godot_version")){
|
||||||
|
string_list v = get<string_list>(opts.at("godot-version"));
|
||||||
|
if(v.empty()){
|
||||||
|
// print godot-version
|
||||||
|
}
|
||||||
|
else
|
||||||
|
config.info.godot_version = get<string_list>(opts.at("godot-version"))[0];
|
||||||
|
}
|
||||||
|
if(opts.contains("threads")){
|
||||||
|
string_list v = get<string_list>(opts.at("threads"));
|
||||||
|
if(v.empty()){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save(config.path, config);
|
||||||
|
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
context make_context(
|
context make_context(
|
||||||
const string& username,
|
const string& username,
|
||||||
const string& password,
|
const string& password,
|
||||||
|
|
@ -220,15 +252,17 @@ namespace gdpm::config{
|
||||||
.password = password,
|
.password = password,
|
||||||
.path = path,
|
.path = path,
|
||||||
.token = token,
|
.token = token,
|
||||||
.godot_version = godot_version,
|
|
||||||
.packages_dir = (packages_dir.empty()) ? string(getenv("HOME")) + ".gdpm" : packages_dir,
|
.packages_dir = (packages_dir.empty()) ? string(getenv("HOME")) + ".gdpm" : packages_dir,
|
||||||
.tmp_dir = tmp_dir,
|
.tmp_dir = tmp_dir,
|
||||||
.remote_sources = remote_sources,
|
.remote_sources = remote_sources,
|
||||||
.threads = threads,
|
.jobs = threads,
|
||||||
.timeout = timeout,
|
.timeout = timeout,
|
||||||
.enable_sync = enable_sync,
|
.enable_sync = enable_sync,
|
||||||
.enable_file_logging = enable_file_logging,
|
.enable_file_logging = enable_file_logging,
|
||||||
.verbose = verbose
|
.verbose = verbose,
|
||||||
|
.info = {
|
||||||
|
.godot_version = godot_version,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
@ -252,4 +286,8 @@ namespace gdpm::config{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print(const context& config){
|
||||||
|
log::println("{}", to_json(config, true));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -11,9 +11,8 @@ int main(int argc, char **argv){
|
||||||
using namespace gdpm;
|
using namespace gdpm;
|
||||||
using namespace gdpm::package_manager;
|
using namespace gdpm::package_manager;
|
||||||
|
|
||||||
result_t <exec_args> r_input = initialize(argc, argv);
|
error error = initialize(argc, argv);
|
||||||
exec_args input = r_input.unwrap_unsafe();
|
parse_arguments(argc, argv);
|
||||||
execute(input);
|
|
||||||
finalize();
|
finalize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ namespace gdpm::package{
|
||||||
}
|
}
|
||||||
log::println("");
|
log::println("");
|
||||||
|
|
||||||
if(!params.skip_prompt){
|
if(!config.skip_prompt){
|
||||||
if(!utils::prompt_user_yn("Do you want to install these packages? (y/n)"))
|
if(!utils::prompt_user_yn("Do you want to install these packages? (y/n)"))
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ namespace gdpm::package{
|
||||||
/* Try and obtain all requested packages. */
|
/* Try and obtain all requested packages. */
|
||||||
std::vector<string_pair> dir_pairs;
|
std::vector<string_pair> dir_pairs;
|
||||||
task_list tasks;
|
task_list tasks;
|
||||||
rest_api::context rest_api_params = rest_api::make_from_config(config);
|
rest_api::request_params rest_api_params = rest_api::make_from_config(config);
|
||||||
for(auto& p : p_found){ // TODO: Execute each in parallel using coroutines??
|
for(auto& p : p_found){ // TODO: Execute each in parallel using coroutines??
|
||||||
|
|
||||||
/* Check if a remote source was provided. If not, then try to get packages
|
/* Check if a remote source was provided. If not, then try to get packages
|
||||||
|
|
@ -131,22 +131,6 @@ namespace gdpm::package{
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
log::error("Not a valid package.");
|
log::error("Not a valid package.");
|
||||||
/* Package for in cache so no remote request. Still need to populate RapidJson::Document to write to package.json.
|
|
||||||
NOTE: This may not be necessary at all!
|
|
||||||
*/
|
|
||||||
// doc["asset_id"].SetUint64(p.asset_id
|
|
||||||
// doc["type"].SetString(p.type, doc.GetAllocator());
|
|
||||||
// doc["title"].SetString(p.title, doc.GetAllocator());
|
|
||||||
// doc["author"].SetString(p.author, doc.GetAllocator());
|
|
||||||
// doc["author_id"].SetUint64(p.author_id);
|
|
||||||
// doc["version"].SetString(p.version, doc.GetAllocator());
|
|
||||||
// doc["category"].SetString(p.category, doc.GetAllocator());
|
|
||||||
// doc["godot_version"].SetString(p.godot_version, doc.GetAllocator());
|
|
||||||
// doc["cost"].SetString(p.cost, doc.GetAllocator());
|
|
||||||
// doc["description"].SetString(p.description, doc.GetAllocator());
|
|
||||||
// doc["support_level"].SetString(p.support_level, doc.GetAllocator());
|
|
||||||
// doc["download_url"].SetString(p.download_url, doc.GetAllocator());
|
|
||||||
// doc["download_hash"].SetString(p.download_hash, doc.GetAllocator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set directory and temp paths for storage */
|
/* Set directory and temp paths for storage */
|
||||||
|
|
@ -263,7 +247,7 @@ namespace gdpm::package{
|
||||||
log::print(" {} ", p.title);
|
log::print(" {} ", p.title);
|
||||||
log::println("");
|
log::println("");
|
||||||
|
|
||||||
if(!params.skip_prompt){
|
if(!config.skip_prompt){
|
||||||
if(!utils::prompt_user_yn("Do you want to remove these packages? (y/n)"))
|
if(!utils::prompt_user_yn("Do you want to remove these packages? (y/n)"))
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
@ -336,7 +320,7 @@ namespace gdpm::package{
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
/* If no package titles provided, update everything and then exit */
|
/* If no package titles provided, update everything and then exit */
|
||||||
rest_api::context rest_api_params = rest_api::make_from_config(config);
|
rest_api::request_params rest_api_params = rest_api::make_from_config(config);
|
||||||
if(package_titles.empty()){
|
if(package_titles.empty()){
|
||||||
std::string url{constants::HostUrl};
|
std::string url{constants::HostUrl};
|
||||||
url += rest_api::endpoints::GET_AssetId;
|
url += rest_api::endpoints::GET_AssetId;
|
||||||
|
|
@ -370,7 +354,7 @@ namespace gdpm::package{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!params.skip_prompt){
|
if(!config.skip_prompt){
|
||||||
if(!utils::prompt_user_yn("Do you want to update the following packages? (y/n)"))
|
if(!utils::prompt_user_yn("Do you want to update the following packages? (y/n)"))
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
@ -397,13 +381,13 @@ namespace gdpm::package{
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
rest_api::context rest_api_params = rest_api::make_from_config(config);
|
rest_api::request_params rest_api_params = rest_api::make_from_config(config);
|
||||||
for(const auto& p_title : package_titles){
|
for(const auto& p_title : package_titles){
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
rest_api_params.filter = http::url_escape(p_title);
|
rest_api_params.filter = http::url_escape(p_title);
|
||||||
rest_api_params.verbose = config.verbose;
|
rest_api_params.verbose = config.verbose;
|
||||||
rest_api_params.godot_version = config.godot_version;
|
rest_api_params.godot_version = config.info.godot_version;
|
||||||
rest_api_params.max_results = 200;
|
rest_api_params.max_results = 200;
|
||||||
|
|
||||||
std::string request_url{constants::HostUrl};
|
std::string request_url{constants::HostUrl};
|
||||||
|
|
@ -427,13 +411,12 @@ namespace gdpm::package{
|
||||||
|
|
||||||
error list(
|
error list(
|
||||||
const config::context& config,
|
const config::context& config,
|
||||||
const args_t& args,
|
const package::params& params
|
||||||
const opts_t& opts
|
|
||||||
){
|
){
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
string show((!args.empty()) ? args[0] : "");
|
string show((!params.sub_commands.empty()) ? params.sub_commands[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();
|
||||||
|
|
@ -493,13 +476,13 @@ 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 opts_t& opts
|
const package::params& params
|
||||||
){
|
){
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
path_list paths = {};
|
path_list paths = {};
|
||||||
if(opts.contains("path")){
|
if(params.opts.contains("path")){
|
||||||
paths = opts.at("path");
|
paths = get<path_list>(params.opts.at("path"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(paths.empty()){
|
if(paths.empty()){
|
||||||
|
|
@ -567,11 +550,11 @@ namespace gdpm::package{
|
||||||
error clone(
|
error clone(
|
||||||
const config::context& config,
|
const config::context& config,
|
||||||
const title_list& package_titles,
|
const title_list& package_titles,
|
||||||
const opts_t& paths
|
const package::params& params
|
||||||
){
|
){
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
if(paths.empty()){
|
if(params.opts.empty()){
|
||||||
error error(
|
error error(
|
||||||
constants::error::PATH_NOT_DEFINED,
|
constants::error::PATH_NOT_DEFINED,
|
||||||
"No path set. Use '--path' option to set a path."
|
"No path set. Use '--path' option to set a path."
|
||||||
|
|
@ -609,10 +592,10 @@ 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"));
|
||||||
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_list : paths){
|
for(const auto& path : paths){
|
||||||
for(const auto& path : path_list.second){
|
|
||||||
log::info("Cloning \"{}\" package to {}", p.title, path + "/" + p.title);
|
log::info("Cloning \"{}\" package to {}", 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};
|
||||||
|
|
@ -623,7 +606,6 @@ namespace gdpm::package{
|
||||||
std::filesystem::copy(from, to, copy_options::update_existing | copy_options::recursive);
|
std::filesystem::copy(from, to, copy_options::update_existing | copy_options::recursive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -705,12 +687,11 @@ namespace gdpm::package{
|
||||||
if(o.count(k)){ p = std::get<T>(o.at(k)); }
|
if(o.count(k)){ p = std::get<T>(o.at(k)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
params make_params(const var_args& args, const var_opts& opts){
|
params make_params(
|
||||||
|
const var_args& args,
|
||||||
|
const var_opts& opts
|
||||||
|
){
|
||||||
params p;
|
params p;
|
||||||
set_if_key_exists<int>(opts, "jobs", p.parallel_jobs);
|
|
||||||
set_if_key_exists(opts, "cache", p.enable_cache);
|
|
||||||
set_if_key_exists(opts, "sync", p.enable_sync);
|
|
||||||
set_if_key_exists(opts, "skip-prompt", p.skip_prompt);
|
|
||||||
set_if_key_exists(opts, "remote-source", p.remote_source);
|
set_if_key_exists(opts, "remote-source", p.remote_source);
|
||||||
// set_if_key_exists(opts, "install-method", p.install_method);
|
// set_if_key_exists(opts, "install-method", p.install_method);
|
||||||
|
|
||||||
|
|
@ -724,13 +705,13 @@ namespace gdpm::package{
|
||||||
){
|
){
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
rest_api::context rest_api_params = rest_api::make_from_config(config);
|
rest_api::request_params rest_api_params = rest_api::make_from_config(config);
|
||||||
rest_api_params.page = 0;
|
rest_api_params.page = 0;
|
||||||
int page = 0;
|
int page = 0;
|
||||||
int page_length = 0;
|
int page_length = 0;
|
||||||
// int total_pages = 0;
|
|
||||||
int total_items = 0;
|
int total_items = 0;
|
||||||
int items_left = 0;
|
int items_left = 0;
|
||||||
|
// int total_pages = 0;
|
||||||
|
|
||||||
log::info("Sychronizing database...");
|
log::info("Sychronizing database...");
|
||||||
do{
|
do{
|
||||||
|
|
@ -824,4 +805,13 @@ namespace gdpm::package{
|
||||||
|
|
||||||
return result_t(p_deps, error());
|
return result_t(p_deps, error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string to_json(
|
||||||
|
const info& info,
|
||||||
|
bool pretty_pretty
|
||||||
|
){
|
||||||
|
string json("");
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include <fmt/printf.h>
|
#include <fmt/printf.h>
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <cxxopts.hpp>
|
#include <cxxopts.hpp>
|
||||||
|
#include "clipp.h"
|
||||||
|
|
||||||
#include <rapidjson/ostreamwrapper.h>
|
#include <rapidjson/ostreamwrapper.h>
|
||||||
#include <rapidjson/prettywriter.h>
|
#include <rapidjson/prettywriter.h>
|
||||||
|
|
@ -35,24 +36,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace gdpm::package_manager{
|
namespace gdpm::package_manager{
|
||||||
remote::repository_map remote_sources;
|
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
config::context config;
|
config::context config;
|
||||||
rest_api::context api_params;
|
remote::repository_map remote_sources;
|
||||||
action_e action;
|
action_e action;
|
||||||
string_list packages;
|
|
||||||
// opts_t opts;
|
// opts_t opts;
|
||||||
bool skip_prompt = false;
|
bool skip_prompt = false;
|
||||||
bool clean_tmp_dir = false;
|
bool clean_tmp_dir = false;
|
||||||
int priority = -1;
|
int priority = -1;
|
||||||
|
|
||||||
|
|
||||||
result_t<exec_args> 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();
|
||||||
config = config::make_context();
|
config = config::make_context();
|
||||||
api_params = rest_api::make_context();
|
|
||||||
action = action_e::none;
|
action = action_e::none;
|
||||||
|
|
||||||
/* Check for config and create if not exists */
|
/* Check for config and create if not exists */
|
||||||
|
|
@ -62,287 +61,190 @@ namespace gdpm::package_manager{
|
||||||
error error = config::load(config.path, config);
|
error error = config::load(config.path, config);
|
||||||
if(error.has_occurred()){
|
if(error.has_occurred()){
|
||||||
log::error(error);
|
log::error(error);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the local databases if it doesn't exist already */
|
/* Create the local databases if it doesn't exist already */
|
||||||
error = cache::create_package_database();
|
error = cache::create_package_database();
|
||||||
if(error.has_occurred()){
|
if(error.has_occurred()){
|
||||||
log::error(error);
|
log::error(error);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run the rest of the program then exit */
|
return error;
|
||||||
cxxargs args = _parse_arguments(argc, argv);
|
|
||||||
return _handle_arguments(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int execute(const exec_args& in){
|
error finalize(){
|
||||||
run_command(action, in.args, in.opts);
|
|
||||||
if(clean_tmp_dir)
|
|
||||||
package::clean_temporary(config, packages);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void finalize(){
|
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
error error = config::save(config.path, config);
|
error error = config::save(config.path, config);
|
||||||
if(error()){
|
return error;
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cxxargs _parse_arguments(int argc, char **argv){
|
error parse_arguments(int argc, char **argv){
|
||||||
/* Parse command-line arguments using cxxopts */
|
/* Replace cxxopts with clipp */
|
||||||
cxxopts::Options options(
|
action_e action = action_e::none;
|
||||||
argv[0],
|
package::title_list package_titles;
|
||||||
"Experimental package manager made for managing assets for the Godot game engine through the command-line.\n"
|
string_list input;
|
||||||
|
package::params params;
|
||||||
|
args_t args;
|
||||||
|
var_opts opts;
|
||||||
|
|
||||||
|
/* Set global options */
|
||||||
|
auto configOpt = clipp::option("--config-path").set(config.path)% "set config path";
|
||||||
|
auto fileOpt = clipp::option("--file", "-f").set(input) % "read file as input";
|
||||||
|
auto pathOpt = clipp::option("--path").set(params.paths) % "specify a path to use with command";
|
||||||
|
auto typeOpt = clipp::option("--type").set(config.info.type) % "set package type (any|addon|project)";
|
||||||
|
auto sortOpt = clipp::option("--sort").set(config.api_params.sort) % "sort packages in order (rating|cost|name|updated)";
|
||||||
|
auto supportOpt = clipp::option("--support").set(config.api_params.support) % "set the support level for API (all|official|community|testing)";
|
||||||
|
auto maxResultsOpt = clipp::option("--max-results").set(config.api_params.max_results) % "set the request max results";
|
||||||
|
auto godotVersionOpt = clipp::option("--godot-version").set(config.api_params.godot_version) % "set the request Godot version";
|
||||||
|
auto packageDirOpt = clipp::option("--package-dir").set(config.packages_dir) % "set the global package location";
|
||||||
|
auto tmpDirOpt = clipp::option("--tmp-dir").set(config.tmp_dir) % "set the temporary download location";
|
||||||
|
auto timeoutOpt = clipp::option("--timeout").set(config.timeout) % "set the request timeout";
|
||||||
|
auto verboseOpt = clipp::option("--verbose", "-v").set(config.verbose) % "show verbose output";
|
||||||
|
|
||||||
|
/* Set the options */
|
||||||
|
auto cleanOpt = clipp::option("--clean").set(config.clean_temporary) % "enable/disable cleaning temps";
|
||||||
|
auto parallelOpt = clipp::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 syncOpt = clipp::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 remoteOpt = clipp::option("--remote").set(params.remote_source) % "set remote source to use";
|
||||||
|
|
||||||
|
auto packageValues = clipp::values("packages", package_titles);
|
||||||
|
auto requiredPath = clipp::required("--path", input);
|
||||||
|
|
||||||
|
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 addCmd = (
|
||||||
|
clipp::command("add").set(action, action_e::add)
|
||||||
|
.doc("Add a package to a local project"),
|
||||||
|
packageValues
|
||||||
|
);
|
||||||
|
auto removeCmd = (
|
||||||
|
clipp::command("remove")
|
||||||
|
.set(action, action_e::remove)
|
||||||
|
.doc("Remove a package from local project"),
|
||||||
|
packageValues
|
||||||
|
);
|
||||||
|
auto updateCmd = (
|
||||||
|
clipp::command("update")
|
||||||
|
.set(action, action_e::update)
|
||||||
|
.doc("Update package(s)"),
|
||||||
|
packageValues
|
||||||
|
);
|
||||||
|
auto searchCmd = (
|
||||||
|
clipp::command("search")
|
||||||
|
.set(action, action_e::search)
|
||||||
|
.doc("Search for package(s)"),
|
||||||
|
packageValues
|
||||||
|
);
|
||||||
|
auto exportCmd = (
|
||||||
|
clipp::command("export")
|
||||||
|
.set(action, action_e::p_export)
|
||||||
|
.doc("Export package list"),
|
||||||
|
clipp::values("path", input)
|
||||||
|
);
|
||||||
|
auto listCmd = (
|
||||||
|
clipp::command("list")
|
||||||
|
.set(action, action_e::list)
|
||||||
|
.doc("Show installed packages")
|
||||||
|
);
|
||||||
|
auto linkCmd = (
|
||||||
|
clipp::command("link")
|
||||||
|
.set(action, action_e::link)
|
||||||
|
.doc("Create symlink packages to project"),
|
||||||
|
packageValues,
|
||||||
|
requiredPath
|
||||||
|
);
|
||||||
|
auto cloneCmd = (
|
||||||
|
clipp::command("clone")
|
||||||
|
.set(action, action_e::clone)
|
||||||
|
.doc("Clone packages to project"),
|
||||||
|
packageValues,
|
||||||
|
requiredPath
|
||||||
|
);
|
||||||
|
auto cleanCmd = (
|
||||||
|
clipp::command("clean")
|
||||||
|
.set(action, action_e::clean)
|
||||||
|
.doc("Clean temporary files"),
|
||||||
|
packageValues
|
||||||
|
);
|
||||||
|
auto configCmd = (
|
||||||
|
clipp::command("config")
|
||||||
|
.set(action, action_e::config)
|
||||||
|
.doc("Set/get config properties")
|
||||||
|
);
|
||||||
|
auto fetchCmd = (
|
||||||
|
clipp::command("fetch")
|
||||||
|
.set(action, action_e::fetch)
|
||||||
|
.doc("Fetch asset metadata from remote source")
|
||||||
|
);
|
||||||
|
auto remoteCmd = (
|
||||||
|
clipp::command("remote")
|
||||||
|
.set(action, action_e::remote)
|
||||||
|
.doc("Manage remote sources")
|
||||||
|
.required("subcommand")
|
||||||
|
);
|
||||||
|
auto uiCmd = (
|
||||||
|
clipp::command("ui")
|
||||||
|
.set(action, action_e::ui)
|
||||||
|
.doc("Show the UI")
|
||||||
|
);
|
||||||
|
auto helpCmd = (
|
||||||
|
clipp::command("help")
|
||||||
|
.set(action, action_e::help)
|
||||||
);
|
);
|
||||||
options.allow_unrecognised_options();
|
|
||||||
options.custom_help("[COMMAND] [OPTIONS...]");
|
|
||||||
options.add_options("Command")
|
|
||||||
("command", "Specify the input parameters", cxxopts::value<string>())
|
|
||||||
("positional", "", cxxopts::value<string_list>())
|
|
||||||
("install", "Install package or packages.", cxxopts::value<string_list>()->implicit_value(""), "<packages...>")
|
|
||||||
("remove", "Remove a package or packages.", cxxopts::value<string_list>()->implicit_value(""), "<packages...>")
|
|
||||||
("update", "Update a package or packages. This will update all packages if no argument is provided.", cxxopts::value<string_list>()->implicit_value(""), "<packages...>")
|
|
||||||
("search", "Search for a package or packages.", cxxopts::value<string_list>(), "<packages...>")
|
|
||||||
("export", "Export list of packages", cxxopts::value<string>()->default_value("./gdpm-packages.txt"))
|
|
||||||
("list", "Show list of installed packages.")
|
|
||||||
("link", "Create a symlink (or shortcut) to target directory. Must be used with the `--path` argument.", cxxopts::value<string_list>(), "<packages...>")
|
|
||||||
("clone", "Clone packages into target directory. Must be used with the `--path` argument.", cxxopts::value<string_list>(), "<packages...>")
|
|
||||||
("cache", "Caching operations", cxxopts::value<string_list>())
|
|
||||||
("clean", "Clean temporary downloaded files.")
|
|
||||||
("fetch", "Fetch asset data from remote sources.")
|
|
||||||
("remote", "Set a source repository.", cxxopts::value<string>()->default_value(constants::AssetRepo), "<url>")
|
|
||||||
("h,help", "Print this message and exit.")
|
|
||||||
("version", "Show the current version and exit.")
|
|
||||||
;
|
|
||||||
options.parse_positional({"command", "positional"});
|
|
||||||
options.positional_help("");
|
|
||||||
options.add_options("Other")
|
|
||||||
("c,config", "Set the config file path.", cxxopts::value<string>())
|
|
||||||
("f,file", "Read file to install or remove packages.", cxxopts::value<string>(), "<path>")
|
|
||||||
("path", "Specify a path to use with a command", cxxopts::value<string_list>())
|
|
||||||
("type", "Set package type (any|addon|project).", cxxopts::value<string>())
|
|
||||||
("sort", "Sort packages in order (rating|cost|name|updated).", cxxopts::value<string>())
|
|
||||||
("support", "Set the support level for API (all|official|community|testing).")
|
|
||||||
("max-results", "Set the max results to return from search.", cxxopts::value<int>()->default_value("500"), "<int>")
|
|
||||||
("godot-version", "Set the Godot version to include in request.", cxxopts::value<string>())
|
|
||||||
("package-dir", "Set the local package storage location.", cxxopts::value<string>())
|
|
||||||
("tmp-dir", "Set the local temporary storage location.", cxxopts::value<string>())
|
|
||||||
("timeout", "Set the amount of time to wait for a response.", cxxopts::value<size_t>())
|
|
||||||
("no-sync", "Disable synchronizing with remote.", cxxopts::value<bool>()->implicit_value("true")->default_value("false"))
|
|
||||||
("y,no-prompt", "Bypass yes/no prompt for installing or removing packages.")
|
|
||||||
("v,verbose", "Show verbose output.", cxxopts::value<int>()->implicit_value("1")->default_value("0"), "0-5")
|
|
||||||
;
|
|
||||||
|
|
||||||
auto result = options.parse(argc, argv);
|
auto cli = (
|
||||||
return {result, options};
|
(installCmd | addCmd | removeCmd | updateCmd | searchCmd | exportCmd |
|
||||||
}
|
listCmd | linkCmd | cloneCmd | cleanCmd | configCmd | fetchCmd |
|
||||||
|
remoteCmd | uiCmd | helpCmd)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Make help output */
|
||||||
template <typename T>
|
string map_page_format("");
|
||||||
void insert(
|
auto man_page = clipp::make_man_page(cli);
|
||||||
var_opts& opts,
|
std::for_each(man_page.begin(), man_page.end(),
|
||||||
const cxxopts::ParseResult& result,
|
[&map_page_format](const clipp::man_page::section& s){
|
||||||
const string& key
|
map_page_format += s.title() + "\n";
|
||||||
){
|
map_page_format += s.content() + "\n";
|
||||||
opts.insert(var_opt(key, result[key].as<T>()));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
result_t<exec_args> _handle_arguments(const cxxargs& args){
|
|
||||||
const auto& result = args.result;
|
|
||||||
const auto& options = args.options;
|
|
||||||
exec_args in;
|
|
||||||
|
|
||||||
// auto get_opt = [](const string& key){
|
|
||||||
// result[key].as<T>();
|
|
||||||
// }
|
|
||||||
// auto get_opt = [&result]<typename V>(const string& key){
|
|
||||||
// return opt(key, result[key].as<V>());
|
|
||||||
// };
|
|
||||||
|
|
||||||
/* Set option variables first to be used in functions below. */
|
|
||||||
if(result.count("search")){
|
|
||||||
in.args = result["search"].as<var_args>();
|
|
||||||
}
|
}
|
||||||
if(result.count("help")){
|
);
|
||||||
log::println("{}", options.help());
|
if(clipp::parse(argc, argv, cli)){
|
||||||
}
|
switch(action){
|
||||||
if(result.count("config")){
|
case action_e::install: package::install(config, package_titles, params); break;
|
||||||
config.path = result["config"].as<string>();
|
case action_e::add: break;
|
||||||
insert<string>(in.opts, result, "config");
|
case action_e::remove: package::remove(config, package_titles, params); break;
|
||||||
config::load(config.path, config);
|
case action_e::update: package::update(config, package_titles, params); break;
|
||||||
log::info("Config: {}", config.path);
|
case action_e::search: package::search(config, package_titles, params); break;
|
||||||
}
|
case action_e::p_export: package::export_to(input); break;
|
||||||
if(result.count("remote")){
|
case action_e::list: package::list(config, params); break;
|
||||||
string sub_command = result["remote"].as<string>();
|
|
||||||
log::print("sub command: {}", sub_command);
|
|
||||||
if(sub_command == "add"){
|
|
||||||
string argv = result.arguments_string();
|
|
||||||
log::println("argv: {}", argv);
|
|
||||||
remote::add_repositories(config, {});
|
|
||||||
}
|
|
||||||
else if(sub_command == "remove"){
|
|
||||||
remote::remove_respositories(config, {});
|
|
||||||
log::println("argv: {}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(result.count("file")){
|
|
||||||
string path = result["file"].as<string>();
|
|
||||||
string contents = utils::readfile(path);
|
|
||||||
packages = utils::parse_lines(contents);
|
|
||||||
insert<string>(in.opts, result, "file");
|
|
||||||
}
|
|
||||||
if(result.count("path")){
|
|
||||||
insert<string_list>(in.opts, result, "path");
|
|
||||||
}
|
|
||||||
if(result.count("sort")){
|
|
||||||
string r = result["sort"].as<string>();
|
|
||||||
rest_api::sort_e sort = rest_api::sort_e::none;
|
|
||||||
if(r == "none") sort = rest_api::sort_e::none;
|
|
||||||
else if(r == "rating") sort = rest_api::sort_e::rating;
|
|
||||||
else if(r == "cost") sort = rest_api::sort_e::cost;
|
|
||||||
else if(r == "name") sort = rest_api::sort_e::name;
|
|
||||||
else if(r == "updated") sort = rest_api::sort_e::updated;
|
|
||||||
api_params.sort = sort;
|
|
||||||
in.opts.insert(var_opt("sort", r));
|
|
||||||
}
|
|
||||||
if(result.count("type")){
|
|
||||||
string r = result["type"].as<string>();
|
|
||||||
rest_api::type_e type = rest_api::type_e::any;
|
|
||||||
if(r == "any") type = rest_api::type_e::any;
|
|
||||||
else if(r == "addon") type = rest_api::type_e::addon;
|
|
||||||
else if(r == "project") type = rest_api::type_e::project;
|
|
||||||
api_params.type = type;
|
|
||||||
in.opts.insert(var_opt("type", r));
|
|
||||||
}
|
|
||||||
if(result.count("support")){
|
|
||||||
string r = result["support"].as<string>();
|
|
||||||
rest_api::support_e support = rest_api::support_e::all;
|
|
||||||
if(r == "all") support = rest_api::support_e::all;
|
|
||||||
else if(r == "official") support = rest_api::support_e::official;
|
|
||||||
else if(r == "community") support = rest_api::support_e::community;
|
|
||||||
else if(r == "testing") support = rest_api::support_e::testing;
|
|
||||||
api_params.support = support;
|
|
||||||
in.opts.insert(var_opt("support", r));
|
|
||||||
}
|
|
||||||
if(result.count("max-results")){
|
|
||||||
api_params.max_results = result["max-results"].as<int>();
|
|
||||||
insert<int>(in.opts, result, "max-results");
|
|
||||||
}
|
|
||||||
if(result.count("godot-version")){
|
|
||||||
config.godot_version = result["godot-version"].as<string>();
|
|
||||||
insert<string>(in.opts, result, "godot-version");
|
|
||||||
}
|
|
||||||
if(result.count("timeout")){
|
|
||||||
config.timeout = result["timeout"].as<size_t>();
|
|
||||||
insert<size_t>(in.opts, result, "timeout");
|
|
||||||
}
|
|
||||||
if(result.count("no-sync")){
|
|
||||||
config.enable_sync = false;
|
|
||||||
in.opts.insert(var_opt("sync", "disabled"));
|
|
||||||
}
|
|
||||||
if(result.count("package-dir")){
|
|
||||||
config.packages_dir = result["package-dir"].as<string>();
|
|
||||||
insert<string>(in.opts, result, "package-dir");
|
|
||||||
}
|
|
||||||
if(result.count("tmp-dir")){
|
|
||||||
config.tmp_dir = result["tmp-dir"].as<string>();
|
|
||||||
insert<string>(in.opts, result, "tmp-dir");
|
|
||||||
}
|
|
||||||
if(result.count("yes")){
|
|
||||||
skip_prompt = true;
|
|
||||||
in.opts.insert(opt("skip-prompt", true));
|
|
||||||
}
|
|
||||||
if(result.count("link")){
|
|
||||||
packages = result["link"].as<string_list>();
|
|
||||||
insert<string_list>(in.opts, result, "link");
|
|
||||||
}
|
|
||||||
if(result.count("clone")){
|
|
||||||
packages = result["clone"].as<string_list>();
|
|
||||||
insert<string_list>(in.opts, result, "clone");
|
|
||||||
}
|
|
||||||
if(result.count("clean")){
|
|
||||||
in.opts.insert(opt("clean", true));
|
|
||||||
clean_tmp_dir = true;
|
|
||||||
}
|
|
||||||
config.verbose = 0;
|
|
||||||
config.verbose += result["verbose"].as<int>();
|
|
||||||
insert<int>(in.opts, result, "verbose");
|
|
||||||
|
|
||||||
string json = to_json(config);
|
|
||||||
if(config.verbose > 0){
|
|
||||||
log::println("Verbose set to level {}", config.verbose);
|
|
||||||
log::println("{}", json);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!result.count("command")){
|
|
||||||
log::error("Command required. See \"help\" for more information.");
|
|
||||||
return result_t(in, error());
|
|
||||||
}
|
|
||||||
|
|
||||||
string sub_command = result["command"].as<string>();
|
|
||||||
if(result.count("positional")){
|
|
||||||
string_list _argv = result["positional"].as<string_list>();
|
|
||||||
args_t argv{_argv.begin(), _argv.end()};
|
|
||||||
if(!argv.empty()){
|
|
||||||
for(const auto& arg : argv){
|
|
||||||
in.args.emplace_back(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Catch arguments passed with dashes */
|
|
||||||
if(sub_command == "install") action = action_e::install;
|
|
||||||
else if(sub_command == "add") action = action_e::add;
|
|
||||||
else if(sub_command == "remove") action = action_e::remove;
|
|
||||||
else if(sub_command == "update") action = action_e::update;
|
|
||||||
else if(sub_command == "search") action = action_e::search;
|
|
||||||
else if(sub_command == "export") action = action_e::p_export;
|
|
||||||
else if(sub_command == "list") action = action_e::list;
|
|
||||||
else if(sub_command == "link") action = action_e::link;
|
|
||||||
else if(sub_command == "clone") action = action_e::clone;
|
|
||||||
else if(sub_command == "clean") action = action_e::clean;
|
|
||||||
else if(sub_command == "sync") action = action_e::sync;
|
|
||||||
else if(sub_command == "remote") action = action_e::remote;
|
|
||||||
else if(sub_command == "help"){ action = action_e::help;
|
|
||||||
log::println("{}", options.help());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
log::error("Unrecognized command. Try 'gdpm help' for more info.");
|
|
||||||
}
|
|
||||||
return result_t(in, error());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Used to run the command AFTER parsing and setting all command line args. */
|
|
||||||
void run_command(action_e c, const var_args& args, const var_opts& opts){
|
|
||||||
package::params params = package::make_params(args, opts);
|
|
||||||
string_list args_list = unwrap(args);
|
|
||||||
opts_t opts_list = unwrap(opts);
|
|
||||||
params.skip_prompt = skip_prompt;
|
|
||||||
switch(c){
|
|
||||||
case action_e::install: package::install(config, args_list, params); break;
|
|
||||||
case action_e::remove: package::remove(config, args_list, params); break;
|
|
||||||
case action_e::update: package::update(config, args_list, params); break;
|
|
||||||
case action_e::search: package::search(config, args_list, params); break;
|
|
||||||
case action_e::p_export: package::export_to(args_list); break;
|
|
||||||
case action_e::list: package::list(config, args_list, opts_list); break;
|
|
||||||
/* ...opts are the paths here */
|
/* ...opts are the paths here */
|
||||||
case action_e::link: package::link(config, args_list, opts_list); break;
|
case action_e::link: package::link(config, package_titles, params); break;
|
||||||
case action_e::clone: package::clone(config, args_list, opts_list); break;
|
case action_e::clone: package::clone(config, package_titles, params); break;
|
||||||
case action_e::clean: package::clean_temporary(config, args_list); break;
|
case action_e::clean: package::clean_temporary(config, package_titles); break;
|
||||||
case action_e::sync: package::synchronize_database(config, args_list); break;
|
case action_e::config: config::handle_config(config, package_titles, opts); break;
|
||||||
case action_e::remote: remote::_handle_remote(config, args_list, opts_list); break;
|
case action_e::fetch: package::synchronize_database(config, package_titles); break;
|
||||||
case action_e::help: /* ...runs in handle_arguments() */ 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::ui: log::info("ui not implemented yet"); break;
|
||||||
|
case action_e::help: log::println("{}", map_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 {
|
||||||
|
log::println("{}", map_page_format);
|
||||||
|
}
|
||||||
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gdpm::package_manager
|
} // namespace gdpm::package_manager
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
|
|
||||||
namespace gdpm::remote{
|
namespace gdpm::remote{
|
||||||
error _handle_remote(
|
error handle_remote(
|
||||||
config::context& config,
|
config::context& config,
|
||||||
const args_t& args,
|
const args_t& args,
|
||||||
const opts_t& opts
|
const var_opts& opts
|
||||||
){
|
){
|
||||||
/* Check if enough arguments are supplied */
|
/* Check if enough arguments are supplied */
|
||||||
size_t argc = args.size();
|
size_t argc = args.size();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
#include "rest_api.hpp"
|
#include "rest_api.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "http.hpp"
|
#include "http.hpp"
|
||||||
|
|
@ -16,15 +17,27 @@
|
||||||
|
|
||||||
namespace gdpm::rest_api{
|
namespace gdpm::rest_api{
|
||||||
|
|
||||||
context make_from_config(const config::context& config){
|
request_params make_from_config(const config::context& config){
|
||||||
context params = make_context();
|
request_params params = make_request_params();
|
||||||
params.godot_version = config.godot_version;
|
params.godot_version = config.info.godot_version;
|
||||||
params.verbose = config.verbose;
|
params.verbose = config.verbose;
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
context make_context(type_e type, int category, support_e support, const std::string& filter, const std::string& user, const std::string& godot_version, int max_results, int page, sort_e sort, bool reverse, int verbose){
|
request_params make_request_params(
|
||||||
context params{
|
type_e type,
|
||||||
|
int category,
|
||||||
|
support_e support,
|
||||||
|
const string& filter,
|
||||||
|
const string& user,
|
||||||
|
const string& godot_version,
|
||||||
|
int max_results,
|
||||||
|
int page,
|
||||||
|
sort_e sort,
|
||||||
|
bool reverse,
|
||||||
|
int verbose
|
||||||
|
){
|
||||||
|
request_params params{
|
||||||
.type = type,
|
.type = type,
|
||||||
.category = category,
|
.category = category,
|
||||||
.support = support,
|
.support = support,
|
||||||
|
|
@ -76,6 +89,10 @@ namespace gdpm::rest_api{
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string to_json(const rapidjson::Document& doc){
|
||||||
|
return doc.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
string to_string(type_e type){
|
string to_string(type_e type){
|
||||||
string _s{"type="};
|
string _s{"type="};
|
||||||
switch(type){
|
switch(type){
|
||||||
|
|
@ -98,6 +115,7 @@ namespace gdpm::rest_api{
|
||||||
}
|
}
|
||||||
|
|
||||||
string to_string(sort_e sort){
|
string to_string(sort_e sort){
|
||||||
|
|
||||||
string _s{"sort="};
|
string _s{"sort="};
|
||||||
switch(sort){
|
switch(sort){
|
||||||
case none: _s += ""; break;
|
case none: _s += ""; break;
|
||||||
|
|
@ -111,13 +129,13 @@ namespace gdpm::rest_api{
|
||||||
|
|
||||||
string _prepare_request(
|
string _prepare_request(
|
||||||
const string &url,
|
const string &url,
|
||||||
const context &c
|
const request_params &c
|
||||||
){
|
){
|
||||||
string request_url{url};
|
string request_url{url};
|
||||||
request_url += to_string(c.type);
|
request_url += to_string(static_cast<type_e>(c.type));
|
||||||
request_url += (c.category <= 0) ? "&category=" : "&category="+std::to_string(c.category);
|
request_url += (c.category <= 0) ? "&category=" : "&category="+std::to_string(c.category);
|
||||||
request_url += "&" + to_string(c.support);
|
request_url += "&" + to_string(static_cast<support_e>(c.support));
|
||||||
request_url += "&" + to_string(c.sort);
|
request_url += "&" + to_string(static_cast<sort_e>(c.sort));
|
||||||
request_url += (!c.filter.empty()) ? "&filter="+c.filter : "";
|
request_url += (!c.filter.empty()) ? "&filter="+c.filter : "";
|
||||||
request_url += (!c.godot_version.empty()) ? "&godot_version="+c.godot_version : "";
|
request_url += (!c.godot_version.empty()) ? "&godot_version="+c.godot_version : "";
|
||||||
request_url += "&max_results=" + std::to_string(c.max_results);
|
request_url += "&max_results=" + std::to_string(c.max_results);
|
||||||
|
|
@ -126,7 +144,7 @@ namespace gdpm::rest_api{
|
||||||
return request_url;
|
return request_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _print_params(const context& params){
|
void _print_params(const request_params& params){
|
||||||
log::println("params: \n"
|
log::println("params: \n"
|
||||||
"\ttype: {}\n"
|
"\ttype: {}\n"
|
||||||
"\tcategory: {}\n"
|
"\tcategory: {}\n"
|
||||||
|
|
@ -170,7 +188,7 @@ namespace gdpm::rest_api{
|
||||||
bool reverse,
|
bool reverse,
|
||||||
int verbose
|
int verbose
|
||||||
){
|
){
|
||||||
context c{
|
request_params c{
|
||||||
.type = type,
|
.type = type,
|
||||||
.category = category,
|
.category = category,
|
||||||
.support = support,
|
.support = support,
|
||||||
|
|
@ -188,7 +206,7 @@ namespace gdpm::rest_api{
|
||||||
|
|
||||||
rapidjson::Document get_assets_list(
|
rapidjson::Document get_assets_list(
|
||||||
const string& url,
|
const string& url,
|
||||||
const context& c
|
const request_params& c
|
||||||
){
|
){
|
||||||
string request_url = _prepare_request(url, c);
|
string request_url = _prepare_request(url, c);
|
||||||
http::response r = http::request_get(request_url);
|
http::response r = http::request_get(request_url);
|
||||||
|
|
@ -200,13 +218,14 @@ namespace gdpm::rest_api{
|
||||||
rapidjson::Document get_asset(
|
rapidjson::Document get_asset(
|
||||||
const string& url,
|
const string& url,
|
||||||
int asset_id,
|
int asset_id,
|
||||||
const context& params
|
const request_params& params
|
||||||
){
|
){
|
||||||
string request_url = _prepare_request(url, params);
|
string request_url = _prepare_request(url, params);
|
||||||
utils::replace_all(request_url, "{id}", std::to_string(asset_id));
|
utils::replace_all(request_url, "{id}", std::to_string(asset_id));
|
||||||
http::response r = http::request_get(request_url.c_str());
|
http::response r = http::request_get(request_url.c_str());
|
||||||
if(params.verbose > 0)
|
if(params.verbose > 0)
|
||||||
log::info("URL: {}", request_url);
|
log::info("URL: {}", request_url);
|
||||||
|
|
||||||
return _parse_json(r.body);
|
return _parse_json(r.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <asm-generic/errno-base.h>
|
#include <asm-generic/errno-base.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
@ -202,4 +203,39 @@ namespace gdpm::utils{
|
||||||
});
|
});
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace json {
|
||||||
|
|
||||||
|
std::string from_array(
|
||||||
|
const std::set<std::string>& a,
|
||||||
|
const std::string& prefix
|
||||||
|
){
|
||||||
|
std::string o{"["};
|
||||||
|
for(const std::string& src : a)
|
||||||
|
o += prefix + "\t\"" + src + "\",";
|
||||||
|
if(o.back() == ',')
|
||||||
|
o.pop_back();
|
||||||
|
o += prefix + "]";
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::string from_object(
|
||||||
|
const std::unordered_map<std::string, std::string>& m,
|
||||||
|
const std::string& prefix,
|
||||||
|
const std::string& spaces
|
||||||
|
){
|
||||||
|
std::string o{"{"};
|
||||||
|
std::for_each(m.begin(), m.end(),
|
||||||
|
[&o, &prefix, &spaces](const std::pair<std::string, std::string>& p){
|
||||||
|
o += std::format("{}\t\"{}\":{}\"{}\",", prefix, p.first, spaces, p.second);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if(o.back() == ',')
|
||||||
|
o.pop_back();
|
||||||
|
o += prefix + "}";
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace gdpm::utils
|
} // namespace gdpm::utils
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,26 @@ TEST_SUITE("Command functions"){
|
||||||
using namespace gdpm;
|
using namespace gdpm;
|
||||||
using namespace gdpm::package_manager;
|
using namespace gdpm::package_manager;
|
||||||
|
|
||||||
config::context config = config::make_context();
|
package::params params = package::params{
|
||||||
package::params params = package::params();
|
.remote_source = "test"
|
||||||
|
};
|
||||||
|
config::context config = config::context{
|
||||||
|
.username = "",
|
||||||
|
.password = "",
|
||||||
|
.path = "tests/gdpm/config.json",
|
||||||
|
.packages_dir = "tests/gdpm/packages",
|
||||||
|
.tmp_dir = "tests/gdpm/.tmp",
|
||||||
|
.remote_sources = {
|
||||||
|
{"test", "http://godotengine.org/asset-library/api"}
|
||||||
|
},
|
||||||
|
.info {
|
||||||
|
.godot_version = "latest",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
package::title_list package_titles{"ResolutionManagerPlugin","godot-hmac", "Godot"};
|
package::title_list package_titles{"ResolutionManagerPlugin","godot-hmac", "Godot"};
|
||||||
|
|
||||||
|
/* Set the default parameters to use. */
|
||||||
auto check_error = [](const error& error){
|
auto check_error = [](const error& error){
|
||||||
if(error.has_occurred()){
|
if(error.has_occurred()){
|
||||||
log::error(error);
|
log::error(error);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue