diff --git a/src/cmd/build.cpp b/src/cmd/build.cpp index a5bfce0..684abf0 100644 --- a/src/cmd/build.cpp +++ b/src/cmd/build.cpp @@ -1,7 +1,10 @@ #include "pch.h" #include "commands.h" #include "../core/ini.h" -#include "../tasks/tasks.h" +#include "../core/conf.h" +#include "../core/context.h" +#include "../core/op.h" +#include "../tasks/task_manager.h" namespace mob { @@ -154,7 +157,7 @@ int build_command::do_run() { create_prefix_ini(); - run_all_tasks(); + task_manager::instance().run_all(); if (!keep_msbuild_) terminate_msbuild(); diff --git a/src/cmd/commands.cpp b/src/cmd/commands.cpp index d01105d..4b4bd60 100644 --- a/src/cmd/commands.cpp +++ b/src/cmd/commands.cpp @@ -89,7 +89,7 @@ clipp::group command::common_options_group() % "sets an option, such as 'versions/openssl=1.2'", (clipp::option("--no-default-inis") >> o.no_default_inis) - % "disables auto loading of ini files, only uses --ini; the first" + % "disables auto loading of ini files, only uses --ini; the first " "--ini must be the master ini file"; } diff --git a/src/cmd/list.cpp b/src/cmd/list.cpp index 5faaf0f..7e80acc 100644 --- a/src/cmd/list.cpp +++ b/src/cmd/list.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "commands.h" -#include "../tasks/tasks.h" +#include "../tasks/task_manager.h" +#include "../tasks/task.h" +#include "../utility/io.h" namespace mob { @@ -37,6 +39,8 @@ clipp::group list_command::do_group() int list_command::do_run() { + auto& tm = task_manager::instance(); + if (aliases_) { load_options(); @@ -50,14 +54,14 @@ int list_command::do_run() set_task_enabled_flags(tasks_); load_options(); - dump(get_top_level_tasks(), 0); + dump(tm.top_level(), 0); u8cout << "\n\naliases:\n"; dump_aliases(); } else { - for (auto&& t : get_all_tasks()) + for (auto&& t : tm.all()) u8cout << " - " << join(t->names(), ", ") << "\n"; } } @@ -85,7 +89,7 @@ void list_command::dump(const std::vector& v, std::size_t indent) const void list_command::dump_aliases() const { - const auto v = get_all_aliases(); + const auto v = task_manager::instance().aliases(); if (v.empty()) return; diff --git a/src/cmd/pr.cpp b/src/cmd/pr.cpp index 5de8259..d37d7bf 100644 --- a/src/cmd/pr.cpp +++ b/src/cmd/pr.cpp @@ -1,6 +1,9 @@ #include "pch.h" #include "commands.h" +#include "../core/conf.h" +#include "../tasks/task_manager.h" #include "../tasks/tasks.h" +#include "../utility.h" namespace mob { @@ -95,7 +98,7 @@ std::pair pr_command::parse_pr( const std::string pattern = cs[0]; const std::string pr_number = cs[1]; - const auto* task = find_one_task(pattern); + const auto* task = task_manager::instance().find_one(pattern); if (!task) return {}; @@ -124,7 +127,7 @@ int pr_command::pull() for (auto&& pr : okay_prs) { const auto* task = dynamic_cast( - find_one_task(pr.repo)); + task_manager::instance().find_one(pr.repo)); if (!task) return 1; @@ -173,7 +176,7 @@ int pr_command::revert() for (auto&& pr : okay_prs) { const auto* task = dynamic_cast( - find_one_task(pr.repo)); + task_manager::instance().find_one(pr.repo)); if (!task) return 1; @@ -346,7 +349,7 @@ std::vector pr_command::validate_prs( } else { - const auto tasks = find_tasks(pr.repo); + const auto tasks = task_manager::instance().find(pr.repo); if (tasks.empty()) { diff --git a/src/cmd/release.cpp b/src/cmd/release.cpp index 649ce51..f2994b2 100644 --- a/src/cmd/release.cpp +++ b/src/cmd/release.cpp @@ -5,6 +5,7 @@ #include "../core/context.h" #include "../core/op.h" #include "../tasks/tasks.h" +#include "../tasks/task_manager.h" #include "../utility/threading.h" namespace mob @@ -302,7 +303,7 @@ int release_command::do_official() if (!check_clean_prefix()) return 1; - run_all_tasks(); + task_manager::instance().run_all(); build_command::terminate_msbuild(); prepare(); @@ -321,7 +322,7 @@ void release_command::check_repos_for_branch() thread_pool tp; std::atomic failed = false; - for (const auto* t : find_tasks("super")) + for (const auto* t : task_manager::instance().find("super")) { if (!t->enabled()) continue; diff --git a/src/core/conf.cpp b/src/core/conf.cpp index 28c1ae8..9038058 100644 --- a/src/core/conf.cpp +++ b/src/core/conf.cpp @@ -6,6 +6,7 @@ #include "paths.h" #include "../utility.h" #include "../tasks/task.h" +#include "../tasks/task_manager.h" #include "../tools/tools.h" namespace mob::details @@ -156,7 +157,7 @@ std::string get_string_for_task( // for super for (auto&& tn : task_names) { - for (auto&& t : find_tasks(tn)) + for (auto&& t : task_manager::instance().find(tn)) { if (t->is_super()) { @@ -217,6 +218,8 @@ namespace mob std::vector format_options() { + auto& tm = task_manager::instance(); + std::size_t longest_what = 0; std::size_t longest_key = 0; @@ -231,7 +234,7 @@ std::vector format_options() for (auto&& [k, v] : details::g_tasks[""]) longest_key = std::max(longest_key, k.size()); - for (const auto* task : get_all_tasks()) + for (const auto* task : tm.all()) longest_what = std::max(longest_what, task->name().size()); std::vector lines; @@ -263,7 +266,7 @@ std::vector format_options() pad_right(k, longest_key) + " = " + v); } - for (const auto* t : get_all_tasks()) + for (const auto* t : tm.all()) { for (auto&& [k, unused] : details::g_tasks[""]) { @@ -395,7 +398,7 @@ void process_option( // task specific // task must exist - const auto& tasks = find_tasks(task); + const auto& tasks = task_manager::instance().find(task); MOB_ASSERT(!tasks.empty()); for (auto& t : tasks) @@ -429,7 +432,7 @@ void process_ini(const fs::path& ini, bool master) const auto data = parse_ini(ini); for (auto&& a : data.aliases) - add_alias(a.first, a.second); + task_manager::instance().add_alias(a.first, a.second); for (auto&& [section_string, kvs] : data.sections) { diff --git a/src/core/ini.cpp b/src/core/ini.cpp index fb567ff..c78100e 100644 --- a/src/core/ini.cpp +++ b/src/core/ini.cpp @@ -4,7 +4,7 @@ #include "context.h" #include "env.h" #include "conf.h" -#include "../tasks/tasks.h" +#include "../tasks/task_manager.h" #include "../utility/string.h" namespace mob @@ -220,6 +220,8 @@ void parse_line( ini_data& ini, std::size_t i, const std::string& line, const std::string& task, const std::string& section) { + auto& tm = task_manager::instance(); + const auto sep = line.find("="); if (sep == std::string::npos) ini_error(ini, i, "bad line '{}'", line); @@ -232,7 +234,7 @@ void parse_line( if (section == "aliases") { - add_alias(k, split_quoted(v, " ")); + tm.add_alias(k, split_quoted(v, " ")); } else if (task.empty()) { @@ -240,7 +242,7 @@ void parse_line( } else { - if (!valid_task_name(task)) + if (!tm.valid_name(task)) ini_error(ini, i, "no task matching '{}' found", task); ini.set(task + ":" + section, k, v); diff --git a/src/core/paths.cpp b/src/core/paths.cpp index 15d7102..382e884 100644 --- a/src/core/paths.cpp +++ b/src/core/paths.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "paths.h" +#include "../tasks/task_manager.h" #include "../tasks/tasks.h" #include "../utility/string.h" @@ -337,7 +338,7 @@ fs::path find_qt() fs::path find_iscc() { // don't bother if the installer isn't enabled, it might fail anyway - if (!find_one_task("installer")->enabled()) + if (!task_manager::instance().find_one("installer")->enabled()) return {}; // check from the ini first, supports both relative and absolute diff --git a/src/main.cpp b/src/main.cpp index c6bba7e..b9f38dc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include "core/conf.h" #include "core/op.h" #include "tasks/tasks.h" +#include "tasks/task_manager.h" #include "tools/tools.h" #include "utility/threading.h" diff --git a/src/tasks/task.cpp b/src/tasks/task.cpp index 6e6846c..1386702 100644 --- a/src/tasks/task.cpp +++ b/src/tasks/task.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "task.h" +#include "task_manager.h" #include "../core/conf.h" #include "../core/op.h" #include "../tools/tools.h" @@ -8,204 +9,6 @@ namespace mob { -class interrupted {}; - -static std::vector> g_top_level_tasks; -static std::vector g_all_tasks; -static std::atomic g_interrupt = false; -static alias_map g_aliases; -std::mutex task::interrupt_mutex_; - - -void add_task(std::unique_ptr t) -{ - g_top_level_tasks.push_back(std::move(t)); -} - -std::vector get_all_tasks() -{ - std::vector v; - - for (auto&& t : g_all_tasks) - v.push_back(t); - - return v; -} - -std::vector get_top_level_tasks() -{ - std::vector v; - - for (auto&& t : g_top_level_tasks) - v.push_back(t.get()); - - return v; -} - -std::vector find_tasks_by_pattern(std::string_view pattern) -{ - std::vector tasks; - - for (auto&& t : g_all_tasks) - { - if (pattern == "super" && t->is_super()) - { - tasks.push_back(t); - } - else - { - for (auto&& n : t->names()) - { - if (mob::glob_match(pattern, n)) - { - tasks.push_back(t); - break; - } - } - } - } - - return tasks; -} - -std::vector find_tasks_by_alias(std::string_view pattern) -{ - std::vector v; - - auto itor = g_aliases.find(pattern); - if (itor == g_aliases.end()) - return v; - - for (auto&& a : itor->second) - { - const auto temp = find_tasks_by_pattern(a); - v.insert(v.end(), temp.begin(), temp.end()); - } - - return v; -} - -std::vector find_tasks(std::string_view pattern) -{ - std::vector tasks; - - for (auto&& t : g_all_tasks) - { - if (pattern == "super" && t->is_super()) - { - tasks.push_back(t); - } - else - { - for (auto&& n : t->names()) - { - if (mob::glob_match(pattern, n)) - { - tasks.push_back(t); - break; - } - } - } - } - - if (tasks.empty()) - tasks = find_tasks_by_alias(pattern); - - return tasks; -} - -task* find_one_task(std::string_view pattern, bool verbose) -{ - const auto tasks = find_tasks(pattern); - - if (tasks.empty()) - { - if (verbose) - u8cerr << "no task matches '" << pattern << "'\n"; - - return nullptr; - } - else if (tasks.size() > 1) - { - if (verbose) - { - u8cerr - << "found " << tasks.size() << " matches for pattern " - << "'" << pattern << "'\n" - << "the pattern must only match one task\n"; - } - - return nullptr; - } - - return tasks[0]; -} - -bool valid_task_name(std::string_view pattern) -{ - if (!find_tasks(pattern).empty()) - return true; - - if (pattern == "_override") - return true; - - return false; -} - -void run_all_tasks() -{ - try - { - for (auto& t : g_top_level_tasks) - { - t->fetch(); - - if (g_interrupt) - throw interrupted(); - } - - for (auto& t : g_top_level_tasks) - { - t->join(); - - if (g_interrupt) - throw interrupted(); - - t->build_and_install(); - - if (g_interrupt) - throw interrupted(); - - t->join(); - - if (g_interrupt) - throw interrupted(); - } - } - catch(interrupted&) - { - } -} - -void add_alias(std::string name, std::vector names) -{ - auto itor = g_aliases.find(name); - if (itor != g_aliases.end()) - { - gcx().warning(context::generic, "alias {} already exists", name); - return; - } - - g_aliases.emplace(std::move(name), std::move(names)); -} - -const alias_map& get_all_aliases() -{ - return g_aliases; -} - - - std::string to_string(task::clean c) { // generate warnings if something is added @@ -361,7 +164,7 @@ task::task(std::vector names) std::this_thread::get_id(), context(name()))); if (name() != "parallel") - g_all_tasks.push_back(this); + task_manager::instance().register_task(this); } task::~task() @@ -414,11 +217,7 @@ void task::add_name(std::string s) void task::interrupt_all() { - std::scoped_lock lock(interrupt_mutex_); - - g_interrupt = true; - for (auto&& t : g_top_level_tasks) - t->interrupt(); + task_manager::instance().interrupt_all(); } const std::string& task::name() const diff --git a/src/tasks/task.h b/src/tasks/task.h index b6f8a83..7361194 100644 --- a/src/tasks/task.h +++ b/src/tasks/task.h @@ -10,30 +10,6 @@ namespace mob class task; class tool; -void add_task(std::unique_ptr t); - -template -Task& add_task(Args&&... args) -{ - auto sp = std::make_unique(std::forward(args)...); - auto* p = sp.get(); - add_task(std::move(sp)); - return *p; -} - -void run_all_tasks(); -bool is_super_task(const std::string& name); -std::vector find_tasks(std::string_view pattern); -task* find_one_task(std::string_view pattern, bool verbose=true); -bool valid_task_name(std::string_view pattern); - -std::vector get_all_tasks(); -std::vector get_top_level_tasks(); - -using alias_map = std::map, std::less<>>; -void add_alias(std::string name, std::vector patterns); -const alias_map& get_all_aliases(); - class task_conf_holder { @@ -146,8 +122,6 @@ private: std::vector tools_; mutable std::mutex tools_mutex_; - static std::mutex interrupt_mutex_; - clean make_clean_flags() const; void run_tool_impl(tool* t); }; diff --git a/src/tasks/task_manager.cpp b/src/tasks/task_manager.cpp new file mode 100644 index 0000000..255f36c --- /dev/null +++ b/src/tasks/task_manager.cpp @@ -0,0 +1,220 @@ +#include "pch.h" +#include "task_manager.h" +#include "task.h" + +namespace mob +{ + +task_manager::task_manager() + : interrupt_(false) +{ +} + +task_manager& task_manager::instance() +{ + static task_manager m; + return m; +} + +void task_manager::add(std::unique_ptr t) +{ + top_level_.push_back(std::move(t)); +} + +std::vector task_manager::find(std::string_view pattern) +{ + std::vector tasks; + + for (auto&& t : all_) + { + if (pattern == "super" && t->is_super()) + { + tasks.push_back(t); + } + else + { + for (auto&& n : t->names()) + { + if (mob::glob_match(pattern, n)) + { + tasks.push_back(t); + break; + } + } + } + } + + if (tasks.empty()) + tasks = find_by_alias(pattern); + + return tasks; +} + +task* task_manager::find_one(std::string_view pattern, bool verbose) +{ + const auto tasks = find(pattern); + + if (tasks.empty()) + { + if (verbose) + u8cerr << "no task matches '" << pattern << "'\n"; + + return nullptr; + } + else if (tasks.size() > 1) + { + if (verbose) + { + u8cerr + << "found " << tasks.size() << " matches for pattern " + << "'" << pattern << "'\n" + << "the pattern must only match one task\n"; + } + + return nullptr; + } + + return tasks[0]; +} + +std::vector task_manager::all() +{ + std::vector v; + + for (auto&& t : all_) + v.push_back(t); + + return v; +} + +std::vector task_manager::top_level() +{ + std::vector v; + + for (auto&& t : top_level_) + v.push_back(t.get()); + + return v; +} + +void task_manager::add_alias(std::string name, std::vector names) +{ + auto itor = aliases_.find(name); + if (itor != aliases_.end()) + { + gcx().warning(context::generic, "alias {} already exists", name); + return; + } + + aliases_.emplace(std::move(name), std::move(names)); +} + +const task_manager::alias_map& task_manager::aliases() +{ + return aliases_; +} + +void task_manager::run_all() +{ + try + { + for (auto& t : top_level_) + { + t->fetch(); + + if (interrupt_) + throw interrupted(); + } + + for (auto& t : top_level_) + { + t->join(); + + if (interrupt_) + throw interrupted(); + + t->build_and_install(); + + if (interrupt_) + throw interrupted(); + + t->join(); + + if (interrupt_) + throw interrupted(); + } + } + catch(interrupted&) + { + } +} + +void task_manager::interrupt_all() +{ + std::scoped_lock lock(interrupt_mutex_); + + interrupt_ = true; + for (auto&& t : top_level_) + t->interrupt(); +} + +void task_manager::register_task(task* t) +{ + all_.push_back(t); +} + +std::vector task_manager::find_by_pattern(std::string_view pattern) +{ + std::vector tasks; + + for (auto&& t : all_) + { + if (pattern == "super" && t->is_super()) + { + tasks.push_back(t); + } + else + { + for (auto&& n : t->names()) + { + if (mob::glob_match(pattern, n)) + { + tasks.push_back(t); + break; + } + } + } + } + + return tasks; +} + +std::vector task_manager::find_by_alias(std::string_view pattern) +{ + std::vector v; + + auto itor = aliases_.find(pattern); + if (itor == aliases_.end()) + return v; + + for (auto&& a : itor->second) + { + const auto temp = find_by_pattern(a); + v.insert(v.end(), temp.begin(), temp.end()); + } + + return v; +} + +bool task_manager::valid_name(std::string_view pattern) +{ + if (!find(pattern).empty()) + return true; + + if (pattern == "_override") + return true; + + return false; +} + +} // namespace diff --git a/src/tasks/task_manager.h b/src/tasks/task_manager.h new file mode 100644 index 0000000..ad9751f --- /dev/null +++ b/src/tasks/task_manager.h @@ -0,0 +1,58 @@ +#pragma once + +namespace mob +{ + +class interrupted {}; +class task; + +class task_manager +{ +public: + using alias_map = + std::map, std::less<>>; + + + task_manager(); + static task_manager& instance(); + + void add(std::unique_ptr t); + + std::vector find(std::string_view pattern); + task* find_one(std::string_view pattern, bool verbose=true); + bool valid_name(std::string_view pattern); + + std::vector all(); + std::vector top_level(); + + void add_alias(std::string name, std::vector patterns); + const alias_map& aliases(); + + void run_all(); + void interrupt_all(); + + void register_task(task* t); + +private: + std::vector> top_level_; + std::vector all_; + std::atomic interrupt_; + std::mutex interrupt_mutex_; + alias_map aliases_; + + std::vector find_by_pattern(std::string_view pattern); + std::vector find_by_alias(std::string_view pattern); +}; + +template +Task& add_task(Args&&... args) +{ + auto t = std::make_unique(std::forward(args)...); + auto& ref = *t; + + task_manager::instance().add(std::move(t)); + + return ref; +} + +} // namespace diff --git a/src/tasks/translations.cpp b/src/tasks/translations.cpp index 004e914..71029e8 100644 --- a/src/tasks/translations.cpp +++ b/src/tasks/translations.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "tasks.h" +#include "task_manager.h" #include "../core/env.h" #include "../utility/threading.h" @@ -48,7 +49,7 @@ void translations::projects::create() bool translations::projects::is_gamebryo_plugin( const std::string& dir, const std::string& project) { - auto tasks = find_tasks(project); + auto tasks = task_manager::instance().find(project); if (tasks.empty()) { warnings_.push_back(::fmt::format( diff --git a/vs/mob.vcxproj b/vs/mob.vcxproj index ac13289..0676685 100644 --- a/vs/mob.vcxproj +++ b/vs/mob.vcxproj @@ -103,6 +103,7 @@ + @@ -137,6 +138,7 @@ + diff --git a/vs/mob.vcxproj.filters b/vs/mob.vcxproj.filters index 5537c7c..d4c3787 100644 --- a/vs/mob.vcxproj.filters +++ b/vs/mob.vcxproj.filters @@ -204,6 +204,9 @@ src\tools + + src\tasks + @@ -281,5 +284,8 @@ src\tools + + src\tasks + \ No newline at end of file