From 6e250c7282a5efd06d36b4cc0241d721948a859b Mon Sep 17 00:00:00 2001 From: Aaron Fiore Date: Sat, 10 Aug 2024 18:50:06 -0700 Subject: [PATCH] container: root: add plugins support - Implements support for docker-finance C++ plugins - Adds shell command execution wrapper - Refactors previous loader path * A './' path is unnecessary and will break calls to '/' path --- container/src/root/macro/common/utility.hh | 89 +++++++++++++++++++++- container/src/root/macro/rootlogon.C | 26 ++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/container/src/root/macro/common/utility.hh b/container/src/root/macro/common/utility.hh index 95149bd..8d308df 100644 --- a/container/src/root/macro/common/utility.hh +++ b/container/src/root/macro/common/utility.hh @@ -72,7 +72,7 @@ class Command final //! \brief Load given file path static void load(const std::string& path) { - std::string cmd{".L ./" + path}; + std::string cmd{".L " + path}; Command::cmd_handler({cmd}); } @@ -97,6 +97,15 @@ std::string get_env(const std::string& var) return std::string{env}; } +//! \brief Execute command in shell +//! \param cmd Shell command [args] +//! \returns Return value of command +//! \since docker-finance 1.0.0 +int exec(const std::string& cmd) +{ + return gSystem->Exec(cmd.c_str()); +} + //! \brief Make current timestamp //! \return timestamp in "yyyy-mm-ddThh:mm:ssZ" format //! \since docker-finance 1.0.0 @@ -140,6 +149,84 @@ void load(const std::initializer_list& paths) common::Command::load(path); } } // namespace macro + +//! \namespace docker_finance::plugin +//! \brief docker-finance plugins +//! \warning All plugins (repo/custom) must exist within this namespace +//! and work within their own inner namespace +//! \since docker-finance 1.0.0 +namespace plugin +{ +//! \brief Load plugin by pseudo-paths +//! \details Wrapper to load from directory outside of default tree +//! \param path Must be of string "repo/file" or "custom/file" where file is +//! a plugin filename that exists in repository plugin path or +//! a client-side end-user's custom plugin path. +//! \ingroup cpp_plugin +//! \details +//! Example: +//!
  root [0] docker_finance::plugin::load("repo/example.cc")
+//! +//! Will load: +//!
  ${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example.cc
+//! +//! Example: +//!
  root [0] docker_finance::plugin::load("custom/example.cc")
+//! +//! Will load: +//!
  ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example.cc
+//! +//! \note Parent directory for all plugins are outside of repository's `root` directory +void load(const std::string& path) +{ + const std::string type{path.substr(0, path.find("/"))}; + + std::string file{path}; + file.erase(0, file.find("/") + 1); + + if (type == "repo") + { + file.insert( + 0, + macro::common::get_env("DOCKER_FINANCE_CONTAINER_REPO") + + "/plugins/root/"); + } + else if (type == "custom") + { + file.insert( + 0, + macro::common::get_env("DOCKER_FINANCE_CONTAINER_PLUGINS") + + "/root/"); + } + else + { + throw std::runtime_error( + "must be of type 'repo/' or 'custom/'"); + } + + macro::common::Command::load(file); +} + +//! \brief Wrapper to load plugins by list of pseudo-paths +//! \ingroup cpp_plugin +//! \param paths List must consist of string "repo/file" or "custom/file" where file is +//! a plugin filename that exists in repository plugin path or +//! a client-side end-user's custom plugin path. +//! \details +//! Example: +//!
  root [0] docker_finance::plugin::load({"repo/example.cc", "custom/example.cc"})
+//! +//! Will load: +//!
  ${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example.cc +//! and ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example.cc
+//! +//! \note Parent directory for all plugins are outside of repository's `root` directory +void load(const std::initializer_list& paths) +{ + for (const auto& path : paths) + macro::common::Command::load(path); +} +} // namespace plugin } // namespace docker_finance #endif // CONTAINER_SRC_ROOT_MACRO_COMMON_UTILITY_HH_ diff --git a/container/src/root/macro/rootlogon.C b/container/src/root/macro/rootlogon.C index c25706f..ce2ed8d 100644 --- a/container/src/root/macro/rootlogon.C +++ b/container/src/root/macro/rootlogon.C @@ -46,6 +46,8 @@ void help() << "\n" << " docker-finance C++ interpretations / interactive calculations\n" << "\n" + << " *** TIP: save your fingers! Use tab completion! ***\n" + << "\n" << " 1. Print current directory (all commands/files are relative to\n" << " this directory):\n" << "\n" @@ -101,9 +103,31 @@ void help() << " Maximum = 1.00000077\n" << " Printed = 1.00000077\n" << "\n" + << "Plugins:\n" + << "\n" + << " WARNING: unlike macro loader, the prepended 'repo' and 'custom'\n" + << " are not real directories but rather indications that the file\n" + << " is either a repository plugin or an non-repo (custom) plugin.\n" + << "\n" + << " 1. Connect to docker-finance API via plugins:\n" + << "\n" + << " // Load and run an example repository plugin\n" + << " root [0] docker_finance::plugin::load(\"repo/example.cc\");\n" + << " root [1] " + "docker_finance::plugin::my_plugin_namespace::example1();\n" + << " root [2] " + "docker_finance::plugin::my_plugin_namespace::example2();\n" + << " root [3] " + "docker_finance::plugin::my_plugin_namespace::example3();\n" + << "\n" + << " // Load and run your own custom plugin\n" + << " root [4] docker_finance::plugin::load(\"custom/example.cc\");\n" + << " root [5] " + "docker_finance::plugin::your_plugin_namespace::example();\n" + << "\n" << "Macros:\n" << "\n" - << " TIP: use tab auto-complete to easily run macros\n" + << " NOTE: the macro loader interprets from base 'macro' path (.!pwd)\n" << "\n" << " 1. Load and run docker-finance unit tests and benchmarks:\n" << "\n"