mirror of https://github.com/mamba-org/mamba.git
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:
parent
67fd10a830
commit
d20d176b86
|
@ -183,9 +183,11 @@ set(
|
|||
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solvable.cpp
|
||||
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.cpp
|
||||
${LIBMAMBA_SOURCE_DIR}/solv-cpp/transaction.cpp
|
||||
# Solver interface
|
||||
# Solver generic interface
|
||||
${LIBMAMBA_SOURCE_DIR}/solver/helpers.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/parameters.cpp
|
||||
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/repo_info.cpp
|
||||
|
@ -212,6 +214,7 @@ set(
|
|||
# Core API (low-level)
|
||||
${LIBMAMBA_SOURCE_DIR}/core/singletons.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/context.cpp
|
||||
${LIBMAMBA_SOURCE_DIR}/core/download_progress_bar.cpp
|
||||
|
@ -224,7 +227,6 @@ set(
|
|||
${LIBMAMBA_SOURCE_DIR}/core/output.cpp
|
||||
${LIBMAMBA_SOURCE_DIR}/core/package_handling.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/progress_bar.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/version.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/request.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/repo_info.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/download_progress_bar.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/history.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_handling.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/progress_bar.hpp
|
||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/pinning.hpp
|
||||
|
|
|
@ -11,15 +11,18 @@
|
|||
|
||||
namespace mamba
|
||||
{
|
||||
namespace solver::libsolv
|
||||
{
|
||||
class Database;
|
||||
}
|
||||
class Context;
|
||||
class ChannelContext;
|
||||
class MPool;
|
||||
class MultiPackageCache;
|
||||
|
||||
auto load_channels( //
|
||||
Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& pool,
|
||||
MultiPackageCache& package_caches
|
||||
) -> expected_t<void, mamba_aggregated_error>;
|
||||
}
|
||||
|
|
|
@ -7,23 +7,33 @@
|
|||
#ifndef MAMBA_API_INSTALL_HPP
|
||||
#define MAMBA_API_INSTALL_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "mamba/core/package_cache.hpp"
|
||||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/fs/filesystem.hpp"
|
||||
#include "mamba/solver/request.hpp"
|
||||
#include "mamba/specs/package_info.hpp"
|
||||
|
||||
namespace mamba
|
||||
{
|
||||
class Context;
|
||||
class ChannelContext;
|
||||
class Configuration;
|
||||
class PrefixData;
|
||||
class MultiPackageCache;
|
||||
|
||||
namespace specs
|
||||
{
|
||||
class PackageInfo;
|
||||
}
|
||||
|
||||
namespace solver::libsolv
|
||||
{
|
||||
class DataBase;
|
||||
}
|
||||
|
||||
void install(Configuration& config);
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
|
||||
namespace mamba
|
||||
{
|
||||
namespace solver::libsolv
|
||||
{
|
||||
class DataBase;
|
||||
}
|
||||
|
||||
enum class QueryResultFormat
|
||||
{
|
||||
Json = 0,
|
||||
|
@ -23,7 +28,7 @@ namespace mamba
|
|||
};
|
||||
|
||||
[[nodiscard]] auto make_repoquery(
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& pool,
|
||||
QueryType type,
|
||||
QueryResultFormat format,
|
||||
const std::vector<std::string>& queries,
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -14,12 +14,16 @@
|
|||
#include <vector>
|
||||
|
||||
#include "mamba/core/context.hpp"
|
||||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/specs/package_info.hpp"
|
||||
#include "mamba/util/graph.hpp"
|
||||
|
||||
namespace mamba
|
||||
{
|
||||
namespace solver::libsolv
|
||||
{
|
||||
class Database;
|
||||
}
|
||||
|
||||
enum class QueryType
|
||||
{
|
||||
Search,
|
||||
|
@ -88,12 +92,14 @@ namespace mamba
|
|||
{
|
||||
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;
|
||||
|
||||
[[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;
|
||||
};
|
||||
|
||||
/********************
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace mamba
|
|||
{
|
||||
class Channel;
|
||||
}
|
||||
class MPool;
|
||||
|
||||
class Context;
|
||||
class ChannelContext;
|
||||
class DownloadMonitor;
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
|
||||
#include "mamba/api/install.hpp"
|
||||
#include "mamba/core/package_cache.hpp"
|
||||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/core/prefix_data.hpp"
|
||||
#include "mamba/core/transaction_context.hpp"
|
||||
#include "mamba/fs/filesystem.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/solver/solution.hpp"
|
||||
#include "mamba/specs/match_spec.hpp"
|
||||
#include "mamba/specs/package_info.hpp"
|
||||
|
@ -37,7 +37,7 @@ namespace mamba
|
|||
|
||||
MTransaction(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
std::vector<specs::PackageInfo> pkgs_to_remove,
|
||||
std::vector<specs::PackageInfo> pkgs_to_install,
|
||||
MultiPackageCache& caches
|
||||
|
@ -45,7 +45,7 @@ namespace mamba
|
|||
|
||||
MTransaction(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
const solver::Request& request,
|
||||
solver::Solution solution,
|
||||
MultiPackageCache& caches
|
||||
|
@ -54,7 +54,7 @@ namespace mamba
|
|||
// Only use if the packages have been solved previously already.
|
||||
MTransaction(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
std::vector<specs::PackageInfo> packages,
|
||||
MultiPackageCache& caches
|
||||
);
|
||||
|
@ -93,7 +93,7 @@ namespace mamba
|
|||
|
||||
MTransaction create_explicit_transaction_from_urls(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
const std::vector<std::string>& urls,
|
||||
MultiPackageCache& package_caches,
|
||||
std::vector<detail::other_pkg_mgr_spec>& other_specs
|
||||
|
@ -101,7 +101,7 @@ namespace mamba
|
|||
|
||||
MTransaction create_explicit_transaction_from_lockfile(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
const fs::u8path& env_lockfile_path,
|
||||
const std::vector<std::string>& categories,
|
||||
MultiPackageCache& package_caches,
|
||||
|
|
|
@ -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
|
|
@ -17,24 +17,21 @@ extern "C"
|
|||
using Repo = struct s_Repo;
|
||||
}
|
||||
|
||||
namespace mamba
|
||||
{
|
||||
class MPool;
|
||||
class MTransaction;
|
||||
}
|
||||
|
||||
namespace mamba::solver::libsolv
|
||||
{
|
||||
class Database;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* a new repository in the Pool.
|
||||
* Some modifications to the repo are possible throught the Pool.
|
||||
* @see MPool::add_repo_from_repodata_json
|
||||
* @see MPool::add_repo_from_packages
|
||||
* @see MPool::remove_repo
|
||||
* a new repository in the @ref Database.
|
||||
* Some modifications to the repo are possible throught the @ref Database.
|
||||
* @see Database::add_repo_from_repodata_json
|
||||
* @see Database::add_repo_from_packages
|
||||
* @see Database::remove_repo
|
||||
*/
|
||||
class RepoInfo
|
||||
{
|
||||
|
@ -61,8 +58,7 @@ namespace mamba::solver::libsolv
|
|||
|
||||
explicit RepoInfo(::Repo* repo);
|
||||
|
||||
friend class ::mamba::MPool;
|
||||
friend class ::mamba::MTransaction; // As long as MTransaction leaks libsolv impl
|
||||
friend class Database;
|
||||
friend auto operator==(RepoInfo lhs, RepoInfo rhs) -> bool;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,18 +14,20 @@
|
|||
|
||||
namespace mamba::solver::libsolv
|
||||
{
|
||||
class Database;
|
||||
|
||||
class Solver
|
||||
{
|
||||
public:
|
||||
|
||||
using Outcome = std::variant<Solution, UnSolvable>;
|
||||
|
||||
[[nodiscard]] auto solve(MPool& pool, Request&& request) -> expected_t<Outcome>;
|
||||
[[nodiscard]] auto solve(MPool& pool, const Request& request) -> expected_t<Outcome>;
|
||||
[[nodiscard]] auto solve(Database& pool, Request&& request) -> expected_t<Outcome>;
|
||||
[[nodiscard]] auto solve(Database& pool, const Request& request) -> expected_t<Outcome>;
|
||||
|
||||
private:
|
||||
|
||||
auto solve_impl(MPool& pool, const Request& request) -> expected_t<Outcome>;
|
||||
auto solve_impl(Database& pool, const Request& request) -> expected_t<Outcome>;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
namespace mamba
|
||||
{
|
||||
class MPool;
|
||||
class Palette;
|
||||
|
||||
namespace solv
|
||||
|
@ -28,6 +27,7 @@ namespace mamba
|
|||
namespace mamba::solver::libsolv
|
||||
{
|
||||
class Solver;
|
||||
class Database;
|
||||
|
||||
class UnSolvable
|
||||
{
|
||||
|
@ -39,21 +39,22 @@ namespace mamba::solver::libsolv
|
|||
|
||||
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( //
|
||||
MPool& pool,
|
||||
Database& pool,
|
||||
std::ostream& out,
|
||||
const Palette& palette
|
||||
) 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:
|
||||
|
||||
|
|
|
@ -24,13 +24,12 @@
|
|||
#include "mamba/util/flat_set.hpp"
|
||||
#include "mamba/util/graph.hpp"
|
||||
|
||||
namespace mamba
|
||||
{
|
||||
class MPool;
|
||||
}
|
||||
|
||||
namespace mamba::solver
|
||||
{
|
||||
namespace libsolv
|
||||
{
|
||||
class Database;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class conflict_map : private std::unordered_map<T, util::flat_set<T>>
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
#include "mamba/core/channel_context.hpp"
|
||||
#include "mamba/core/download_progress_bar.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/subdirdata.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||
#include "mamba/specs/package_info.hpp"
|
||||
|
||||
|
@ -21,7 +22,7 @@ namespace mamba
|
|||
auto create_repo_from_pkgs_dir(
|
||||
const Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& pool,
|
||||
const fs::u8path& pkgs_dir
|
||||
) -> solver::libsolv::RepoInfo
|
||||
{
|
||||
|
@ -45,7 +46,7 @@ namespace mamba
|
|||
}
|
||||
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(
|
||||
|
@ -112,7 +113,7 @@ namespace mamba
|
|||
auto load_channels_impl(
|
||||
Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& pool,
|
||||
MultiPackageCache& package_caches,
|
||||
bool is_retry
|
||||
) -> expected_t<void, mamba_aggregated_error>
|
||||
|
@ -231,7 +232,7 @@ namespace mamba
|
|||
continue;
|
||||
}
|
||||
|
||||
load_subdir_in_pool(ctx, pool, subdir)
|
||||
load_subdir_in_database(ctx, pool, subdir)
|
||||
.transform([&](solver::libsolv::RepoInfo&& repo)
|
||||
{ pool.set_repo_priority(repo, priorities[i]); })
|
||||
.or_else(
|
||||
|
@ -276,9 +277,12 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
|
||||
auto
|
||||
load_channels(Context& ctx, ChannelContext& channel_context, MPool& pool, MultiPackageCache& package_caches)
|
||||
-> expected_t<void, mamba_aggregated_error>
|
||||
auto load_channels(
|
||||
Context& ctx,
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "mamba/core/environments_manager.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/package_cache.hpp"
|
||||
#include "mamba/core/package_database_loader.hpp"
|
||||
#include "mamba/core/pinning.hpp"
|
||||
#include "mamba/core/transaction.hpp"
|
||||
#include "mamba/core/virtual_packages.hpp"
|
||||
|
@ -530,8 +531,8 @@ namespace mamba
|
|||
LOG_WARNING << "No 'channels' specified";
|
||||
}
|
||||
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
solver::libsolv::Database pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(pool);
|
||||
// functions implied in 'and_then' coding-styles must return the same type
|
||||
// which limits this syntax
|
||||
/*auto exp_prefix_data = load_channels(pool, package_caches)
|
||||
|
@ -552,7 +553,7 @@ namespace mamba
|
|||
}
|
||||
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);
|
||||
|
@ -674,7 +675,7 @@ namespace mamba
|
|||
|
||||
namespace
|
||||
{
|
||||
// TransactionFunc: (MPool& pool, MultiPackageCache& package_caches) -> MTransaction
|
||||
// TransactionFunc: (Database& pool, MultiPackageCache& package_caches) -> MTransaction
|
||||
template <typename TransactionFunc>
|
||||
void install_explicit_with_transaction(
|
||||
Context& ctx,
|
||||
|
@ -684,8 +685,8 @@ namespace mamba
|
|||
bool remove_prefix_on_failure
|
||||
)
|
||||
{
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
solver::libsolv::Database db{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(db);
|
||||
|
||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!exp_prefix_data)
|
||||
|
@ -697,12 +698,12 @@ namespace mamba
|
|||
|
||||
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;
|
||||
// Note that the Transaction will gather the Solvables,
|
||||
// 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;
|
||||
|
||||
|
@ -754,8 +755,8 @@ namespace mamba
|
|||
install_explicit_with_transaction(
|
||||
ctx,
|
||||
channel_context,
|
||||
[&](auto& pool, auto& pkg_caches, auto& others)
|
||||
{ return create_explicit_transaction_from_urls(ctx, pool, specs, pkg_caches, others); },
|
||||
[&](auto& db, auto& pkg_caches, auto& others)
|
||||
{ return create_explicit_transaction_from_urls(ctx, db, specs, pkg_caches, others); },
|
||||
create_env,
|
||||
remove_prefix_on_failure
|
||||
);
|
||||
|
@ -802,11 +803,11 @@ namespace mamba
|
|||
install_explicit_with_transaction(
|
||||
ctx,
|
||||
channel_context,
|
||||
[&](auto& pool, auto& pkg_caches, auto& others)
|
||||
[&](auto& db, auto& pkg_caches, auto& others)
|
||||
{
|
||||
return create_explicit_transaction_from_lockfile(
|
||||
ctx,
|
||||
pool,
|
||||
db,
|
||||
file,
|
||||
categories,
|
||||
pkg_caches,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "mamba/core/channel_context.hpp"
|
||||
#include "mamba/core/output.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/transaction.hpp"
|
||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||
|
@ -127,9 +127,9 @@ namespace mamba
|
|||
}
|
||||
PrefixData& prefix_data = exp_prefix_data.value();
|
||||
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
||||
solver::libsolv::Database pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(pool);
|
||||
load_installed_packages_in_database(ctx, pool, prefix_data);
|
||||
|
||||
const fs::u8path pkgs_dirs(ctx.prefix_params.root_prefix / "pkgs");
|
||||
MultiPackageCache package_caches({ pkgs_dirs }, ctx.validation_params);
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#include "mamba/api/repoquery.hpp"
|
||||
#include "mamba/core/channel_context.hpp"
|
||||
#include "mamba/core/package_cache.hpp"
|
||||
#include "mamba/core/package_database_loader.hpp"
|
||||
#include "mamba/core/prefix_data.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||
#include "mamba/util/string.hpp"
|
||||
|
||||
|
@ -28,8 +30,8 @@ namespace mamba
|
|||
config.load();
|
||||
|
||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
solver::libsolv::Database db{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(db);
|
||||
|
||||
// bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds);
|
||||
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||
|
@ -50,7 +52,7 @@ namespace mamba
|
|||
}
|
||||
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)
|
||||
{
|
||||
|
@ -65,18 +67,18 @@ namespace mamba
|
|||
{
|
||||
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)
|
||||
{
|
||||
throw std::runtime_error(exp_load.error().what());
|
||||
}
|
||||
}
|
||||
return pool;
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
auto make_repoquery(
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
QueryType type,
|
||||
QueryResultFormat format,
|
||||
const std::vector<std::string>& queries,
|
||||
|
@ -87,7 +89,7 @@ namespace mamba
|
|||
{
|
||||
if (type == QueryType::Search)
|
||||
{
|
||||
auto res = Query::find(pool, queries);
|
||||
auto res = Query::find(db, queries);
|
||||
switch (format)
|
||||
{
|
||||
case QueryResultFormat::Json:
|
||||
|
@ -108,7 +110,7 @@ namespace mamba
|
|||
throw std::invalid_argument("Only one query supported for 'depends'.");
|
||||
}
|
||||
auto res = Query::depends(
|
||||
pool,
|
||||
db,
|
||||
queries.front(),
|
||||
/* tree= */ format == QueryResultFormat::Tree
|
||||
|| format == QueryResultFormat::RecursiveTable
|
||||
|
@ -135,7 +137,7 @@ namespace mamba
|
|||
throw std::invalid_argument("Only one query supported for 'whoneeds'.");
|
||||
}
|
||||
auto res = Query::whoneeds(
|
||||
pool,
|
||||
db,
|
||||
queries.front(),
|
||||
/* tree= */ format == QueryResultFormat::Tree
|
||||
|| format == QueryResultFormat::RecursiveTable
|
||||
|
@ -177,9 +179,9 @@ namespace mamba
|
|||
)
|
||||
{
|
||||
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(
|
||||
pool,
|
||||
db,
|
||||
type,
|
||||
format,
|
||||
queries,
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
#include "mamba/api/update.hpp"
|
||||
#include "mamba/core/channel_context.hpp"
|
||||
#include "mamba/core/context.hpp"
|
||||
#include "mamba/core/package_database_loader.hpp"
|
||||
#include "mamba/core/pinning.hpp"
|
||||
#include "mamba/core/transaction.hpp"
|
||||
#include "mamba/core/virtual_packages.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/solver/libsolv/solver.hpp"
|
||||
#include "mamba/solver/request.hpp"
|
||||
|
||||
|
@ -106,12 +108,12 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
solver::libsolv::Database db{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(db);
|
||||
|
||||
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)
|
||||
{
|
||||
throw std::runtime_error(exp_loaded.error().what());
|
||||
|
@ -131,7 +133,7 @@ namespace mamba
|
|||
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(
|
||||
prefix_data,
|
||||
|
@ -157,13 +159,13 @@ namespace mamba
|
|||
// 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 (ctx.output_params.json)
|
||||
{
|
||||
Console::instance().json_write({ { "success", false },
|
||||
{ "solver_problems", unsolvable->problems(pool) } });
|
||||
{ "solver_problems", unsolvable->problems(db) } });
|
||||
}
|
||||
throw mamba_error(
|
||||
"Could not solve for environment specs",
|
||||
|
@ -174,7 +176,7 @@ namespace mamba
|
|||
Console::instance().json_write({ { "success", true } });
|
||||
auto transaction = MTransaction(
|
||||
ctx,
|
||||
pool,
|
||||
db,
|
||||
request,
|
||||
std::get<solver::Solution>(outcome),
|
||||
package_caches
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
#include "mamba/core/context.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/query.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/specs/conda_url.hpp"
|
||||
#include "mamba/specs/package_info.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>
|
||||
{
|
||||
auto out = std::optional<specs::PackageInfo>();
|
||||
pool.for_each_package_matching(
|
||||
db.for_each_package_matching(
|
||||
spec,
|
||||
[&](auto pkg)
|
||||
{
|
||||
|
@ -96,7 +97,7 @@ namespace mamba
|
|||
using DepGraph = typename QueryResult::dependency_graph;
|
||||
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);
|
||||
|
@ -113,14 +114,14 @@ namespace mamba
|
|||
DepGraph m_graph;
|
||||
VisitedMap m_visited;
|
||||
NotFoundMap m_not_found;
|
||||
MPool& m_pool;
|
||||
solver::libsolv::Database& m_database;
|
||||
|
||||
void walk_impl(node_id id, std::size_t max_depth);
|
||||
void reverse_walk_impl(node_id id);
|
||||
};
|
||||
|
||||
PoolWalker::PoolWalker(MPool& pool)
|
||||
: m_pool(pool)
|
||||
PoolWalker::PoolWalker(solver::libsolv::Database& db)
|
||||
: m_database(db)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -148,7 +149,7 @@ namespace mamba
|
|||
// as taking any package matching a dependency recursively.
|
||||
// Package dependencies can appear mulitple time, further reducing its valid set.
|
||||
// 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())
|
||||
{
|
||||
|
@ -185,7 +186,7 @@ namespace mamba
|
|||
|
||||
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::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;
|
||||
for (const auto& query : queries)
|
||||
{
|
||||
mpool.for_each_package_matching(
|
||||
db.for_each_package_matching(
|
||||
specs::MatchSpec::parse(query),
|
||||
[&](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 (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());
|
||||
return { QueryType::WhoNeeds, std::move(query), std::move(walker).graph() };
|
||||
}
|
||||
|
@ -242,7 +243,7 @@ namespace mamba
|
|||
else
|
||||
{
|
||||
QueryResult::dependency_graph g;
|
||||
mpool.for_each_package_depending_on(
|
||||
db.for_each_package_depending_on(
|
||||
specs::MatchSpec::parse(query),
|
||||
[&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); }
|
||||
);
|
||||
|
@ -251,11 +252,11 @@ namespace mamba
|
|||
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)
|
||||
{
|
||||
walker.walk(std::move(pkg).value());
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
#include "mamba/core/link.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/package_fetcher.hpp"
|
||||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/core/thread_utils.hpp"
|
||||
#include "mamba/core/transaction.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/specs/match_spec.hpp"
|
||||
#include "mamba/util/variant_cmp.hpp"
|
||||
|
||||
|
@ -47,10 +47,10 @@ namespace mamba
|
|||
}
|
||||
|
||||
// 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;
|
||||
pool.for_each_package_matching(
|
||||
db.for_each_package_matching(
|
||||
spec,
|
||||
[&](const auto&)
|
||||
{
|
||||
|
@ -76,13 +76,14 @@ namespace mamba
|
|||
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
|
||||
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,
|
||||
[&](specs::PackageInfo&& pkg)
|
||||
{
|
||||
|
@ -98,7 +99,8 @@ namespace mamba
|
|||
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>
|
||||
{
|
||||
// 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.
|
||||
// Could also be written in term of PrefixData.
|
||||
std::string installed_py_ver = {};
|
||||
if (auto pkg = installed_python(pool))
|
||||
if (auto pkg = installed_python(db))
|
||||
{
|
||||
installed_py_ver = pkg->version;
|
||||
LOG_INFO << "Found python in installed packages " << installed_py_ver;
|
||||
|
@ -132,7 +134,7 @@ namespace mamba
|
|||
|
||||
MTransaction::MTransaction(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
std::vector<specs::PackageInfo> pkgs_to_remove,
|
||||
std::vector<specs::PackageInfo> pkgs_to_install,
|
||||
MultiPackageCache& caches
|
||||
|
@ -143,7 +145,7 @@ namespace mamba
|
|||
for (const auto& pkg : pkgs_to_remove)
|
||||
{
|
||||
auto spec = explicit_spec(pkg);
|
||||
if (!pool_has_package(pool, spec))
|
||||
if (!database_has_package(db, spec))
|
||||
{
|
||||
not_found << "\n - " << spec.str();
|
||||
}
|
||||
|
@ -203,14 +205,14 @@ namespace mamba
|
|||
ctx,
|
||||
ctx.prefix_params.target_prefix,
|
||||
ctx.prefix_params.relocate_prefix,
|
||||
find_python_version(m_solution, pool),
|
||||
find_python_version(m_solution, db),
|
||||
specs_to_install
|
||||
);
|
||||
}
|
||||
|
||||
MTransaction::MTransaction(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
const solver::Request& request,
|
||||
solver::Solution solution,
|
||||
MultiPackageCache& caches
|
||||
|
@ -257,7 +259,7 @@ namespace mamba
|
|||
ctx,
|
||||
ctx.prefix_params.target_prefix,
|
||||
ctx.prefix_params.relocate_prefix,
|
||||
find_python_version(m_solution, pool),
|
||||
find_python_version(m_solution, db),
|
||||
std::move(requested_specs)
|
||||
);
|
||||
|
||||
|
@ -273,7 +275,7 @@ namespace mamba
|
|||
|
||||
MTransaction::MTransaction(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
std::vector<specs::PackageInfo> packages,
|
||||
MultiPackageCache& caches
|
||||
)
|
||||
|
@ -307,7 +309,7 @@ namespace mamba
|
|||
ctx,
|
||||
ctx.prefix_params.target_prefix,
|
||||
ctx.prefix_params.relocate_prefix,
|
||||
find_python_version(m_solution, pool),
|
||||
find_python_version(m_solution, db),
|
||||
std::move(specs_to_install)
|
||||
);
|
||||
}
|
||||
|
@ -1112,7 +1114,7 @@ namespace mamba
|
|||
}
|
||||
|
||||
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 = {};
|
||||
specs_to_install.reserve(urls.size());
|
||||
|
@ -1122,12 +1124,12 @@ namespace mamba
|
|||
std::back_insert_iterator(specs_to_install),
|
||||
[&](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(
|
||||
const Context& ctx,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
const fs::u8path& env_lockfile_path,
|
||||
const std::vector<std::string>& categories,
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -6,9 +6,8 @@
|
|||
|
||||
#include <solv/solver.h>
|
||||
|
||||
#include "mamba/core/channel_context.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/util/variant_cmp.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& 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)
|
||||
{
|
||||
|
@ -96,7 +95,7 @@ namespace mamba::solver::libsolv
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "mamba/core/output.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/specs/match_spec.hpp"
|
||||
#include "mamba/specs/package_info.hpp"
|
||||
|
@ -41,9 +41,9 @@ namespace mamba::solver::libsolv
|
|||
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;
|
||||
solver().for_each_problem_id([&](solv::ProblemId pb)
|
||||
{ problems.emplace_back(solver().problem_to_string(pool, pb)); }
|
||||
|
@ -51,9 +51,9 @@ namespace mamba::solver::libsolv
|
|||
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;
|
||||
problems << "Encountered problems while solving:\n";
|
||||
solver().for_each_problem_id(
|
||||
|
@ -63,9 +63,9 @@ namespace mamba::solver::libsolv
|
|||
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;
|
||||
solver().for_each_problem_id(
|
||||
[&](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);
|
||||
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&
|
||||
{
|
||||
out << "Could not solve for environment specs\n";
|
||||
|
@ -491,7 +492,7 @@ namespace mamba::solver::libsolv
|
|||
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;
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
#include "mamba/core/channel_context.hpp"
|
||||
#include "mamba/core/env_lockfile.hpp"
|
||||
#include "mamba/core/fsutil.hpp"
|
||||
#include "mamba/core/package_database_loader.hpp"
|
||||
#include "mamba/core/transaction.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
|
||||
#include "mambatests.hpp"
|
||||
|
||||
|
@ -126,8 +128,8 @@ namespace mamba
|
|||
const fs::u8path lockfile_path{ mambatests::test_data_dir
|
||||
/ "env_lockfile/good_multiple_categories-lock.yaml" };
|
||||
auto channel_context = ChannelContext::make_conda_compatible(mambatests::context());
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
solver::libsolv::Database db{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(db);
|
||||
mamba::MultiPackageCache pkg_cache({ "/tmp/" }, ctx.validation_params);
|
||||
|
||||
ctx.platform = "linux-64";
|
||||
|
@ -138,7 +140,7 @@ namespace mamba
|
|||
std::vector<detail::other_pkg_mgr_spec> other_specs;
|
||||
auto transaction = create_explicit_transaction_from_lockfile(
|
||||
ctx,
|
||||
pool,
|
||||
db,
|
||||
lockfile_path,
|
||||
categories,
|
||||
pkg_cache,
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
#include <nlohmann/json.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/subdirdata.hpp"
|
||||
#include "mamba/core/util.hpp"
|
||||
#include "mamba/fs/filesystem.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||
#include "mamba/solver/libsolv/solver.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.
|
||||
*/
|
||||
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() };
|
||||
pool.add_repo_from_packages(packages);
|
||||
return pool;
|
||||
solver::libsolv::Database db{ channel_context.params() };
|
||||
db.add_repo_from_packages(packages);
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test create_pool utility")
|
||||
TEST_CASE("Test create_pkgs_database utility")
|
||||
{
|
||||
auto& ctx = mambatests::context();
|
||||
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 } } };
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -124,12 +125,12 @@ TEST_CASE("Test empty specs")
|
|||
{
|
||||
auto& ctx = mambatests::context();
|
||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||
auto pool = create_pkgs_pool(
|
||||
auto db = create_pkgs_database(
|
||||
channel_context,
|
||||
std::array{ mkpkg("foo", "0.1.0", {}), mkpkg("", "", {}) }
|
||||
);
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,7 @@ namespace
|
|||
auto create_basic_conflict(Context&, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_pkgs_pool(
|
||||
create_pkgs_database(
|
||||
channel_context,
|
||||
std::array{
|
||||
mkpkg("A", "0.1.0"),
|
||||
|
@ -159,7 +160,7 @@ namespace
|
|||
auto create_pubgrub(Context&, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_pkgs_pool(
|
||||
create_pkgs_database(
|
||||
channel_context,
|
||||
std::array{
|
||||
mkpkg("menu", "1.5.0", { "dropdown=2.*" }),
|
||||
|
@ -241,7 +242,7 @@ namespace
|
|||
packages.push_back(mkpkg("dropdown", "2.9.0", { "libicons>10.0" }));
|
||||
}
|
||||
return std::pair(
|
||||
create_pkgs_pool(channel_context, packages),
|
||||
create_pkgs_database(channel_context, packages),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -287,7 +288,7 @@ namespace
|
|||
auto load_channels(
|
||||
Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
solver::libsolv::Database& db,
|
||||
MultiPackageCache& cache,
|
||||
std::vector<std::string>&& channels
|
||||
)
|
||||
|
@ -317,14 +318,14 @@ namespace
|
|||
|
||||
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,
|
||||
ChannelContext& channel_context,
|
||||
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();
|
||||
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);
|
||||
create_cache_dir(cache.first_writable_path());
|
||||
|
@ -350,13 +351,13 @@ namespace
|
|||
load_channels(
|
||||
ctx,
|
||||
channel_context,
|
||||
pool,
|
||||
db,
|
||||
cache,
|
||||
make_platform_channels(std::move(channels), platforms)
|
||||
);
|
||||
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 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 } } };
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -375,7 +376,7 @@ namespace
|
|||
auto create_pytorch_cpu(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(ctx, channel_context),
|
||||
create_conda_forge_database(ctx, channel_context),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -389,7 +390,7 @@ namespace
|
|||
auto create_pytorch_cuda(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(
|
||||
create_conda_forge_database(
|
||||
ctx,
|
||||
channel_context,
|
||||
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "10.2.0") }
|
||||
|
@ -407,7 +408,7 @@ namespace
|
|||
auto create_cudatoolkit(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(
|
||||
create_conda_forge_database(
|
||||
ctx,
|
||||
channel_context,
|
||||
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "11.1") }
|
||||
|
@ -428,7 +429,7 @@ namespace
|
|||
auto create_jpeg9b(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(ctx, channel_context),
|
||||
create_conda_forge_database(ctx, channel_context),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -442,7 +443,7 @@ namespace
|
|||
auto create_r_base(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(ctx, channel_context),
|
||||
create_conda_forge_database(ctx, channel_context),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -459,7 +460,7 @@ namespace
|
|||
auto create_scip(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(ctx, channel_context),
|
||||
create_conda_forge_database(ctx, channel_context),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -473,7 +474,7 @@ namespace
|
|||
auto create_double_python(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(ctx, channel_context),
|
||||
create_conda_forge_database(ctx, channel_context),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -487,7 +488,7 @@ namespace
|
|||
auto create_numba(Context& ctx, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_conda_forge_pool(ctx, channel_context),
|
||||
create_conda_forge_database(ctx, channel_context),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -583,11 +584,11 @@ TEST_CASE("Create problem graph")
|
|||
// Somehow the capture does not work directly on ``name``
|
||||
std::string_view name_copy = name;
|
||||
CAPTURE(name_copy);
|
||||
auto [pool, request] = factory(ctx, channel_context);
|
||||
auto outcome = solver::libsolv::Solver().solve(pool, request).value();
|
||||
auto [db, request] = factory(ctx, channel_context);
|
||||
auto outcome = solver::libsolv::Solver().solve(db, request).value();
|
||||
// REQUIRE(std::holds_alternative<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();
|
||||
|
||||
REQUIRE_GE(graph_init.number_of_nodes(), 1);
|
||||
|
|
|
@ -23,14 +23,15 @@
|
|||
#include "mamba/core/download_progress_bar.hpp"
|
||||
#include "mamba/core/execution.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/package_database_loader.hpp"
|
||||
#include "mamba/core/package_handling.hpp"
|
||||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/core/prefix_data.hpp"
|
||||
#include "mamba/core/query.hpp"
|
||||
#include "mamba/core/subdirdata.hpp"
|
||||
#include "mamba/core/transaction.hpp"
|
||||
#include "mamba/core/util_os.hpp"
|
||||
#include "mamba/core/virtual_packages.hpp"
|
||||
#include "mamba/solver/libsolv/database.hpp"
|
||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||
#include "mamba/solver/problems_graph.hpp"
|
||||
#include "mamba/validation/tools.hpp"
|
||||
|
@ -379,12 +380,16 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
|
||||
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("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(
|
||||
"add_repo_from_repodata_json",
|
||||
&MPool::add_repo_from_repodata_json,
|
||||
&solver::libsolv::Database::add_repo_from_repodata_json,
|
||||
py::arg("path"),
|
||||
py::arg("url"),
|
||||
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No,
|
||||
|
@ -393,14 +398,14 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
)
|
||||
.def(
|
||||
"add_repo_from_native_serialization",
|
||||
&MPool::add_repo_from_native_serialization,
|
||||
&solver::libsolv::Database::add_repo_from_native_serialization,
|
||||
py::arg("path"),
|
||||
py::arg("expected"),
|
||||
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No
|
||||
)
|
||||
.def(
|
||||
"add_repo_from_packages",
|
||||
[](MPool& pool,
|
||||
[](solver::libsolv::Database& db,
|
||||
py::iterable packages,
|
||||
std::string_view name,
|
||||
solver::libsolv::PipAsPythonDependency add)
|
||||
|
@ -411,7 +416,7 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
{
|
||||
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("name") = "",
|
||||
|
@ -419,17 +424,22 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
)
|
||||
.def(
|
||||
"native_serialize_repo",
|
||||
&MPool::native_serialize_repo,
|
||||
&solver::libsolv::Database::native_serialize_repo,
|
||||
py::arg("repo"),
|
||||
py::arg("path"),
|
||||
py::arg("metadata")
|
||||
)
|
||||
.def("set_installed_repo", &MPool::set_installed_repo, py::arg("repo"))
|
||||
.def("set_repo_priority", &MPool::set_repo_priority, py::arg("repo"), py::arg("priorities"));
|
||||
.def("set_installed_repo", &solver::libsolv::Database::set_installed_repo, py::arg("repo"))
|
||||
.def(
|
||||
"set_repo_priority",
|
||||
&solver::libsolv::Database::set_repo_priority,
|
||||
py::arg("repo"),
|
||||
py::arg("priorities")
|
||||
);
|
||||
|
||||
m.def(
|
||||
"load_subdir_in_pool",
|
||||
&load_subdir_in_pool,
|
||||
&load_subdir_in_database,
|
||||
py::arg("context"),
|
||||
py::arg("pool"),
|
||||
py::arg("subdir")
|
||||
|
@ -437,7 +447,7 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
|
||||
m.def(
|
||||
"load_installed_packages_in_pool",
|
||||
&load_installed_packages_in_pool,
|
||||
&load_installed_packages_in_database,
|
||||
py::arg("context"),
|
||||
py::arg("pool"),
|
||||
py::arg("prefix_data")
|
||||
|
@ -457,7 +467,7 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
.def_property_readonly("first_writable_path", &MultiPackageCache::first_writable_path);
|
||||
|
||||
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("log_json", &MTransaction::log_json)
|
||||
|
@ -522,10 +532,10 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
py::class_<SubdirData>(m, "SubdirData")
|
||||
.def(
|
||||
"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");
|
||||
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)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <pybind11/pybind11.h>
|
||||
|
||||
#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/repo_info.hpp"
|
||||
#include "mamba/solver/libsolv/solver.hpp"
|
||||
|
@ -125,8 +125,8 @@ namespace mambapy
|
|||
.def(py::init())
|
||||
.def(
|
||||
"solve",
|
||||
[](Solver& self, MPool& pool, const solver::Request& request)
|
||||
{ return self.solve(pool, request); }
|
||||
[](Solver& self, Database& db, const solver::Request& request)
|
||||
{ return self.solve(db, request); }
|
||||
)
|
||||
.def("add_jobs", solver_job_v2_migrator)
|
||||
.def("add_global_job", solver_job_v2_migrator)
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
using namespace mamba;
|
||||
|
||||
MPool
|
||||
Database
|
||||
load_pool(
|
||||
const std::vector<std::string>& channels,
|
||||
MultiPackageCache& package_caches,
|
||||
|
@ -40,7 +40,7 @@ load_pool(
|
|||
)
|
||||
{
|
||||
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);
|
||||
if (!exp_load)
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ handle_solve_request(
|
|||
{
|
||||
struct cache
|
||||
{
|
||||
std::optional<mamba::MPool> pool;
|
||||
std::optional<mamba::Database> pool;
|
||||
std::chrono::time_point<std::chrono::system_clock> last_update;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mamba/api/update.hpp"
|
||||
#include "mamba/core/channel_context.hpp"
|
||||
#include "mamba/core/context.hpp"
|
||||
#include "mamba/core/package_database_loader.hpp"
|
||||
#include "mamba/core/transaction.hpp"
|
||||
#include "mamba/core/util_os.hpp"
|
||||
#include "mamba/util/build.hpp"
|
||||
|
@ -28,10 +29,10 @@ using namespace mamba; // NOLINT(build/namespaces)
|
|||
|
||||
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;
|
||||
pool.for_each_package_matching(
|
||||
database.for_each_package_matching(
|
||||
spec,
|
||||
[&](const auto&)
|
||||
{
|
||||
|
@ -42,10 +43,11 @@ namespace
|
|||
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>();
|
||||
pool.for_each_package_matching(
|
||||
db.for_each_package_matching(
|
||||
spec,
|
||||
[&](auto pkg)
|
||||
{
|
||||
|
@ -72,12 +74,12 @@ update_self(Configuration& config, const std::optional<std::string>& version)
|
|||
|
||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
solver::libsolv::Database db{ channel_context.params() };
|
||||
add_spdlog_logger_to_database(db);
|
||||
|
||||
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)
|
||||
{
|
||||
throw exp_loaded.error();
|
||||
|
@ -88,11 +90,11 @@ update_self(Configuration& config, const std::optional<std::string>& 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 (pool_has_package(pool, specs::MatchSpec::parse("micromamba")))
|
||||
if (database_has_package(db, specs::MatchSpec::parse("micromamba")))
|
||||
{
|
||||
Console::instance().print(
|
||||
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;
|
||||
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);
|
||||
if (!exp_prefix_data)
|
||||
{
|
||||
|
|
|
@ -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):
|
||||
pin_name = "xtensor"
|
||||
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"
|
||||
rc_file = tmp_path / "rc.yaml"
|
||||
|
||||
|
|
Loading…
Reference in New Issue