Skip to content

Commit

Permalink
[libdnf5 API] Base::enable_disable_plugins
Browse files Browse the repository at this point in the history
Adds a request to enable/disable libdnf5 library plugins that match
the names (glob patterns) in the list.
  • Loading branch information
jrohel authored and jan-kolarik committed Apr 18, 2024
1 parent 424d215 commit 80cfea9
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 21 deletions.
9 changes: 9 additions & 0 deletions include/libdnf5/base/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ class Base {
repo::RepoSackWeakPtr get_repo_sack();
rpm::PackageSackWeakPtr get_rpm_package_sack();

/// Adds a request to enable/disable plugins that match the names (glob patterns) in the list.
/// Can be called multiple times. Requests (`plugin_names` and `enable` state) are queued.
/// The enable state of a plugin is set according to the last matching request.
/// Must be called before the Base::setup.
/// @param plugin_names Plugin names (glob patterns) to enable/disable
/// @param enable Request: true - enable plugins, false - disable plugins
/// @exception libdnf5::UserAssertionError When called after Base::setup
void enable_disable_plugins(const std::vector<std::string> & plugin_names, bool enable);

/// Loads libdnf plugins, vars from environment, varsdirs and installroot (releasever, arch) and resolves
/// configuration of protected_packages (glob:).
/// To prevent differences between configuration and internal Base settings, following configurations
Expand Down
14 changes: 12 additions & 2 deletions libdnf5/base/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,19 @@ void Base::load_plugins() {
const char * plugins_config_dir = std::getenv("LIBDNF_PLUGINS_CONFIG_DIR");
if (plugins_config_dir &&
p_impl->config.get_pluginconfpath_option().get_priority() < Option::Priority::COMMANDLINE) {
p_impl->plugins.load_plugins(plugins_config_dir);
p_impl->plugins.load_plugins(plugins_config_dir, p_impl->plugins_enablement);
} else {
p_impl->plugins.load_plugins(p_impl->config.get_pluginconfpath_option().get_value());
p_impl->plugins.load_plugins(
p_impl->config.get_pluginconfpath_option().get_value(), p_impl->plugins_enablement);
}
}

void Base::enable_disable_plugins(const std::vector<std::string> & plugin_names, bool enable) {
libdnf_user_assert(!p_impl->pool, "Base::enable_disable_plugins must be called before Base::setup");

for (const auto & plugin_name : plugin_names) {
p_impl->plugins_enablement.erase(plugin_name);
p_impl->plugins_enablement.insert({plugin_name, enable});
}
}

Expand Down
3 changes: 3 additions & 0 deletions libdnf5/base/base_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ class Base::Impl {
Vars vars;
std::unique_ptr<repo::DownloadCallbacks> download_callbacks;

/// map of plugin names (global patterns) that we want to enable (true) or disable (false)
PreserveOrderMap<std::string, bool> plugins_enablement;

WeakPtrGuard<LogRouter, false> log_router_guard;
WeakPtrGuard<Vars, false> vars_guard;
};
Expand Down
48 changes: 31 additions & 17 deletions libdnf5/plugin/plugins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ void Plugins::load_plugin_library(
logger.debug("End of loading plugins using the \"{}\" plugin.", name);
}

void Plugins::load_plugin(const std::string & config_file_path) {
void Plugins::load_plugin(
const std::string & config_file_path, const PreserveOrderMap<std::string, bool> & plugin_enablement) {
auto & logger = *base->get_logger();

libdnf5::ConfigParser parser;
Expand All @@ -157,22 +158,34 @@ void Plugins::load_plugin(const std::string & config_file_path) {
"Missing plugin name in configuration file \"{}\". \"{}\" will be used.", config_file_path, plugin_name);
}

enum class Enabled { NO, YES, HOST_ONLY, INSTALLROOT_ONLY } enabled;
const auto & enabled_str = parser.get_value("main", "enabled");
if (enabled_str == "host-only") {
enabled = Enabled::HOST_ONLY;
} else if (enabled_str == "installroot-only") {
enabled = Enabled::INSTALLROOT_ONLY;
} else {
try {
enabled = OptionBool(false).from_string(enabled_str) ? Enabled::YES : Enabled::NO;
} catch (OptionInvalidValueError & ex) {
throw OptionInvalidValueError(M_("Invalid option value: enabled={}"), enabled_str);
bool is_enabled;
bool is_enabled_set{false};
for (auto it = plugin_enablement.rbegin(); it != plugin_enablement.rend(); ++it) {
if (sack::match_string(plugin_name, sack::QueryCmp::GLOB, it->first)) {
is_enabled = it->second;
is_enabled_set = true;
break;
}
}
const auto & installroot = base->get_config().get_installroot_option().get_value();
const bool is_enabled = enabled == Enabled::YES || (enabled == Enabled::HOST_ONLY && installroot == "/") ||
(enabled == Enabled::INSTALLROOT_ONLY && installroot != "/");
if (!is_enabled_set) {
enum class Enabled { NO, YES, HOST_ONLY, INSTALLROOT_ONLY } enabled;
const auto & enabled_str = parser.get_value("main", "enabled");
if (enabled_str == "host-only") {
enabled = Enabled::HOST_ONLY;
} else if (enabled_str == "installroot-only") {
enabled = Enabled::INSTALLROOT_ONLY;
} else {
try {
enabled = OptionBool(false).from_string(enabled_str) ? Enabled::YES : Enabled::NO;
} catch (OptionInvalidValueError & ex) {
throw OptionInvalidValueError(M_("Invalid option value: enabled={}"), enabled_str);
}
}
const auto & installroot = base->get_config().get_installroot_option().get_value();
is_enabled = enabled == Enabled::YES || (enabled == Enabled::HOST_ONLY && installroot == "/") ||
(enabled == Enabled::INSTALLROOT_ONLY && installroot != "/");
}

if (!is_enabled) {
logger.debug("Skip disabled plugin \"{}\"", config_file_path);
return;
Expand All @@ -182,7 +195,8 @@ void Plugins::load_plugin(const std::string & config_file_path) {
load_plugin_library(std::move(parser), library_path, plugin_name);
}

void Plugins::load_plugins(const std::string & config_dir_path) {
void Plugins::load_plugins(
const std::string & config_dir_path, const PreserveOrderMap<std::string, bool> & plugin_enablement) {
auto & logger = *base->get_logger();
if (config_dir_path.empty())
throw PluginError(M_("Plugins::load_plugins(): config_dir_path cannot be empty"));
Expand All @@ -199,7 +213,7 @@ void Plugins::load_plugins(const std::string & config_dir_path) {
std::string failed_filenames;
for (const auto & path : config_paths) {
try {
load_plugin(path);
load_plugin(path, plugin_enablement);
} catch (const std::exception & ex) {
logger.error("Cannot load plugin \"{}\": {}", path.string(), ex.what());
if (!failed_filenames.empty()) {
Expand Down
6 changes: 4 additions & 2 deletions libdnf5/plugin/plugins.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,12 @@ class Plugins {
void register_plugin(std::unique_ptr<Plugin> && plugin);

/// Loads the plugin from the library defined by the configuration file config_file_path.
void load_plugin(const std::string & config_file_path);
void load_plugin(
const std::string & config_file_path, const PreserveOrderMap<std::string, bool> & plugin_enablement);

/// Loads plugins defined by configuration files in the directory.
void load_plugins(const std::string & config_dir_path);
void load_plugins(
const std::string & config_dir_path, const PreserveOrderMap<std::string, bool> & plugin_enablement);

/// Returns the number of registered plugins.
size_t count() const noexcept;
Expand Down

0 comments on commit 80cfea9

Please sign in to comment.