diff --git a/bindings/libdnf5/base.i b/bindings/libdnf5/base.i index a40ac0c36..3c683990c 100644 --- a/bindings/libdnf5/base.i +++ b/bindings/libdnf5/base.i @@ -50,6 +50,15 @@ %template(BaseWeakPtr) libdnf5::WeakPtr; %template(VarsWeakPtr) libdnf5::WeakPtr; +%ignore std::vector::insert; +%ignore std::vector::pop; +%ignore std::vector::pop_back; +%ignore std::vector::push; +%ignore std::vector::push_back; +%ignore std::vector::reserve; +%ignore std::vector::resize; +%template(VectorPluginInfo) std::vector; + %include "libdnf5/base/base.hpp" %include "libdnf5/base/solver_problems.hpp" diff --git a/bindings/libdnf5/plugin.i b/bindings/libdnf5/plugin.i index c36b2a277..6cdd37556 100644 --- a/bindings/libdnf5/plugin.i +++ b/bindings/libdnf5/plugin.i @@ -16,10 +16,20 @@ %{ #include "libdnf5/plugin/iplugin.hpp" + #include "libdnf5/plugin/plugin_info.hpp" %} #define CV __perl_CV +%include "libdnf5/plugin/plugin_version.hpp" + +%extend libdnf5::plugin::Version { + Version(std::uint16_t major, std::uint16_t minor, std::uint16_t micro) { + libdnf5::plugin::Version * ver = new libdnf5::plugin::Version({major, minor, micro}); + return ver; + } +} + %ignore PluginError; %ignore libdnf_plugin_get_api_version; %ignore libdnf_plugin_get_name; @@ -29,9 +39,4 @@ %feature("director") IPlugin; %include "libdnf5/plugin/iplugin.hpp" -%extend libdnf5::plugin::Version { - Version(std::uint16_t major, std::uint16_t minor, std::uint16_t micro) { - libdnf5::plugin::Version * ver = new libdnf5::plugin::Version({major, minor, micro}); - return ver; - } -} +%include "libdnf5/plugin/plugin_info.hpp" diff --git a/include/libdnf5/base/base.hpp b/include/libdnf5/base/base.hpp index 837d8d3e5..e24fff6c0 100644 --- a/include/libdnf5/base/base.hpp +++ b/include/libdnf5/base/base.hpp @@ -28,6 +28,7 @@ along with libdnf. If not, see . #include "libdnf5/conf/vars.hpp" #include "libdnf5/logger/log_router.hpp" #include "libdnf5/module/module_sack.hpp" +#include "libdnf5/plugin/plugin_info.hpp" #include "libdnf5/repo/download_callbacks.hpp" #include "libdnf5/repo/repo_sack.hpp" #include "libdnf5/rpm/package_sack.hpp" @@ -94,6 +95,10 @@ class Base { /// @exception libdnf5::UserAssertionError When called after Base::setup void enable_disable_plugins(const std::vector & plugin_names, bool enable); + /// @return a list of information about plugins found during Base::setup + /// @exception libdnf5::UserAssertionError When called before Base::setup + const std::vector & get_plugins_info() const; + /// 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 diff --git a/include/libdnf5/plugin/iplugin.hpp b/include/libdnf5/plugin/iplugin.hpp index 269ca06c0..03c247c68 100644 --- a/include/libdnf5/plugin/iplugin.hpp +++ b/include/libdnf5/plugin/iplugin.hpp @@ -20,10 +20,11 @@ along with libdnf. If not, see . #ifndef LIBDNF5_PLUGIN_IPLUGIN_HPP #define LIBDNF5_PLUGIN_IPLUGIN_HPP +#include "plugin_version.hpp" + #include "libdnf5/common/impl_ptr.hpp" #include "libdnf5/version.hpp" -#include #include #include @@ -40,13 +41,6 @@ class Transaction; namespace libdnf5::plugin { -/// Plugin version -struct Version { - std::uint16_t major; - std::uint16_t minor; - std::uint16_t micro; -}; - class IPluginData; /// @brief A base class for implementing LIBDNF5 plugins that introduce additional logic into the library using hooks. diff --git a/include/libdnf5/plugin/plugin_info.hpp b/include/libdnf5/plugin/plugin_info.hpp new file mode 100644 index 000000000..769cf0950 --- /dev/null +++ b/include/libdnf5/plugin/plugin_info.hpp @@ -0,0 +1,75 @@ +/* +Copyright Contributors to the libdnf project. + +This file is part of li +bdnf: https://github.com/rpm-software-management/libdnf/ + +Libdnf is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 of the License, or +(at your option) any later version. + +Libdnf is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with libdnf. If not, see . +*/ + +#ifndef LIBDNF5_PLUGIN_PLUGIN_INFO_HPP +#define LIBDNF5_PLUGIN_PLUGIN_INFO_HPP + +#include "plugin_version.hpp" + +#include "libdnf5/common/impl_ptr.hpp" +#include "libdnf5/version.hpp" + +namespace libdnf5::plugin { + +class PluginInfo { +public: + ~PluginInfo(); + + PluginInfo(const PluginInfo & src); + PluginInfo(PluginInfo && src) noexcept; + PluginInfo & operator=(const PluginInfo & src); + PluginInfo & operator=(PluginInfo && src) noexcept; + + PluginInfo() = delete; + + /// @return the real name of the plugin or derived from the configuration file if the plugin is not loaded + const std::string & get_name() const noexcept; + + /// @return true if the plugin is loaded + bool is_loaded() const noexcept; + + /// @return the version of the API supported by the plugin, or zeros if the plugin is not loaded + PluginAPIVersion get_api_version() const noexcept; + + /// @return the real plugin name (returned from plugin) or nullptr if the plugin is not loaded + const char * get_real_name() const noexcept; + + /// @return the version of the plugin, or zeros if the plugin is not loaded + Version get_version() const noexcept; + + /// @return a nullptr terminated array of attributes supported by the plugin or nullptr if the plugin is not loaded + const char * const * get_attributes() const noexcept; + + /// Gets the value of the attribute from the plugin. + /// Returns nullptr if the attribute does not exist or plugin is not loaded. + /// @return the value of the `name` attribute or nullptr + const char * get_attribute(const char * name) const noexcept; + + class Impl; + +private: + explicit PluginInfo(Impl & p_impl); + + ImplPtr p_impl; +}; + +} // namespace libdnf5::plugin + +#endif diff --git a/include/libdnf5/plugin/plugin_version.hpp b/include/libdnf5/plugin/plugin_version.hpp new file mode 100644 index 000000000..6ed0a5606 --- /dev/null +++ b/include/libdnf5/plugin/plugin_version.hpp @@ -0,0 +1,36 @@ +/* +Copyright Contributors to the libdnf project. + +This file is part of libdnf: https://github.com/rpm-software-management/libdnf/ + +Libdnf is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 of the License, or +(at your option) any later version. + +Libdnf is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with libdnf. If not, see . +*/ + +#ifndef LIBDNF5_PLUGIN_PLUGIN_VERSION_HPP +#define LIBDNF5_PLUGIN_PLUGIN_VERSION_HPP + +#include + +namespace libdnf5::plugin { + +/// Plugin version +struct Version { + std::uint16_t major; + std::uint16_t minor; + std::uint16_t micro; +}; + +} // namespace libdnf5::plugin + +#endif diff --git a/libdnf5/base/base.cpp b/libdnf5/base/base.cpp index fa63e46b9..4f682d9c9 100644 --- a/libdnf5/base/base.cpp +++ b/libdnf5/base/base.cpp @@ -157,6 +157,11 @@ void Base::enable_disable_plugins(const std::vector & plugin_names, } } +const std::vector & Base::get_plugins_info() const { + libdnf_user_assert(p_impl->pool, "Base::get_plugins_info must not be called before Base::setup"); + return p_impl->get_plugins_info(); +} + void Base::setup() { auto & pool = p_impl->pool; libdnf_user_assert(!pool, "Base was already initialized"); diff --git a/libdnf5/base/base_impl.hpp b/libdnf5/base/base_impl.hpp index 3a5cdf6a7..def8a0289 100644 --- a/libdnf5/base/base_impl.hpp +++ b/libdnf5/base/base_impl.hpp @@ -56,6 +56,10 @@ class Base::Impl { plugin::Plugins & get_plugins() { return plugins; } + std::vector & get_plugins_info() { return plugins_info; } + + const std::vector & get_plugins_info() const { return plugins_info; } + /// Call a function that loads the config file, catching errors appropriately void with_config_file_path(std::function func); @@ -94,6 +98,7 @@ class Base::Impl { /// map of plugin names (global patterns) that we want to enable (true) or disable (false) PreserveOrderMap plugins_enablement; + std::vector plugins_info; WeakPtrGuard log_router_guard; WeakPtrGuard vars_guard; @@ -102,10 +107,13 @@ class Base::Impl { class InternalBaseUser { public: - static solv::RpmPool & get_rpm_pool(const libdnf5::BaseWeakPtr & base) { return base->p_impl->get_rpm_pool(); } static solv::CompsPool & get_comps_pool(const libdnf5::BaseWeakPtr & base) { return base->p_impl->get_comps_pool(); } + + static std::vector & get_plugins_info(Base * base) { return base->p_impl->get_plugins_info(); } + + static solv::RpmPool & get_rpm_pool(const libdnf5::BaseWeakPtr & base) { return base->p_impl->get_rpm_pool(); } }; } // namespace libdnf5 diff --git a/libdnf5/plugin/plugin_info.cpp b/libdnf5/plugin/plugin_info.cpp new file mode 100644 index 000000000..1f3a06d5c --- /dev/null +++ b/libdnf5/plugin/plugin_info.cpp @@ -0,0 +1,64 @@ +/* +Copyright Contributors to the libdnf project. + +This file is part of libdnf: https://github.com/rpm-software-management/libdnf/ + +Libdnf is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 of the License, or +(at your option) any later version. + +Libdnf is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with libdnf. If not, see . +*/ + +#include "plugin_info_impl.hpp" + +namespace libdnf5::plugin { + +PluginInfo::PluginInfo(Impl & p_impl) : p_impl{&p_impl} {} + +PluginInfo::~PluginInfo() = default; + +PluginInfo::PluginInfo(const PluginInfo & src) = default; + +PluginInfo::PluginInfo(PluginInfo && src) noexcept = default; + +PluginInfo & PluginInfo::operator=(const PluginInfo & src) = default; + +PluginInfo & PluginInfo::operator=(PluginInfo && src) noexcept = default; + +const std::string & PluginInfo::get_name() const noexcept { + return p_impl->get_name(); +} + +bool PluginInfo::is_loaded() const noexcept { + return p_impl->is_loaded(); +} + +PluginAPIVersion PluginInfo::get_api_version() const noexcept { + return p_impl->get_api_version(); +} + +const char * PluginInfo::get_real_name() const noexcept { + return p_impl->get_real_name(); +} + +Version PluginInfo::get_version() const noexcept { + return p_impl->get_version(); +} + +const char * const * PluginInfo::get_attributes() const noexcept { + return p_impl->get_attributes(); +} + +const char * PluginInfo::get_attribute(const char * name) const noexcept { + return p_impl->get_attribute(name); +} + +} // namespace libdnf5::plugin diff --git a/libdnf5/plugin/plugin_info_impl.hpp b/libdnf5/plugin/plugin_info_impl.hpp new file mode 100644 index 000000000..58930aa55 --- /dev/null +++ b/libdnf5/plugin/plugin_info_impl.hpp @@ -0,0 +1,70 @@ +/* +Copyright Contributors to the libdnf project. + +This file is part of libdnf: https://github.com/rpm-software-management/libdnf/ + +Libdnf is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 of the License, or +(at your option) any later version. + +Libdnf is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with libdnf. If not, see . +*/ + +#ifndef LIBDNF5_PLUGIN_PLUGIN_INFO_IMPL_HPP +#define LIBDNF5_PLUGIN_PLUGIN_INFO_IMPL_HPP + +#include "libdnf5/plugin/iplugin.hpp" +#include "libdnf5/plugin/plugin_info.hpp" + +namespace libdnf5::plugin { + +class PluginInfo::Impl { +public: + static PluginInfo create_plugin_info(std::string name_from_config, const IPlugin * iplugin) { + return PluginInfo(*new Impl(name_from_config, iplugin)); + } + + Impl() = delete; + Impl(const Impl & src) = default; + Impl(Impl && src) = delete; + + ~Impl() = default; + + Impl & operator=(const Impl & src) = default; + Impl & operator=(Impl &&) = delete; + + const std::string & get_name() const noexcept { return name; } + + bool is_loaded() const noexcept { return iplugin; } + + PluginAPIVersion get_api_version() const noexcept { + return iplugin ? iplugin->get_api_version() : PluginAPIVersion{0, 0}; + } + + const char * get_real_name() const noexcept { return iplugin ? iplugin->get_name() : nullptr; } + + Version get_version() const noexcept { return iplugin ? iplugin->get_version() : Version{0, 0, 0}; } + + const char * const * get_attributes() const noexcept { return iplugin ? iplugin->get_attributes() : nullptr; } + + const char * get_attribute(const char * name) const noexcept { + return iplugin ? iplugin->get_attribute(name) : nullptr; + } + +private: + explicit Impl(std::string name, const IPlugin * iplugin) : name{name}, iplugin{iplugin} {} + + std::string name; + const IPlugin * iplugin; +}; + +} // namespace libdnf5::plugin + +#endif diff --git a/libdnf5/plugin/plugins.cpp b/libdnf5/plugin/plugins.cpp index 3d37a2895..7fd3abaac 100644 --- a/libdnf5/plugin/plugins.cpp +++ b/libdnf5/plugin/plugins.cpp @@ -19,10 +19,11 @@ along with libdnf. If not, see . #include "plugins.hpp" +#include "base/base_impl.hpp" #include "iplugin_private.hpp" +#include "plugin_info_impl.hpp" #include "utils/library.hpp" -#include "libdnf5/base/base.hpp" #include "libdnf5/utils/bgettext/bgettext-mark-domain.h" #include @@ -188,6 +189,9 @@ void Plugins::load_plugin( if (!is_enabled) { logger.debug("Skip disabled plugin \"{}\"", config_file_path); + // Creates a PluginInfo for the unloaded plugin. + auto & plugins_info = InternalBaseUser::get_plugins_info(base); + plugins_info.emplace_back(PluginInfo::Impl::create_plugin_info(plugin_name, nullptr)); return; } @@ -226,6 +230,15 @@ void Plugins::load_plugins( if (!failed_filenames.empty()) { throw PluginError(M_("Cannot load plugins: {}"), failed_filenames); } + + // Creates a PluginInfo for each loaded plugin. + auto & plugins_info = InternalBaseUser::get_plugins_info(base); + for (const auto & plugin : plugins) { + const auto * iplugin = plugin->get_iplugin(); + if (iplugin) { + plugins_info.emplace_back(PluginInfo::Impl::create_plugin_info(iplugin->get_name(), iplugin)); + } + } } bool Plugins::init() {