container: root: common: utility: refactor/deprecate, add/enhance free functions

- Factors out (and deprecates) `Command`
- Deprecates certain free functions
- Adds better error handling
- Adds more free functions
- Refactors file handling
- Improves documentation

Notes on file loading (and general file handlers):

The interpreter command `.L` will load files but appears to not fail if
the file isn't source code or a library.

Calling `gSystem->Load()` will load a given library but not source file,
and appears to not accept paths (which will be needed for pluggables).

Because `gInterpreter->LoadFile("path")` will load either a source file
or library by given "path", and is consistent with `dfi`'s approach to
path handling, this function appears to be the winner (for now).
This commit is contained in:
2025-11-26 17:34:25 -08:00
parent ee82e6852f
commit ea20413107

View File

@@ -27,6 +27,7 @@
#include <filesystem>
#include <initializer_list>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
@@ -86,8 +87,48 @@ inline void throw_ex_if(
}
}
//! \brief Wrapper to ROOT Cling commands
// TODO(afiore): add logger with loglevels
//! \brief Process a line of code or interpreter command
//! \since docker-finance 1.1.0
inline void line(const std::string& line)
{
using EErrorCode = ::TInterpreter::EErrorCode;
auto ecode = std::make_unique<EErrorCode>();
// TODO(afiore): log levels
std::cout << "Interpreting: '" << line << "'" << std::endl;
gInterpreter->ProcessLine(line.c_str(), ecode.get());
throw_ex_if<type::RuntimeError>(*ecode != EErrorCode::kNoError, line);
}
//! \brief Load file with given path into interpreter
//! \details Can load a source file or library file
//! \param path Operating system path (absolute or relative)
//! \since docker-finance 1.1.0
inline void load(const std::string& path)
{
throw_ex_if<type::RuntimeError>(
!std::filesystem::is_regular_file(path), "invalid file: '" + path + "'");
// TODO(afiore): log levels
std::cout << "Loading: '" << path << "'" << std::endl;
gInterpreter->LoadFile(path.c_str());
}
//! \brief Load files with given paths into interpreter
//! \details Can load source files and/or library files
//! \param path Operating system paths (absolute or relative)
//! \since docker-finance 1.1.0
inline void load(const std::initializer_list<std::string>& paths)
{
for (const auto& path : paths)
load(path);
}
//! \brief Wrappers to commonly used interpreter abstractions
//! \ingroup cpp_common_impl
//! \deprecated This will be removed in the v2 API; use the `dfi::common` free functions instead
//! \since docker-finance 1.0.0
class Command
{
@@ -101,45 +142,106 @@ class Command
Command(Command&&) = default;
Command& operator=(Command&&) = default;
private:
static void cmd_handler(const std::initializer_list<std::string>& command)
{
for (const auto& cmd : command)
{
std::cout << "Interpreting: '" << cmd << "'" << std::endl;
gInterpreter->ProcessLine(cmd.c_str());
}
}
public:
//! \brief Load given file path
static void load(const std::string& path)
//! \deprecated This will be removed in the v2 API; use the `dfi::common` free function instead
//! \since docker-finance 1.0.0
static void load(const std::string& path) { ::dfi::common::load(path); }
//! \deprecated This will be removed in the v2 API; use the `dfi::common` free function instead
//! \since docker-finance 1.0.0
static void load(const std::initializer_list<std::string>& paths)
{
std::filesystem::path p(path);
throw_ex_if<type::RuntimeError>(
!std::filesystem::exists(p), "'" + path + "' does not exist!");
throw_ex_if<type::RuntimeError>(
!std::filesystem::is_regular_file(p),
"'" + path + "' is not a regular file!");
std::string cmd{".L " + path};
Command::cmd_handler({cmd});
::dfi::common::load(paths);
}
//! \brief Load given file paths
static void load(const std::initializer_list<std::string>& commands)
{
for (const auto& cmd : commands)
Command::load(cmd);
}
// TODO(afiore): unload
};
//! \brief Get ROOT environment variable
//! \param var ROOT variable
//! \brief Unload file with given path out of interpreter
//! \details Can unload a source file or library file
//! \param path Operating system path (absolute or relative)
//! \since docker-finance 1.1.0
inline void unload(const std::string& path)
{
throw_ex_if<type::RuntimeError>(
!std::filesystem::is_regular_file(path), "invalid file: '" + path + "'");
// TODO(afiore): log levels
std::cout << "Unloading: '" << path << "'" << std::endl;
gInterpreter->UnloadFile(path.c_str());
}
//! \brief Unload files with given paths out of interpreter
//! \details Can unload source files and/or library files
//! \param path Operating system paths (absolute or relative)
//! \since docker-finance 1.1.0
inline void unload(const std::initializer_list<std::string>& paths)
{
for (const auto& path : paths)
unload(path);
}
//! \brief Reload file with given path out of/into interpreter
//! \details Can reload source files and/or library files
//! \param path Operating system paths (absolute or relative)
//! \since docker-finance 1.1.0
inline void reload(const std::string& path)
{
unload(path);
load(path);
}
//! \brief Reload files with given paths out of/into interpreter
//! \details Can reload source files and/or library files
//! \param path Operating system paths (absolute or relative)
//! \since docker-finance 1.1.0
inline void reload(const std::initializer_list<std::string>& paths)
{
unload(paths);
load(paths);
}
//! \brief Add an include directory to interpreter
//! \param path Path to include (absolute or relative)
//! \warning Only pass the complete path to directory and not "-I"
//! \warning To pass multiple paths, call this function multiple times
//! \exception type::RuntimeError if path doesn't exist or cannot be included
//! \since docker-finance 1.1.0
inline void add_include_dir(const std::string& path)
{
throw_ex_if<type::RuntimeError>(
!std::filesystem::is_directory(path),
"invalid directory: '" + path + "'");
// TODO(afiore): log levels
std::cout << "Adding: '" << path << "'" << std::endl;
gInterpreter->AddIncludePath(path.c_str());
}
//! \brief Add a linked library into interpreter
//! \param path Path of library to add (absolute or relative)
//! \warning Only pass the complete path to library and not "-l"
//! \warning To pass multiple libraries, call this function multiple times
//! \exception type::RuntimeError if library doesn't exist or cannot be linked
//! \since docker-finance 1.1.0
inline void add_linked_lib(const std::string& path)
{
load(path);
}
//! \brief Remove a linked library from interpreter
//! \param path Path of library to remove (absolute or relative)
//! \warning Only pass the complete path to library and not "-l"
//! \warning To pass multiple libraries, call this function multiple times
//! \exception type::RuntimeError if library doesn't exist or cannot be linked
//! \since docker-finance 1.1.0
inline void remove_linked_lib(const std::string& path)
{
unload(path);
}
//! \brief Get underlying environment variable
//! \param var Environment variable
//! \return Value of given environment variable
//! \exception type::RuntimeError Throws if env var is not set or unavailable
//! \note ROOT environment variables include shell (and shell caller) environment
//! \since docker-finance 1.0.0
std::string get_env(const std::string& var)
@@ -152,9 +254,9 @@ 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
//! \brief Execute a command in operating system shell
//! \param cmd Operating system shell command [args]
//! \return Return value of command
//! \since docker-finance 1.0.0
int exec(const std::string& cmd)
{