Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dnfdaemon: Update goal.resolve() return value with missing attributes #190

Merged
merged 7 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion dnf5daemon-client/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ void Context::init_session(sdbus::IConnection & connection) {
auto config = key_value_map_get<std::map<std::string, std::string>>(cfg, "config", empty_options);
std::filesystem::path ir{installroot.get_value()};
config["installroot"] = ir.string();
config["cachedir"] = (ir / "var/cache/dnf").string();
for (auto & opt : setopts) {
config[opt.first] = opt.second;
}
Expand Down
43 changes: 41 additions & 2 deletions dnf5daemon-client/wrappers/dbus_goal_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,50 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.

#include "dbus_goal_wrapper.hpp"

#include <libdnf/transaction/transaction_item_type.hpp>

#include <iostream>

namespace dnfdaemon::client {

DbusGoalWrapper::DbusGoalWrapper(std::vector<dnfdaemon::DbusTransactionItem> transaction) {
for (auto & ti : transaction) {
transaction_packages.push_back(DbusTransactionPackageWrapper(ti));
// auxiliary map transaction_package.id -> index of package in transaction_package
// used to resolve replaces from id to DbusPackageWrapper instance
std::map<int, size_t> transaction_packages_by_id;

for (const auto & ti : transaction) {
auto object_type = libdnf::transaction::transaction_item_type_from_string(std::get<0>(ti));
if (object_type == libdnf::transaction::TransactionItemType::PACKAGE) {
transaction_packages.push_back(DbusTransactionPackageWrapper(ti));
transaction_packages_by_id.emplace(
transaction_packages.back().get_package().get_id(), transaction_packages.size() - 1);
} else if (object_type == libdnf::transaction::TransactionItemType::GROUP) {
transaction_groups.push_back(DbusTransactionGroupWrapper(ti));
}
}
// set "replaces" for transaction_packages. Since transaction_package contains only
// id of replaced packages we must convert them to packages using transaction_packages_by_id map
for (auto & tpkg : transaction_packages) {
// ids of replaced packages are stored in "replaces" transaction item attribute
auto ti_attrs = tpkg.get_transaction_item_attrs();
auto ti_replaces = ti_attrs.find("replaces");
if (ti_replaces != ti_attrs.end()) {
std::vector<DbusPackageWrapper> replaces;
std::vector<int> replaces_id = ti_replaces->second;
for (const auto & pkg_id : replaces_id) {
auto replaced_pkg_idx = transaction_packages_by_id.find(pkg_id);
if (replaced_pkg_idx != transaction_packages_by_id.end()) {
replaces.emplace_back(transaction_packages[replaced_pkg_idx->second].get_package());
} else {
// TODO(mblaha): proper logging
// log_router.warning()
std::cerr << "Package with id \"" << pkg_id << "\" replaced by package \""
<< tpkg.get_package().get_name() << "-" << tpkg.get_package().get_evr()
<< "\" not found in the transaction." << std::endl;
}
}
tpkg.set_replaces(std::move(replaces));
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions dnf5daemon-client/wrappers/dbus_package_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class DbusPackageWrapper {
std::string get_version() const { return rawdata.at("version"); }
std::string get_release() const { return rawdata.at("release"); }
std::string get_arch() const { return rawdata.at("arch"); }
std::string get_repo_id() const { return rawdata.at("repo"); }
std::string get_from_repo_id() const { return "TODO:from_repo"; }
std::string get_repo_id() const { return rawdata.at("repo_id"); }
std::string get_from_repo_id() const { return rawdata.at("from_repo_id"); }
std::string get_nevra() const { return rawdata.at("nevra"); }
std::string get_full_nevra() const { return rawdata.at("full_nevra"); }
std::string get_evr() const { return rawdata.at("evr"); }
Expand Down
9 changes: 4 additions & 5 deletions dnf5daemon-client/wrappers/dbus_transaction_group_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,18 @@ namespace dnfdaemon::client {
class DbusTransactionGroupWrapper {
public:
explicit DbusTransactionGroupWrapper(const dnfdaemon::DbusTransactionItem & dti)
: group(std::get<1>(dti)),
action(static_cast<libdnf::transaction::TransactionItemAction>(std::get<0>(dti))),
// TODO(lukash) reason needs to be added to dbus
reason(libdnf::transaction::TransactionItemReason::NONE) {}
: action(libdnf::transaction::transaction_item_action_from_string(std::get<1>(dti))),
reason(libdnf::transaction::transaction_item_reason_from_string(std::get<2>(dti))),
group(std::get<4>(dti)) {}

DbusGroupWrapper get_group() const { return group; }
libdnf::transaction::TransactionItemAction get_action() const { return action; }
libdnf::transaction::TransactionItemReason get_reason() const { return reason; }

private:
DbusGroupWrapper group;
libdnf::transaction::TransactionItemAction action;
libdnf::transaction::TransactionItemReason reason;
DbusGroupWrapper group;
};

} // namespace dnfdaemon::client
Expand Down
24 changes: 14 additions & 10 deletions dnf5daemon-client/wrappers/dbus_transaction_package_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,26 @@ namespace dnfdaemon::client {
class DbusTransactionPackageWrapper {
public:
explicit DbusTransactionPackageWrapper(const dnfdaemon::DbusTransactionItem & dti)
: package(std::get<1>(dti)),
action(static_cast<libdnf::transaction::TransactionItemAction>(std::get<0>(dti))),
// TODO(lukash) reason needs to be added to dbus
reason(libdnf::transaction::TransactionItemReason::NONE) {}

DbusPackageWrapper get_package() const { return package; }
libdnf::transaction::TransactionItemAction get_action() const { return action; }
libdnf::transaction::TransactionItemReason get_reason() const { return reason; }
: action(libdnf::transaction::transaction_item_action_from_string(std::get<1>(dti))),
reason(libdnf::transaction::transaction_item_reason_from_string(std::get<2>(dti))),
transaction_item_attrs(std::get<3>(dti)),
package(std::get<4>(dti)) {}

DbusPackageWrapper & get_package() noexcept { return package; }
libdnf::transaction::TransactionItemAction get_action() const noexcept { return action; }
libdnf::transaction::TransactionItemReason get_reason() const noexcept { return reason; }
dnfdaemon::KeyValueMap & get_transaction_item_attrs() noexcept { return transaction_item_attrs; }
// TODO(jmracek) get_replaces() is only a dummy method. In future it requires a private setter and a way how to get
// data from dnf-deamon server
const std::vector<DbusPackageWrapper> get_replaces() const noexcept { return {}; }
const std::vector<DbusPackageWrapper> & get_replaces() const noexcept { return replaces; }
void set_replaces(std::vector<DbusPackageWrapper> && replaces) { this->replaces = replaces; }

private:
DbusPackageWrapper package;
libdnf::transaction::TransactionItemAction action;
libdnf::transaction::TransactionItemReason reason;
dnfdaemon::KeyValueMap transaction_item_attrs;
DbusPackageWrapper package;
std::vector<DbusPackageWrapper> replaces;
};

} // namespace dnfdaemon::client
Expand Down
8 changes: 6 additions & 2 deletions dnf5daemon-server/dbus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ enum class RepoStatus { NOT_READY, PENDING, READY, ERROR };
enum class ResolveResult { NO_PROBLEM, WARNING, ERROR };

using DbusTransactionItem = sdbus::Struct<
unsigned int, //action
KeyValueMap>;
std::string, // libdnf::transaction::TransactionItemType
std::string, // libdnf::transaction::TransactionItemAction
std::string, // libdnf::transaction::TransactionItemReason
KeyValueMap, // other transaction item attributes - e.g. group id for REASON_CHANGE to GROUP,
// packages that are replaced by this transaction item
KeyValueMap>; // transaction object (package / group / module)

using Changelog = sdbus::Struct<int64_t, std::string, std::string>;

Expand Down
4 changes: 2 additions & 2 deletions dnf5daemon-server/dbus/interfaces/org.rpm.dnf.v0.Goal.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
<!--
resolve:
@options: an array of key/value pairs to modify dependency resolving
@transaction: array of (action, {package}) tuples where action is one of libdnf::transaction::TransactionItemAction enum and package is a map {atttibute: value}. These package attributes are returned: "name", "epoch", "version", "release", "arch", "repo", "package_size", "install_size", "evr".
@transaction_items: array of (object_type, action, reason, {transaction_item_attributes}, {object}) tuples. object_type is one of libdnf::transaction::TransactionItemType, action is one of libdnf::transaction::TransactionItemAction, reason is one of libdnf::transaction::TransactionItemReason enums. Each of these enums are represented as strings using corresponding libdnf::transaction::*_to_string() methods. transaction_item_attributes is a map {attribute: value}. Currently "reason_change_group_id" attribute is used for target group id in case the action is ReasonChange and the reason Group, and "replaces" containing a vector of packages ids being replaced by this item. Finally the object is a map {attribute: value} and represents (according to object_type) package, group, environment, or module. These package attributes are returned: "name", "epoch", "version", "release", "arch", "repo_id", "from_repo_id", "package_size", "install_size", "evr", and "reason". For groups the object contains "groupid" and "name" attributes.
@result: problems detected during transaction resolving. Possible values are 0 - no problem, 1 - no problem, but some info / warnings are present or 2 - resolving failed.

Resolve the transaction.
Expand All @@ -41,7 +41,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
-->
<method name="resolve">
<arg name="options" type="a{sv}" direction="in" />
<arg name="transaction" type="a(ua{sv})" direction="out" />
<arg name="transaction_items" type="a(sssa{sv}a{sv})" direction="out" />
<arg name="result" type="u" direction="out" />
</method>

Expand Down
56 changes: 56 additions & 0 deletions dnf5daemon-server/group.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
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 General Public License as published by
the Free Software Foundation, either version 2 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with libdnf. If not, see <https://www.gnu.org/licenses/>.
*/

#include "group.hpp"

#include <fmt/format.h>

#include <map>


// map string group attribute name to actual attribute
const std::map<std::string, GroupAttribute> group_attributes{
{"groupid", GroupAttribute::groupid}, {"name", GroupAttribute::name}, {"description", GroupAttribute::description}};


dnfdaemon::KeyValueMap group_to_map(
const libdnf::comps::Group & libdnf_group, const std::vector<std::string> & attributes) {
dnfdaemon::KeyValueMap dbus_group;
// add group id by default
dbus_group.emplace(std::make_pair("groupid", libdnf_group.get_groupid()));
// attributes required by client
for (auto & attr : attributes) {
auto it = group_attributes.find(attr);
if (it == group_attributes.end()) {
throw std::runtime_error(fmt::format("Group attribute '{}' not supported", attr));
}
switch (it->second) {
case GroupAttribute::groupid:
// already added by default
break;
case GroupAttribute::name:
dbus_group.emplace(attr, libdnf_group.get_name());
break;
case GroupAttribute::description:
dbus_group.emplace(attr, libdnf_group.get_description());
break;
}
}
return dbus_group;
}
41 changes: 41 additions & 0 deletions dnf5daemon-server/group.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
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 General Public License as published by
the Free Software Foundation, either version 2 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with libdnf. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef DNF5DAEMON_SERVER_GROUP_HPP
#define DNF5DAEMON_SERVER_GROUP_HPP

#include "dbus.hpp"

#include <libdnf/comps/group/group.hpp>

#include <string>
#include <vector>

// group attributes available to be retrieved
enum class GroupAttribute {
groupid,
name,
description
// TODO(mblaha): translated_name, translated_description, packages, reason
};

dnfdaemon::KeyValueMap group_to_map(
const libdnf::comps::Group & libdnf_group, const std::vector<std::string> & attributes);

#endif
8 changes: 6 additions & 2 deletions dnf5daemon-server/package.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const std::map<std::string, PackageAttribute> package_attributes{
{"version", PackageAttribute::version},
{"release", PackageAttribute::release},
{"arch", PackageAttribute::arch},
{"repo", PackageAttribute::repo},
{"repo_id", PackageAttribute::repo_id},
{"from_repo_id", PackageAttribute::from_repo_id},
{"is_installed", PackageAttribute::is_installed},
{"install_size", PackageAttribute::install_size},
{"package_size", PackageAttribute::package_size},
Expand Down Expand Up @@ -101,9 +102,12 @@ dnfdaemon::KeyValueMap package_to_map(
case PackageAttribute::arch:
dbus_package.emplace(attr, libdnf_package.get_arch());
break;
case PackageAttribute::repo:
case PackageAttribute::repo_id:
dbus_package.emplace(attr, libdnf_package.get_repo_id());
break;
case PackageAttribute::from_repo_id:
dbus_package.emplace(attr, libdnf_package.get_from_repo_id());
break;
case PackageAttribute::is_installed:
dbus_package.emplace(attr, libdnf_package.is_installed());
break;
Expand Down
3 changes: 2 additions & 1 deletion dnf5daemon-server/package.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ enum class PackageAttribute {
version,
release,
arch,
repo,
repo_id,
from_repo_id,
is_installed,
install_size,
package_size,
Expand Down
46 changes: 42 additions & 4 deletions dnf5daemon-server/services/goal/goal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.

#include "callbacks.hpp"
#include "dbus.hpp"
#include "group.hpp"
#include "package.hpp"
#include "transaction.hpp"
#include "utils.hpp"
Expand All @@ -29,6 +30,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
#include <fmt/format.h>
#include <libdnf/repo/package_downloader.hpp>
#include <libdnf/transaction/transaction_item.hpp>
#include <libdnf/transaction/transaction_item_action.hpp>
#include <sdbus-c++/sdbus-c++.h>

#include <chrono>
Expand All @@ -42,7 +44,7 @@ void Goal::dbus_register() {
// TODO(mblaha) Adjust resolve method to accomodate also groups, environments,
// and modules as part of the transaction
dbus_object->registerMethod(
dnfdaemon::INTERFACE_GOAL, "resolve", "a{sv}", "a(ua{sv})u", [this](sdbus::MethodCall call) -> void {
dnfdaemon::INTERFACE_GOAL, "resolve", "a{sv}", "a(sssa{sv}a{sv})u", [this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Goal::resolve, call, session.session_locale);
});
dbus_object->registerMethod(
Expand Down Expand Up @@ -78,11 +80,47 @@ sdbus::MethodReply Goal::resolve(sdbus::MethodCall & call) {
auto overall_result = dnfdaemon::ResolveResult::ERROR;
if (transaction.get_problems() == libdnf::GoalProblem::NO_PROBLEM) {
// return the transaction only if there were no problems
std::vector<std::string> attr{
"name", "epoch", "version", "release", "arch", "repo", "package_size", "install_size", "evr", "reason"};
std::vector<std::string> pkg_attrs{
"name",
"epoch",
"version",
"release",
"arch",
"repo_id",
"from_repo_id",
"package_size",
"install_size",
"evr",
"reason"};
for (auto & tspkg : transaction.get_transaction_packages()) {
dnfdaemon::KeyValueMap trans_item_attrs{};
if (tspkg.get_reason_change_group_id()) {
trans_item_attrs.emplace("reason_change_group_id", *tspkg.get_reason_change_group_id());
}
auto replaces = tspkg.get_replaces();
if (replaces.size() > 0) {
std::vector<int> replaces_ids{};
for (auto & r : replaces) {
replaces_ids.emplace_back(r.get_id().id);
}
trans_item_attrs.emplace("replaces", replaces_ids);
}
dbus_transaction.push_back(dnfdaemon::DbusTransactionItem(
transaction_item_type_to_string(libdnf::transaction::TransactionItemType::PACKAGE),
transaction_item_action_to_string(tspkg.get_action()),
transaction_item_reason_to_string(tspkg.get_reason()),
trans_item_attrs,
package_to_map(tspkg.get_package(), pkg_attrs)));
}
std::vector<std::string> grp_attrs{"name"};
dnfdaemon::KeyValueMap trans_item_attrs{};
for (auto & tsgrp : transaction.get_transaction_groups()) {
dbus_transaction.push_back(dnfdaemon::DbusTransactionItem(
static_cast<uint32_t>(tspkg.get_action()), package_to_map(tspkg.get_package(), attr)));
transaction_item_type_to_string(libdnf::transaction::TransactionItemType::GROUP),
transaction_item_action_to_string(tsgrp.get_action()),
transaction_item_reason_to_string(tsgrp.get_reason()),
trans_item_attrs,
group_to_map(tsgrp.get_group(), grp_attrs)));
}
// there are transactions resolved without problems but still resolve_logs
// may contain some warnings / informations
Expand Down
Loading