Rename MPool into solver::libsolv::Database (#3180)

* Move only MPool

* Rename MPool > Database

* Move Database to solver::libsolv

* Add missing explicit

* Rename pool in function names

* Rename core/pool.hpp package_database_loader
This commit is contained in:
Antoine Prouvost 2024-02-08 10:41:11 -05:00 committed by GitHub
parent 67fd10a830
commit d20d176b86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 1039 additions and 957 deletions

View File

@ -183,9 +183,11 @@ set(
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solvable.cpp ${LIBMAMBA_SOURCE_DIR}/solv-cpp/solvable.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.cpp ${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/transaction.cpp ${LIBMAMBA_SOURCE_DIR}/solv-cpp/transaction.cpp
# Solver interface # Solver generic interface
${LIBMAMBA_SOURCE_DIR}/solver/helpers.cpp ${LIBMAMBA_SOURCE_DIR}/solver/helpers.cpp
${LIBMAMBA_SOURCE_DIR}/solver/problems_graph.cpp ${LIBMAMBA_SOURCE_DIR}/solver/problems_graph.cpp
# Solver libsolv implementation
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/database.cpp
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/helpers.cpp ${LIBMAMBA_SOURCE_DIR}/solver/libsolv/helpers.cpp
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/parameters.cpp ${LIBMAMBA_SOURCE_DIR}/solver/libsolv/parameters.cpp
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/repo_info.cpp ${LIBMAMBA_SOURCE_DIR}/solver/libsolv/repo_info.cpp
@ -212,6 +214,7 @@ set(
# Core API (low-level) # Core API (low-level)
${LIBMAMBA_SOURCE_DIR}/core/singletons.cpp ${LIBMAMBA_SOURCE_DIR}/core/singletons.cpp
${LIBMAMBA_SOURCE_DIR}/core/activation.cpp ${LIBMAMBA_SOURCE_DIR}/core/activation.cpp
${LIBMAMBA_SOURCE_DIR}/core/package_database_loader.cpp
${LIBMAMBA_SOURCE_DIR}/core/channel_context.cpp ${LIBMAMBA_SOURCE_DIR}/core/channel_context.cpp
${LIBMAMBA_SOURCE_DIR}/core/context.cpp ${LIBMAMBA_SOURCE_DIR}/core/context.cpp
${LIBMAMBA_SOURCE_DIR}/core/download_progress_bar.cpp ${LIBMAMBA_SOURCE_DIR}/core/download_progress_bar.cpp
@ -224,7 +227,6 @@ set(
${LIBMAMBA_SOURCE_DIR}/core/output.cpp ${LIBMAMBA_SOURCE_DIR}/core/output.cpp
${LIBMAMBA_SOURCE_DIR}/core/package_handling.cpp ${LIBMAMBA_SOURCE_DIR}/core/package_handling.cpp
${LIBMAMBA_SOURCE_DIR}/core/package_cache.cpp ${LIBMAMBA_SOURCE_DIR}/core/package_cache.cpp
${LIBMAMBA_SOURCE_DIR}/core/pool.cpp
${LIBMAMBA_SOURCE_DIR}/core/prefix_data.cpp ${LIBMAMBA_SOURCE_DIR}/core/prefix_data.cpp
${LIBMAMBA_SOURCE_DIR}/core/progress_bar.cpp ${LIBMAMBA_SOURCE_DIR}/core/progress_bar.cpp
${LIBMAMBA_SOURCE_DIR}/core/progress_bar_impl.cpp ${LIBMAMBA_SOURCE_DIR}/core/progress_bar_impl.cpp
@ -313,10 +315,12 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/unresolved_channel.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/specs/unresolved_channel.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version_spec.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version_spec.hpp
# Solver Interface # Solver generic interface
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/problems_graph.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/solver/problems_graph.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/request.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/solver/request.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/solution.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/solver/solution.hpp
# Solver libsolv implementation
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/database.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/parameters.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/parameters.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/repo_info.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/repo_info.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/solver.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/solver.hpp
@ -341,6 +345,7 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/core/context.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/context.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/download_progress_bar.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/download_progress_bar.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/environments_manager.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/environments_manager.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_database_loader.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/error_handling.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/error_handling.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/history.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/history.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/link.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/link.hpp
@ -351,7 +356,6 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_fetcher.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_fetcher.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_handling.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_handling.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_paths.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_paths.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/pool.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/prefix_data.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/prefix_data.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/progress_bar.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/progress_bar.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/pinning.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/core/pinning.hpp

View File

@ -11,15 +11,18 @@
namespace mamba namespace mamba
{ {
namespace solver::libsolv
{
class Database;
}
class Context; class Context;
class ChannelContext; class ChannelContext;
class MPool;
class MultiPackageCache; class MultiPackageCache;
auto load_channels( // auto load_channels( //
Context& ctx, Context& ctx,
ChannelContext& channel_context, ChannelContext& channel_context,
MPool& pool, solver::libsolv::Database& pool,
MultiPackageCache& package_caches MultiPackageCache& package_caches
) -> expected_t<void, mamba_aggregated_error>; ) -> expected_t<void, mamba_aggregated_error>;
} }

View File

@ -7,23 +7,33 @@
#ifndef MAMBA_API_INSTALL_HPP #ifndef MAMBA_API_INSTALL_HPP
#define MAMBA_API_INSTALL_HPP #define MAMBA_API_INSTALL_HPP
#include <iosfwd>
#include <string> #include <string>
#include <vector> #include <vector>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include "mamba/core/package_cache.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/fs/filesystem.hpp" #include "mamba/fs/filesystem.hpp"
#include "mamba/solver/request.hpp" #include "mamba/solver/request.hpp"
#include "mamba/specs/package_info.hpp"
namespace mamba namespace mamba
{ {
class Context; class Context;
class ChannelContext; class ChannelContext;
class Configuration; class Configuration;
class PrefixData;
class MultiPackageCache;
namespace specs
{
class PackageInfo;
}
namespace solver::libsolv
{
class DataBase;
}
void install(Configuration& config); void install(Configuration& config);

View File

@ -13,6 +13,11 @@
namespace mamba namespace mamba
{ {
namespace solver::libsolv
{
class DataBase;
}
enum class QueryResultFormat enum class QueryResultFormat
{ {
Json = 0, Json = 0,
@ -23,7 +28,7 @@ namespace mamba
}; };
[[nodiscard]] auto make_repoquery( [[nodiscard]] auto make_repoquery(
MPool& pool, solver::libsolv::Database& pool,
QueryType type, QueryType type,
QueryResultFormat format, QueryResultFormat format,
const std::vector<std::string>& queries, const std::vector<std::string>& queries,

View File

@ -0,0 +1,39 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#ifndef MAMBA_CORE_PACKAGE_DATABASE_LOADER_HPP
#define MAMBA_CORE_PACKAGE_DATABASE_LOADER_HPP
#include "mamba/core/error_handling.hpp"
#include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/specs/channel.hpp"
namespace mamba
{
class Context;
class PrefixData;
class SubdirData;
namespace solver::libsolv
{
class Database;
}
void add_spdlog_logger_to_database(solver::libsolv::Database& db);
auto load_subdir_in_database( //
const Context& ctx,
solver::libsolv::Database& db,
const SubdirData& subdir
) -> expected_t<solver::libsolv::RepoInfo>;
auto load_installed_packages_in_database(
const Context& ctx,
solver::libsolv::Database& db,
const PrefixData& prefix
) -> solver::libsolv::RepoInfo;
}
#endif

View File

@ -1,278 +0,0 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#ifndef MAMBA_CORE_POOL_HPP
#define MAMBA_CORE_POOL_HPP
#include <functional>
#include <memory>
#include <optional>
#include "mamba/core/error_handling.hpp"
#include "mamba/solver/libsolv/parameters.hpp"
#include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/specs/channel.hpp"
#include "mamba/specs/package_info.hpp"
#include "mamba/util/loop_control.hpp"
namespace mamba
{
class Context;
class PrefixData;
class SubdirData;
namespace fs
{
class u8path;
}
namespace solv
{
class ObjPool;
}
namespace specs
{
class MatchSpec;
}
namespace solver::libsolv
{
class Solver;
class UnSolvable;
}
/**
* Pool of solvable involved in resolving en environment.
*
* The pool contains the solvable (packages) information required from the ``MSolver``.
* The pool can be reused by multiple solvers to solve differents requirements with the same
* ecosystem.
* Behaves like a ``std::shared_ptr``, meaning ressources are shared on copy.
*/
class MPool
{
public:
using logger_type = std::function<void(solver::libsolv::LogLevel, std::string_view)>;
MPool(specs::ChannelResolveParams channel_params);
~MPool();
[[nodiscard]] auto channel_params() const -> const specs::ChannelResolveParams&;
void set_logger(logger_type callback);
auto add_repo_from_repodata_json(
const fs::u8path& path,
std::string_view url,
solver::libsolv::PipAsPythonDependency add = solver::libsolv::PipAsPythonDependency::No,
solver::libsolv::UseOnlyTarBz2 only_tar = solver::libsolv::UseOnlyTarBz2::No,
solver::libsolv::RepodataParser parser = solver::libsolv::RepodataParser::Mamba
) -> expected_t<solver::libsolv::RepoInfo>;
auto add_repo_from_native_serialization(
const fs::u8path& path,
const solver::libsolv::RepodataOrigin& expected,
solver::libsolv::PipAsPythonDependency add = solver::libsolv::PipAsPythonDependency::No
) -> expected_t<solver::libsolv::RepoInfo>;
template <typename Iter>
auto add_repo_from_packages(
Iter first_package,
Iter last_package,
std::string_view name = "",
solver::libsolv::PipAsPythonDependency add = solver::libsolv::PipAsPythonDependency::No
) -> solver::libsolv::RepoInfo;
template <typename Range>
auto add_repo_from_packages(
const Range& packages,
std::string_view name = "",
solver::libsolv::PipAsPythonDependency add = solver::libsolv::PipAsPythonDependency::No
) -> solver::libsolv::RepoInfo;
auto native_serialize_repo(
const solver::libsolv::RepoInfo& repo,
const fs::u8path& path,
const solver::libsolv::RepodataOrigin& metadata
) -> expected_t<solver::libsolv::RepoInfo>;
[[nodiscard]] auto installed_repo() const -> std::optional<solver::libsolv::RepoInfo>;
void set_installed_repo(solver::libsolv::RepoInfo repo);
void
set_repo_priority(solver::libsolv::RepoInfo repo, solver::libsolv::Priorities priorities);
void remove_repo(solver::libsolv::RepoInfo repo);
template <typename Func>
void for_each_package_in_repo(solver::libsolv::RepoInfo repo, Func&&) const;
template <typename Func>
void for_each_package_matching(const specs::MatchSpec& ms, Func&&);
template <typename Func>
void for_each_package_depending_on(const specs::MatchSpec& ms, Func&&);
/** A wrapper struct to fine-grain controll who can access the raw repr of the Pool. */
class Impl
{
[[nodiscard]] static auto get(MPool& pool) -> solv::ObjPool&;
[[nodiscard]] static auto get(const MPool& pool) -> const solv::ObjPool&;
friend class solver::libsolv::Solver;
friend class solver::libsolv::UnSolvable;
};
private:
struct MPoolData;
/**
* Make MPool behave like a shared_ptr (with move and copy).
*
* The pool is passed to the ``MSolver`` for its lifetime but the pool can legitimely
* be reused with different solvers (in fact it is in ``conda-forge``'s ``regro-bot``
* and ``boa``).
* An alternative considered was to make ``MPool`` a move-only type, moving it in and out
* of ``MSolver`` (effectively borrowing).
* It was decided to make ``MPool`` share ressources for the following reasons.
* - Rvalue semantics would be unexpected in Python (and breaking ``conda-forge``);
* - Facilitate (potential) future investigation of parallel solves.
*/
std::shared_ptr<MPoolData> m_data;
friend class Impl;
auto pool() -> solv::ObjPool&;
[[nodiscard]] auto pool() const -> const solv::ObjPool&;
auto add_repo_from_packages_impl_pre(std::string_view name) -> solver::libsolv::RepoInfo;
void add_repo_from_packages_impl_loop(
const solver::libsolv::RepoInfo& repo,
const specs::PackageInfo& pkg
);
void add_repo_from_packages_impl_post(
const solver::libsolv::RepoInfo& repo,
solver::libsolv::PipAsPythonDependency add
);
enum class PackageId : int;
[[nodiscard]] auto package_id_to_package_info(PackageId id) const -> specs::PackageInfo;
[[nodiscard]] auto packages_in_repo(solver::libsolv::RepoInfo repo) const
-> std::vector<PackageId>;
[[nodiscard]] auto packages_matching_ids(const specs::MatchSpec& ms)
-> std::vector<PackageId>;
[[nodiscard]] auto packages_depending_on_ids(const specs::MatchSpec& ms)
-> std::vector<PackageId>;
};
// TODO machinery functions in separate files
void add_spdlog_logger_to_pool(MPool& pool);
auto load_subdir_in_pool(const Context& ctx, MPool& pool, const SubdirData& subdir)
-> expected_t<solver::libsolv::RepoInfo>;
auto load_installed_packages_in_pool(const Context& ctx, MPool& pool, const PrefixData& prefix)
-> solver::libsolv::RepoInfo;
/********************
* Implementation *
********************/
template <typename Iter>
auto MPool::add_repo_from_packages(
Iter first_package,
Iter last_package,
std::string_view name,
solver::libsolv::PipAsPythonDependency add
) -> solver::libsolv::RepoInfo
{
auto repo = add_repo_from_packages_impl_pre(name);
for (; first_package != last_package; ++first_package)
{
add_repo_from_packages_impl_loop(repo, *first_package);
}
add_repo_from_packages_impl_post(repo, add);
return repo;
}
template <typename Range>
auto MPool::add_repo_from_packages(
const Range& packages,
std::string_view name,
solver::libsolv::PipAsPythonDependency add
) -> solver::libsolv::RepoInfo
{
return add_repo_from_packages(packages.begin(), packages.end(), name, add);
}
// TODO(C++20): Use ranges::transform
template <typename Func>
void MPool::for_each_package_in_repo(solver::libsolv::RepoInfo repo, Func&& func) const
{
for (auto id : packages_in_repo(repo))
{
if constexpr (std::is_same_v<decltype(func(package_id_to_package_info(id))), util::LoopControl>)
{
if (func(package_id_to_package_info(id)) == util::LoopControl::Break)
{
break;
}
}
else
{
func(package_id_to_package_info(id));
}
}
}
// TODO(C++20): Use ranges::transform
template <typename Func>
void MPool::for_each_package_matching(const specs::MatchSpec& ms, Func&& func)
{
for (auto id : packages_matching_ids(ms))
{
if constexpr (std::is_same_v<decltype(func(package_id_to_package_info(id))), util::LoopControl>)
{
if (func(package_id_to_package_info(id)) == util::LoopControl::Break)
{
break;
}
}
else
{
func(package_id_to_package_info(id));
}
}
}
// TODO(C++20): Use ranges::transform
template <typename Func>
void MPool::for_each_package_depending_on(const specs::MatchSpec& ms, Func&& func)
{
for (auto id : packages_depending_on_ids(ms))
{
if constexpr (std::is_same_v<decltype(func(package_id_to_package_info(id))), util::LoopControl>)
{
if (func(package_id_to_package_info(id)) == util::LoopControl::Break)
{
break;
}
}
else
{
func(package_id_to_package_info(id));
}
}
}
}
#endif

View File

@ -14,12 +14,16 @@
#include <vector> #include <vector>
#include "mamba/core/context.hpp" #include "mamba/core/context.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/specs/package_info.hpp" #include "mamba/specs/package_info.hpp"
#include "mamba/util/graph.hpp" #include "mamba/util/graph.hpp"
namespace mamba namespace mamba
{ {
namespace solver::libsolv
{
class Database;
}
enum class QueryType enum class QueryType
{ {
Search, Search,
@ -88,12 +92,14 @@ namespace mamba
{ {
public: public:
[[nodiscard]] static auto find(MPool& pool, const std::vector<std::string>& queries) using Database = solver::libsolv::Database;
[[nodiscard]] static auto find(Database& db, const std::vector<std::string>& queries)
-> QueryResult; -> QueryResult;
[[nodiscard]] static auto whoneeds(MPool& pool, std::string query, bool tree) -> QueryResult; [[nodiscard]] static auto whoneeds(Database& db, std::string query, bool tree) -> QueryResult;
[[nodiscard]] static auto depends(MPool& pool, std::string query, bool tree) -> QueryResult; [[nodiscard]] static auto depends(Database& db, std::string query, bool tree) -> QueryResult;
}; };
/******************** /********************

View File

@ -24,7 +24,7 @@ namespace mamba
{ {
class Channel; class Channel;
} }
class MPool;
class Context; class Context;
class ChannelContext; class ChannelContext;
class DownloadMonitor; class DownloadMonitor;

View File

@ -13,10 +13,10 @@
#include "mamba/api/install.hpp" #include "mamba/api/install.hpp"
#include "mamba/core/package_cache.hpp" #include "mamba/core/package_cache.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/prefix_data.hpp" #include "mamba/core/prefix_data.hpp"
#include "mamba/core/transaction_context.hpp" #include "mamba/core/transaction_context.hpp"
#include "mamba/fs/filesystem.hpp" #include "mamba/fs/filesystem.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/solution.hpp" #include "mamba/solver/solution.hpp"
#include "mamba/specs/match_spec.hpp" #include "mamba/specs/match_spec.hpp"
#include "mamba/specs/package_info.hpp" #include "mamba/specs/package_info.hpp"
@ -37,7 +37,7 @@ namespace mamba
MTransaction( MTransaction(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
std::vector<specs::PackageInfo> pkgs_to_remove, std::vector<specs::PackageInfo> pkgs_to_remove,
std::vector<specs::PackageInfo> pkgs_to_install, std::vector<specs::PackageInfo> pkgs_to_install,
MultiPackageCache& caches MultiPackageCache& caches
@ -45,7 +45,7 @@ namespace mamba
MTransaction( MTransaction(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
const solver::Request& request, const solver::Request& request,
solver::Solution solution, solver::Solution solution,
MultiPackageCache& caches MultiPackageCache& caches
@ -54,7 +54,7 @@ namespace mamba
// Only use if the packages have been solved previously already. // Only use if the packages have been solved previously already.
MTransaction( MTransaction(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
std::vector<specs::PackageInfo> packages, std::vector<specs::PackageInfo> packages,
MultiPackageCache& caches MultiPackageCache& caches
); );
@ -93,7 +93,7 @@ namespace mamba
MTransaction create_explicit_transaction_from_urls( MTransaction create_explicit_transaction_from_urls(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
const std::vector<std::string>& urls, const std::vector<std::string>& urls,
MultiPackageCache& package_caches, MultiPackageCache& package_caches,
std::vector<detail::other_pkg_mgr_spec>& other_specs std::vector<detail::other_pkg_mgr_spec>& other_specs
@ -101,7 +101,7 @@ namespace mamba
MTransaction create_explicit_transaction_from_lockfile( MTransaction create_explicit_transaction_from_lockfile(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
const fs::u8path& env_lockfile_path, const fs::u8path& env_lockfile_path,
const std::vector<std::string>& categories, const std::vector<std::string>& categories,
MultiPackageCache& package_caches, MultiPackageCache& package_caches,

View File

@ -0,0 +1,252 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#ifndef MAMBA_SOLVER_LIBSOLV_DATABASE_HPP
#define MAMBA_SOLVER_LIBSOLV_DATABASE_HPP
#include <functional>
#include <memory>
#include <optional>
#include <string_view>
#include "mamba/core/error_handling.hpp"
#include "mamba/solver/libsolv/parameters.hpp"
#include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/specs/channel.hpp"
#include "mamba/specs/package_info.hpp"
#include "mamba/util/loop_control.hpp"
namespace mamba
{
namespace fs
{
class u8path;
}
namespace solv
{
class ObjPool;
}
namespace specs
{
class MatchSpec;
}
}
namespace mamba::solver::libsolv
{
class Solver;
class UnSolvable;
/**
* Database of solvable involved in resolving en environment.
*
* The database contains the solvable (packages) information required from the @ref Solver.
* The database can be reused by multiple solvers to solve differents requirements with the
* same ecosystem.
*/
class Database
{
public:
using logger_type = std::function<void(LogLevel, std::string_view)>;
explicit Database(specs::ChannelResolveParams channel_params);
Database(const Database&) = delete;
Database(Database&&);
~Database();
auto operator=(const Database&) -> Database& = delete;
auto operator=(Database&&) -> Database&;
[[nodiscard]] auto channel_params() const -> const specs::ChannelResolveParams&;
void set_logger(logger_type callback);
auto add_repo_from_repodata_json(
const fs::u8path& path,
std::string_view url,
PipAsPythonDependency add = PipAsPythonDependency::No,
UseOnlyTarBz2 only_tar = UseOnlyTarBz2::No,
RepodataParser parser = RepodataParser::Mamba
) -> expected_t<RepoInfo>;
auto add_repo_from_native_serialization(
const fs::u8path& path,
const RepodataOrigin& expected,
PipAsPythonDependency add = PipAsPythonDependency::No
) -> expected_t<RepoInfo>;
template <typename Iter>
auto add_repo_from_packages(
Iter first_package,
Iter last_package,
std::string_view name = "",
PipAsPythonDependency add = PipAsPythonDependency::No
) -> RepoInfo;
template <typename Range>
auto add_repo_from_packages(
const Range& packages,
std::string_view name = "",
PipAsPythonDependency add = PipAsPythonDependency::No
) -> RepoInfo;
auto
native_serialize_repo(const RepoInfo& repo, const fs::u8path& path, const RepodataOrigin& metadata)
-> expected_t<RepoInfo>;
[[nodiscard]] auto installed_repo() const -> std::optional<RepoInfo>;
void set_installed_repo(RepoInfo repo);
void set_repo_priority(RepoInfo repo, Priorities priorities);
void remove_repo(RepoInfo repo);
template <typename Func>
void for_each_package_in_repo(RepoInfo repo, Func&&) const;
template <typename Func>
void for_each_package_matching(const specs::MatchSpec& ms, Func&&);
template <typename Func>
void for_each_package_depending_on(const specs::MatchSpec& ms, Func&&);
/**
* An access control wrapper.
*
* This struct is to control who can access the underlying private representation
* of the ObjPool without giving them full friend access.
*/
class Impl
{
[[nodiscard]] static auto get(Database& pool) -> solv::ObjPool&;
[[nodiscard]] static auto get(const Database& pool) -> const solv::ObjPool&;
friend class Solver;
friend class UnSolvable;
};
private:
struct DatabaseImpl;
std::unique_ptr<DatabaseImpl> m_data;
friend class Impl;
auto pool() -> solv::ObjPool&;
[[nodiscard]] auto pool() const -> const solv::ObjPool&;
auto add_repo_from_packages_impl_pre(std::string_view name) -> RepoInfo;
void add_repo_from_packages_impl_loop(const RepoInfo& repo, const specs::PackageInfo& pkg);
void add_repo_from_packages_impl_post(const RepoInfo& repo, PipAsPythonDependency add);
enum class PackageId : int;
[[nodiscard]] auto package_id_to_package_info(PackageId id) const -> specs::PackageInfo;
[[nodiscard]] auto packages_in_repo(RepoInfo repo) const -> std::vector<PackageId>;
[[nodiscard]] auto packages_matching_ids(const specs::MatchSpec& ms)
-> std::vector<PackageId>;
[[nodiscard]] auto packages_depending_on_ids(const specs::MatchSpec& ms)
-> std::vector<PackageId>;
};
/********************
* Implementation *
********************/
template <typename Iter>
auto Database::add_repo_from_packages(
Iter first_package,
Iter last_package,
std::string_view name,
PipAsPythonDependency add
) -> RepoInfo
{
auto repo = add_repo_from_packages_impl_pre(name);
for (; first_package != last_package; ++first_package)
{
add_repo_from_packages_impl_loop(repo, *first_package);
}
add_repo_from_packages_impl_post(repo, add);
return repo;
}
template <typename Range>
auto
Database::add_repo_from_packages(const Range& packages, std::string_view name, PipAsPythonDependency add)
-> RepoInfo
{
return add_repo_from_packages(packages.begin(), packages.end(), name, add);
}
// TODO(C++20): Use ranges::transform
template <typename Func>
void Database::for_each_package_in_repo(RepoInfo repo, Func&& func) const
{
for (auto id : packages_in_repo(repo))
{
if constexpr (std::is_same_v<decltype(func(package_id_to_package_info(id))), util::LoopControl>)
{
if (func(package_id_to_package_info(id)) == util::LoopControl::Break)
{
break;
}
}
else
{
func(package_id_to_package_info(id));
}
}
}
// TODO(C++20): Use ranges::transform
template <typename Func>
void Database::for_each_package_matching(const specs::MatchSpec& ms, Func&& func)
{
for (auto id : packages_matching_ids(ms))
{
if constexpr (std::is_same_v<decltype(func(package_id_to_package_info(id))), util::LoopControl>)
{
if (func(package_id_to_package_info(id)) == util::LoopControl::Break)
{
break;
}
}
else
{
func(package_id_to_package_info(id));
}
}
}
// TODO(C++20): Use ranges::transform
template <typename Func>
void Database::for_each_package_depending_on(const specs::MatchSpec& ms, Func&& func)
{
for (auto id : packages_depending_on_ids(ms))
{
if constexpr (std::is_same_v<decltype(func(package_id_to_package_info(id))), util::LoopControl>)
{
if (func(package_id_to_package_info(id)) == util::LoopControl::Break)
{
break;
}
}
else
{
func(package_id_to_package_info(id));
}
}
}
}
#endif

View File

@ -17,24 +17,21 @@ extern "C"
using Repo = struct s_Repo; using Repo = struct s_Repo;
} }
namespace mamba
{
class MPool;
class MTransaction;
}
namespace mamba::solver::libsolv namespace mamba::solver::libsolv
{ {
class Database;
/** /**
* A libsolv repository descriptor. * A libsolv repository descriptor.
* *
* In libsolv, most of the data is help in the Pool, and repo are tightly coupled with them. * In libsolv, most of the data is help in the @ref Database, and repo are tightly coupled
* with them.
* This repository class is a lightwight description of a repository returned when creating * This repository class is a lightwight description of a repository returned when creating
* a new repository in the Pool. * a new repository in the @ref Database.
* Some modifications to the repo are possible throught the Pool. * Some modifications to the repo are possible throught the @ref Database.
* @see MPool::add_repo_from_repodata_json * @see Database::add_repo_from_repodata_json
* @see MPool::add_repo_from_packages * @see Database::add_repo_from_packages
* @see MPool::remove_repo * @see Database::remove_repo
*/ */
class RepoInfo class RepoInfo
{ {
@ -61,8 +58,7 @@ namespace mamba::solver::libsolv
explicit RepoInfo(::Repo* repo); explicit RepoInfo(::Repo* repo);
friend class ::mamba::MPool; friend class Database;
friend class ::mamba::MTransaction; // As long as MTransaction leaks libsolv impl
friend auto operator==(RepoInfo lhs, RepoInfo rhs) -> bool; friend auto operator==(RepoInfo lhs, RepoInfo rhs) -> bool;
}; };

View File

@ -14,18 +14,20 @@
namespace mamba::solver::libsolv namespace mamba::solver::libsolv
{ {
class Database;
class Solver class Solver
{ {
public: public:
using Outcome = std::variant<Solution, UnSolvable>; using Outcome = std::variant<Solution, UnSolvable>;
[[nodiscard]] auto solve(MPool& pool, Request&& request) -> expected_t<Outcome>; [[nodiscard]] auto solve(Database& pool, Request&& request) -> expected_t<Outcome>;
[[nodiscard]] auto solve(MPool& pool, const Request& request) -> expected_t<Outcome>; [[nodiscard]] auto solve(Database& pool, const Request& request) -> expected_t<Outcome>;
private: private:
auto solve_impl(MPool& pool, const Request& request) -> expected_t<Outcome>; auto solve_impl(Database& pool, const Request& request) -> expected_t<Outcome>;
}; };
} }
#endif #endif

View File

@ -16,7 +16,6 @@
namespace mamba namespace mamba
{ {
class MPool;
class Palette; class Palette;
namespace solv namespace solv
@ -28,6 +27,7 @@ namespace mamba
namespace mamba::solver::libsolv namespace mamba::solver::libsolv
{ {
class Solver; class Solver;
class Database;
class UnSolvable class UnSolvable
{ {
@ -39,21 +39,22 @@ namespace mamba::solver::libsolv
auto operator=(UnSolvable&&) -> UnSolvable&; auto operator=(UnSolvable&&) -> UnSolvable&;
[[nodiscard]] auto problems(MPool& pool) const -> std::vector<std::string>; [[nodiscard]] auto problems(Database& pool) const -> std::vector<std::string>;
[[nodiscard]] auto problems_to_str(MPool& pool) const -> std::string; [[nodiscard]] auto problems_to_str(Database& pool) const -> std::string;
[[nodiscard]] auto all_problems_to_str(MPool& pool) const -> std::string; [[nodiscard]] auto all_problems_to_str(Database& pool) const -> std::string;
[[nodiscard]] auto problems_graph(const MPool& pool) const -> ProblemsGraph; [[nodiscard]] auto problems_graph(const Database& pool) const -> ProblemsGraph;
auto explain_problems_to( // auto explain_problems_to( //
MPool& pool, Database& pool,
std::ostream& out, std::ostream& out,
const Palette& palette const Palette& palette
) const -> std::ostream&; ) const -> std::ostream&;
[[nodiscard]] auto explain_problems(MPool& pool, const Palette& palette) const -> std::string; [[nodiscard]] auto explain_problems(Database& pool, const Palette& palette) const
-> std::string;
private: private:

View File

@ -24,13 +24,12 @@
#include "mamba/util/flat_set.hpp" #include "mamba/util/flat_set.hpp"
#include "mamba/util/graph.hpp" #include "mamba/util/graph.hpp"
namespace mamba
{
class MPool;
}
namespace mamba::solver namespace mamba::solver
{ {
namespace libsolv
{
class Database;
}
template <typename T> template <typename T>
class conflict_map : private std::unordered_map<T, util::flat_set<T>> class conflict_map : private std::unordered_map<T, util::flat_set<T>>

View File

@ -8,9 +8,10 @@
#include "mamba/core/channel_context.hpp" #include "mamba/core/channel_context.hpp"
#include "mamba/core/download_progress_bar.hpp" #include "mamba/core/download_progress_bar.hpp"
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/pool.hpp" #include "mamba/core/package_database_loader.hpp"
#include "mamba/core/prefix_data.hpp" #include "mamba/core/prefix_data.hpp"
#include "mamba/core/subdirdata.hpp" #include "mamba/core/subdirdata.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/repo_info.hpp" #include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/specs/package_info.hpp" #include "mamba/specs/package_info.hpp"
@ -21,7 +22,7 @@ namespace mamba
auto create_repo_from_pkgs_dir( auto create_repo_from_pkgs_dir(
const Context& ctx, const Context& ctx,
ChannelContext& channel_context, ChannelContext& channel_context,
MPool& pool, solver::libsolv::Database& pool,
const fs::u8path& pkgs_dir const fs::u8path& pkgs_dir
) -> solver::libsolv::RepoInfo ) -> solver::libsolv::RepoInfo
{ {
@ -45,7 +46,7 @@ namespace mamba
} }
prefix_data.load_single_record(repodata_record_json); prefix_data.load_single_record(repodata_record_json);
} }
return load_installed_packages_in_pool(ctx, pool, prefix_data); return load_installed_packages_in_database(ctx, pool, prefix_data);
} }
void create_subdirs( void create_subdirs(
@ -112,7 +113,7 @@ namespace mamba
auto load_channels_impl( auto load_channels_impl(
Context& ctx, Context& ctx,
ChannelContext& channel_context, ChannelContext& channel_context,
MPool& pool, solver::libsolv::Database& pool,
MultiPackageCache& package_caches, MultiPackageCache& package_caches,
bool is_retry bool is_retry
) -> expected_t<void, mamba_aggregated_error> ) -> expected_t<void, mamba_aggregated_error>
@ -231,7 +232,7 @@ namespace mamba
continue; continue;
} }
load_subdir_in_pool(ctx, pool, subdir) load_subdir_in_database(ctx, pool, subdir)
.transform([&](solver::libsolv::RepoInfo&& repo) .transform([&](solver::libsolv::RepoInfo&& repo)
{ pool.set_repo_priority(repo, priorities[i]); }) { pool.set_repo_priority(repo, priorities[i]); })
.or_else( .or_else(
@ -276,9 +277,12 @@ namespace mamba
} }
} }
auto auto load_channels(
load_channels(Context& ctx, ChannelContext& channel_context, MPool& pool, MultiPackageCache& package_caches) Context& ctx,
-> expected_t<void, mamba_aggregated_error> ChannelContext& channel_context,
solver::libsolv::Database& pool,
MultiPackageCache& package_caches
) -> expected_t<void, mamba_aggregated_error>
{ {
return load_channels_impl(ctx, channel_context, pool, package_caches, false); return load_channels_impl(ctx, channel_context, pool, package_caches, false);
} }

View File

@ -22,6 +22,7 @@
#include "mamba/core/environments_manager.hpp" #include "mamba/core/environments_manager.hpp"
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/package_cache.hpp" #include "mamba/core/package_cache.hpp"
#include "mamba/core/package_database_loader.hpp"
#include "mamba/core/pinning.hpp" #include "mamba/core/pinning.hpp"
#include "mamba/core/transaction.hpp" #include "mamba/core/transaction.hpp"
#include "mamba/core/virtual_packages.hpp" #include "mamba/core/virtual_packages.hpp"
@ -530,8 +531,8 @@ namespace mamba
LOG_WARNING << "No 'channels' specified"; LOG_WARNING << "No 'channels' specified";
} }
MPool pool{ channel_context.params() }; solver::libsolv::Database pool{ channel_context.params() };
add_spdlog_logger_to_pool(pool); add_spdlog_logger_to_database(pool);
// functions implied in 'and_then' coding-styles must return the same type // functions implied in 'and_then' coding-styles must return the same type
// which limits this syntax // which limits this syntax
/*auto exp_prefix_data = load_channels(pool, package_caches) /*auto exp_prefix_data = load_channels(pool, package_caches)
@ -552,7 +553,7 @@ namespace mamba
} }
PrefixData& prefix_data = exp_prefix_data.value(); PrefixData& prefix_data = exp_prefix_data.value();
load_installed_packages_in_pool(ctx, pool, prefix_data); load_installed_packages_in_database(ctx, pool, prefix_data);
auto request = create_install_request(prefix_data, specs, freeze_installed); auto request = create_install_request(prefix_data, specs, freeze_installed);
@ -674,7 +675,7 @@ namespace mamba
namespace namespace
{ {
// TransactionFunc: (MPool& pool, MultiPackageCache& package_caches) -> MTransaction // TransactionFunc: (Database& pool, MultiPackageCache& package_caches) -> MTransaction
template <typename TransactionFunc> template <typename TransactionFunc>
void install_explicit_with_transaction( void install_explicit_with_transaction(
Context& ctx, Context& ctx,
@ -684,8 +685,8 @@ namespace mamba
bool remove_prefix_on_failure bool remove_prefix_on_failure
) )
{ {
MPool pool{ channel_context.params() }; solver::libsolv::Database db{ channel_context.params() };
add_spdlog_logger_to_pool(pool); add_spdlog_logger_to_database(db);
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context); auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
if (!exp_prefix_data) if (!exp_prefix_data)
@ -697,12 +698,12 @@ namespace mamba
MultiPackageCache pkg_caches(ctx.pkgs_dirs, ctx.validation_params); MultiPackageCache pkg_caches(ctx.pkgs_dirs, ctx.validation_params);
load_installed_packages_in_pool(ctx, pool, prefix_data); load_installed_packages_in_database(ctx, db, prefix_data);
std::vector<detail::other_pkg_mgr_spec> others; std::vector<detail::other_pkg_mgr_spec> others;
// Note that the Transaction will gather the Solvables, // Note that the Transaction will gather the Solvables,
// so they must have been ready in the pool before this line // so they must have been ready in the pool before this line
auto transaction = create_transaction(pool, pkg_caches, others); auto transaction = create_transaction(db, pkg_caches, others);
std::vector<LockFile> lock_pkgs; std::vector<LockFile> lock_pkgs;
@ -754,8 +755,8 @@ namespace mamba
install_explicit_with_transaction( install_explicit_with_transaction(
ctx, ctx,
channel_context, channel_context,
[&](auto& pool, auto& pkg_caches, auto& others) [&](auto& db, auto& pkg_caches, auto& others)
{ return create_explicit_transaction_from_urls(ctx, pool, specs, pkg_caches, others); }, { return create_explicit_transaction_from_urls(ctx, db, specs, pkg_caches, others); },
create_env, create_env,
remove_prefix_on_failure remove_prefix_on_failure
); );
@ -802,11 +803,11 @@ namespace mamba
install_explicit_with_transaction( install_explicit_with_transaction(
ctx, ctx,
channel_context, channel_context,
[&](auto& pool, auto& pkg_caches, auto& others) [&](auto& db, auto& pkg_caches, auto& others)
{ {
return create_explicit_transaction_from_lockfile( return create_explicit_transaction_from_lockfile(
ctx, ctx,
pool, db,
file, file,
categories, categories,
pkg_caches, pkg_caches,

View File

@ -9,7 +9,7 @@
#include "mamba/core/channel_context.hpp" #include "mamba/core/channel_context.hpp"
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/package_cache.hpp" #include "mamba/core/package_cache.hpp"
#include "mamba/core/pool.hpp" #include "mamba/core/package_database_loader.hpp"
#include "mamba/core/prefix_data.hpp" #include "mamba/core/prefix_data.hpp"
#include "mamba/core/transaction.hpp" #include "mamba/core/transaction.hpp"
#include "mamba/solver/libsolv/repo_info.hpp" #include "mamba/solver/libsolv/repo_info.hpp"
@ -127,9 +127,9 @@ namespace mamba
} }
PrefixData& prefix_data = exp_prefix_data.value(); PrefixData& prefix_data = exp_prefix_data.value();
MPool pool{ channel_context.params() }; solver::libsolv::Database pool{ channel_context.params() };
add_spdlog_logger_to_pool(pool); add_spdlog_logger_to_database(pool);
load_installed_packages_in_pool(ctx, pool, prefix_data); load_installed_packages_in_database(ctx, pool, prefix_data);
const fs::u8path pkgs_dirs(ctx.prefix_params.root_prefix / "pkgs"); const fs::u8path pkgs_dirs(ctx.prefix_params.root_prefix / "pkgs");
MultiPackageCache package_caches({ pkgs_dirs }, ctx.validation_params); MultiPackageCache package_caches({ pkgs_dirs }, ctx.validation_params);

View File

@ -11,7 +11,9 @@
#include "mamba/api/repoquery.hpp" #include "mamba/api/repoquery.hpp"
#include "mamba/core/channel_context.hpp" #include "mamba/core/channel_context.hpp"
#include "mamba/core/package_cache.hpp" #include "mamba/core/package_cache.hpp"
#include "mamba/core/package_database_loader.hpp"
#include "mamba/core/prefix_data.hpp" #include "mamba/core/prefix_data.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/repo_info.hpp" #include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/util/string.hpp" #include "mamba/util/string.hpp"
@ -28,8 +30,8 @@ namespace mamba
config.load(); config.load();
auto channel_context = ChannelContext::make_conda_compatible(ctx); auto channel_context = ChannelContext::make_conda_compatible(ctx);
MPool pool{ channel_context.params() }; solver::libsolv::Database db{ channel_context.params() };
add_spdlog_logger_to_pool(pool); add_spdlog_logger_to_database(db);
// bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds); // bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds);
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params); MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
@ -50,7 +52,7 @@ namespace mamba
} }
PrefixData& prefix_data = exp_prefix_data.value(); PrefixData& prefix_data = exp_prefix_data.value();
load_installed_packages_in_pool(ctx, pool, prefix_data); load_installed_packages_in_database(ctx, db, prefix_data);
if (format != QueryResultFormat::Json) if (format != QueryResultFormat::Json)
{ {
@ -65,18 +67,18 @@ namespace mamba
{ {
Console::stream() << "Getting repodata from channels..." << std::endl; Console::stream() << "Getting repodata from channels..." << std::endl;
} }
auto exp_load = load_channels(ctx, channel_context, pool, package_caches); auto exp_load = load_channels(ctx, channel_context, db, package_caches);
if (!exp_load) if (!exp_load)
{ {
throw std::runtime_error(exp_load.error().what()); throw std::runtime_error(exp_load.error().what());
} }
} }
return pool; return db;
} }
} }
auto make_repoquery( auto make_repoquery(
MPool& pool, solver::libsolv::Database& db,
QueryType type, QueryType type,
QueryResultFormat format, QueryResultFormat format,
const std::vector<std::string>& queries, const std::vector<std::string>& queries,
@ -87,7 +89,7 @@ namespace mamba
{ {
if (type == QueryType::Search) if (type == QueryType::Search)
{ {
auto res = Query::find(pool, queries); auto res = Query::find(db, queries);
switch (format) switch (format)
{ {
case QueryResultFormat::Json: case QueryResultFormat::Json:
@ -108,7 +110,7 @@ namespace mamba
throw std::invalid_argument("Only one query supported for 'depends'."); throw std::invalid_argument("Only one query supported for 'depends'.");
} }
auto res = Query::depends( auto res = Query::depends(
pool, db,
queries.front(), queries.front(),
/* tree= */ format == QueryResultFormat::Tree /* tree= */ format == QueryResultFormat::Tree
|| format == QueryResultFormat::RecursiveTable || format == QueryResultFormat::RecursiveTable
@ -135,7 +137,7 @@ namespace mamba
throw std::invalid_argument("Only one query supported for 'whoneeds'."); throw std::invalid_argument("Only one query supported for 'whoneeds'.");
} }
auto res = Query::whoneeds( auto res = Query::whoneeds(
pool, db,
queries.front(), queries.front(),
/* tree= */ format == QueryResultFormat::Tree /* tree= */ format == QueryResultFormat::Tree
|| format == QueryResultFormat::RecursiveTable || format == QueryResultFormat::RecursiveTable
@ -177,9 +179,9 @@ namespace mamba
) )
{ {
auto& ctx = config.context(); auto& ctx = config.context();
auto pool = repoquery_init(ctx, config, format, use_local); auto db = repoquery_init(ctx, config, format, use_local);
return make_repoquery( return make_repoquery(
pool, db,
type, type,
format, format,
queries, queries,

View File

@ -10,9 +10,11 @@
#include "mamba/api/update.hpp" #include "mamba/api/update.hpp"
#include "mamba/core/channel_context.hpp" #include "mamba/core/channel_context.hpp"
#include "mamba/core/context.hpp" #include "mamba/core/context.hpp"
#include "mamba/core/package_database_loader.hpp"
#include "mamba/core/pinning.hpp" #include "mamba/core/pinning.hpp"
#include "mamba/core/transaction.hpp" #include "mamba/core/transaction.hpp"
#include "mamba/core/virtual_packages.hpp" #include "mamba/core/virtual_packages.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/solver.hpp" #include "mamba/solver/libsolv/solver.hpp"
#include "mamba/solver/request.hpp" #include "mamba/solver/request.hpp"
@ -106,12 +108,12 @@ namespace mamba
} }
} }
MPool pool{ channel_context.params() }; solver::libsolv::Database db{ channel_context.params() };
add_spdlog_logger_to_pool(pool); add_spdlog_logger_to_database(db);
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params); MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
auto exp_loaded = load_channels(ctx, channel_context, pool, package_caches); auto exp_loaded = load_channels(ctx, channel_context, db, package_caches);
if (!exp_loaded) if (!exp_loaded)
{ {
throw std::runtime_error(exp_loaded.error().what()); throw std::runtime_error(exp_loaded.error().what());
@ -131,7 +133,7 @@ namespace mamba
prefix_pkgs.push_back(it.first); prefix_pkgs.push_back(it.first);
} }
load_installed_packages_in_pool(ctx, pool, prefix_data); load_installed_packages_in_database(ctx, db, prefix_data);
auto request = create_update_request( auto request = create_update_request(
prefix_data, prefix_data,
@ -157,13 +159,13 @@ namespace mamba
// Console stream prints on destrucion // Console stream prints on destrucion
} }
auto outcome = solver::libsolv::Solver().solve(pool, request).value(); auto outcome = solver::libsolv::Solver().solve(db, request).value();
if (auto* unsolvable = std::get_if<solver::libsolv::UnSolvable>(&outcome)) if (auto* unsolvable = std::get_if<solver::libsolv::UnSolvable>(&outcome))
{ {
if (ctx.output_params.json) if (ctx.output_params.json)
{ {
Console::instance().json_write({ { "success", false }, Console::instance().json_write({ { "success", false },
{ "solver_problems", unsolvable->problems(pool) } }); { "solver_problems", unsolvable->problems(db) } });
} }
throw mamba_error( throw mamba_error(
"Could not solve for environment specs", "Could not solve for environment specs",
@ -174,7 +176,7 @@ namespace mamba
Console::instance().json_write({ { "success", true } }); Console::instance().json_write({ { "success", true } });
auto transaction = MTransaction( auto transaction = MTransaction(
ctx, ctx,
pool, db,
request, request,
std::get<solver::Solution>(outcome), std::get<solver::Solution>(outcome),
package_caches package_caches

View File

@ -0,0 +1,149 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#include <string_view>
#include <fmt/format.h>
#include <solv/evr.h>
#include <solv/selection.h>
#include <solv/solver.h>
#include <spdlog/spdlog.h>
#include "mamba/core/channel_context.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/package_database_loader.hpp"
#include "mamba/core/prefix_data.hpp"
#include "mamba/core/subdirdata.hpp"
#include "mamba/core/virtual_packages.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/util/build.hpp"
#include "mamba/util/string.hpp"
#include "solver/libsolv/helpers.hpp"
namespace mamba
{
void add_spdlog_logger_to_database(solver::libsolv::Database& db)
{
db.set_logger(
[logger = spdlog::get("libsolv")](solver::libsolv::LogLevel level, std::string_view msg)
{
switch (level)
{
case (solver::libsolv::LogLevel::Fatal):
logger->critical(msg);
break;
case (solver::libsolv::LogLevel::Error):
logger->error(msg);
break;
case (solver::libsolv::LogLevel::Warning):
logger->warn(msg);
break;
case (solver::libsolv::LogLevel::Debug):
logger->debug(msg);
break;
}
}
);
}
auto
load_subdir_in_database(const Context& ctx, solver::libsolv::Database& db, const SubdirData& subdir)
-> expected_t<solver::libsolv::RepoInfo>
{
const auto expected_cache_origin = solver::libsolv::RepodataOrigin{
/* .url= */ util::rsplit(subdir.metadata().url(), "/", 1).front(),
/* .etag= */ subdir.metadata().etag(),
/* .mod= */ subdir.metadata().last_modified(),
};
const auto add_pip = static_cast<solver::libsolv::PipAsPythonDependency>(
ctx.add_pip_as_python_dependency
);
const auto json_parser = ctx.experimental_repodata_parsing
? solver::libsolv::RepodataParser::Mamba
: solver::libsolv::RepodataParser::Libsolv;
// Solv files are too slow on Windows.
if (!util::on_win)
{
auto maybe_repo = subdir.valid_solv_cache().and_then(
[&](fs::u8path&& solv_file) {
return db.add_repo_from_native_serialization(
solv_file,
expected_cache_origin,
add_pip
);
}
);
if (maybe_repo)
{
return maybe_repo;
}
}
return subdir.valid_json_cache()
.and_then(
[&](fs::u8path&& repodata_json)
{
LOG_INFO << "Trying to load repo from json file " << repodata_json;
return db.add_repo_from_repodata_json(
repodata_json,
util::rsplit(subdir.metadata().url(), "/", 1).front(),
add_pip,
static_cast<solver::libsolv::UseOnlyTarBz2>(ctx.use_only_tar_bz2),
json_parser
);
}
)
.transform(
[&](solver::libsolv::RepoInfo&& repo) -> solver::libsolv::RepoInfo
{
if (!util::on_win)
{
db.native_serialize_repo(repo, subdir.writable_solv_cache(), expected_cache_origin)
.or_else(
[&](const auto& err)
{
LOG_WARNING << R"(Fail to write native serialization to file ")"
<< subdir.writable_solv_cache() << R"(" for repo ")"
<< subdir.name() << ": " << err.what();
;
}
);
}
return std::move(repo);
}
);
}
auto load_installed_packages_in_database(
const Context& ctx,
solver::libsolv::Database& db,
const PrefixData& prefix
) -> solver::libsolv::RepoInfo
{
// TODO(C++20): We could do a PrefixData range that returns packages without storing thems.
auto pkgs = prefix.sorted_records();
// TODO(C++20): We only need a range that concatenate both
for (auto&& pkg : get_virtual_packages(ctx))
{
pkgs.push_back(std::move(pkg));
}
// Not adding Pip dependency since it might needlessly make the installed/active environment
// broken if pip is not already installed (debatable).
auto repo = db.add_repo_from_packages(
pkgs,
"installed",
solver::libsolv::PipAsPythonDependency::No
);
db.set_installed_repo(repo);
return repo;
}
}

View File

@ -1,464 +0,0 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#include <exception>
#include <iostream>
#include <limits>
#include <string_view>
#include <fmt/format.h>
#include <solv/evr.h>
#include <solv/selection.h>
#include <solv/solver.h>
#include <spdlog/spdlog.h>
#include "mamba/core/channel_context.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/prefix_data.hpp"
#include "mamba/core/subdirdata.hpp"
#include "mamba/core/virtual_packages.hpp"
#include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/specs/match_spec.hpp"
#include "mamba/util/build.hpp"
#include "mamba/util/random.hpp"
#include "mamba/util/string.hpp"
#include "solv-cpp/pool.hpp"
#include "solv-cpp/queue.hpp"
#include "solver/libsolv/helpers.hpp"
namespace mamba
{
struct MPool::MPoolData
{
MPoolData(specs::ChannelResolveParams p_channel_params)
: channel_params(std::move(p_channel_params))
{
}
specs::ChannelResolveParams channel_params;
solv::ObjPool pool = {};
};
MPool::MPool(specs::ChannelResolveParams channel_params)
: m_data(std::make_unique<MPoolData>(std::move(channel_params)))
{
pool().set_disttype(DISTTYPE_CONDA);
// Ensure that debug logging never goes to stdout as to not interfere json output
pool().raw()->debugmask |= SOLV_DEBUG_TO_STDERR;
::pool_setdebuglevel(pool().raw(), -1); // Off
}
MPool::~MPool() = default;
auto MPool::pool() -> solv::ObjPool&
{
return m_data->pool;
}
auto MPool::pool() const -> const solv::ObjPool&
{
return m_data->pool;
}
auto MPool::Impl::get(MPool& pool) -> solv::ObjPool&
{
return pool.pool();
}
auto MPool::Impl::get(const MPool& pool) -> const solv::ObjPool&
{
return pool.pool();
}
auto MPool::channel_params() const -> const specs::ChannelResolveParams&
{
return m_data->channel_params;
}
namespace
{
auto libsolv_to_log_level(int type) -> solver::libsolv::LogLevel
{
if (type & SOLV_FATAL)
{
return solver::libsolv::LogLevel::Fatal;
}
if (type & SOLV_ERROR)
{
return solver::libsolv::LogLevel::Error;
}
if (type & SOLV_WARN)
{
return solver::libsolv::LogLevel::Warning;
}
return solver::libsolv::LogLevel::Debug;
}
}
void MPool::set_logger(logger_type callback)
{
::pool_setdebuglevel(pool().raw(), std::numeric_limits<int>::max()); // All
pool().set_debug_callback(
[logger = std::move(callback)](::Pool*, int type, std::string_view msg) noexcept
{
try
{
logger(libsolv_to_log_level(type), msg);
}
catch (std::exception const& e)
{
std::cerr << "Developer error: error in libsolv logging function: \n"
<< e.what();
}
}
);
}
auto MPool::add_repo_from_repodata_json(
const fs::u8path& path,
std::string_view url,
solver::libsolv::PipAsPythonDependency add,
solver::libsolv::UseOnlyTarBz2 only_tar,
solver::libsolv::RepodataParser parser
) -> expected_t<solver::libsolv::RepoInfo>
{
const auto use_only_tar_bz2 = static_cast<bool>(only_tar);
if (!fs::exists(path))
{
return make_unexpected(
fmt::format(R"(File "{}" does not exist)", path),
mamba_error_code::repodata_not_loaded
);
}
auto repo = pool().add_repo(url).second;
repo.set_url(std::string(url));
auto make_repo = [&]() -> expected_t<solv::ObjRepoView>
{
if (parser == solver::libsolv::RepodataParser::Mamba)
{
return solver::libsolv::mamba_read_json(
pool(),
repo,
path,
std::string(url),
use_only_tar_bz2
);
}
return solver::libsolv::libsolv_read_json(repo, path, use_only_tar_bz2)
.transform(
[&url](solv::ObjRepoView p_repo)
{
solver::libsolv::set_solvables_url(p_repo, std::string(url));
return p_repo;
}
);
};
return make_repo()
.transform(
[&](solv::ObjRepoView p_repo) -> solver::libsolv::RepoInfo
{
if (add == solver::libsolv::PipAsPythonDependency::Yes)
{
solver::libsolv::add_pip_as_python_dependency(pool(), p_repo);
}
p_repo.internalize();
return solver::libsolv::RepoInfo{ p_repo.raw() };
}
)
.or_else([&](const auto&) { pool().remove_repo(repo.id(), /* reuse_ids= */ true); });
}
auto MPool::add_repo_from_native_serialization(
const fs::u8path& path,
const solver::libsolv::RepodataOrigin& expected,
solver::libsolv::PipAsPythonDependency add
) -> expected_t<solver::libsolv::RepoInfo>
{
auto repo = pool().add_repo(expected.url).second;
return solver::libsolv::read_solv(pool(), repo, path, expected, static_cast<bool>(add))
.transform(
[&](solv::ObjRepoView p_repo) -> solver::libsolv::RepoInfo
{
p_repo.set_url(expected.url);
solver::libsolv::set_solvables_url(p_repo, expected.url);
if (add == solver::libsolv::PipAsPythonDependency::Yes)
{
solver::libsolv::add_pip_as_python_dependency(pool(), p_repo);
}
p_repo.internalize();
return solver::libsolv::RepoInfo(p_repo.raw());
}
)
.or_else([&](const auto&) { pool().remove_repo(repo.id(), /* reuse_ids= */ true); });
}
auto MPool::add_repo_from_packages_impl_pre(std::string_view name) -> solver::libsolv::RepoInfo
{
if (name.empty())
{
return solver::libsolv::RepoInfo(
pool().add_repo(util::generate_random_alphanumeric_string(20)).second.raw()
);
}
return solver::libsolv::RepoInfo(pool().add_repo(name).second.raw());
}
void MPool::add_repo_from_packages_impl_loop(
const solver::libsolv::RepoInfo& repo,
const specs::PackageInfo& pkg
)
{
auto s_repo = solv::ObjRepoView(*repo.m_ptr);
auto [id, solv] = s_repo.add_solvable();
solver::libsolv::set_solvable(pool(), solv, pkg);
}
void MPool::add_repo_from_packages_impl_post(
const solver::libsolv::RepoInfo& repo,
solver::libsolv::PipAsPythonDependency add
)
{
auto s_repo = solv::ObjRepoView(*repo.m_ptr);
if (add == solver::libsolv::PipAsPythonDependency::Yes)
{
solver::libsolv::add_pip_as_python_dependency(pool(), s_repo);
}
s_repo.internalize();
}
auto MPool::native_serialize_repo(
const solver::libsolv::RepoInfo& repo,
const fs::u8path& path,
const solver::libsolv::RepodataOrigin& metadata
) -> expected_t<solver::libsolv::RepoInfo>
{
assert(repo.m_ptr != nullptr);
return solver::libsolv::write_solv(solv::ObjRepoView(*repo.m_ptr), path, metadata)
.transform([](solv::ObjRepoView solv_repo)
{ return solver::libsolv::RepoInfo(solv_repo.raw()); });
}
void MPool::remove_repo(solver::libsolv::RepoInfo repo)
{
pool().remove_repo(repo.id(), /* reuse_ids= */ true);
}
auto MPool::installed_repo() const -> std::optional<solver::libsolv::RepoInfo>
{
if (auto repo = pool().installed_repo())
{
// Safe because the Repo does not modify its internals
return solver::libsolv::RepoInfo(const_cast<::Repo*>(repo->raw()));
}
return {};
}
void MPool::set_installed_repo(solver::libsolv::RepoInfo repo)
{
pool().set_installed_repo(repo.id());
}
void
MPool::set_repo_priority(solver::libsolv::RepoInfo repo, solver::libsolv::Priorities priorities)
{
// NOTE: The Pool is not involved directly in this operations, but since it is needed
// in so many repo operations, this setter was put here to keep the Repo class
// immutable.
static_assert(std::is_same_v<decltype(repo.m_ptr->priority), solver::libsolv::Priorities::value_type>);
repo.m_ptr->priority = priorities.priority;
repo.m_ptr->subpriority = priorities.subpriority;
}
auto MPool::package_id_to_package_info(PackageId id) const -> specs::PackageInfo
{
static_assert(std::is_same_v<std::underlying_type_t<PackageId>, solv::SolvableId>);
const auto solv = pool().get_solvable(static_cast<solv::SolvableId>(id));
assert(solv.has_value()); // Safe because the ID is coming from libsolv
return { solver::libsolv::make_package_info(pool(), solv.value()) };
}
auto MPool::packages_in_repo(solver::libsolv::RepoInfo repo) const -> std::vector<PackageId>
{
// TODO maybe we could use a span here depending on libsolv layout
auto solv_repo = solv::ObjRepoViewConst(*repo.m_ptr);
auto out = std::vector<PackageId>();
out.reserve(solv_repo.solvable_count());
solv_repo.for_each_solvable_id([&](auto id) { out.push_back(static_cast<PackageId>(id)); });
return out;
}
namespace
{
auto matchspec2id(
solv::ObjPool& pool,
const specs::ChannelResolveParams& channel_params,
const specs::MatchSpec& ms
) -> solv::DependencyId
{
return solver::libsolv::pool_add_matchspec(pool, ms, channel_params)
.or_else([](mamba_error&& error) { throw std::move(error); })
.value_or(0);
}
}
auto MPool::packages_matching_ids(const specs::MatchSpec& ms) -> std::vector<PackageId>
{
static_assert(std::is_same_v<std::underlying_type_t<PackageId>, solv::SolvableId>);
pool().ensure_whatprovides();
const auto ms_id = matchspec2id(pool(), channel_params(), ms);
auto solvables = pool().select_solvables({ SOLVER_SOLVABLE_PROVIDES, ms_id });
auto out = std::vector<PackageId>(solvables.size());
std::transform(
solvables.begin(),
solvables.end(),
out.begin(),
[](auto id) { return static_cast<PackageId>(id); }
);
return out;
}
auto MPool::packages_depending_on_ids(const specs::MatchSpec& ms) -> std::vector<PackageId>
{
static_assert(std::is_same_v<std::underlying_type_t<PackageId>, solv::SolvableId>);
pool().ensure_whatprovides();
const auto ms_id = matchspec2id(pool(), channel_params(), ms);
auto solvables = pool().what_matches_dep(SOLVABLE_REQUIRES, ms_id);
auto out = std::vector<PackageId>(solvables.size());
std::transform(
solvables.begin(),
solvables.end(),
out.begin(),
[](auto id) { return static_cast<PackageId>(id); }
);
return out;
}
// TODO machinery functions in separate files
void add_spdlog_logger_to_pool(MPool& pool)
{
pool.set_logger(
[logger = spdlog::get("libsolv")](solver::libsolv::LogLevel level, std::string_view msg)
{
switch (level)
{
case (solver::libsolv::LogLevel::Fatal):
logger->critical(msg);
break;
case (solver::libsolv::LogLevel::Error):
logger->error(msg);
break;
case (solver::libsolv::LogLevel::Warning):
logger->warn(msg);
break;
case (solver::libsolv::LogLevel::Debug):
logger->debug(msg);
break;
}
}
);
}
auto load_subdir_in_pool(const Context& ctx, MPool& pool, const SubdirData& subdir)
-> expected_t<solver::libsolv::RepoInfo>
{
const auto expected_cache_origin = solver::libsolv::RepodataOrigin{
/* .url= */ util::rsplit(subdir.metadata().url(), "/", 1).front(),
/* .etag= */ subdir.metadata().etag(),
/* .mod= */ subdir.metadata().last_modified(),
};
const auto add_pip = static_cast<solver::libsolv::PipAsPythonDependency>(
ctx.add_pip_as_python_dependency
);
const auto json_parser = ctx.experimental_repodata_parsing
? solver::libsolv::RepodataParser::Mamba
: solver::libsolv::RepodataParser::Libsolv;
// Solv files are too slow on Windows.
if (!util::on_win)
{
auto maybe_repo = subdir.valid_solv_cache().and_then(
[&](fs::u8path&& solv_file) {
return pool.add_repo_from_native_serialization(
solv_file,
expected_cache_origin,
add_pip
);
}
);
if (maybe_repo)
{
return maybe_repo;
}
}
return subdir.valid_json_cache()
.and_then(
[&](fs::u8path&& repodata_json)
{
LOG_INFO << "Trying to load repo from json file " << repodata_json;
return pool.add_repo_from_repodata_json(
repodata_json,
util::rsplit(subdir.metadata().url(), "/", 1).front(),
add_pip,
static_cast<solver::libsolv::UseOnlyTarBz2>(ctx.use_only_tar_bz2),
json_parser
);
}
)
.transform(
[&](solver::libsolv::RepoInfo&& repo) -> solver::libsolv::RepoInfo
{
if (!util::on_win)
{
pool.native_serialize_repo(repo, subdir.writable_solv_cache(), expected_cache_origin)
.or_else(
[&](const auto& err)
{
LOG_WARNING << R"(Fail to write native serialization to file ")"
<< subdir.writable_solv_cache() << R"(" for repo ")"
<< subdir.name() << ": " << err.what();
;
}
);
}
return std::move(repo);
}
);
}
auto load_installed_packages_in_pool(const Context& ctx, MPool& pool, const PrefixData& prefix)
-> solver::libsolv::RepoInfo
{
// TODO(C++20): We could do a PrefixData range that returns packages without storing thems.
auto pkgs = prefix.sorted_records();
// TODO(C++20): We only need a range that concatenate both
for (auto&& pkg : get_virtual_packages(ctx))
{
pkgs.push_back(std::move(pkg));
}
// Not adding Pip dependency since it might needlessly make the installed/active environment
// broken if pip is not already installed (debatable).
auto repo = pool.add_repo_from_packages(
pkgs,
"installed",
solver::libsolv::PipAsPythonDependency::No
);
pool.set_installed_repo(repo);
return repo;
}
}

View File

@ -18,6 +18,7 @@
#include "mamba/core/context.hpp" #include "mamba/core/context.hpp"
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/query.hpp" #include "mamba/core/query.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/specs/conda_url.hpp" #include "mamba/specs/conda_url.hpp"
#include "mamba/specs/package_info.hpp" #include "mamba/specs/package_info.hpp"
#include "mamba/util/string.hpp" #include "mamba/util/string.hpp"
@ -72,11 +73,11 @@ namespace mamba
} }
}; };
auto pool_latest_package(MPool& pool, specs::MatchSpec spec) auto database_latest_package(solver::libsolv::Database& db, specs::MatchSpec spec)
-> std::optional<specs::PackageInfo> -> std::optional<specs::PackageInfo>
{ {
auto out = std::optional<specs::PackageInfo>(); auto out = std::optional<specs::PackageInfo>();
pool.for_each_package_matching( db.for_each_package_matching(
spec, spec,
[&](auto pkg) [&](auto pkg)
{ {
@ -96,7 +97,7 @@ namespace mamba
using DepGraph = typename QueryResult::dependency_graph; using DepGraph = typename QueryResult::dependency_graph;
using node_id = typename QueryResult::dependency_graph::node_id; using node_id = typename QueryResult::dependency_graph::node_id;
PoolWalker(MPool& pool); PoolWalker(solver::libsolv::Database& db);
void walk(specs::PackageInfo pkg, std::size_t max_depth); void walk(specs::PackageInfo pkg, std::size_t max_depth);
void walk(specs::PackageInfo pkg); void walk(specs::PackageInfo pkg);
@ -113,14 +114,14 @@ namespace mamba
DepGraph m_graph; DepGraph m_graph;
VisitedMap m_visited; VisitedMap m_visited;
NotFoundMap m_not_found; NotFoundMap m_not_found;
MPool& m_pool; solver::libsolv::Database& m_database;
void walk_impl(node_id id, std::size_t max_depth); void walk_impl(node_id id, std::size_t max_depth);
void reverse_walk_impl(node_id id); void reverse_walk_impl(node_id id);
}; };
PoolWalker::PoolWalker(MPool& pool) PoolWalker::PoolWalker(solver::libsolv::Database& db)
: m_pool(pool) : m_database(db)
{ {
} }
@ -148,7 +149,7 @@ namespace mamba
// as taking any package matching a dependency recursively. // as taking any package matching a dependency recursively.
// Package dependencies can appear mulitple time, further reducing its valid set. // Package dependencies can appear mulitple time, further reducing its valid set.
// To do this properly, we should instanciate a solver and resolve the spec. // To do this properly, we should instanciate a solver and resolve the spec.
if (auto child = pool_latest_package(m_pool, specs::MatchSpec::parse(dep))) if (auto child = database_latest_package(m_database, specs::MatchSpec::parse(dep)))
{ {
if (auto it = m_visited.find(&(*child)); it != m_visited.cend()) if (auto it = m_visited.find(&(*child)); it != m_visited.cend())
{ {
@ -185,7 +186,7 @@ namespace mamba
void PoolWalker::reverse_walk_impl(node_id id) void PoolWalker::reverse_walk_impl(node_id id)
{ {
m_pool.for_each_package_depending_on( m_database.for_each_package_depending_on(
specs::MatchSpec::parse(m_graph.node(id).name), specs::MatchSpec::parse(m_graph.node(id).name),
[&](specs::PackageInfo pkg) [&](specs::PackageInfo pkg)
{ {
@ -210,12 +211,12 @@ namespace mamba
} }
} }
auto Query::find(MPool& mpool, const std::vector<std::string>& queries) -> QueryResult auto Query::find(Database& db, const std::vector<std::string>& queries) -> QueryResult
{ {
QueryResult::dependency_graph g; QueryResult::dependency_graph g;
for (const auto& query : queries) for (const auto& query : queries)
{ {
mpool.for_each_package_matching( db.for_each_package_matching(
specs::MatchSpec::parse(query), specs::MatchSpec::parse(query),
[&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); } [&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); }
); );
@ -228,13 +229,13 @@ namespace mamba
}; };
} }
auto Query::whoneeds(MPool& mpool, std::string query, bool tree) -> QueryResult auto Query::whoneeds(Database& db, std::string query, bool tree) -> QueryResult
{ {
if (tree) if (tree)
{ {
if (auto pkg = pool_latest_package(mpool, specs::MatchSpec::parse(query))) if (auto pkg = database_latest_package(db, specs::MatchSpec::parse(query)))
{ {
auto walker = PoolWalker(mpool); auto walker = PoolWalker(db);
walker.reverse_walk(std::move(pkg).value()); walker.reverse_walk(std::move(pkg).value());
return { QueryType::WhoNeeds, std::move(query), std::move(walker).graph() }; return { QueryType::WhoNeeds, std::move(query), std::move(walker).graph() };
} }
@ -242,7 +243,7 @@ namespace mamba
else else
{ {
QueryResult::dependency_graph g; QueryResult::dependency_graph g;
mpool.for_each_package_depending_on( db.for_each_package_depending_on(
specs::MatchSpec::parse(query), specs::MatchSpec::parse(query),
[&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); } [&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); }
); );
@ -251,11 +252,11 @@ namespace mamba
return { QueryType::WhoNeeds, std::move(query), QueryResult::dependency_graph() }; return { QueryType::WhoNeeds, std::move(query), QueryResult::dependency_graph() };
} }
auto Query::depends(MPool& mpool, std::string query, bool tree) -> QueryResult auto Query::depends(Database& db, std::string query, bool tree) -> QueryResult
{ {
if (auto pkg = pool_latest_package(mpool, specs::MatchSpec::parse(query))) if (auto pkg = database_latest_package(db, specs::MatchSpec::parse(query)))
{ {
auto walker = PoolWalker(mpool); auto walker = PoolWalker(db);
if (tree) if (tree)
{ {
walker.walk(std::move(pkg).value()); walker.walk(std::move(pkg).value());

View File

@ -24,9 +24,9 @@
#include "mamba/core/link.hpp" #include "mamba/core/link.hpp"
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/package_fetcher.hpp" #include "mamba/core/package_fetcher.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/thread_utils.hpp" #include "mamba/core/thread_utils.hpp"
#include "mamba/core/transaction.hpp" #include "mamba/core/transaction.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/specs/match_spec.hpp" #include "mamba/specs/match_spec.hpp"
#include "mamba/util/variant_cmp.hpp" #include "mamba/util/variant_cmp.hpp"
@ -47,10 +47,10 @@ namespace mamba
} }
// TODO duplicated function, consider moving it to Pool // TODO duplicated function, consider moving it to Pool
auto pool_has_package(MPool& pool, const specs::MatchSpec& spec) -> bool auto database_has_package(solver::libsolv::Database& db, const specs::MatchSpec& spec) -> bool
{ {
bool found = false; bool found = false;
pool.for_each_package_matching( db.for_each_package_matching(
spec, spec,
[&](const auto&) [&](const auto&)
{ {
@ -76,13 +76,14 @@ namespace mamba
return out; return out;
} }
auto installed_python(const MPool& pool) -> std::optional<specs::PackageInfo> auto installed_python(const solver::libsolv::Database& db)
-> std::optional<specs::PackageInfo>
{ {
// TODO combine Repo and MatchSpec search API in Pool // TODO combine Repo and MatchSpec search API in Pool
auto out = std::optional<specs::PackageInfo>(); auto out = std::optional<specs::PackageInfo>();
if (auto repo = pool.installed_repo()) if (auto repo = db.installed_repo())
{ {
pool.for_each_package_in_repo( db.for_each_package_in_repo(
*repo, *repo,
[&](specs::PackageInfo&& pkg) [&](specs::PackageInfo&& pkg)
{ {
@ -98,7 +99,8 @@ namespace mamba
return out; return out;
} }
auto find_python_version(const solver::Solution& solution, const MPool& pool) auto
find_python_version(const solver::Solution& solution, const solver::libsolv::Database& db)
-> std::pair<std::string, std::string> -> std::pair<std::string, std::string>
{ {
// We need to find the python version that will be there after this // We need to find the python version that will be there after this
@ -108,7 +110,7 @@ namespace mamba
// version but keeping the current one. // version but keeping the current one.
// Could also be written in term of PrefixData. // Could also be written in term of PrefixData.
std::string installed_py_ver = {}; std::string installed_py_ver = {};
if (auto pkg = installed_python(pool)) if (auto pkg = installed_python(db))
{ {
installed_py_ver = pkg->version; installed_py_ver = pkg->version;
LOG_INFO << "Found python in installed packages " << installed_py_ver; LOG_INFO << "Found python in installed packages " << installed_py_ver;
@ -132,7 +134,7 @@ namespace mamba
MTransaction::MTransaction( MTransaction::MTransaction(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
std::vector<specs::PackageInfo> pkgs_to_remove, std::vector<specs::PackageInfo> pkgs_to_remove,
std::vector<specs::PackageInfo> pkgs_to_install, std::vector<specs::PackageInfo> pkgs_to_install,
MultiPackageCache& caches MultiPackageCache& caches
@ -143,7 +145,7 @@ namespace mamba
for (const auto& pkg : pkgs_to_remove) for (const auto& pkg : pkgs_to_remove)
{ {
auto spec = explicit_spec(pkg); auto spec = explicit_spec(pkg);
if (!pool_has_package(pool, spec)) if (!database_has_package(db, spec))
{ {
not_found << "\n - " << spec.str(); not_found << "\n - " << spec.str();
} }
@ -203,14 +205,14 @@ namespace mamba
ctx, ctx,
ctx.prefix_params.target_prefix, ctx.prefix_params.target_prefix,
ctx.prefix_params.relocate_prefix, ctx.prefix_params.relocate_prefix,
find_python_version(m_solution, pool), find_python_version(m_solution, db),
specs_to_install specs_to_install
); );
} }
MTransaction::MTransaction( MTransaction::MTransaction(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
const solver::Request& request, const solver::Request& request,
solver::Solution solution, solver::Solution solution,
MultiPackageCache& caches MultiPackageCache& caches
@ -257,7 +259,7 @@ namespace mamba
ctx, ctx,
ctx.prefix_params.target_prefix, ctx.prefix_params.target_prefix,
ctx.prefix_params.relocate_prefix, ctx.prefix_params.relocate_prefix,
find_python_version(m_solution, pool), find_python_version(m_solution, db),
std::move(requested_specs) std::move(requested_specs)
); );
@ -273,7 +275,7 @@ namespace mamba
MTransaction::MTransaction( MTransaction::MTransaction(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
std::vector<specs::PackageInfo> packages, std::vector<specs::PackageInfo> packages,
MultiPackageCache& caches MultiPackageCache& caches
) )
@ -307,7 +309,7 @@ namespace mamba
ctx, ctx,
ctx.prefix_params.target_prefix, ctx.prefix_params.target_prefix,
ctx.prefix_params.relocate_prefix, ctx.prefix_params.relocate_prefix,
find_python_version(m_solution, pool), find_python_version(m_solution, db),
std::move(specs_to_install) std::move(specs_to_install)
); );
} }
@ -1112,7 +1114,7 @@ namespace mamba
} }
MTransaction MTransaction
create_explicit_transaction_from_urls(const Context& ctx, MPool& pool, const std::vector<std::string>& urls, MultiPackageCache& package_caches, std::vector<detail::other_pkg_mgr_spec>&) create_explicit_transaction_from_urls(const Context& ctx, solver::libsolv::Database& db, const std::vector<std::string>& urls, MultiPackageCache& package_caches, std::vector<detail::other_pkg_mgr_spec>&)
{ {
std::vector<specs::PackageInfo> specs_to_install = {}; std::vector<specs::PackageInfo> specs_to_install = {};
specs_to_install.reserve(urls.size()); specs_to_install.reserve(urls.size());
@ -1122,12 +1124,12 @@ namespace mamba
std::back_insert_iterator(specs_to_install), std::back_insert_iterator(specs_to_install),
[&](const auto& u) { return specs::PackageInfo::from_url(u); } [&](const auto& u) { return specs::PackageInfo::from_url(u); }
); );
return MTransaction(ctx, pool, {}, specs_to_install, package_caches); return MTransaction(ctx, db, {}, specs_to_install, package_caches);
} }
MTransaction create_explicit_transaction_from_lockfile( MTransaction create_explicit_transaction_from_lockfile(
const Context& ctx, const Context& ctx,
MPool& pool, solver::libsolv::Database& db,
const fs::u8path& env_lockfile_path, const fs::u8path& env_lockfile_path,
const std::vector<std::string>& categories, const std::vector<std::string>& categories,
MultiPackageCache& package_caches, MultiPackageCache& package_caches,
@ -1191,7 +1193,7 @@ namespace mamba
); );
} }
return MTransaction{ ctx, pool, std::move(conda_packages), package_caches }; return MTransaction{ ctx, db, std::move(conda_packages), package_caches };
} }
} // namespace mamba } // namespace mamba

View File

@ -0,0 +1,331 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#include <exception>
#include <iostream>
#include <limits>
#include <string_view>
#include <fmt/format.h>
#include <solv/evr.h>
#include <solv/selection.h>
#include <solv/solver.h>
#include <spdlog/spdlog.h>
#include "mamba/fs/filesystem.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/specs/match_spec.hpp"
#include "mamba/util/random.hpp"
#include "solv-cpp/pool.hpp"
#include "solv-cpp/queue.hpp"
#include "solver/libsolv/helpers.hpp"
namespace mamba::solver::libsolv
{
struct Database::DatabaseImpl
{
DatabaseImpl(specs::ChannelResolveParams p_channel_params)
: channel_params(std::move(p_channel_params))
{
}
specs::ChannelResolveParams channel_params;
solv::ObjPool pool = {};
};
Database::Database(specs::ChannelResolveParams channel_params)
: m_data(std::make_unique<DatabaseImpl>(std::move(channel_params)))
{
pool().set_disttype(DISTTYPE_CONDA);
// Ensure that debug logging never goes to stdout as to not interfere json output
pool().raw()->debugmask |= SOLV_DEBUG_TO_STDERR;
::pool_setdebuglevel(pool().raw(), -1); // Off
}
Database::~Database() = default;
Database::Database(Database&&) = default;
auto Database::operator=(Database&&) -> Database& = default;
auto Database::pool() -> solv::ObjPool&
{
return m_data->pool;
}
auto Database::pool() const -> const solv::ObjPool&
{
return m_data->pool;
}
auto Database::Impl::get(Database& pool) -> solv::ObjPool&
{
return pool.pool();
}
auto Database::Impl::get(const Database& pool) -> const solv::ObjPool&
{
return pool.pool();
}
auto Database::channel_params() const -> const specs::ChannelResolveParams&
{
return m_data->channel_params;
}
namespace
{
auto libsolv_to_log_level(int type) -> LogLevel
{
if (type & SOLV_FATAL)
{
return LogLevel::Fatal;
}
if (type & SOLV_ERROR)
{
return LogLevel::Error;
}
if (type & SOLV_WARN)
{
return LogLevel::Warning;
}
return LogLevel::Debug;
}
}
void Database::set_logger(logger_type callback)
{
::pool_setdebuglevel(pool().raw(), std::numeric_limits<int>::max()); // All
pool().set_debug_callback(
[logger = std::move(callback)](::Pool*, int type, std::string_view msg) noexcept
{
try
{
logger(libsolv_to_log_level(type), msg);
}
catch (std::exception const& e)
{
std::cerr << "Developer error: error in libsolv logging function: \n"
<< e.what();
}
}
);
}
auto Database::add_repo_from_repodata_json(
const fs::u8path& path,
std::string_view url,
PipAsPythonDependency add,
UseOnlyTarBz2 only_tar,
RepodataParser parser
) -> expected_t<RepoInfo>
{
const auto use_only_tar_bz2 = static_cast<bool>(only_tar);
if (!fs::exists(path))
{
return make_unexpected(
fmt::format(R"(File "{}" does not exist)", path),
mamba_error_code::repodata_not_loaded
);
}
auto repo = pool().add_repo(url).second;
repo.set_url(std::string(url));
auto make_repo = [&]() -> expected_t<solv::ObjRepoView>
{
if (parser == RepodataParser::Mamba)
{
return mamba_read_json(pool(), repo, path, std::string(url), use_only_tar_bz2);
}
return libsolv_read_json(repo, path, use_only_tar_bz2)
.transform(
[&url](solv::ObjRepoView p_repo)
{
set_solvables_url(p_repo, std::string(url));
return p_repo;
}
);
};
return make_repo()
.transform(
[&](solv::ObjRepoView p_repo) -> RepoInfo
{
if (add == PipAsPythonDependency::Yes)
{
add_pip_as_python_dependency(pool(), p_repo);
}
p_repo.internalize();
return RepoInfo{ p_repo.raw() };
}
)
.or_else([&](const auto&) { pool().remove_repo(repo.id(), /* reuse_ids= */ true); });
}
auto Database::add_repo_from_native_serialization(
const fs::u8path& path,
const RepodataOrigin& expected,
PipAsPythonDependency add
) -> expected_t<RepoInfo>
{
auto repo = pool().add_repo(expected.url).second;
return read_solv(pool(), repo, path, expected, static_cast<bool>(add))
.transform(
[&](solv::ObjRepoView p_repo) -> RepoInfo
{
p_repo.set_url(expected.url);
set_solvables_url(p_repo, expected.url);
if (add == PipAsPythonDependency::Yes)
{
add_pip_as_python_dependency(pool(), p_repo);
}
p_repo.internalize();
return RepoInfo(p_repo.raw());
}
)
.or_else([&](const auto&) { pool().remove_repo(repo.id(), /* reuse_ids= */ true); });
}
auto Database::add_repo_from_packages_impl_pre(std::string_view name) -> RepoInfo
{
if (name.empty())
{
return RepoInfo(
pool().add_repo(util::generate_random_alphanumeric_string(20)).second.raw()
);
}
return RepoInfo(pool().add_repo(name).second.raw());
}
void
Database::add_repo_from_packages_impl_loop(const RepoInfo& repo, const specs::PackageInfo& pkg)
{
auto s_repo = solv::ObjRepoView(*repo.m_ptr);
auto [id, solv] = s_repo.add_solvable();
set_solvable(pool(), solv, pkg);
}
void Database::add_repo_from_packages_impl_post(const RepoInfo& repo, PipAsPythonDependency add)
{
auto s_repo = solv::ObjRepoView(*repo.m_ptr);
if (add == PipAsPythonDependency::Yes)
{
add_pip_as_python_dependency(pool(), s_repo);
}
s_repo.internalize();
}
auto Database::native_serialize_repo(
const RepoInfo& repo,
const fs::u8path& path,
const RepodataOrigin& metadata
) -> expected_t<RepoInfo>
{
assert(repo.m_ptr != nullptr);
return write_solv(solv::ObjRepoView(*repo.m_ptr), path, metadata)
.transform([](solv::ObjRepoView solv_repo) { return RepoInfo(solv_repo.raw()); });
}
void Database::remove_repo(RepoInfo repo)
{
pool().remove_repo(repo.id(), /* reuse_ids= */ true);
}
auto Database::installed_repo() const -> std::optional<RepoInfo>
{
if (auto repo = pool().installed_repo())
{
// Safe because the Repo does not modify its internals
return RepoInfo(const_cast<::Repo*>(repo->raw()));
}
return {};
}
void Database::set_installed_repo(RepoInfo repo)
{
pool().set_installed_repo(repo.id());
}
void Database::set_repo_priority(RepoInfo repo, Priorities priorities)
{
// NOTE: The Pool is not involved directly in this operations, but since it is needed
// in so many repo operations, this setter was put here to keep the Repo class
// immutable.
static_assert(std::is_same_v<decltype(repo.m_ptr->priority), Priorities::value_type>);
repo.m_ptr->priority = priorities.priority;
repo.m_ptr->subpriority = priorities.subpriority;
}
auto Database::package_id_to_package_info(PackageId id) const -> specs::PackageInfo
{
static_assert(std::is_same_v<std::underlying_type_t<PackageId>, solv::SolvableId>);
const auto solv = pool().get_solvable(static_cast<solv::SolvableId>(id));
assert(solv.has_value()); // Safe because the ID is coming from libsolv
return { make_package_info(pool(), solv.value()) };
}
auto Database::packages_in_repo(RepoInfo repo) const -> std::vector<PackageId>
{
// TODO maybe we could use a span here depending on libsolv layout
auto solv_repo = solv::ObjRepoViewConst(*repo.m_ptr);
auto out = std::vector<PackageId>();
out.reserve(solv_repo.solvable_count());
solv_repo.for_each_solvable_id([&](auto id) { out.push_back(static_cast<PackageId>(id)); });
return out;
}
namespace
{
auto matchspec2id(
solv::ObjPool& pool,
const specs::ChannelResolveParams& channel_params,
const specs::MatchSpec& ms
) -> solv::DependencyId
{
return pool_add_matchspec(pool, ms, channel_params)
.or_else([](mamba_error&& error) { throw std::move(error); })
.value_or(0);
}
}
auto Database::packages_matching_ids(const specs::MatchSpec& ms) -> std::vector<PackageId>
{
static_assert(std::is_same_v<std::underlying_type_t<PackageId>, solv::SolvableId>);
pool().ensure_whatprovides();
const auto ms_id = matchspec2id(pool(), channel_params(), ms);
auto solvables = pool().select_solvables({ SOLVER_SOLVABLE_PROVIDES, ms_id });
auto out = std::vector<PackageId>(solvables.size());
std::transform(
solvables.begin(),
solvables.end(),
out.begin(),
[](auto id) { return static_cast<PackageId>(id); }
);
return out;
}
auto Database::packages_depending_on_ids(const specs::MatchSpec& ms) -> std::vector<PackageId>
{
static_assert(std::is_same_v<std::underlying_type_t<PackageId>, solv::SolvableId>);
pool().ensure_whatprovides();
const auto ms_id = matchspec2id(pool(), channel_params(), ms);
auto solvables = pool().what_matches_dep(SOLVABLE_REQUIRES, ms_id);
auto out = std::vector<PackageId>(solvables.size());
std::transform(
solvables.begin(),
solvables.end(),
out.begin(),
[](auto id) { return static_cast<PackageId>(id); }
);
return out;
}
}

View File

@ -6,9 +6,8 @@
#include <solv/solver.h> #include <solv/solver.h>
#include "mamba/core/channel_context.hpp"
#include "mamba/core/error_handling.hpp" #include "mamba/core/error_handling.hpp"
#include "mamba/core/pool.hpp" #include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/solver.hpp" #include "mamba/solver/libsolv/solver.hpp"
#include "mamba/util/variant_cmp.hpp" #include "mamba/util/variant_cmp.hpp"
#include "solv-cpp/solver.hpp" #include "solv-cpp/solver.hpp"
@ -51,9 +50,9 @@ namespace mamba::solver::libsolv
} }
} }
auto Solver::solve_impl(MPool& mpool, const Request& request) -> expected_t<Outcome> auto Solver::solve_impl(Database& mpool, const Request& request) -> expected_t<Outcome>
{ {
auto& pool = MPool::Impl::get(mpool); auto& pool = Database::Impl::get(mpool);
const auto& chan_params = mpool.channel_params(); const auto& chan_params = mpool.channel_params();
const auto& flags = request.flags; const auto& flags = request.flags;
@ -87,7 +86,7 @@ namespace mamba::solver::libsolv
); );
} }
auto Solver::solve(MPool& mpool, Request&& request) -> expected_t<Outcome> auto Solver::solve(Database& mpool, Request&& request) -> expected_t<Outcome>
{ {
if (request.flags.order_request) if (request.flags.order_request)
{ {
@ -96,7 +95,7 @@ namespace mamba::solver::libsolv
return solve_impl(mpool, request); return solve_impl(mpool, request);
} }
auto Solver::solve(MPool& mpool, const Request& request) -> expected_t<Outcome> auto Solver::solve(Database& mpool, const Request& request) -> expected_t<Outcome>
{ {
if (request.flags.order_request) if (request.flags.order_request)
{ {

View File

@ -13,7 +13,7 @@
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/palette.hpp" #include "mamba/core/palette.hpp"
#include "mamba/core/pool.hpp" #include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/unsolvable.hpp" #include "mamba/solver/libsolv/unsolvable.hpp"
#include "mamba/specs/match_spec.hpp" #include "mamba/specs/match_spec.hpp"
#include "mamba/specs/package_info.hpp" #include "mamba/specs/package_info.hpp"
@ -41,9 +41,9 @@ namespace mamba::solver::libsolv
return *m_solver; return *m_solver;
} }
auto UnSolvable::problems(MPool& mpool) const -> std::vector<std::string> auto UnSolvable::problems(Database& mpool) const -> std::vector<std::string>
{ {
auto& pool = MPool::Impl::get(mpool); auto& pool = Database::Impl::get(mpool);
std::vector<std::string> problems; std::vector<std::string> problems;
solver().for_each_problem_id([&](solv::ProblemId pb) solver().for_each_problem_id([&](solv::ProblemId pb)
{ problems.emplace_back(solver().problem_to_string(pool, pb)); } { problems.emplace_back(solver().problem_to_string(pool, pb)); }
@ -51,9 +51,9 @@ namespace mamba::solver::libsolv
return problems; return problems;
} }
auto UnSolvable::problems_to_str(MPool& mpool) const -> std::string auto UnSolvable::problems_to_str(Database& mpool) const -> std::string
{ {
auto& pool = MPool::Impl::get(mpool); auto& pool = Database::Impl::get(mpool);
std::stringstream problems; std::stringstream problems;
problems << "Encountered problems while solving:\n"; problems << "Encountered problems while solving:\n";
solver().for_each_problem_id( solver().for_each_problem_id(
@ -63,9 +63,9 @@ namespace mamba::solver::libsolv
return problems.str(); return problems.str();
} }
auto UnSolvable::all_problems_to_str(MPool& mpool) const -> std::string auto UnSolvable::all_problems_to_str(Database& mpool) const -> std::string
{ {
auto& pool = MPool::Impl::get(mpool); auto& pool = Database::Impl::get(mpool);
std::stringstream problems; std::stringstream problems;
solver().for_each_problem_id( solver().for_each_problem_id(
[&](solv::ProblemId pb) [&](solv::ProblemId pb)
@ -467,13 +467,14 @@ namespace mamba::solver::libsolv
} }
} }
auto UnSolvable::problems_graph(const MPool& pool) const -> ProblemsGraph auto UnSolvable::problems_graph(const Database& pool) const -> ProblemsGraph
{ {
assert(m_solver != nullptr); assert(m_solver != nullptr);
return ProblemsGraphCreator(MPool::Impl::get(pool), *m_solver).problem_graph(); return ProblemsGraphCreator(Database::Impl::get(pool), *m_solver).problem_graph();
} }
auto UnSolvable::explain_problems_to(MPool& pool, std::ostream& out, const Palette& palette) const auto
UnSolvable::explain_problems_to(Database& pool, std::ostream& out, const Palette& palette) const
-> std::ostream& -> std::ostream&
{ {
out << "Could not solve for environment specs\n"; out << "Could not solve for environment specs\n";
@ -491,7 +492,7 @@ namespace mamba::solver::libsolv
return out; return out;
} }
auto UnSolvable::explain_problems(MPool& pool, const Palette& palette) const -> std::string auto UnSolvable::explain_problems(Database& pool, const Palette& palette) const -> std::string
{ {
std::stringstream ss; std::stringstream ss;

View File

@ -10,7 +10,9 @@
#include "mamba/core/channel_context.hpp" #include "mamba/core/channel_context.hpp"
#include "mamba/core/env_lockfile.hpp" #include "mamba/core/env_lockfile.hpp"
#include "mamba/core/fsutil.hpp" #include "mamba/core/fsutil.hpp"
#include "mamba/core/package_database_loader.hpp"
#include "mamba/core/transaction.hpp" #include "mamba/core/transaction.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mambatests.hpp" #include "mambatests.hpp"
@ -126,8 +128,8 @@ namespace mamba
const fs::u8path lockfile_path{ mambatests::test_data_dir const fs::u8path lockfile_path{ mambatests::test_data_dir
/ "env_lockfile/good_multiple_categories-lock.yaml" }; / "env_lockfile/good_multiple_categories-lock.yaml" };
auto channel_context = ChannelContext::make_conda_compatible(mambatests::context()); auto channel_context = ChannelContext::make_conda_compatible(mambatests::context());
MPool pool{ channel_context.params() }; solver::libsolv::Database db{ channel_context.params() };
add_spdlog_logger_to_pool(pool); add_spdlog_logger_to_database(db);
mamba::MultiPackageCache pkg_cache({ "/tmp/" }, ctx.validation_params); mamba::MultiPackageCache pkg_cache({ "/tmp/" }, ctx.validation_params);
ctx.platform = "linux-64"; ctx.platform = "linux-64";
@ -138,7 +140,7 @@ namespace mamba
std::vector<detail::other_pkg_mgr_spec> other_specs; std::vector<detail::other_pkg_mgr_spec> other_specs;
auto transaction = create_explicit_transaction_from_lockfile( auto transaction = create_explicit_transaction_from_lockfile(
ctx, ctx,
pool, db,
lockfile_path, lockfile_path,
categories, categories,
pkg_cache, pkg_cache,

View File

@ -14,11 +14,12 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "mamba/core/channel_context.hpp" #include "mamba/core/channel_context.hpp"
#include "mamba/core/pool.hpp" #include "mamba/core/package_database_loader.hpp"
#include "mamba/core/prefix_data.hpp" #include "mamba/core/prefix_data.hpp"
#include "mamba/core/subdirdata.hpp" #include "mamba/core/subdirdata.hpp"
#include "mamba/core/util.hpp" #include "mamba/core/util.hpp"
#include "mamba/fs/filesystem.hpp" #include "mamba/fs/filesystem.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/repo_info.hpp" #include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/solver/libsolv/solver.hpp" #include "mamba/solver/libsolv/solver.hpp"
#include "mamba/solver/libsolv/unsolvable.hpp" #include "mamba/solver/libsolv/unsolvable.hpp"
@ -97,26 +98,26 @@ namespace
} }
/** /**
* Create a solver and a pool of a conflict. * Create a solver and a database of a conflict.
* *
* The underlying packages do not exist, we are onl interested in the conflict. * The underlying packages do not exist, we are onl interested in the conflict.
*/ */
template <typename PkgRange> template <typename PkgRange>
auto create_pkgs_pool(ChannelContext& channel_context, const PkgRange& packages) auto create_pkgs_database(ChannelContext& channel_context, const PkgRange& packages)
{ {
MPool pool{ channel_context.params() }; solver::libsolv::Database db{ channel_context.params() };
pool.add_repo_from_packages(packages); db.add_repo_from_packages(packages);
return pool; return db;
} }
} }
TEST_CASE("Test create_pool utility") TEST_CASE("Test create_pkgs_database utility")
{ {
auto& ctx = mambatests::context(); auto& ctx = mambatests::context();
auto channel_context = ChannelContext::make_conda_compatible(ctx); auto channel_context = ChannelContext::make_conda_compatible(ctx);
auto pool = create_pkgs_pool(channel_context, std::array{ mkpkg("foo", "0.1.0", {}) }); auto db = create_pkgs_database(channel_context, std::array{ mkpkg("foo", "0.1.0", {}) });
auto request = Request{ {}, { Request::Install{ "foo"_ms } } }; auto request = Request{ {}, { Request::Install{ "foo"_ms } } };
const auto outcome = solver::libsolv::Solver().solve(pool, request).value(); const auto outcome = solver::libsolv::Solver().solve(db, request).value();
REQUIRE(std::holds_alternative<solver::Solution>(outcome)); REQUIRE(std::holds_alternative<solver::Solution>(outcome));
} }
@ -124,12 +125,12 @@ TEST_CASE("Test empty specs")
{ {
auto& ctx = mambatests::context(); auto& ctx = mambatests::context();
auto channel_context = ChannelContext::make_conda_compatible(ctx); auto channel_context = ChannelContext::make_conda_compatible(ctx);
auto pool = create_pkgs_pool( auto db = create_pkgs_database(
channel_context, channel_context,
std::array{ mkpkg("foo", "0.1.0", {}), mkpkg("", "", {}) } std::array{ mkpkg("foo", "0.1.0", {}), mkpkg("", "", {}) }
); );
auto request = Request{ {}, { Request::Install{ "foo"_ms } } }; auto request = Request{ {}, { Request::Install{ "foo"_ms } } };
const auto outcome = solver::libsolv::Solver().solve(pool, request).value(); const auto outcome = solver::libsolv::Solver().solve(db, request).value();
REQUIRE(std::holds_alternative<solver::Solution>(outcome)); REQUIRE(std::holds_alternative<solver::Solution>(outcome));
} }
@ -138,7 +139,7 @@ namespace
auto create_basic_conflict(Context&, ChannelContext& channel_context) auto create_basic_conflict(Context&, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_pkgs_pool( create_pkgs_database(
channel_context, channel_context,
std::array{ std::array{
mkpkg("A", "0.1.0"), mkpkg("A", "0.1.0"),
@ -159,7 +160,7 @@ namespace
auto create_pubgrub(Context&, ChannelContext& channel_context) auto create_pubgrub(Context&, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_pkgs_pool( create_pkgs_database(
channel_context, channel_context,
std::array{ std::array{
mkpkg("menu", "1.5.0", { "dropdown=2.*" }), mkpkg("menu", "1.5.0", { "dropdown=2.*" }),
@ -241,7 +242,7 @@ namespace
packages.push_back(mkpkg("dropdown", "2.9.0", { "libicons>10.0" })); packages.push_back(mkpkg("dropdown", "2.9.0", { "libicons>10.0" }));
} }
return std::pair( return std::pair(
create_pkgs_pool(channel_context, packages), create_pkgs_database(channel_context, packages),
Request{ Request{
{}, {},
{ {
@ -287,7 +288,7 @@ namespace
auto load_channels( auto load_channels(
Context& ctx, Context& ctx,
ChannelContext& channel_context, ChannelContext& channel_context,
MPool& pool, solver::libsolv::Database& db,
MultiPackageCache& cache, MultiPackageCache& cache,
std::vector<std::string>&& channels std::vector<std::string>&& channels
) )
@ -317,14 +318,14 @@ namespace
for (auto& sub_dir : sub_dirs) for (auto& sub_dir : sub_dirs)
{ {
auto repo = load_subdir_in_pool(ctx, pool, sub_dir); auto repo = load_subdir_in_database(ctx, db, sub_dir);
} }
} }
/** /**
* Create a solver and a pool of a conflict from conda-forge packages. * Create a solver and a database of a conflict from conda-forge packages.
*/ */
auto create_conda_forge_pool( auto create_conda_forge_database(
Context& ctx, Context& ctx,
ChannelContext& channel_context, ChannelContext& channel_context,
const std::vector<specs::PackageInfo>& virtual_packages = { mkpkg("__glibc", "2.17.0") }, const std::vector<specs::PackageInfo>& virtual_packages = { mkpkg("__glibc", "2.17.0") },
@ -338,9 +339,9 @@ namespace
auto prefix_data = PrefixData::create(tmp_dir.path() / "prefix", channel_context).value(); auto prefix_data = PrefixData::create(tmp_dir.path() / "prefix", channel_context).value();
prefix_data.add_packages(virtual_packages); prefix_data.add_packages(virtual_packages);
auto pool = MPool{ channel_context.params() }; auto db = solver::libsolv::Database{ channel_context.params() };
load_installed_packages_in_pool(ctx, pool, prefix_data); load_installed_packages_in_database(ctx, db, prefix_data);
auto cache = MultiPackageCache({ tmp_dir.path() / "cache" }, ctx.validation_params); auto cache = MultiPackageCache({ tmp_dir.path() / "cache" }, ctx.validation_params);
create_cache_dir(cache.first_writable_path()); create_cache_dir(cache.first_writable_path());
@ -350,13 +351,13 @@ namespace
load_channels( load_channels(
ctx, ctx,
channel_context, channel_context,
pool, db,
cache, cache,
make_platform_channels(std::move(channels), platforms) make_platform_channels(std::move(channels), platforms)
); );
ctx.graphics_params.no_progress_bars = prev_progress_bars_value; ctx.graphics_params.no_progress_bars = prev_progress_bars_value;
return pool; return db;
} }
} }
@ -364,9 +365,9 @@ TEST_CASE("Test create_conda_forge utility")
{ {
auto& ctx = mambatests::context(); auto& ctx = mambatests::context();
auto channel_context = ChannelContext::make_conda_compatible(ctx); auto channel_context = ChannelContext::make_conda_compatible(ctx);
auto pool = create_conda_forge_pool(ctx, channel_context); auto db = create_conda_forge_database(ctx, channel_context);
auto request = Request{ {}, { Request::Install{ "xtensor>=0.7"_ms } } }; auto request = Request{ {}, { Request::Install{ "xtensor>=0.7"_ms } } };
const auto outcome = solver::libsolv::Solver().solve(pool, request).value(); const auto outcome = solver::libsolv::Solver().solve(db, request).value();
REQUIRE(std::holds_alternative<solver::Solution>(outcome)); REQUIRE(std::holds_alternative<solver::Solution>(outcome));
} }
@ -375,7 +376,7 @@ namespace
auto create_pytorch_cpu(Context& ctx, ChannelContext& channel_context) auto create_pytorch_cpu(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool(ctx, channel_context), create_conda_forge_database(ctx, channel_context),
Request{ Request{
{}, {},
{ {
@ -389,7 +390,7 @@ namespace
auto create_pytorch_cuda(Context& ctx, ChannelContext& channel_context) auto create_pytorch_cuda(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool( create_conda_forge_database(
ctx, ctx,
channel_context, channel_context,
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "10.2.0") } { mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "10.2.0") }
@ -407,7 +408,7 @@ namespace
auto create_cudatoolkit(Context& ctx, ChannelContext& channel_context) auto create_cudatoolkit(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool( create_conda_forge_database(
ctx, ctx,
channel_context, channel_context,
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "11.1") } { mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "11.1") }
@ -428,7 +429,7 @@ namespace
auto create_jpeg9b(Context& ctx, ChannelContext& channel_context) auto create_jpeg9b(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool(ctx, channel_context), create_conda_forge_database(ctx, channel_context),
Request{ Request{
{}, {},
{ {
@ -442,7 +443,7 @@ namespace
auto create_r_base(Context& ctx, ChannelContext& channel_context) auto create_r_base(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool(ctx, channel_context), create_conda_forge_database(ctx, channel_context),
Request{ Request{
{}, {},
{ {
@ -459,7 +460,7 @@ namespace
auto create_scip(Context& ctx, ChannelContext& channel_context) auto create_scip(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool(ctx, channel_context), create_conda_forge_database(ctx, channel_context),
Request{ Request{
{}, {},
{ {
@ -473,7 +474,7 @@ namespace
auto create_double_python(Context& ctx, ChannelContext& channel_context) auto create_double_python(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool(ctx, channel_context), create_conda_forge_database(ctx, channel_context),
Request{ Request{
{}, {},
{ {
@ -487,7 +488,7 @@ namespace
auto create_numba(Context& ctx, ChannelContext& channel_context) auto create_numba(Context& ctx, ChannelContext& channel_context)
{ {
return std::pair( return std::pair(
create_conda_forge_pool(ctx, channel_context), create_conda_forge_database(ctx, channel_context),
Request{ Request{
{}, {},
{ {
@ -583,11 +584,11 @@ TEST_CASE("Create problem graph")
// Somehow the capture does not work directly on ``name`` // Somehow the capture does not work directly on ``name``
std::string_view name_copy = name; std::string_view name_copy = name;
CAPTURE(name_copy); CAPTURE(name_copy);
auto [pool, request] = factory(ctx, channel_context); auto [db, request] = factory(ctx, channel_context);
auto outcome = solver::libsolv::Solver().solve(pool, request).value(); auto outcome = solver::libsolv::Solver().solve(db, request).value();
// REQUIRE(std::holds_alternative<solver::libsolv::UnSolvable>(outcome)); // REQUIRE(std::holds_alternative<solver::libsolv::UnSolvable>(outcome));
auto& unsolvable = std::get<solver::libsolv::UnSolvable>(outcome); auto& unsolvable = std::get<solver::libsolv::UnSolvable>(outcome);
const auto pbs_init = unsolvable.problems_graph(pool); const auto pbs_init = unsolvable.problems_graph(db);
const auto& graph_init = pbs_init.graph(); const auto& graph_init = pbs_init.graph();
REQUIRE_GE(graph_init.number_of_nodes(), 1); REQUIRE_GE(graph_init.number_of_nodes(), 1);

View File

@ -23,14 +23,15 @@
#include "mamba/core/download_progress_bar.hpp" #include "mamba/core/download_progress_bar.hpp"
#include "mamba/core/execution.hpp" #include "mamba/core/execution.hpp"
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/package_database_loader.hpp"
#include "mamba/core/package_handling.hpp" #include "mamba/core/package_handling.hpp"
#include "mamba/core/pool.hpp"
#include "mamba/core/prefix_data.hpp" #include "mamba/core/prefix_data.hpp"
#include "mamba/core/query.hpp" #include "mamba/core/query.hpp"
#include "mamba/core/subdirdata.hpp" #include "mamba/core/subdirdata.hpp"
#include "mamba/core/transaction.hpp" #include "mamba/core/transaction.hpp"
#include "mamba/core/util_os.hpp" #include "mamba/core/util_os.hpp"
#include "mamba/core/virtual_packages.hpp" #include "mamba/core/virtual_packages.hpp"
#include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/repo_info.hpp" #include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/solver/problems_graph.hpp" #include "mamba/solver/problems_graph.hpp"
#include "mamba/validation/tools.hpp" #include "mamba/validation/tools.hpp"
@ -379,12 +380,16 @@ bind_submodule_impl(pybind11::module_ m)
py::add_ostream_redirect(m, "ostream_redirect"); py::add_ostream_redirect(m, "ostream_redirect");
py::class_<MPool>(m, "Pool") py::class_<solver::libsolv::Database>(m, "Pool")
.def(py::init<specs::ChannelResolveParams>(), py::arg("channel_params")) .def(py::init<specs::ChannelResolveParams>(), py::arg("channel_params"))
.def("set_logger", &MPool::set_logger, py::call_guard<py::gil_scoped_acquire>()) .def(
"set_logger",
&solver::libsolv::Database::set_logger,
py::call_guard<py::gil_scoped_acquire>()
)
.def( .def(
"add_repo_from_repodata_json", "add_repo_from_repodata_json",
&MPool::add_repo_from_repodata_json, &solver::libsolv::Database::add_repo_from_repodata_json,
py::arg("path"), py::arg("path"),
py::arg("url"), py::arg("url"),
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No, py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No,
@ -393,14 +398,14 @@ bind_submodule_impl(pybind11::module_ m)
) )
.def( .def(
"add_repo_from_native_serialization", "add_repo_from_native_serialization",
&MPool::add_repo_from_native_serialization, &solver::libsolv::Database::add_repo_from_native_serialization,
py::arg("path"), py::arg("path"),
py::arg("expected"), py::arg("expected"),
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No
) )
.def( .def(
"add_repo_from_packages", "add_repo_from_packages",
[](MPool& pool, [](solver::libsolv::Database& db,
py::iterable packages, py::iterable packages,
std::string_view name, std::string_view name,
solver::libsolv::PipAsPythonDependency add) solver::libsolv::PipAsPythonDependency add)
@ -411,7 +416,7 @@ bind_submodule_impl(pybind11::module_ m)
{ {
pkg_infos.push_back(pkg.cast<specs::PackageInfo>()); pkg_infos.push_back(pkg.cast<specs::PackageInfo>());
} }
return pool.add_repo_from_packages(pkg_infos, name, add); return db.add_repo_from_packages(pkg_infos, name, add);
}, },
py::arg("packages"), py::arg("packages"),
py::arg("name") = "", py::arg("name") = "",
@ -419,17 +424,22 @@ bind_submodule_impl(pybind11::module_ m)
) )
.def( .def(
"native_serialize_repo", "native_serialize_repo",
&MPool::native_serialize_repo, &solver::libsolv::Database::native_serialize_repo,
py::arg("repo"), py::arg("repo"),
py::arg("path"), py::arg("path"),
py::arg("metadata") py::arg("metadata")
) )
.def("set_installed_repo", &MPool::set_installed_repo, py::arg("repo")) .def("set_installed_repo", &solver::libsolv::Database::set_installed_repo, py::arg("repo"))
.def("set_repo_priority", &MPool::set_repo_priority, py::arg("repo"), py::arg("priorities")); .def(
"set_repo_priority",
&solver::libsolv::Database::set_repo_priority,
py::arg("repo"),
py::arg("priorities")
);
m.def( m.def(
"load_subdir_in_pool", "load_subdir_in_pool",
&load_subdir_in_pool, &load_subdir_in_database,
py::arg("context"), py::arg("context"),
py::arg("pool"), py::arg("pool"),
py::arg("subdir") py::arg("subdir")
@ -437,7 +447,7 @@ bind_submodule_impl(pybind11::module_ m)
m.def( m.def(
"load_installed_packages_in_pool", "load_installed_packages_in_pool",
&load_installed_packages_in_pool, &load_installed_packages_in_database,
py::arg("context"), py::arg("context"),
py::arg("pool"), py::arg("pool"),
py::arg("prefix_data") py::arg("prefix_data")
@ -457,7 +467,7 @@ bind_submodule_impl(pybind11::module_ m)
.def_property_readonly("first_writable_path", &MultiPackageCache::first_writable_path); .def_property_readonly("first_writable_path", &MultiPackageCache::first_writable_path);
py::class_<MTransaction>(m, "Transaction") py::class_<MTransaction>(m, "Transaction")
.def(py::init<const Context&, MPool&, const solver::Request&, solver::Solution, MultiPackageCache&>( .def(py::init<const Context&, solver::libsolv::Database&, const solver::Request&, solver::Solution, MultiPackageCache&>(
)) ))
.def("to_conda", &MTransaction::to_conda) .def("to_conda", &MTransaction::to_conda)
.def("log_json", &MTransaction::log_json) .def("log_json", &MTransaction::log_json)
@ -522,10 +532,10 @@ bind_submodule_impl(pybind11::module_ m)
py::class_<SubdirData>(m, "SubdirData") py::class_<SubdirData>(m, "SubdirData")
.def( .def(
"create_repo", "create_repo",
[](SubdirData& subdir, MPool& pool) -> solver::libsolv::RepoInfo [](SubdirData& subdir, solver::libsolv::Database& db) -> solver::libsolv::RepoInfo
{ {
deprecated("Use `load_subdir_in_pool` instead", "2.0"); deprecated("Use `load_subdir_in_pool` instead", "2.0");
return extract(load_subdir_in_pool(mambapy::singletons.context(), pool, subdir)); return extract(load_subdir_in_database(mambapy::singletons.context(), db, subdir));
} }
) )
.def("loaded", &SubdirData::is_loaded) .def("loaded", &SubdirData::is_loaded)

View File

@ -8,7 +8,7 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include "mamba/core/palette.hpp" #include "mamba/core/palette.hpp"
#include "mamba/core/pool.hpp" #include "mamba/solver/libsolv/database.hpp"
#include "mamba/solver/libsolv/parameters.hpp" #include "mamba/solver/libsolv/parameters.hpp"
#include "mamba/solver/libsolv/repo_info.hpp" #include "mamba/solver/libsolv/repo_info.hpp"
#include "mamba/solver/libsolv/solver.hpp" #include "mamba/solver/libsolv/solver.hpp"
@ -125,8 +125,8 @@ namespace mambapy
.def(py::init()) .def(py::init())
.def( .def(
"solve", "solve",
[](Solver& self, MPool& pool, const solver::Request& request) [](Solver& self, Database& db, const solver::Request& request)
{ return self.solve(pool, request); } { return self.solve(db, request); }
) )
.def("add_jobs", solver_job_v2_migrator) .def("add_jobs", solver_job_v2_migrator)
.def("add_global_job", solver_job_v2_migrator) .def("add_global_job", solver_job_v2_migrator)

View File

@ -31,7 +31,7 @@
using namespace mamba; using namespace mamba;
MPool Database
load_pool( load_pool(
const std::vector<std::string>& channels, const std::vector<std::string>& channels,
MultiPackageCache& package_caches, MultiPackageCache& package_caches,
@ -40,7 +40,7 @@ load_pool(
) )
{ {
ctx.channels = channels; ctx.channels = channels;
mamba::MPool pool{ ctx, channel_context }; mamba::Database pool{ ctx, channel_context };
auto exp_load = load_channels(ctx, pool, package_caches, false); auto exp_load = load_channels(ctx, pool, package_caches, false);
if (!exp_load) if (!exp_load)
{ {
@ -59,7 +59,7 @@ handle_solve_request(
{ {
struct cache struct cache
{ {
std::optional<mamba::MPool> pool; std::optional<mamba::Database> pool;
std::chrono::time_point<std::chrono::system_clock> last_update; std::chrono::time_point<std::chrono::system_clock> last_update;
}; };

View File

@ -13,6 +13,7 @@
#include "mamba/api/update.hpp" #include "mamba/api/update.hpp"
#include "mamba/core/channel_context.hpp" #include "mamba/core/channel_context.hpp"
#include "mamba/core/context.hpp" #include "mamba/core/context.hpp"
#include "mamba/core/package_database_loader.hpp"
#include "mamba/core/transaction.hpp" #include "mamba/core/transaction.hpp"
#include "mamba/core/util_os.hpp" #include "mamba/core/util_os.hpp"
#include "mamba/util/build.hpp" #include "mamba/util/build.hpp"
@ -28,10 +29,10 @@ using namespace mamba; // NOLINT(build/namespaces)
namespace namespace
{ {
auto pool_has_package(MPool& pool, specs::MatchSpec spec) -> bool auto database_has_package(solver::libsolv::Database& database, specs::MatchSpec spec) -> bool
{ {
bool found = false; bool found = false;
pool.for_each_package_matching( database.for_each_package_matching(
spec, spec,
[&](const auto&) [&](const auto&)
{ {
@ -42,10 +43,11 @@ namespace
return found; return found;
}; };
auto pool_latest_package(MPool& pool, specs::MatchSpec spec) -> std::optional<specs::PackageInfo> auto database_latest_package(solver::libsolv::Database& db, specs::MatchSpec spec)
-> std::optional<specs::PackageInfo>
{ {
auto out = std::optional<specs::PackageInfo>(); auto out = std::optional<specs::PackageInfo>();
pool.for_each_package_matching( db.for_each_package_matching(
spec, spec,
[&](auto pkg) [&](auto pkg)
{ {
@ -72,12 +74,12 @@ update_self(Configuration& config, const std::optional<std::string>& version)
auto channel_context = ChannelContext::make_conda_compatible(ctx); auto channel_context = ChannelContext::make_conda_compatible(ctx);
MPool pool{ channel_context.params() }; solver::libsolv::Database db{ channel_context.params() };
add_spdlog_logger_to_pool(pool); add_spdlog_logger_to_database(db);
mamba::MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params); mamba::MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
auto exp_loaded = load_channels(ctx, channel_context, pool, package_caches); auto exp_loaded = load_channels(ctx, channel_context, db, package_caches);
if (!exp_loaded) if (!exp_loaded)
{ {
throw exp_loaded.error(); throw exp_loaded.error();
@ -88,11 +90,11 @@ update_self(Configuration& config, const std::optional<std::string>& version)
: fmt::format("micromamba>{}", umamba::version()) : fmt::format("micromamba>{}", umamba::version())
); );
auto latest_micromamba = pool_latest_package(pool, matchspec); auto latest_micromamba = database_latest_package(db, matchspec);
if (!latest_micromamba.has_value()) if (!latest_micromamba.has_value())
{ {
if (pool_has_package(pool, specs::MatchSpec::parse("micromamba"))) if (database_has_package(db, specs::MatchSpec::parse("micromamba")))
{ {
Console::instance().print( Console::instance().print(
fmt::format("\nYour micromamba version ({}) is already up to date.", umamba::version()) fmt::format("\nYour micromamba version ({}) is already up to date.", umamba::version())
@ -120,7 +122,7 @@ update_self(Configuration& config, const std::optional<std::string>& version)
); );
ctx.download_only = true; ctx.download_only = true;
MTransaction t(ctx, pool, { latest_micromamba.value() }, package_caches); MTransaction t(ctx, db, { latest_micromamba.value() }, package_caches);
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.root_prefix, channel_context); auto exp_prefix_data = PrefixData::create(ctx.prefix_params.root_prefix, channel_context);
if (!exp_prefix_data) if (!exp_prefix_data)
{ {

View File

@ -756,7 +756,7 @@ def test_channel_nodefaults(tmp_home, tmp_root_prefix, tmp_path):
def test_pin_applicable(tmp_home, tmp_root_prefix, tmp_path): def test_pin_applicable(tmp_home, tmp_root_prefix, tmp_path):
pin_name = "xtensor" pin_name = "xtensor"
pin_max_version = "0.20" pin_max_version = "0.20"
# We add the channel to test a fragile behavior of ``MPool`` # We add the channel to test a fragile behavior of ``Database``
spec_name = "conda-forge::xtensor" spec_name = "conda-forge::xtensor"
rc_file = tmp_path / "rc.yaml" rc_file = tmp_path / "rc.yaml"