File: module_sack_impl.hpp

package info (click to toggle)
dnf5 5.4.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 17,960 kB
  • sloc: cpp: 94,312; python: 3,370; xml: 1,073; ruby: 600; sql: 250; ansic: 232; sh: 104; perl: 62; makefile: 30
file content (207 lines) | stat: -rw-r--r-- 8,832 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright Contributors to the DNF5 project.
// Copyright Contributors to the libdnf project.
// SPDX-License-Identifier: LGPL-2.1-or-later
//
// 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 <https://www.gnu.org/licenses/>.

#ifndef LIBDNF5_MODULE_MODULE_SACK_IMPL_HPP
#define LIBDNF5_MODULE_MODULE_SACK_IMPL_HPP

#include "base/base_impl.hpp"
#include "module/module_db.hpp"
#include "module/module_metadata.hpp"
#include "solv/id_queue.hpp"
#include "solv/solv_map.hpp"

#include "libdnf5/base/base.hpp"
#include "libdnf5/module/module_sack.hpp"
#include "libdnf5/rpm/reldep_list.hpp"

extern "C" {
#include <solv/pool.h>
#include <solv/poolarch.h>
}

#include <optional>


namespace libdnf5::base {

class Transaction;

}

namespace libdnf5::module {


class ModuleGoalPrivate;


class ModuleSack::Impl {
public:
    /// Create libsolv pool and set the appropriate pool flags
    Impl(ModuleSack & module_sack, const BaseWeakPtr & base)
        : module_sack(&module_sack),
          base(base),
          module_metadata(base),
          pool(pool_create()),
          module_db(new ModuleDB(base)) {
        // Ensure excluded packages are not taken as candidates for solver
        pool_set_flag(pool, POOL_FLAG_WHATPROVIDESWITHDISABLED, 1);
        // Allow packages of the same name with different architectures to be installed in parallel
        pool_set_flag(pool, POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS, 1);
    }
    ~Impl() {
        //TODO(amatej): Perhaps it would be good to create and use ModulePool which would take care of considered.
        //              It would also unify the approach with CompsPool and RpmPool.
        if (pool->considered) {
            map_free(pool->considered);
            g_free(pool->considered);
        }
        pool_free(pool);
    }

    const std::vector<std::unique_ptr<ModuleItem>> & get_modules();

    /// Apply modular filtering to package set. For proper functionality, all repositories must be loaded and active
    /// modules must be resolved (modular solver).
    void module_filtering();

    /// Supporting method that iterates over all modules and creates filtering sets for modular filtering
    /// include_NEVRAs contains artifacts from active modules
    /// exclude_NEVRAs contains artifacts from not active modules
    /// names and reldep_name_list contain names from include_NEVRAs that are not source
    /// src_names contains names from include_NEVRAs that are source
    ///
    /// @return <include_NEVRAs>, <exclude_NEVRAs>, <names>, <src_names>, <reldep_name_list>
    std::tuple<
        std::vector<std::string>,
        std::vector<std::string>,
        std::vector<std::string>,
        std::vector<std::string>,
        rpm::ReldepList>
    collect_data_for_modular_filtering();

    // Compute static context for older modules and move these modules to `ModuleSack.modules`.
    void add_modules_without_static_context();

    void make_provides_ready();
    void recompute_considered_in_pool();

    // Requires resolved goal. Takes list_installs() from goal and adds all modules with the same SOLVABLE_NAME
    // (<name>:<stream>:<context>) into active_modules.
    void set_active_modules(ModuleGoalPrivate & goal);

    // Requires resolved goal. Enable all modules that are required by any newly enabled modules.
    // @replaces libdnf:ModulePackageContainer.hpp:method:ModulePackageContainer.enableDependencyTree()
    void enable_dependent_modules();

    /// Resolve given module items.
    ///
    /// @param module_items Module Items to resolve.
    /// @return `std::pair` of problems in resolving and a GoalProblem.
    /// @since 5.0
    std::pair<std::vector<std::vector<std::tuple<ProblemRules, Id, Id, Id, std::string>>>, GoalProblem> module_solve(
        std::vector<ModuleItem *> & module_items);

    /// Enable module stream.
    /// @param name module name to be enabled.
    /// @param stream module stream to be enabled.
    /// @param count if `true`, count the change towards the limit of module status modifications.
    /// @return `true` if requested change really triggers a change in the ModuleDB, `false` otherwise.
    /// @throw EnableMultipleStreamsError in case of conflicting enable requests.
    /// @throw NoModuleError if the module doesn't exist.
    /// @since 5.0.14
    bool enable(const std::string & name, const std::string & stream, bool count = true);
    /// Enable module stream.
    /// @param module_spec module to be enabled.
    /// @param count if `true`, count the change towards the limit of module status modifications.
    /// @return `true` if requested change realy triggers a change in the ModuleDB, `false` otherwise,
    ///         and a set of module:stream strings for modules with multiple streams and no enabled or default one.
    /// @throw NoModuleError if the module doesn't exist.
    /// @since 5.0.14
    std::pair<bool, std::set<std::string>> enable(const std::string & module_spec, bool count = true);
    /// Disable module.
    /// @param module_spec module to be disabled.
    /// @param count if `true`, count the change towards the limit of module status modifications.
    /// @throw NoModuleError if the module doesn't exist.
    /// @since 5.0.14
    bool disable(const std::string & module_spec, bool count = true);
    /// Reset module, so it's no longer enabled nor disabled.
    /// @param module_spec module to be reset.
    /// @param count if `true`, count the change towards the limit of module status modifications.
    /// @throw NoModuleError if the module doesn't exist.
    /// @since 5.0.14
    bool reset(const std::string & module_spec, bool count = true);
    /// Set architecture for module pool
    /// @param arch architecture.
    /// @since 5.1.8
    void set_arch(const char * arch) { pool_setarch(pool, arch); };


private:
    friend class libdnf5::base::Transaction;
    friend class libdnf5::Goal;
    friend ModuleSack;
    friend ModuleItem;
    friend ModuleGoalPrivate;
    friend class ModuleQuery;

    ModuleSack * module_sack;
    BaseWeakPtr base;
    ModuleMetadata module_metadata;
    std::vector<std::unique_ptr<ModuleItem>> modules;
    Pool * pool;
    // Repositories containing any modules. Key is repoid, value is Id of the repo in libsolv.
    // This is needed in `ModuleItem::create_solvable` for creating solvable in the correct repository.
    std::map<std::string, Id> repositories;

    // Older ModuleItems that don't have static context. After all metadata are loaded, static contexts are assigned
    // also to these ModuleItems and they are removed from this vector and added to `ModuleSack.modules`.
    // This is done in `ModuleSack::add_modules_without_static_context`.
    std::vector<std::unique_ptr<ModuleItem>> modules_without_static_context;

    bool provides_ready = false;
    bool considered_uptodate = false;
    bool platform_detected = false;

    std::map<std::string, std::string> module_defaults;
    std::unique_ptr<libdnf5::solv::SolvMap> excludes;
    std::map<Id, ModuleItem *> active_modules;
    std::vector<libdnf5::solv::IdQueue> modules_to_enable;

    std::unique_ptr<ModuleDB> module_db;

    /// @brief Method for autodetection of the platform id.
    /// @return If platform id was detected, it returns a pair where the first item is the platform
    ///         module name and second is the platform stream. Otherwise std::nullopt is returned.
    std::optional<std::pair<std::string, std::string>> detect_platform_name_and_stream() const;

    /// @brief Keep only one stream for each module. If more than one stream is originally there, keep only
    // the enabled or default one if possible.
    /// @return Set of module:stream strings for modules with multiple streams and no enabled or default one.
    std::set<std::string> prune_module_dict(
        std::unordered_map<std::string, std::unordered_map<std::string, libdnf5::solv::IdQueue>> & module_dict);
};

inline const std::vector<std::unique_ptr<ModuleItem>> & ModuleSack::Impl::get_modules() {
    add_modules_without_static_context();
    return modules;
}

}  // namespace libdnf5::module

#endif  // LIBDNF5_MODULE_MODULE_SACK_IMPL_HPP