Refaaaacttt00000rr

This commit is contained in:
Your Name 2025-05-04 11:30:57 +12:00
parent 6380ce9178
commit 0e9466365e
11 changed files with 25977 additions and 219 deletions

View File

@ -2,9 +2,8 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "config.hpp" #include "config.hpp"
#include "utils/envmanager.hpp"
#include "utils/utils.hpp" #include "utils/utils.hpp"
#include "utils/json.hpp"
#include <filesystem> #include <filesystem>
namespace dropshell { namespace dropshell {
@ -16,103 +15,116 @@ config & gConfig() {
} }
config::config() { config::config() : mIsConfigSet(false) {
} }
config::~config() { config::~config() {
} }
bool config::load_config() { bool config::load_config() { // load json config file.
std::string config_path = localfile::dropshell_env(); std::string config_path = localfile::dropshell_json();
if (config_path.empty() || !std::filesystem::exists(config_path)) if (config_path.empty() || !std::filesystem::exists(config_path))
return false; return false;
envmanager config_env(config_path); std::ifstream config_file(config_path);
if (!config_env.load()) if (!config_file.is_open())
return false; return false;
std::string directories = config_env.get_variable_substituted("local.config.directories"); try {
if (directories.empty()) mConfig = nlohmann::json::parse(config_file);
return false; }
catch (nlohmann::json::parse_error& ex)
{
std::cerr << "Error: Failed to parse config file: " << ex.what() << std::endl;
return false;
}
// Split the directories string into a vector of strings mIsConfigSet = true;
mLocalConfigPaths = string2multi(directories);
mLocalBackupPath = config_env.get_variable_substituted("local.backup.directory");
// legacy config file conversion
if (mLocalBackupPath.empty() && mLocalConfigPaths.size()>0)
mLocalBackupPath = mLocalConfigPaths[0] + "/backups";
//std::cout << "Local config path: " << mLocalConfigPath << std::endl;
return true; return true;
} }
void config::save_config() bool config::save_config()
{ {
if (mLocalConfigPaths.empty()) std::string config_path = localfile::dropshell_json();
if (config_path.empty())
return false;
std::filesystem::create_directories(get_parent(config_path));
std::ofstream config_file(config_path);
if (!config_file.is_open())
return false;
if (!mIsConfigSet)
{ {
std::cerr << "Warning: Unable to save configuration file, as DropShell has not been initialised."<< std::endl; std::string homedir = localpath::current_user_home();
std::cerr << "Please run 'dropshell init <path>' to initialise DropShell." << std::endl; std::string dropshell_base = homedir + "/.dropshell";
return; mConfig["tempfiles"] = dropshell_base + "/tmp";
} mConfig["backups"] = dropshell_base + "/backups";
mConfig["template_cache"] = dropshell_base + "/cache";
mConfig["template_registry_urls"] = {
"https://templates.dropshell.app"
};
mConfig["server_definition_paths"] = {
dropshell_base + "/servers"
};
mConfig["template_upload_registry_url"] = "https://templates.dropshell.app";
mConfig["template_upload_registry_token"] = "SECRETTOKEN";
}
std::string parent_path = dropshell::get_parent(localfile::dropshell_env()); config_file << mConfig.dump(4);
std::filesystem::create_directories(parent_path); config_file.close();
return true;
std::string config_path = localfile::dropshell_env(); std::filesystem::create_directories(get_local_template_cache_path());
envmanager config_env(config_path); std::filesystem::create_directories(get_local_backup_path());
std::filesystem::create_directories(get_local_tempfiles_path());
config_env.set_variable("local.config.directories", multi2string(mLocalConfigPaths)); for (auto & p : get_local_server_definition_paths())
config_env.set_variable("local.backup.directory", mLocalBackupPath); std::filesystem::create_directories(p);
config_env.save();
} }
bool config::is_config_set() const bool config::is_config_set() const
{ {
return !mLocalConfigPaths.empty() && !mLocalBackupPath.empty(); return mIsConfigSet;
} }
std::string config::get_local_tempfiles_path() {
const std::vector<std::string> & config::get_local_config_directories() const return mConfig["tempfiles"];
{
return mLocalConfigPaths;
} }
bool config::add_local_config_directory(const std::string &path) std::string config::get_local_backup_path() {
{ return mConfig["backups"];
if (path.empty()) }
return false;
// Convert to canonical path, using std::filesystem std::string config::get_local_template_cache_path() {
std::filesystem::path abs_path = std::filesystem::canonical(path); return mConfig["template_cache"];
}
// The directory must exist
if (!std::filesystem::exists(abs_path)) { std::vector<std::string> config::get_template_registry_urls() {
std::cerr << "Error: The local config directory does not exist: " << abs_path.string() << std::endl; nlohmann::json template_registry_urls = mConfig["template_registry_urls"];
return false; std::vector<std::string> urls;
for (auto &url : template_registry_urls) {
urls.push_back(url);
} }
return urls;
// Add to config paths if not already there
for (auto &p : mLocalConfigPaths)
{ // robustly compare the two paths.
if (p == abs_path.string())
{
std::cerr << "Warning: The local config directory is already registered: " << abs_path.string() << std::endl;
std::cerr << "No changes made to the DropShell configuration." << std::endl;
return false;
}
}
mLocalConfigPaths.push_back(abs_path.string());
if (mLocalBackupPath.empty())
mLocalBackupPath = abs_path.string() + "/backups";
return true;
} }
const std::string &config::get_local_backup_path() const std::vector<std::string> config::get_local_server_definition_paths() {
{ nlohmann::json server_definition_paths = mConfig["server_definition_paths"];
return mLocalBackupPath; std::vector<std::string> paths;
for (auto &path : server_definition_paths) {
paths.push_back(path);
}
return paths;
}
std::string config::get_template_upload_registry_url() {
return mConfig["template_upload_registry_url"];
}
std::string config::get_template_upload_registry_token() {
return mConfig["template_upload_registry_token"];
} }
} // namespace dropshell } // namespace dropshell

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "utils/json.hpp"
namespace dropshell { namespace dropshell {
@ -9,19 +10,25 @@ class config {
public: public:
config(); config();
~config(); ~config();
bool load_config(); bool load_config();
void save_config(); bool save_config();
bool is_config_set() const; bool is_config_set() const;
const std::vector<std::string> & get_local_config_directories() const;
bool add_local_config_directory(const std::string& path);
const std::string & get_local_backup_path() const; std::string get_local_tempfiles_path();
std::string get_local_backup_path();
std::string get_local_template_cache_path();
std::vector<std::string> get_template_registry_urls();
std::vector<std::string> get_local_server_definition_paths();
std::string get_template_upload_registry_url();
std::string get_template_upload_registry_token();
private: private:
std::vector<std::string> mLocalConfigPaths; nlohmann::json mConfig;
std::string mLocalBackupPath; bool mIsConfigSet;
}; };

View File

@ -33,7 +33,7 @@ void print_help() {
std::cout << std::endl; std::cout << std::endl;
std::cout << "dropshell ..." << std::endl; std::cout << "dropshell ..." << std::endl;
std::cout << " help Show this help message" << std::endl; std::cout << " help Show this help message" << std::endl;
std::cout << " init DIR Add DIR as a local server config directory (can add several)" << std::endl; std::cout << " edit Edit the configuration of dropshell" << std::endl;
if (gConfig().is_config_set()) { if (gConfig().is_config_set()) {
std::cout << " server NAME Show details for specific server" << std::endl; std::cout << " server NAME Show details for specific server" << std::endl;
@ -68,39 +68,6 @@ int die(const std::string & msg) {
return 1; return 1;
} }
int init(const std::vector<std::string> &args)
{
std::string lcd;
if (args.size() < 3) {
std::cerr << "Error: init command requires a directory argument" << std::endl;
return 1;
}
try {
if (!gConfig().add_local_config_directory(args[2]))
return 1; // error already reported
gConfig().save_config();
std::cout << "Config directory added: " << gConfig().get_local_config_directories().back() << std::endl;
dropshell::create_readme_local_config_dir(gConfig().get_local_config_directories().back());
if (gConfig().get_local_config_directories().size() ==1)
std::cout << "DropShell is now initialised and you can add a server with 'dropshell create-server <server-name>'" << std::endl;
else
{
std::cout << "DropShell will now use all of the following directories for configuration:" << std::endl;
for (const auto& dir : gConfig().get_local_config_directories()) {
std::cout << " " << dir << std::endl;
}
std::cout << "You can edit the config file manually with: dropshell edit" << std::endl;
}
} catch (const std::exception& e) {
std::cerr << "Error in init: " << e.what() << std::endl;
return 1;
}
return 0;
}
struct ServerAndServices { struct ServerAndServices {
std::string server_name; std::string server_name;
std::vector<LocalServiceInfo> servicelist; std::vector<LocalServiceInfo> servicelist;
@ -162,32 +129,38 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
if (cmd == "init") {
return init(argvec);
}
if (cmd == "help" || cmd == "-h" || cmd == "--help" || cmd== "h" || cmd=="halp") { if (cmd == "help" || cmd == "-h" || cmd == "--help" || cmd== "h" || cmd=="halp") {
print_help(); print_help();
return 0; return 0;
} }
if (cmd == "edit" && argc < 3) { if (cmd == "edit" && argc < 3) {
std::string config_file = localfile::dropshell_env(); std::string config_file = localfile::dropshell_json();
std::filesystem::create_directories( get_parent(config_file) ); if (!edit_file(config_file) || !std::filesystem::exists(config_file))
edit_file(config_file, "Please ensure any directories you have introduced in the config file exist."); return die("Error: Failed to edit config file.");
gConfig().load_config();
if (!gConfig().is_config_set())
return die("Error: Failed to load and parse edited config file.");
gConfig().save_config();
gConfig().load_config();
std::cout << "Successfully edited config file." << std::endl;
return 0; return 0;
} }
// ------------------------------------------------------------ // ------------------------------------------------------------
// from here we require the config file to be loaded. // from here we require the config file to be loaded.
if (!gConfig().is_config_set()) if (!gConfig().is_config_set())
return die("Please run 'dropshell init <path>' to initialise the user directory and create a configuration file."); return die("Please run 'dropshell edit' to set up the dropshell configuration.");
const std::vector<std::string> & local_config_directories = gConfig().get_local_config_directories(); const std::vector<std::string> & server_definition_paths = gConfig().get_local_server_definition_paths();
std::cout << "Config directories: "; if (server_definition_paths.size()>1) { // only show if there are multiple.
for (auto & dir : local_config_directories) std::cout << "Server definition paths: ";
std::cout << "["<< dir << "] "; for (auto & dir : server_definition_paths)
std::cout << std::endl; std::cout << "["<< dir << "] ";
std::cout << std::endl;
}
if (cmd == "server" || cmd == "servers" || cmd == "list" || cmd == "view") if (cmd == "server" || cmd == "servers" || cmd == "list" || cmd == "view")
switch (argc) switch (argc)

View File

@ -144,7 +144,12 @@ bool server_env_manager::run_remote_template_command_and_capture_output(const st
} }
bool server_env_manager::execute_local_command(const sCommand& command) { bool server_env_manager::execute_local_command(const sCommand& command) {
return (system(command.construct_safecmd().c_str()) == 0); auto status = system(command.construct_safecmd().c_str());
if ( WIFEXITED(status) ) {
int returned = WEXITSTATUS(status);
return (returned == 0);
}
return false;
} }
bool server_env_manager::execute_local_command_and_capture_output(const sCommand& command, std::string &output) bool server_env_manager::execute_local_command_and_capture_output(const sCommand& command, std::string &output)
@ -159,7 +164,11 @@ bool server_env_manager::execute_local_command_and_capture_output(const sCommand
output += buffer; output += buffer;
} }
int status = pclose(pipe); int status = pclose(pipe);
return (status == 0); if ( WIFEXITED(status) ) {
int returned = WEXITSTATUS(status);
return (returned == 0);
}
return false;
} }

View File

@ -450,17 +450,20 @@ void edit_server(const std::string &server_name)
<< "Once moved, reinstall all services with: dropshell install " << server_name; << "Once moved, reinstall all services with: dropshell install " << server_name;
std::string config_file = serverpath + "/server.env"; std::string config_file = serverpath + "/server.env";
edit_file(config_file, aftertext.str()); if (!edit_file(config_file))
std::cerr << "Error: Failed to edit server.env" << std::endl;
else
std::cout << aftertext.str() << std::endl;
} }
void edit_file(const std::string &file_path, const std::string & aftertext) bool edit_file(const std::string &file_path)
{ {
std::string cmd = "nano -w "+file_path+" ; echo \""+aftertext+"\""; // make sure parent directory exists.
execlp("bash","bash","-c",cmd.c_str(), nullptr); std::string parent_dir = get_parent(file_path);
std::filesystem::create_directories(parent_dir);
// If exec returns, it means there was an error
perror("ssh execution failed"); std::string cmd = "nano -w " + file_path;
exit(EXIT_FAILURE); return server_env_manager::execute_local_command(cmd);
} }
void service_runner::interactive_ssh_service() void service_runner::interactive_ssh_service()
@ -483,9 +486,8 @@ void service_runner::edit_service_config()
return; return;
} }
std::string aftertext = "To apply your changes, run:\n dropshell install " + mServer + " " + mService; if (edit_file(config_file) && std::filesystem::exists(config_file))
std::cout << "To apply your changes, run:\n dropshell install " + mServer + " " + mService << std::endl;
edit_file(config_file, aftertext);
} }
@ -497,7 +499,7 @@ bool service_runner::restore(std::string backup_file, bool silent)
return false; return false;
} }
std::string local_backups_dir = localpath::backups_path(); std::string local_backups_dir = gConfig().get_local_backup_path();
std::string local_backup_file_path = (std::filesystem::path(local_backups_dir) / backup_file).string(); std::string local_backup_file_path = (std::filesystem::path(local_backups_dir) / backup_file).string();
if (! std::filesystem::exists(local_backup_file_path)) { if (! std::filesystem::exists(local_backup_file_path)) {
@ -632,7 +634,7 @@ bool service_runner::backup(bool silent) {
} }
// Create backups directory locally if it doesn't exist // Create backups directory locally if it doesn't exist
std::string local_backups_dir = localpath::backups_path(); std::string local_backups_dir = gConfig().get_local_backup_path();
if (local_backups_dir.empty()) { if (local_backups_dir.empty()) {
std::cerr << "Error: Local backups directory not found - is DropShell initialised?" << std::endl; std::cerr << "Error: Local backups directory not found - is DropShell initialised?" << std::endl;
return false; return false;

View File

@ -109,7 +109,7 @@ class service_runner {
// other utility routines (not specific to service_runner) // other utility routines (not specific to service_runner)
void interactive_ssh(const std::string & server_name, const std::string & command); void interactive_ssh(const std::string & server_name, const std::string & command);
void edit_server(const std::string & server_name); void edit_server(const std::string & server_name);
void edit_file(const std::string & file_path, const std::string & aftertext); bool edit_file(const std::string & file_path);
// check if the service template and config are up to date on the remote server. // check if the service template and config are up to date on the remote server.
class service_versions { class service_versions {

View File

@ -12,14 +12,13 @@ namespace dropshell {
namespace localfile { namespace localfile {
std::string dropshell_env() { std::string dropshell_json() {
// Try ~/.config/dropshell/dropshell.env // Try ~/.config/dropshell/dropshell.json
const char* home = std::getenv("HOME"); std::string homedir = localpath::current_user_home();
if (home) { if (!homedir.empty()) {
fs::path user_path = fs::path(home) / ".config" / "dropshell" / "dropshell.env"; fs::path user_path = fs::path(homedir) / ".config" / "dropshell" / "dropshell.json";
return user_path.string(); return user_path.string();
} }
std::cerr << "Warning: Couldn't determine user directory" << std::endl;
return std::string(); return std::string();
} }
@ -39,60 +38,46 @@ namespace localfile {
return (servicepath.empty() ? "" : (fs::path(servicepath) / ".template_info.env").string()); return (servicepath.empty() ? "" : (fs::path(servicepath) / ".template_info.env").string());
} }
std::string service_hash(const std::string &server_name, const std::string &service_name) {
std::string config_path = localpath::config();
if (server_name.empty() || service_name.empty() || config_path.empty())
return std::string();
return (fs::path(config_path) / ".remote_versions" / server_name / (service_name + ".hash.env")).string();
}
} // namespace localfile } // namespace localfile
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
namespace localpath { namespace localpath {
// /opt/dropshell/templates
std::string system_templates() {
return "/opt/dropshell/templates";
}
// configured by user - defaults to first config_path/backups.
std::string backups_path() {
return gConfig().get_local_backup_path();
}
int num_config_directories() {
return gConfig().get_local_config_directories().size();
}
std::string config(int index) {
return (num_config_directories()>index) ? gConfig().get_local_config_directories()[index] : "";
}
std::string config_templates(int index) {
return (num_config_directories()>index) ? (gConfig().get_local_config_directories()[index]+"/templates") : "";
}
std::string config_servers(int index) {
return (num_config_directories()>index) ? (gConfig().get_local_config_directories()[index]+"/servers") : "";
}
std::string server(const std::string &server_name) { std::string server(const std::string &server_name) {
if (server_name.empty()) return ""; if (server_name.empty()) return "";
for (auto &dir : gConfig().get_local_config_directories()) for (auto &dir : gConfig().get_local_server_definition_paths())
if (fs::exists(dir + "/servers/" + server_name)) if (fs::exists(dir + server_name))
return dir + "/servers/" + server_name; return dir + server_name;
return ""; return "";
} }
std::string service(const std::string &server_name, const std::string &service_name) { std::string service(const std::string &server_name, const std::string &service_name) {
std::string serverpath = localpath::server(server_name); std::string serverpath = localpath::server(server_name);
return (serverpath.empty() || service_name.empty() ? "" : (serverpath+"/"+service_name)); return ((serverpath.empty() || service_name.empty()) ? "" : (serverpath+"/"+service_name));
}
std::string remote_versions(const std::string &server_name, const std::string &service_name)
{
std::string template_cache_path = gConfig().get_local_template_cache_path();
return ((template_cache_path.empty() || service_name.empty()) ? "" :
(template_cache_path+"/remote_versions/"+service_name+".json"));
}
std::string local_bin(){
return current_user_home() + "/.local/bin";
}
std::string current_user_home(){
char * homedir = std::getenv("HOME");
if (homedir)
{
std::filesystem::path homedir_path(homedir);
return fs::canonical(homedir_path).string();
}
std::cerr << "Warning: Couldn't determine user directory" << std::endl;
return std::string();
} }
} // namespace localpath } // namespace localpath
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// remote paths // remote paths

View File

@ -9,49 +9,52 @@ namespace dropshell {
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// local user config directories // local user config directories
// config_path
// |-- servers // ~/.config/dropshell/dropshell.json
// | |-- server_name
// | |-- server.env // server_definition_path
// | |-- services // |-- <server_name>
// | |-- service_name // |-- server.env
// | |-- service.env // |-- services
// | |-- .template_info.env // |-- <service_name>
// | |-- (other config files for specific server&service) // |-- service.env
// |-- templates // |-- .template_info.env
// | |-- template_name // |-- (...other config files for specific server&service...)
// | |-- (script files)
// | |-- _default.env // backup path
// | |-- example // |-- katie-_-squashkiwi-_-squashkiwi-test-_-2025-04-28_21-23-59.tgz
// | |-- service.env
// | |-- .template_info.env // temp files path
// | |-- (other service config files)
// |-- .remote_versions // template cache path
// | |-- server_name // |-- templates
// | |-- service_name.hash.env // | |-- <template_name>.json
// | |-- <template_name>
// | |-- (...script files...)
// | |-- _default.env
// | |-- example
// | |-- service.env
// | |-- .template_info.env
// | |-- (...other service config files...)
// |-- remote_versions
// | |-- server_name-service_name.json
namespace localfile { namespace localfile {
// ~/.config/dropshell/dropshell.conf // ~/.config/dropshell/dropshell.json
std::string dropshell_env(); std::string dropshell_json();
std::string server_env(const std::string &server_name); std::string server_env(const std::string &server_name);
std::string service_env(const std::string &server_name, const std::string &service_name); std::string service_env(const std::string &server_name, const std::string &service_name);
std::string template_info_env(const std::string &server_name, const std::string &service_name); std::string template_info_env(const std::string &server_name, const std::string &service_name);
std::string service_hash(const std::string &server_name, const std::string &service_name);
} // namespace localfile } // namespace localfile
namespace localpath { namespace localpath {
// /opt/dropshell/templates
std::string system_templates();
// configured by user - defaults to first config_path/backups.
std::string backups_path();
int num_config_directories();
std::string config(int index=0);
std::string config_templates(int index=0);
std::string config_servers(int index=0);
std::string server(const std::string &server_name); std::string server(const std::string &server_name);
std::string service(const std::string &server_name, const std::string &service_name); std::string service(const std::string &server_name, const std::string &service_name);
std::string remote_versions(const std::string &server_name, const std::string &service_name);
std::string local_bin();
std::string current_user_home();
} // namespace local } // namespace local
@ -88,4 +91,4 @@ namespace dropshell {
} // namespace dropshell } // namespace dropshell
#endif #endif // DIRECTORIES_HPP

25578
src/utils/json.hpp Normal file

File diff suppressed because it is too large Load Diff

187
src/utils/json_fwd.hpp Normal file
View File

@ -0,0 +1,187 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
// #include <nlohmann/detail/abi_macros.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// This file contains all macro definitions affecting or depending on the ABI
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
#warning "Already included a different version of the library!"
#endif
#endif
#endif
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
#ifndef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0
#endif
#ifndef JSON_DIAGNOSTIC_POSITIONS
#define JSON_DIAGNOSTIC_POSITIONS 0
#endif
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
#endif
#if JSON_DIAGNOSTICS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
#endif
#if JSON_DIAGNOSTIC_POSITIONS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
#else
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
#endif
// Construct the namespace ABI tags component
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
#define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
// Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
_v ## major ## _ ## minor ## _ ## patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#else
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
NLOHMANN_JSON_VERSION_MINOR, \
NLOHMANN_JSON_VERSION_PATCH)
#endif
// Combine namespace components
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#ifndef NLOHMANN_JSON_NAMESPACE
#define NLOHMANN_JSON_NAMESPACE \
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION)
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#endif
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@since version 1.0.0
*/
NLOHMANN_JSON_NAMESPACE_BEGIN
/*!
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
template<typename T = void, typename SFINAE = void>
struct adl_serializer;
/// a class to store JSON values
/// @sa https://json.nlohmann.me/api/basic_json/
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
class CustomBaseClass = void>
class basic_json;
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
/// @sa https://json.nlohmann.me/api/json_pointer/
template<typename RefStringType>
class json_pointer;
/*!
@brief default specialization
@sa https://json.nlohmann.me/api/json/
*/
using json = basic_json<>;
/// @brief a minimal map-like container that preserves insertion order
/// @sa https://json.nlohmann.me/api/ordered_map/
template<class Key, class T, class IgnoredLess, class Allocator>
struct ordered_map;
/// @brief specialization that maintains the insertion order of object keys
/// @sa https://json.nlohmann.me/api/ordered_json/
using ordered_json = basic_json<nlohmann::ordered_map>;
NLOHMANN_JSON_NAMESPACE_END
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

View File

@ -5,6 +5,8 @@ _autocommandrun() {
command="$1" command="$1"
key="$2" key="$2"
value="$3" value="$3"
# only passed through if command is backup or restore.
backup_file="$4" backup_file="$4"
temp_path="$5" temp_path="$5"
@ -26,7 +28,7 @@ _autocommandrun() {
_autocommandparse() { _autocommandparse() {
# first argument is the command # first argument is the command
# last two arguments are the backup file and the temporary path # if the command is backup or restore, then the last two arguments are the backup file and the temporary path
# all other arguments are of form: # all other arguments are of form:
# key=value # key=value
# where key can be one of volume, path or file. # where key can be one of volume, path or file.