diff --git a/include/Frate/Command/Template.hpp b/include/Frate/Command/Template.hpp new file mode 100644 index 0000000..9018927 --- /dev/null +++ b/include/Frate/Command/Template.hpp @@ -0,0 +1,5 @@ +#include "Frate/Interface.hpp" +#include +namespace Frate::Command::Template{ + bool remove(std::shared_ptr inter); +} diff --git a/include/Frate/Template/Manager.hpp b/include/Frate/Template/Manager.hpp index 99c356d..cc269bc 100644 --- a/include/Frate/Template/Manager.hpp +++ b/include/Frate/Template/Manager.hpp @@ -66,14 +66,15 @@ namespace Frate::Project { * install that template * @param git url of the template to install */ - TemplateRenderer getLatest(std::string &git_url); + TemplateRenderer installLatest(std::string &git_url); + TemplateRenderer uninstallAll(std::string &name); TemplateRenderer get(std::string &name,std::string &hash); TemplateRenderer promptList(); /* * Uninstalls a template * @param name the name of the template to uninstall */ - void uninstall(std::string &name); + void uninstall(std::string &name,std::string &hash); /* * Updates to the latest version of the template * @param name the name of the template to update @@ -84,8 +85,10 @@ namespace Frate::Project { void installAll(); + void deleteAll(); + /* - * Creates a tempalte in a tmp path and then returns the path that rendering + * Creates a template in a tmp path and then returns the path that rendering * is supposed to happen in * @param override_path the path to override the template path with * @param name the name of the template to create diff --git a/src/Command/Actions/New.cpp b/src/Command/Actions/New.cpp index 93a191f..fbb5e33 100644 --- a/src/Command/Actions/New.cpp +++ b/src/Command/Actions/New.cpp @@ -51,7 +51,7 @@ namespace Frate::Command::New { if(inter->pro->type.empty()){ current_template = inter->templates->promptList(); }else{ - current_template = inter->templates->getLatest(inter->pro->type); + current_template = inter->templates->installLatest(inter->pro->type); } try{ diff --git a/src/Command/Actions/Remove.cpp b/src/Command/Actions/Remove.cpp index 13c98d6..399c3ef 100644 --- a/src/Command/Actions/Remove.cpp +++ b/src/Command/Actions/Remove.cpp @@ -1,12 +1,10 @@ #include "Frate/Command/Library.hpp" -#include "Frate/Generators.hpp" -#include "Frate/Project/Config.hpp" -#include "Frate/Utils/General.hpp" #include #include #include #include #include +#include namespace Frate::Command::Remove { @@ -19,7 +17,8 @@ namespace Frate::Command::Remove { ("m,mode","make changes to compile mode",cxxopts::value()) ("subcommand", "Subcommand to run", cxxopts::value()) ("h,help", "Print usage") - ("args","Arguments to pass to subcommand",cxxopts::value>()); + ("args","Arguments to pass to subcommand",cxxopts::value>()) + ("a,all","Remove all",cxxopts::value()); // clang-format on return inter->parse(); } @@ -31,7 +30,8 @@ namespace Frate::Command::Remove { } std::vector handlers(std::shared_ptr inter) { - return {{ + return { + { .aliases = {"packages", "p", "package"}, .flags = {"-l,--latest", "-m,--mode", "-t,--target"}, .positional_args = {"package_name"}, @@ -64,7 +64,15 @@ namespace Frate::Command::Remove { .docs = "Remove an author from the project", .callback = &Author::remove, .unlimited_args = true, - }}; + }, + { + .aliases = {"template"}, + .flags = {"-a,--all"}, + .positional_args = {"template_name"}, + .docs = "Remove a template from the project", + .callback = &Template::remove + } + }; } bool run(std::shared_ptr inter) { diff --git a/src/Command/Actions/Update.cpp b/src/Command/Actions/Update.cpp index 7b2b58d..5b86848 100644 --- a/src/Command/Actions/Update.cpp +++ b/src/Command/Actions/Update.cpp @@ -32,7 +32,7 @@ namespace Frate::Command::Update { .aliases = {"template-index", "tindex"}, .docs = "Update template index", .callback = &TemplateIndex::update, - } + }, }; } diff --git a/src/Command/Template/Remove.cpp b/src/Command/Template/Remove.cpp new file mode 100644 index 0000000..aaf0a75 --- /dev/null +++ b/src/Command/Template/Remove.cpp @@ -0,0 +1,43 @@ +#include + +namespace Frate::Command::Template { + bool remove(std::shared_ptr inter) { + std::string template_name; + bool all; + + + if (inter->args->count("args")) { + template_name = inter->args->operator[]("args").as(); + } + if (inter->args->count("all")) { + all = inter->args->operator[]("all").as(); + } + + Utils::info << "Removing template " << template_name << std::endl; + Utils::info << "All: " << all << std::endl; + + if (all) { + try{ + inter->templates->deleteAll(); + return true; + } catch (std::exception &e) { + Utils::error << e.what() << std::endl; + return false; + } + } else { + if(template_name.empty()) { + Utils::error << "No template name given" << std::endl; + return false; + } + try{ + inter->templates->uninstallAll(template_name); + return true; + } catch (std::exception &e) { + Utils::error << e.what() << std::endl; + return false; + } + } + + return false; + } +} diff --git a/src/Template/Manager.cpp b/src/Template/Manager.cpp index e0b96da..73cf75d 100644 --- a/src/Template/Manager.cpp +++ b/src/Template/Manager.cpp @@ -1,7 +1,7 @@ #include "Frate/Constants.hpp" +#include "Frate/System/GitProvider.hpp" #include "Frate/Template/IndexEntry.hpp" #include "Frate/Template/Renderer.hpp" -#include "Frate/System/GitProvider.hpp" #include "Frate/Utils/CLIPrompt.hpp" #include "Frate/Utils/General.hpp" #include "Frate/Utils/Logging.hpp" @@ -91,38 +91,41 @@ namespace Frate::Project { Constants::INSTALLED_TEMPLATE_PATH / name / hash; if (!installed.contains(name)) { - Utils::verbose << "Template not installed in config, could not find key: " << name << std::endl; + Utils::verbose << "Template not installed in config, could not find key: " + << name << std::endl; return false; } Utils::verbose << nlohmann::json(installed[name]).dump(2) << std::endl; if (!installed[name].contains(hash)) { - Utils::verbose << "Template not installed in config, could not find key " << name << "->" << hash << std::endl; + Utils::verbose << "Template not installed in config, could not find key " + << name << "->" << hash << std::endl; return false; } if (!std::filesystem::exists(template_path)) { Utils::verbose << "Template not installed in template path at: " - << template_path << std::endl; + << template_path << std::endl; return false; } return true; } - bool TemplateManager::is_installed(TemplateIndexEntry &entry){ - return is_installed(entry.getName(), entry.getBranchHash(Constants::TEMPLATE_BRANCH)); + + bool TemplateManager::is_installed(TemplateIndexEntry &entry) { + return is_installed(entry.getName(), + entry.getBranchHash(Constants::TEMPLATE_BRANCH)); } - Project::TemplateRenderer &TemplateManager::find_template(const std::string &name, - std::string &hash) { + Project::TemplateRenderer & + TemplateManager::find_template(const std::string &name, std::string &hash) { if (!is_installed(name, hash)) { throw TemplateNotInstalled("Template not installed"); } return installed[name][hash]; } - void TemplateManager::template_to_installed_path( std::filesystem::path &tmp_path, std::filesystem::path &new_template_path, std::string &hash) { @@ -169,14 +172,29 @@ namespace Frate::Project { return index; } - std::unordered_map> & + std::unordered_map< + std::string, std::unordered_map> & TemplateManager::getInstalled() { return installed; } - void TemplateManager::uninstall(std::string &name) { - // TODO: implement + void TemplateManager::uninstall(std::string &name, std::string &hash) { + if (!is_installed(name, hash)) { + throw TemplateNotInstalled("Template not installed"); + } + + std::filesystem::path template_path = + Constants::INSTALLED_TEMPLATE_PATH / name / hash; + + std::filesystem::remove_all(template_path); + + installed[name].erase(hash); + + if (installed[name].empty()) { + installed.erase(name); + } + + save(); } void TemplateManager::update(std::string &name) { @@ -187,7 +205,7 @@ namespace Frate::Project { load_index(); for (TemplateIndexEntry template_info : index) { - if(is_installed(template_info)){ + if (is_installed(template_info)) { continue; } @@ -195,6 +213,16 @@ namespace Frate::Project { } } + void TemplateManager::deleteAll() { + if(!std::filesystem::exists(Constants::INSTALLED_TEMPLATE_PATH)) { + return; + } + std::filesystem::remove_all(Constants::INSTALLED_TEMPLATE_PATH); + + installed.clear(); + save(); + } + void TemplateManager::updateIndex() { Utils::verbose << "Updating template index" << std::endl; @@ -229,7 +257,7 @@ namespace Frate::Project { } } - TemplateRenderer TemplateManager::getLatest(std::string &git_url) { + TemplateRenderer TemplateManager::installLatest(std::string &git_url) { load_index(); for (TemplateIndexEntry template_info : index) { @@ -243,10 +271,26 @@ namespace Frate::Project { } } - throw TemplateNotFoundInIndex("Template " + git_url + " not found in index"); + throw TemplateNotFoundInIndex("Template " + git_url + + " not found in index"); } - TemplateRenderer TemplateManager::promptList(){ + TemplateRenderer TemplateManager::uninstallAll(std::string &name){ + if (!installed.contains(name)) { + throw TemplateNotInstalled("Template " + name + " not installed"); + } + + std::filesystem::path template_path = + Constants::INSTALLED_TEMPLATE_PATH / name; + + std::filesystem::remove_all(template_path); + + installed.erase(name); + + save(); + } + + TemplateRenderer TemplateManager::promptList() { load_index(); @@ -256,7 +300,8 @@ namespace Frate::Project { template_names.push_back(template_info.getName()); } - auto template_prompt = Utils::CLI::Prompt("Template").addOptions(template_names); + auto template_prompt = + Utils::CLI::Prompt("Template").addOptions(template_names); template_prompt.run(); auto template_name = template_prompt.get(); @@ -270,15 +315,16 @@ namespace Frate::Project { return template_info; } } - throw TemplateNotFoundInIndex("Template " + template_name + " not found in index"); + throw TemplateNotFoundInIndex("Template " + template_name + + " not found in index"); }; + TemplateRenderer TemplateManager::get(std::string &name, std::string &hash) { load_index(); for (TemplateIndexEntry template_info : index) { - for(auto &branch : template_info.getBranches()){ - if (template_info.getName() == name && - branch == hash) { + for (auto &branch : template_info.getBranches()) { + if (template_info.getName() == name && branch == hash) { if (!is_installed(template_info)) { throw TemplateNotInstalled("Template " + template_info.getName() + @@ -293,20 +339,21 @@ namespace Frate::Project { } TemplateRenderer TemplateManager::install(TemplateIndexEntry &template_info) { - Utils::info << "Installing template: " << template_info.getName() << " on branch: " << branch << std::endl; - + Utils::info << "Installing template: " << template_info.getName() + << " on branch: " << branch << std::endl; std::filesystem::path tmp_path = Utils::randomTmpPath("frate-template-download-"); std::filesystem::path new_template_path = Constants::INSTALLED_TEMPLATE_PATH / template_info.getName(); - + std::string selected_hash; - if(branch.empty()){ + if (branch.empty()) { selected_hash = template_info.getHead(); - }else{ + } + else { selected_hash = template_info.getBranchHash(branch); } @@ -321,21 +368,21 @@ namespace Frate::Project { try { - git.setBranch(branch) - .setRecurseSubmodules(true) - .clone(template_info.getGit()); + git.setBranch(branch).setRecurseSubmodules(true).clone( + template_info.getGit()); } catch (std::exception &e) { Utils::error << e.what() << std::endl; - throw TemplateFailedToDownload("Failed to download template " + template_info.getName()); + throw TemplateFailedToDownload("Failed to download template " + + template_info.getName()); } if (std::filesystem::exists(new_template_path)) { Utils::verbose << "Template already exists at: " << new_template_path - << " we're going to delete it because we already " - "assume that it's not installed" - << std::endl; + << " we're going to delete it because we already " + "assume that it's not installed" + << std::endl; // This should only happen in rare cases std::filesystem::remove_all(new_template_path); } @@ -347,13 +394,12 @@ namespace Frate::Project { Utils::error << e.what() << std::endl; throw std::runtime_error("Failed to create directories: " + - new_template_path.string()); + new_template_path.string()); } try { - template_to_installed_path(tmp_path, new_template_path, - selected_hash); + template_to_installed_path(tmp_path, new_template_path, selected_hash); } catch (std::exception &e) { Utils::error << e.what() << std::endl; @@ -362,9 +408,9 @@ namespace Frate::Project { installed[template_info.getName()][selected_hash] = template_info; - // Cleanup + // Cleanup - //std::filesystem::remove_all(tmp_path); + // std::filesystem::remove_all(tmp_path); this->save(); @@ -421,7 +467,8 @@ namespace Frate::Project { std::ifstream file(config_path); if (!file.is_open()) { - throw std::runtime_error("Failed to open config file"); } + throw std::runtime_error("Failed to open config file"); + } nlohmann::json json_obj;