This commit is contained in:
John 2025-04-27 13:03:48 +12:00
parent 8614d29b06
commit 192cc48d42
4 changed files with 195 additions and 191 deletions

View File

@ -244,8 +244,6 @@ int main(int argc, char* argv[]) {
std::cerr << command << " "; std::cerr << command << " ";
} }
std::cerr << std::endl; std::cerr << std::endl;
// print help
dropshell::print_help();
return 1; return 1;
} catch (const std::exception& e) { } catch (const std::exception& e) {

View File

@ -95,7 +95,7 @@ ServiceInfo get_service_info(const std::string &server_name, const std::string &
// find the template path // find the template path
service.local_template_path = tinfo.local_template_path; service.local_template_path = tinfo.local_template_path;
service.local_template_default_env_path = tinfo.local_template_default_env_path; service.local_template_default_env_path = tinfo.local_template_path + "/_default.env";
return service; return service;
} }

View File

@ -1,188 +1,193 @@
#include "templates.hpp" #include "templates.hpp"
#include "config.hpp" #include "config.hpp"
#include "utils/directories.hpp" #include "utils/directories.hpp"
#include "utils/utils.hpp" #include "utils/utils.hpp"
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
namespace dropshell { namespace dropshell {
bool get_templates(std::vector<template_info>& templates) { bool get_templates(std::vector<template_info>& templates) {
templates.clear(); templates.clear();
// Helper function to add templates from a directory
auto add_templates_from_dir = [&templates](const std::string& dir_path) {
if (!std::filesystem::exists(dir_path))
return;
for (const auto& entry : std::filesystem::directory_iterator(dir_path))
if (entry.is_directory()) {
template_info info(entry.path().filename().string(), entry.path().string());
// Check if template with same name already exists
bool duplicate = false;
auto it = std::find_if(templates.begin(), templates.end(),
[&info](const template_info& t) { return t.template_name == info.template_name; });
duplicate = (it!=templates.end());
if (!duplicate)
templates.push_back(info);
}
};
// add templates from the local config directories
std::vector<std::string> template_config_directories;
get_all_template_config_directories(template_config_directories);
for (const auto& path : template_config_directories) {
add_templates_from_dir(path);
}
// Helper function to add templates from a directory return true;
auto add_templates_from_dir = [&templates](const std::string& dir_path) { }
if (!std::filesystem::exists(dir_path)) {
bool get_template_info(const std::string& template_name, template_info& info) {
// add templates from the local config directories
std::vector<std::string> paths_to_search;
get_all_template_config_directories(paths_to_search);
for (const auto& path : paths_to_search) {
std::filesystem::path full_path = path + "/" + template_name;
if (std::filesystem::exists(full_path))
{
info.template_name = template_name;
info.local_template_path = full_path.string();
return true;
}
}
std::cout << "Warning: Template '" << template_name << "' not found" << std::endl;
return false;
}
bool template_command_exists(const std::string &template_name, const std::string &command)
{
template_info info;
if (!get_template_info(template_name, info)) {
return false;
}
std::string path = info.local_template_path + "/" + command + ".sh";
return (std::filesystem::exists(path));
}
void list_templates() {
std::vector<template_info> templates;
if (!get_templates(templates)) {
std::cerr << "Error: Failed to get templates" << std::endl;
return; return;
} }
for (const auto& entry : std::filesystem::directory_iterator(dir_path)) { if (templates.empty()) {
if (entry.is_directory()) { std::cout << "No templates found." << std::endl;
template_info info; return;
info.template_name = entry.path().filename().string(); }
info.local_template_path = entry.path().string();
info.local_template_default_env_path = entry.path() / "_default.env"; std::cout << "Available templates:" << std::endl;
std::cout << std::left << std::setw(20) << "Name" << "Path" << std::endl;
// Check if template with same name already exists std::cout << std::string(60, '-') << std::endl;
bool duplicate = false;
auto it = std::find_if(templates.begin(), templates.end(), for (const auto& t : templates) {
[&info](const template_info& t) { return t.template_name == info.template_name; }); std::cout << std::left << std::setw(20) << t.template_name << t.local_template_path << std::endl;
duplicate = (it!=templates.end()); }
//duplicate |= (info.template_name=="example"); // don't include the example template! }
if (!duplicate) { void create_template(const std::string& template_name) {
templates.push_back(info); // 1. Create a new directory in the user templates directory
} std::vector<std::string> local_config_directories = get_global_config()->get_local_config_directories();
if (local_config_directories.empty()) {
std::cerr << "Error: No local config directories found" << std::endl;
std::cerr << "Run 'dropshell init' to initialise DropShell" << std::endl;
return;
}
template_info info;
if (get_template_info(template_name, info)) {
std::cerr << "Error: Template '" << template_name << "' already exists at " << info.local_template_path << std::endl;
return;
}
std::string user_templates_dir = local_config_directories[0] + "/templates";
std::string new_template_path = user_templates_dir + "/" + template_name;
// Create the new template directory
std::filesystem::create_directories(new_template_path);
// 2. Copy the example template from the system templates directory
std::string system_templates_dir = get_local_system_templates_path();
std::string example_template_path = system_templates_dir + "/example";
if (!std::filesystem::exists(example_template_path)) {
std::cerr << "Error: Example template not found at " << example_template_path << std::endl;
return;
}
// Copy all files from example template to new template
for (const auto& entry : std::filesystem::recursive_directory_iterator(example_template_path)) {
std::string relative_path = entry.path().string().substr(example_template_path.length());
std::string target_path = new_template_path + relative_path;
if (entry.is_directory()) {
std::filesystem::create_directory(target_path);
} else {
std::filesystem::copy_file(entry.path(), target_path);
} }
} }
};
// add templates from the local config directories // modify the TEMPLATE=example line in the service.env file to TEMPLATE=<template_name>
for (int i = 0; i < getNumConfigDirectories(); i++) { std::string search_string = "TEMPLATE=";
std::string path = get_local_config_templates_path(i); std::string replacement_line = "TEMPLATE=" + template_name;
if (path.empty()) { // replace the line in the example/service.env file with the replacement line
std::cerr << "Error: Templates directory not found: " << path << std::endl; std::string service_env_path = new_template_path + "/example/service.env";
return false; if (!replace_line_in_file(service_env_path, search_string, replacement_line)) {
std::cerr << "Error: Failed to replace TEMPLATE= line in service.env file" << std::endl;
return;
} }
add_templates_from_dir(path);
// 3. Print out the README.txt file and the path
std::string readme_path = new_template_path + "/README.txt";
if (std::filesystem::exists(readme_path)) {
std::cout << "\nREADME contents:" << std::endl;
std::cout << std::string(60, '-') << std::endl;
std::ifstream readme_file(readme_path);
if (readme_file.is_open()) {
std::string line;
while (std::getline(readme_file, line)) {
std::cout << line << std::endl;
}
readme_file.close();
}
std::cout << std::string(60, '-') << std::endl;
} else {
std::cout << "No README.txt file found in the template." << std::endl;
}
std::cout << std::endl;
std::cout << "Template '" << template_name << "' created at " << new_template_path << std::endl;
} }
// add templates from the system templates directory bool get_all_template_config_directories(std::vector<std::string> &template_config_directories)
add_templates_from_dir(get_local_system_templates_path()); {
template_config_directories.clear();
return true; for (int i = 0; i < getNumConfigDirectories(); i++) {
} std::string config_templates_path = get_local_config_templates_path(i);
if (config_templates_path.empty()) {
bool get_template_info(const std::string& template_name, template_info& info) { std::cerr << "Error: Templates directory not found: " << config_templates_path << std::endl;
std::vector<template_info> templates; return false;
if (!get_templates(templates)) { }
return false; template_config_directories.push_back(config_templates_path);
} }
template_config_directories.push_back(get_local_system_templates_path());
auto it = std::find_if(templates.begin(), templates.end(),
[&template_name](const template_info& t) { return t.template_name == template_name; });
if (it != templates.end()) {
info = *it;
return true; return true;
} }
return false;
}
bool template_command_exists(const std::string &template_name, const std::string &command) } // namespace dropshell
{
template_info info;
if (!get_template_info(template_name, info)) {
return false;
}
std::string path = info.local_template_path + "/" + command + ".sh";
return (std::filesystem::exists(path));
}
void list_templates() {
std::vector<template_info> templates;
if (!get_templates(templates)) {
std::cerr << "Error: Failed to get templates" << std::endl;
return;
}
if (templates.empty()) {
std::cout << "No templates found." << std::endl;
return;
}
std::cout << "Available templates:" << std::endl;
std::cout << std::left << std::setw(20) << "Name" << "Path" << std::endl;
std::cout << std::string(60, '-') << std::endl;
for (const auto& t : templates) {
std::cout << std::left << std::setw(20) << t.template_name << t.local_template_path << std::endl;
}
}
void create_template(const std::string& template_name) {
// 1. Create a new directory in the user templates directory
std::vector<std::string> local_config_directories = get_global_config()->get_local_config_directories();
if (local_config_directories.empty()) {
std::cerr << "Error: No local config directories found" << std::endl;
std::cerr << "Run 'dropshell init' to initialise DropShell" << std::endl;
return;
}
template_info info;
if (get_template_info(template_name, info)) {
std::cerr << "Error: Template '" << template_name << "' already exists at " << info.local_template_path << std::endl;
return;
}
std::string user_templates_dir = local_config_directories[0] + "/templates";
std::string new_template_path = user_templates_dir + "/" + template_name;
// Create the new template directory
std::filesystem::create_directories(new_template_path);
// 2. Copy the example template from the system templates directory
std::string system_templates_dir = get_local_system_templates_path();
std::string example_template_path = system_templates_dir + "/example";
if (!std::filesystem::exists(example_template_path)) {
std::cerr << "Error: Example template not found at " << example_template_path << std::endl;
return;
}
// Copy all files from example template to new template
for (const auto& entry : std::filesystem::recursive_directory_iterator(example_template_path)) {
std::string relative_path = entry.path().string().substr(example_template_path.length());
std::string target_path = new_template_path + relative_path;
if (entry.is_directory()) {
std::filesystem::create_directory(target_path);
} else {
std::filesystem::copy_file(entry.path(), target_path);
}
}
// modify the TEMPLATE=example line in the service.env file to TEMPLATE=<template_name>
std::string search_string = "TEMPLATE=";
std::string replacement_line = "TEMPLATE=" + template_name;
// replace the line in the example/service.env file with the replacement line
std::string service_env_path = new_template_path + "/example/service.env";
if (!replace_line_in_file(service_env_path, search_string, replacement_line)) {
std::cerr << "Error: Failed to replace TEMPLATE= line in service.env file" << std::endl;
return;
}
// 3. Print out the README.txt file and the path
std::string readme_path = new_template_path + "/README.txt";
if (std::filesystem::exists(readme_path)) {
std::cout << "\nREADME contents:" << std::endl;
std::cout << std::string(60, '-') << std::endl;
std::ifstream readme_file(readme_path);
if (readme_file.is_open()) {
std::string line;
while (std::getline(readme_file, line)) {
std::cout << line << std::endl;
}
readme_file.close();
}
std::cout << std::string(60, '-') << std::endl;
} else {
std::cout << "No README.txt file found in the template." << std::endl;
}
std::cout << std::endl;
std::cout << "Template '" << template_name << "' created at " << new_template_path << std::endl;
}
} // namespace dropshell

View File

@ -1,35 +1,36 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <filesystem>
namespace dropshell { namespace dropshell {
class template_info { class template_info {
public: public:
template_info() {}
template_info(std::string n, std::string p) : template_name(n), local_template_path(p) {}
std::string template_name; std::string template_name;
std::string local_template_path; std::string local_template_path;
std::string local_template_default_env_path;
}; };
// templates are stored in two locations: // templates are stored in multiple locations:
// 1. /opt/dropshell/templates // 1. /opt/dropshell/templates
// 2. CONFIG_DIR/usertemplates (if it exists) // 2. CONFIG_DIR/templates
// we aggregate the templates from both locations and return them in the order of priority.
// if a template exists in both locations, the one in the user directory takes precedence.
// the template name is just the subfolder name in the templates directory.
// the template path is the path of that subfolder.
bool get_templates(std::vector<template_info>& templates); bool get_templates(std::vector<template_info>& templates);
bool get_template_info(const std::string& template_name, template_info& info); bool get_template_info(const std::string& template_name, template_info& info);
bool template_command_exists(const std::string& template_name,const std::string& command); bool template_command_exists(const std::string& template_name,const std::string& command);
void list_templates(); void list_templates();
// create a template // create a template
// 1. create a new directory in the user templates directory // 1. create a new directory in the user templates directory
// 2. copy the example template from the system templates directory into the new directory // 2. copy the example template from the system templates directory into the new directory
// 3. print out the README.txt file in the new template directory, and the path to the new template // 3. print out the README.txt file in the new template directory, and the path to the new template
void create_template(const std::string& template_name); void create_template(const std::string& template_name);
bool get_all_template_config_directories(std::vector<std::string>& template_config_directories);
} // namespace dropshell } // namespace dropshell