This commit is contained in:
Bryson Steck 2025-07-31 23:12:56 -06:00
commit 0b9177a8ce
Signed by: bryson
SSH key fingerprint: SHA256:XpKABw/nP4z8UVaH+weLaBnEOD86+cVwif+QjuYLGT4
7 changed files with 219 additions and 0 deletions

28
.devcontainer/Dockerfile Normal file
View file

@ -0,0 +1,28 @@
FROM fedora:latest AS devcontainer
ARG UID="1000"
ARG GID="1000"
ARG BASENAME="workdir"
# setup packages
USER root
RUN dnf update -y
RUN dnf install -y dnf5-devel libdnf5-devel libdnf5-cli-devel openssh-server vim cmake gcc g++ git just
# setup environment
RUN ssh-keygen -A
RUN sed -i "s|#Port 22|Port 2222|g" /etc/ssh/sshd_config
RUN sed -i "s|AuthorizedKeysFile.*|AuthorizedKeysFile /etc/ssh/authorized_keys|g" /etc/ssh/sshd_config
RUN --mount=type=secret,id=key,target=/root/id.pub \
cp /root/id.pub /etc/ssh/authorized_keys
# setup user and permissions
RUN groupadd -g $GID dev
RUN useradd -u $UID -g $GID -lN dev
RUN chown dev:dev /etc/ssh/ssh_host* /etc/ssh/authorized_keys /etc/ssh/sshd_config
USER dev
WORKDIR /volume/${BASENAME}
EXPOSE 2222/tcp
CMD ["/usr/sbin/sshd", "-D"]
# use docker exec or SSH to access container OR
# use docker compose to specify entrypoint

13
.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
build/
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
CMakeUserPresets.json

31
CMakeLists.txt Normal file
View file

@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.6)
project(lifi LANGUAGES CXX C VERSION 0.1.0)
# includes
include(GNUInstallDirs)
find_package(PkgConfig REQUIRED)
# C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Give inline methods hidden visibility by default
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
# warnings
add_compile_options(-Wall -Wextra -Werror)
add_compile_options(-Wcast-align -Wformat-nonliteral -Wmissing-format-attribute -Wredundant-decls -Wsign-compare -Wsign-conversion -Wtype-limits -Wuninitialized -Wwrite-strings)
add_compile_options(-Werror=unused-result -Wodr)
# not sure about the conversion warnings being errors; review later
add_compile_options(-Wconversion)
# linker options
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# clang doesn't support this option
add_compile_options(-Wl,--as-needed)
endif()
add_subdirectory("src")

37
Justfile Normal file
View file

@ -0,0 +1,37 @@
alias dev := devcontainer
alias t := transaction
workdir := `pwd`
basename := `basename $(pwd)`
dockerfile := '.devcontainer/Dockerfile'
container := basename + '-devcontainer'
uid := `id -u`
gid := `id -g`
image := container + '-img'
ssh_key := env('HOME') + '/.ssh/id_rsa.pub'
# for use in dev container
build:
mkdir -p build
cd build && cmake .. && make
# test a transaction
transaction:
docker exec -u root -it {{container}} dnf reinstall libdnf5 --setopt=pluginpath=build/src \
--setopt=pluginconfpath=src -y
clean:
docker container stop {{container}} || :
docker container rm {{container}} || :
docker image rm {{image}} || :
rm -rf build
# (re)start Docker dev container
devcontainer:
(docker container ls --all | grep -q {{container}} && docker container stop {{container}} \
&& docker container rm {{container}}) || :
docker build --secret id=key,src={{ssh_key}} --build-arg UID={{uid}} --build-arg GID={{gid}} \
--build-arg BASENAME={{basename}} -t {{image}} -f {{dockerfile}} .
docker container create --name {{container}} -v {{workdir}}:/volume/{{basename}} \
-p 2222:2222 {{image}}
docker container start {{container}}

11
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,11 @@
add_library(lifi MODULE lifi.cpp)
# disable the 'lib' prefix in order to create lifi.so
set_target_properties(lifi PROPERTIES PREFIX "")
set_target_properties(lifi PROPERTIES OUTPUT_NAME "lifi")
pkg_check_modules(LIBDNF5 REQUIRED libdnf5)
target_link_libraries(lifi PRIVATE ${LIBDNF5_LIBRARIES})
install(TARGETS lifi LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/libdnf5/plugins/")
install(FILES "lifi.conf" DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}/dnf/libdnf5-plugins")

6
src/lifi.conf Normal file
View file

@ -0,0 +1,6 @@
[main]
name = lifi
enabled = 1
[new]
custom_thing = hi there

93
src/lifi.cpp Normal file
View file

@ -0,0 +1,93 @@
#include <libdnf5-cli/defs.h>
#include <libdnf5/base/base.hpp>
#include <libdnf5/base/transaction.hpp>
#include <libdnf5/base/transaction_package.hpp>
#include <libdnf5/common/exception.hpp>
#include <libdnf5/conf/config_parser.hpp>
#include <libdnf5/defs.h>
#include <libdnf5/plugin/iplugin.hpp>
#include <iostream>
using namespace libdnf5;
namespace {
constexpr const char *PLUGIN_NAME = "lifi";
constexpr plugin::Version PLUGIN_VERSION{0, 1, 0};
constexpr const char *attrs[]{"author.name", "author.email", "description",
nullptr};
constexpr const char *attrs_value[]{"Bryson Steck", "bryson@steck.dev",
"a LIcense FIlter for dnf"};
class Lifi final : public plugin::IPlugin {
public:
ConfigParser config;
Lifi(libdnf5::plugin::IPluginData &data, libdnf5::ConfigParser &config)
: IPlugin(data) {
config = config;
this->config.read(
get_base().get_config().get_pluginconfpath_option().get_value() +
"/lifi.conf");
}
virtual ~Lifi() = default;
PluginAPIVersion get_api_version() const noexcept override {
return PLUGIN_API_VERSION;
}
const char *get_name() const noexcept override { return PLUGIN_NAME; }
plugin::Version get_version() const noexcept override {
return PLUGIN_VERSION;
}
const char *const *get_attributes() const noexcept override { return attrs; }
const char *get_attribute(const char *attribute) const noexcept override {
for (size_t i = 0; attrs[i]; ++i) {
if (std::strcmp(attribute, attrs[i]) == 0) {
return attrs_value[i];
}
}
return nullptr;
}
void pre_transaction(
[[maybe_unused]] const libdnf5::base::Transaction &transaction) override {
std::cout << "----- executing Lifi::pre_transaction() method -----"
<< std ::endl;
auto packages = transaction.get_transaction_packages();
for (auto pkg : packages) {
std::cout << pkg.get_package().get_license() << std::endl;
}
std::cout << config.get_value("new", "custom_thing") << std::endl;
}
private:
};
} // namespace
PluginAPIVersion libdnf_plugin_get_api_version(void) {
return PLUGIN_API_VERSION;
}
const char *libdnf_plugin_get_name(void) { return PLUGIN_NAME; }
plugin::Version libdnf_plugin_get_version(void) { return PLUGIN_VERSION; }
plugin::IPlugin *
libdnf_plugin_new_instance([[maybe_unused]] LibraryVersion library_version,
libdnf5::plugin::IPluginData &data,
libdnf5::ConfigParser &parser) try {
return new Lifi(data, parser);
} catch (...) {
return nullptr;
}
void libdnf_plugin_delete_instance(plugin::IPlugin *plugin_object) {
delete plugin_object;
}