5. Resolving dependencies and running a transaction

This tutorial is a follow-up to Creating and configuring a session and potentially one of Loading repositories (to have some packages to work with), you can prepend them directly for a functional piece of code.

 1#include <libdnf/base/goal.hpp>
 2#include <libdnf/repo/package_downloader.hpp>
 3
 4// Create a goal, which is a class that allows to add items for resolving into
 5// a transaction.
 6libdnf::Goal goal(base);
 7
 8// Add an RPM package named "one" for installation into the goal.
 9goal.add_rpm_install("one");
10
11// Resolve the goal, create a transaction object.
12//
13// The argument is `allow_erasing`, a flag indicating wheter to allow removing
14// packages in the resolved transaction.
15auto transaction = goal.resolve(false);
16
17// We can iterate over the resolved transction and inspect the packages.
18std::cout << "Resolved transaction:" << std::endl;
19for (const auto & tspkg : transaction.get_transaction_packages()) {
20    std::cout
21        << tspkg.get_package().get_nevra() << ": "
22        << transaction_item_action_to_string(tspkg.get_action()) << std::endl;
23}
24
25// This class demonstrates user-defined callbacks for the package downloads.
26//
27// The callbacks are implemented by inheriting from the callbacks base class
28// and overriding its methods.
29//
30// We only override one of the callbacks here, see
31// `libdnf::repo::DownloadCallbacks` documentation for a complete list.
32class PackageDownloadCallbacks : public libdnf::repo::DownloadCallbacks {
33    int mirror_failure(const char * msg, [[maybe_unused]] const char * url) override {
34        std::cout << "Mirror failure: " << msg << std::endl;
35        return 0;
36    }
37};
38
39// Create a package downloader.
40libdnf::repo::PackageDownloader downloader;
41
42// Add the inbound packages (packages that are being installed on the system)
43// to the downloader.
44for (auto & tspkg : transaction.get_transaction_packages()) {
45    if (transaction_item_action_is_inbound(tspkg.get_action())) {
46        downloader.add(
47            tspkg.get_package(),
48            std::make_unique<PackageDownloadCallbacks>()
49        );
50    }
51}
52
53// Download the packages.
54//
55// The first argument is `fail_fast`, meaning the download will fail right away
56// on a first package download failure. The second argument is `resume`, if
57// `true`, the downloader will try to resume downloads of any partially
58// downloaded RPMs.
59downloader.download(true, true);
60
61// A class for defining the RPM transaction callbacks.
62//
63// Again, only a callback for when an RPM package installation starts, for a
64// complete list of the callbacks see `libdnf::rpm::TransactionCallbacks`
65// documentation.
66class TransactionCallbacks : public libdnf::rpm::TransactionCallbacks {
67    void install_start(
68        const libdnf::rpm::TransactionItem & item,
69        [[maybe_unused]] uint64_t total) override
70    {
71        std::cout
72            << transaction_item_action_to_string(item.get_action()) << " "
73            << item.get_package().get_nevra() << std::endl;
74    }
75};
76
77// Run the transaction.
78//
79// The second through fourth arguments are transaction metadata that will be
80// stored in the history database.
81//
82// The second argument is expected to be a verbose description of the
83// transaction. The third argument is user_id, omitted here for simplicity. The
84// fourth argument can be an arbitrary user comment.
85std::cout << std::endl << "Running the transaction:" << std::endl;
86transaction.run(
87    std::make_unique<TransactionCallbacks>(),
88    "install package one",
89    std::nullopt,
90    std::nullopt
91);