187 lines
6.5 KiB
C++
187 lines
6.5 KiB
C++
#include "templates.hpp"
|
|
#include "config.hpp"
|
|
#include "utils/directories.hpp"
|
|
#include "utils/utils.hpp"
|
|
#include <filesystem>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <iomanip>
|
|
|
|
namespace dropshell {
|
|
|
|
|
|
bool get_templates(std::vector<template_info>& templates) {
|
|
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;
|
|
info.name = entry.path().filename().string();
|
|
info.path = entry.path().string();
|
|
|
|
// Check if template with same name already exists
|
|
bool found = false;
|
|
auto it = std::find_if(templates.begin(), templates.end(),
|
|
[&info](const template_info& t) { return t.name == info.name; });
|
|
found = (it!=templates.end());
|
|
found |= info.name=="example"; // don't include the example template!
|
|
|
|
if (!found) {
|
|
templates.push_back(info);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// add templates from the local config directories
|
|
for (int i = 0; i < getNumConfigDirectories(); i++) {
|
|
std::string path = get_local_config_templates_path(i);
|
|
if (path.empty()) {
|
|
std::cerr << "Error: Templates directory not found: " << path << std::endl;
|
|
return false;
|
|
}
|
|
add_templates_from_dir(path);
|
|
}
|
|
|
|
// add templates from the system templates directory
|
|
add_templates_from_dir(get_local_system_templates_path());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool get_template_info(const std::string& name, template_info& info) {
|
|
std::vector<template_info> templates;
|
|
if (!get_templates(templates)) {
|
|
return false;
|
|
}
|
|
|
|
auto it = std::find_if(templates.begin(), templates.end(),
|
|
[&name](const template_info& t) { return t.name == name; });
|
|
|
|
if (it != templates.end()) {
|
|
info = *it;
|
|
return true;
|
|
}
|
|
|
|
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.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.name << t.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.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
|