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/solvable.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.cpp
|
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/solv-cpp/transaction.cpp
|
${LIBMAMBA_SOURCE_DIR}/solv-cpp/transaction.cpp
|
||||||
# Solver interface
|
# Solver generic interface
|
||||||
${LIBMAMBA_SOURCE_DIR}/solver/helpers.cpp
|
${LIBMAMBA_SOURCE_DIR}/solver/helpers.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/solver/problems_graph.cpp
|
${LIBMAMBA_SOURCE_DIR}/solver/problems_graph.cpp
|
||||||
|
# Solver libsolv implementation
|
||||||
|
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/database.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/helpers.cpp
|
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/helpers.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/parameters.cpp
|
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/parameters.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/repo_info.cpp
|
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/repo_info.cpp
|
||||||
|
@ -212,6 +214,7 @@ set(
|
||||||
# Core API (low-level)
|
# Core API (low-level)
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/singletons.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/singletons.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/activation.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/activation.cpp
|
||||||
|
${LIBMAMBA_SOURCE_DIR}/core/package_database_loader.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/channel_context.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/channel_context.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/context.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/context.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/download_progress_bar.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/download_progress_bar.cpp
|
||||||
|
@ -224,7 +227,6 @@ set(
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/output.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/output.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/package_handling.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/package_handling.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/package_cache.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/package_cache.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/pool.cpp
|
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/prefix_data.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/prefix_data.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/progress_bar.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/progress_bar.cpp
|
||||||
${LIBMAMBA_SOURCE_DIR}/core/progress_bar_impl.cpp
|
${LIBMAMBA_SOURCE_DIR}/core/progress_bar_impl.cpp
|
||||||
|
@ -313,10 +315,12 @@ set(
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/unresolved_channel.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/unresolved_channel.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version_spec.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/version_spec.hpp
|
||||||
# Solver Interface
|
# Solver generic interface
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/problems_graph.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/problems_graph.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/request.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/request.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/solution.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/solution.hpp
|
||||||
|
# Solver libsolv implementation
|
||||||
|
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/database.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/parameters.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/parameters.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/repo_info.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/repo_info.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/solver.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/solver.hpp
|
||||||
|
@ -341,6 +345,7 @@ set(
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/context.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/context.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/download_progress_bar.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/download_progress_bar.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/environments_manager.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/environments_manager.hpp
|
||||||
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_database_loader.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/error_handling.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/error_handling.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/history.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/history.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/link.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/link.hpp
|
||||||
|
@ -351,7 +356,6 @@ set(
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_fetcher.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_fetcher.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_handling.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_handling.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_paths.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/package_paths.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/pool.hpp
|
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/prefix_data.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/prefix_data.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/progress_bar.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/progress_bar.hpp
|
||||||
${LIBMAMBA_INCLUDE_DIR}/mamba/core/pinning.hpp
|
${LIBMAMBA_INCLUDE_DIR}/mamba/core/pinning.hpp
|
||||||
|
|
|
@ -11,15 +11,18 @@
|
||||||
|
|
||||||
namespace mamba
|
namespace mamba
|
||||||
{
|
{
|
||||||
|
namespace solver::libsolv
|
||||||
|
{
|
||||||
|
class Database;
|
||||||
|
}
|
||||||
class Context;
|
class Context;
|
||||||
class ChannelContext;
|
class ChannelContext;
|
||||||
class MPool;
|
|
||||||
class MultiPackageCache;
|
class MultiPackageCache;
|
||||||
|
|
||||||
auto load_channels( //
|
auto load_channels( //
|
||||||
Context& ctx,
|
Context& ctx,
|
||||||
ChannelContext& channel_context,
|
ChannelContext& channel_context,
|
||||||
MPool& pool,
|
solver::libsolv::Database& pool,
|
||||||
MultiPackageCache& package_caches
|
MultiPackageCache& package_caches
|
||||||
) -> expected_t<void, mamba_aggregated_error>;
|
) -> expected_t<void, mamba_aggregated_error>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,23 +7,33 @@
|
||||||
#ifndef MAMBA_API_INSTALL_HPP
|
#ifndef MAMBA_API_INSTALL_HPP
|
||||||
#define MAMBA_API_INSTALL_HPP
|
#define MAMBA_API_INSTALL_HPP
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
#include "mamba/core/package_cache.hpp"
|
|
||||||
#include "mamba/core/pool.hpp"
|
|
||||||
#include "mamba/fs/filesystem.hpp"
|
#include "mamba/fs/filesystem.hpp"
|
||||||
#include "mamba/solver/request.hpp"
|
#include "mamba/solver/request.hpp"
|
||||||
#include "mamba/specs/package_info.hpp"
|
|
||||||
|
|
||||||
namespace mamba
|
namespace mamba
|
||||||
{
|
{
|
||||||
class Context;
|
class Context;
|
||||||
class ChannelContext;
|
class ChannelContext;
|
||||||
class Configuration;
|
class Configuration;
|
||||||
|
class PrefixData;
|
||||||
|
class MultiPackageCache;
|
||||||
|
|
||||||
|
namespace specs
|
||||||
|
{
|
||||||
|
class PackageInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace solver::libsolv
|
||||||
|
{
|
||||||
|
class DataBase;
|
||||||
|
}
|
||||||
|
|
||||||
void install(Configuration& config);
|
void install(Configuration& config);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,11 @@
|
||||||
|
|
||||||
namespace mamba
|
namespace mamba
|
||||||
{
|
{
|
||||||
|
namespace solver::libsolv
|
||||||
|
{
|
||||||
|
class DataBase;
|
||||||
|
}
|
||||||
|
|
||||||
enum class QueryResultFormat
|
enum class QueryResultFormat
|
||||||
{
|
{
|
||||||
Json = 0,
|
Json = 0,
|
||||||
|
@ -23,7 +28,7 @@ namespace mamba
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] auto make_repoquery(
|
[[nodiscard]] auto make_repoquery(
|
||||||
MPool& pool,
|
solver::libsolv::Database& pool,
|
||||||
QueryType type,
|
QueryType type,
|
||||||
QueryResultFormat format,
|
QueryResultFormat format,
|
||||||
const std::vector<std::string>& queries,
|
const std::vector<std::string>& queries,
|
||||||
|
|
|
@ -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 <vector>
|
||||||
|
|
||||||
#include "mamba/core/context.hpp"
|
#include "mamba/core/context.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
|
||||||
#include "mamba/specs/package_info.hpp"
|
#include "mamba/specs/package_info.hpp"
|
||||||
#include "mamba/util/graph.hpp"
|
#include "mamba/util/graph.hpp"
|
||||||
|
|
||||||
namespace mamba
|
namespace mamba
|
||||||
{
|
{
|
||||||
|
namespace solver::libsolv
|
||||||
|
{
|
||||||
|
class Database;
|
||||||
|
}
|
||||||
|
|
||||||
enum class QueryType
|
enum class QueryType
|
||||||
{
|
{
|
||||||
Search,
|
Search,
|
||||||
|
@ -88,12 +92,14 @@ namespace mamba
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
[[nodiscard]] static auto find(MPool& pool, const std::vector<std::string>& queries)
|
using Database = solver::libsolv::Database;
|
||||||
|
|
||||||
|
[[nodiscard]] static auto find(Database& db, const std::vector<std::string>& queries)
|
||||||
-> QueryResult;
|
-> QueryResult;
|
||||||
|
|
||||||
[[nodiscard]] static auto whoneeds(MPool& pool, std::string query, bool tree) -> QueryResult;
|
[[nodiscard]] static auto whoneeds(Database& db, std::string query, bool tree) -> QueryResult;
|
||||||
|
|
||||||
[[nodiscard]] static auto depends(MPool& pool, std::string query, bool tree) -> QueryResult;
|
[[nodiscard]] static auto depends(Database& db, std::string query, bool tree) -> QueryResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
/********************
|
/********************
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace mamba
|
||||||
{
|
{
|
||||||
class Channel;
|
class Channel;
|
||||||
}
|
}
|
||||||
class MPool;
|
|
||||||
class Context;
|
class Context;
|
||||||
class ChannelContext;
|
class ChannelContext;
|
||||||
class DownloadMonitor;
|
class DownloadMonitor;
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
|
|
||||||
#include "mamba/api/install.hpp"
|
#include "mamba/api/install.hpp"
|
||||||
#include "mamba/core/package_cache.hpp"
|
#include "mamba/core/package_cache.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
|
||||||
#include "mamba/core/prefix_data.hpp"
|
#include "mamba/core/prefix_data.hpp"
|
||||||
#include "mamba/core/transaction_context.hpp"
|
#include "mamba/core/transaction_context.hpp"
|
||||||
#include "mamba/fs/filesystem.hpp"
|
#include "mamba/fs/filesystem.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/solution.hpp"
|
#include "mamba/solver/solution.hpp"
|
||||||
#include "mamba/specs/match_spec.hpp"
|
#include "mamba/specs/match_spec.hpp"
|
||||||
#include "mamba/specs/package_info.hpp"
|
#include "mamba/specs/package_info.hpp"
|
||||||
|
@ -37,7 +37,7 @@ namespace mamba
|
||||||
|
|
||||||
MTransaction(
|
MTransaction(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
std::vector<specs::PackageInfo> pkgs_to_remove,
|
std::vector<specs::PackageInfo> pkgs_to_remove,
|
||||||
std::vector<specs::PackageInfo> pkgs_to_install,
|
std::vector<specs::PackageInfo> pkgs_to_install,
|
||||||
MultiPackageCache& caches
|
MultiPackageCache& caches
|
||||||
|
@ -45,7 +45,7 @@ namespace mamba
|
||||||
|
|
||||||
MTransaction(
|
MTransaction(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
const solver::Request& request,
|
const solver::Request& request,
|
||||||
solver::Solution solution,
|
solver::Solution solution,
|
||||||
MultiPackageCache& caches
|
MultiPackageCache& caches
|
||||||
|
@ -54,7 +54,7 @@ namespace mamba
|
||||||
// Only use if the packages have been solved previously already.
|
// Only use if the packages have been solved previously already.
|
||||||
MTransaction(
|
MTransaction(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
std::vector<specs::PackageInfo> packages,
|
std::vector<specs::PackageInfo> packages,
|
||||||
MultiPackageCache& caches
|
MultiPackageCache& caches
|
||||||
);
|
);
|
||||||
|
@ -93,7 +93,7 @@ namespace mamba
|
||||||
|
|
||||||
MTransaction create_explicit_transaction_from_urls(
|
MTransaction create_explicit_transaction_from_urls(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
const std::vector<std::string>& urls,
|
const std::vector<std::string>& urls,
|
||||||
MultiPackageCache& package_caches,
|
MultiPackageCache& package_caches,
|
||||||
std::vector<detail::other_pkg_mgr_spec>& other_specs
|
std::vector<detail::other_pkg_mgr_spec>& other_specs
|
||||||
|
@ -101,7 +101,7 @@ namespace mamba
|
||||||
|
|
||||||
MTransaction create_explicit_transaction_from_lockfile(
|
MTransaction create_explicit_transaction_from_lockfile(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
const fs::u8path& env_lockfile_path,
|
const fs::u8path& env_lockfile_path,
|
||||||
const std::vector<std::string>& categories,
|
const std::vector<std::string>& categories,
|
||||||
MultiPackageCache& package_caches,
|
MultiPackageCache& package_caches,
|
||||||
|
|
|
@ -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;
|
using Repo = struct s_Repo;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mamba
|
|
||||||
{
|
|
||||||
class MPool;
|
|
||||||
class MTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mamba::solver::libsolv
|
namespace mamba::solver::libsolv
|
||||||
{
|
{
|
||||||
|
class Database;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A libsolv repository descriptor.
|
* A libsolv repository descriptor.
|
||||||
*
|
*
|
||||||
* In libsolv, most of the data is help in the Pool, and repo are tightly coupled with them.
|
* In libsolv, most of the data is help in the @ref Database, and repo are tightly coupled
|
||||||
|
* with them.
|
||||||
* This repository class is a lightwight description of a repository returned when creating
|
* This repository class is a lightwight description of a repository returned when creating
|
||||||
* a new repository in the Pool.
|
* a new repository in the @ref Database.
|
||||||
* Some modifications to the repo are possible throught the Pool.
|
* Some modifications to the repo are possible throught the @ref Database.
|
||||||
* @see MPool::add_repo_from_repodata_json
|
* @see Database::add_repo_from_repodata_json
|
||||||
* @see MPool::add_repo_from_packages
|
* @see Database::add_repo_from_packages
|
||||||
* @see MPool::remove_repo
|
* @see Database::remove_repo
|
||||||
*/
|
*/
|
||||||
class RepoInfo
|
class RepoInfo
|
||||||
{
|
{
|
||||||
|
@ -61,8 +58,7 @@ namespace mamba::solver::libsolv
|
||||||
|
|
||||||
explicit RepoInfo(::Repo* repo);
|
explicit RepoInfo(::Repo* repo);
|
||||||
|
|
||||||
friend class ::mamba::MPool;
|
friend class Database;
|
||||||
friend class ::mamba::MTransaction; // As long as MTransaction leaks libsolv impl
|
|
||||||
friend auto operator==(RepoInfo lhs, RepoInfo rhs) -> bool;
|
friend auto operator==(RepoInfo lhs, RepoInfo rhs) -> bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,20 @@
|
||||||
|
|
||||||
namespace mamba::solver::libsolv
|
namespace mamba::solver::libsolv
|
||||||
{
|
{
|
||||||
|
class Database;
|
||||||
|
|
||||||
class Solver
|
class Solver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using Outcome = std::variant<Solution, UnSolvable>;
|
using Outcome = std::variant<Solution, UnSolvable>;
|
||||||
|
|
||||||
[[nodiscard]] auto solve(MPool& pool, Request&& request) -> expected_t<Outcome>;
|
[[nodiscard]] auto solve(Database& pool, Request&& request) -> expected_t<Outcome>;
|
||||||
[[nodiscard]] auto solve(MPool& pool, const Request& request) -> expected_t<Outcome>;
|
[[nodiscard]] auto solve(Database& pool, const Request& request) -> expected_t<Outcome>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
auto solve_impl(MPool& pool, const Request& request) -> expected_t<Outcome>;
|
auto solve_impl(Database& pool, const Request& request) -> expected_t<Outcome>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
namespace mamba
|
namespace mamba
|
||||||
{
|
{
|
||||||
class MPool;
|
|
||||||
class Palette;
|
class Palette;
|
||||||
|
|
||||||
namespace solv
|
namespace solv
|
||||||
|
@ -28,6 +27,7 @@ namespace mamba
|
||||||
namespace mamba::solver::libsolv
|
namespace mamba::solver::libsolv
|
||||||
{
|
{
|
||||||
class Solver;
|
class Solver;
|
||||||
|
class Database;
|
||||||
|
|
||||||
class UnSolvable
|
class UnSolvable
|
||||||
{
|
{
|
||||||
|
@ -39,21 +39,22 @@ namespace mamba::solver::libsolv
|
||||||
|
|
||||||
auto operator=(UnSolvable&&) -> UnSolvable&;
|
auto operator=(UnSolvable&&) -> UnSolvable&;
|
||||||
|
|
||||||
[[nodiscard]] auto problems(MPool& pool) const -> std::vector<std::string>;
|
[[nodiscard]] auto problems(Database& pool) const -> std::vector<std::string>;
|
||||||
|
|
||||||
[[nodiscard]] auto problems_to_str(MPool& pool) const -> std::string;
|
[[nodiscard]] auto problems_to_str(Database& pool) const -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] auto all_problems_to_str(MPool& pool) const -> std::string;
|
[[nodiscard]] auto all_problems_to_str(Database& pool) const -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] auto problems_graph(const MPool& pool) const -> ProblemsGraph;
|
[[nodiscard]] auto problems_graph(const Database& pool) const -> ProblemsGraph;
|
||||||
|
|
||||||
auto explain_problems_to( //
|
auto explain_problems_to( //
|
||||||
MPool& pool,
|
Database& pool,
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
const Palette& palette
|
const Palette& palette
|
||||||
) const -> std::ostream&;
|
) const -> std::ostream&;
|
||||||
|
|
||||||
[[nodiscard]] auto explain_problems(MPool& pool, const Palette& palette) const -> std::string;
|
[[nodiscard]] auto explain_problems(Database& pool, const Palette& palette) const
|
||||||
|
-> std::string;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,12 @@
|
||||||
#include "mamba/util/flat_set.hpp"
|
#include "mamba/util/flat_set.hpp"
|
||||||
#include "mamba/util/graph.hpp"
|
#include "mamba/util/graph.hpp"
|
||||||
|
|
||||||
namespace mamba
|
|
||||||
{
|
|
||||||
class MPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mamba::solver
|
namespace mamba::solver
|
||||||
{
|
{
|
||||||
|
namespace libsolv
|
||||||
|
{
|
||||||
|
class Database;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class conflict_map : private std::unordered_map<T, util::flat_set<T>>
|
class conflict_map : private std::unordered_map<T, util::flat_set<T>>
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
#include "mamba/core/channel_context.hpp"
|
#include "mamba/core/channel_context.hpp"
|
||||||
#include "mamba/core/download_progress_bar.hpp"
|
#include "mamba/core/download_progress_bar.hpp"
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/prefix_data.hpp"
|
#include "mamba/core/prefix_data.hpp"
|
||||||
#include "mamba/core/subdirdata.hpp"
|
#include "mamba/core/subdirdata.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||||
#include "mamba/specs/package_info.hpp"
|
#include "mamba/specs/package_info.hpp"
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ namespace mamba
|
||||||
auto create_repo_from_pkgs_dir(
|
auto create_repo_from_pkgs_dir(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
ChannelContext& channel_context,
|
ChannelContext& channel_context,
|
||||||
MPool& pool,
|
solver::libsolv::Database& pool,
|
||||||
const fs::u8path& pkgs_dir
|
const fs::u8path& pkgs_dir
|
||||||
) -> solver::libsolv::RepoInfo
|
) -> solver::libsolv::RepoInfo
|
||||||
{
|
{
|
||||||
|
@ -45,7 +46,7 @@ namespace mamba
|
||||||
}
|
}
|
||||||
prefix_data.load_single_record(repodata_record_json);
|
prefix_data.load_single_record(repodata_record_json);
|
||||||
}
|
}
|
||||||
return load_installed_packages_in_pool(ctx, pool, prefix_data);
|
return load_installed_packages_in_database(ctx, pool, prefix_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_subdirs(
|
void create_subdirs(
|
||||||
|
@ -112,7 +113,7 @@ namespace mamba
|
||||||
auto load_channels_impl(
|
auto load_channels_impl(
|
||||||
Context& ctx,
|
Context& ctx,
|
||||||
ChannelContext& channel_context,
|
ChannelContext& channel_context,
|
||||||
MPool& pool,
|
solver::libsolv::Database& pool,
|
||||||
MultiPackageCache& package_caches,
|
MultiPackageCache& package_caches,
|
||||||
bool is_retry
|
bool is_retry
|
||||||
) -> expected_t<void, mamba_aggregated_error>
|
) -> expected_t<void, mamba_aggregated_error>
|
||||||
|
@ -231,7 +232,7 @@ namespace mamba
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
load_subdir_in_pool(ctx, pool, subdir)
|
load_subdir_in_database(ctx, pool, subdir)
|
||||||
.transform([&](solver::libsolv::RepoInfo&& repo)
|
.transform([&](solver::libsolv::RepoInfo&& repo)
|
||||||
{ pool.set_repo_priority(repo, priorities[i]); })
|
{ pool.set_repo_priority(repo, priorities[i]); })
|
||||||
.or_else(
|
.or_else(
|
||||||
|
@ -276,9 +277,12 @@ namespace mamba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto
|
auto load_channels(
|
||||||
load_channels(Context& ctx, ChannelContext& channel_context, MPool& pool, MultiPackageCache& package_caches)
|
Context& ctx,
|
||||||
-> expected_t<void, mamba_aggregated_error>
|
ChannelContext& channel_context,
|
||||||
|
solver::libsolv::Database& pool,
|
||||||
|
MultiPackageCache& package_caches
|
||||||
|
) -> expected_t<void, mamba_aggregated_error>
|
||||||
{
|
{
|
||||||
return load_channels_impl(ctx, channel_context, pool, package_caches, false);
|
return load_channels_impl(ctx, channel_context, pool, package_caches, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "mamba/core/environments_manager.hpp"
|
#include "mamba/core/environments_manager.hpp"
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
#include "mamba/core/package_cache.hpp"
|
#include "mamba/core/package_cache.hpp"
|
||||||
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/pinning.hpp"
|
#include "mamba/core/pinning.hpp"
|
||||||
#include "mamba/core/transaction.hpp"
|
#include "mamba/core/transaction.hpp"
|
||||||
#include "mamba/core/virtual_packages.hpp"
|
#include "mamba/core/virtual_packages.hpp"
|
||||||
|
@ -530,8 +531,8 @@ namespace mamba
|
||||||
LOG_WARNING << "No 'channels' specified";
|
LOG_WARNING << "No 'channels' specified";
|
||||||
}
|
}
|
||||||
|
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database pool{ channel_context.params() };
|
||||||
add_spdlog_logger_to_pool(pool);
|
add_spdlog_logger_to_database(pool);
|
||||||
// functions implied in 'and_then' coding-styles must return the same type
|
// functions implied in 'and_then' coding-styles must return the same type
|
||||||
// which limits this syntax
|
// which limits this syntax
|
||||||
/*auto exp_prefix_data = load_channels(pool, package_caches)
|
/*auto exp_prefix_data = load_channels(pool, package_caches)
|
||||||
|
@ -552,7 +553,7 @@ namespace mamba
|
||||||
}
|
}
|
||||||
PrefixData& prefix_data = exp_prefix_data.value();
|
PrefixData& prefix_data = exp_prefix_data.value();
|
||||||
|
|
||||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
load_installed_packages_in_database(ctx, pool, prefix_data);
|
||||||
|
|
||||||
|
|
||||||
auto request = create_install_request(prefix_data, specs, freeze_installed);
|
auto request = create_install_request(prefix_data, specs, freeze_installed);
|
||||||
|
@ -674,7 +675,7 @@ namespace mamba
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// TransactionFunc: (MPool& pool, MultiPackageCache& package_caches) -> MTransaction
|
// TransactionFunc: (Database& pool, MultiPackageCache& package_caches) -> MTransaction
|
||||||
template <typename TransactionFunc>
|
template <typename TransactionFunc>
|
||||||
void install_explicit_with_transaction(
|
void install_explicit_with_transaction(
|
||||||
Context& ctx,
|
Context& ctx,
|
||||||
|
@ -684,8 +685,8 @@ namespace mamba
|
||||||
bool remove_prefix_on_failure
|
bool remove_prefix_on_failure
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database db{ channel_context.params() };
|
||||||
add_spdlog_logger_to_pool(pool);
|
add_spdlog_logger_to_database(db);
|
||||||
|
|
||||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||||
if (!exp_prefix_data)
|
if (!exp_prefix_data)
|
||||||
|
@ -697,12 +698,12 @@ namespace mamba
|
||||||
|
|
||||||
MultiPackageCache pkg_caches(ctx.pkgs_dirs, ctx.validation_params);
|
MultiPackageCache pkg_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||||
|
|
||||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
load_installed_packages_in_database(ctx, db, prefix_data);
|
||||||
|
|
||||||
std::vector<detail::other_pkg_mgr_spec> others;
|
std::vector<detail::other_pkg_mgr_spec> others;
|
||||||
// Note that the Transaction will gather the Solvables,
|
// Note that the Transaction will gather the Solvables,
|
||||||
// so they must have been ready in the pool before this line
|
// so they must have been ready in the pool before this line
|
||||||
auto transaction = create_transaction(pool, pkg_caches, others);
|
auto transaction = create_transaction(db, pkg_caches, others);
|
||||||
|
|
||||||
std::vector<LockFile> lock_pkgs;
|
std::vector<LockFile> lock_pkgs;
|
||||||
|
|
||||||
|
@ -754,8 +755,8 @@ namespace mamba
|
||||||
install_explicit_with_transaction(
|
install_explicit_with_transaction(
|
||||||
ctx,
|
ctx,
|
||||||
channel_context,
|
channel_context,
|
||||||
[&](auto& pool, auto& pkg_caches, auto& others)
|
[&](auto& db, auto& pkg_caches, auto& others)
|
||||||
{ return create_explicit_transaction_from_urls(ctx, pool, specs, pkg_caches, others); },
|
{ return create_explicit_transaction_from_urls(ctx, db, specs, pkg_caches, others); },
|
||||||
create_env,
|
create_env,
|
||||||
remove_prefix_on_failure
|
remove_prefix_on_failure
|
||||||
);
|
);
|
||||||
|
@ -802,11 +803,11 @@ namespace mamba
|
||||||
install_explicit_with_transaction(
|
install_explicit_with_transaction(
|
||||||
ctx,
|
ctx,
|
||||||
channel_context,
|
channel_context,
|
||||||
[&](auto& pool, auto& pkg_caches, auto& others)
|
[&](auto& db, auto& pkg_caches, auto& others)
|
||||||
{
|
{
|
||||||
return create_explicit_transaction_from_lockfile(
|
return create_explicit_transaction_from_lockfile(
|
||||||
ctx,
|
ctx,
|
||||||
pool,
|
db,
|
||||||
file,
|
file,
|
||||||
categories,
|
categories,
|
||||||
pkg_caches,
|
pkg_caches,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "mamba/core/channel_context.hpp"
|
#include "mamba/core/channel_context.hpp"
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
#include "mamba/core/package_cache.hpp"
|
#include "mamba/core/package_cache.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/prefix_data.hpp"
|
#include "mamba/core/prefix_data.hpp"
|
||||||
#include "mamba/core/transaction.hpp"
|
#include "mamba/core/transaction.hpp"
|
||||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||||
|
@ -127,9 +127,9 @@ namespace mamba
|
||||||
}
|
}
|
||||||
PrefixData& prefix_data = exp_prefix_data.value();
|
PrefixData& prefix_data = exp_prefix_data.value();
|
||||||
|
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database pool{ channel_context.params() };
|
||||||
add_spdlog_logger_to_pool(pool);
|
add_spdlog_logger_to_database(pool);
|
||||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
load_installed_packages_in_database(ctx, pool, prefix_data);
|
||||||
|
|
||||||
const fs::u8path pkgs_dirs(ctx.prefix_params.root_prefix / "pkgs");
|
const fs::u8path pkgs_dirs(ctx.prefix_params.root_prefix / "pkgs");
|
||||||
MultiPackageCache package_caches({ pkgs_dirs }, ctx.validation_params);
|
MultiPackageCache package_caches({ pkgs_dirs }, ctx.validation_params);
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
#include "mamba/api/repoquery.hpp"
|
#include "mamba/api/repoquery.hpp"
|
||||||
#include "mamba/core/channel_context.hpp"
|
#include "mamba/core/channel_context.hpp"
|
||||||
#include "mamba/core/package_cache.hpp"
|
#include "mamba/core/package_cache.hpp"
|
||||||
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/prefix_data.hpp"
|
#include "mamba/core/prefix_data.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||||
#include "mamba/util/string.hpp"
|
#include "mamba/util/string.hpp"
|
||||||
|
|
||||||
|
@ -28,8 +30,8 @@ namespace mamba
|
||||||
config.load();
|
config.load();
|
||||||
|
|
||||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database db{ channel_context.params() };
|
||||||
add_spdlog_logger_to_pool(pool);
|
add_spdlog_logger_to_database(db);
|
||||||
|
|
||||||
// bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds);
|
// bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds);
|
||||||
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||||
|
@ -50,7 +52,7 @@ namespace mamba
|
||||||
}
|
}
|
||||||
PrefixData& prefix_data = exp_prefix_data.value();
|
PrefixData& prefix_data = exp_prefix_data.value();
|
||||||
|
|
||||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
load_installed_packages_in_database(ctx, db, prefix_data);
|
||||||
|
|
||||||
if (format != QueryResultFormat::Json)
|
if (format != QueryResultFormat::Json)
|
||||||
{
|
{
|
||||||
|
@ -65,18 +67,18 @@ namespace mamba
|
||||||
{
|
{
|
||||||
Console::stream() << "Getting repodata from channels..." << std::endl;
|
Console::stream() << "Getting repodata from channels..." << std::endl;
|
||||||
}
|
}
|
||||||
auto exp_load = load_channels(ctx, channel_context, pool, package_caches);
|
auto exp_load = load_channels(ctx, channel_context, db, package_caches);
|
||||||
if (!exp_load)
|
if (!exp_load)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(exp_load.error().what());
|
throw std::runtime_error(exp_load.error().what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pool;
|
return db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto make_repoquery(
|
auto make_repoquery(
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
QueryType type,
|
QueryType type,
|
||||||
QueryResultFormat format,
|
QueryResultFormat format,
|
||||||
const std::vector<std::string>& queries,
|
const std::vector<std::string>& queries,
|
||||||
|
@ -87,7 +89,7 @@ namespace mamba
|
||||||
{
|
{
|
||||||
if (type == QueryType::Search)
|
if (type == QueryType::Search)
|
||||||
{
|
{
|
||||||
auto res = Query::find(pool, queries);
|
auto res = Query::find(db, queries);
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case QueryResultFormat::Json:
|
case QueryResultFormat::Json:
|
||||||
|
@ -108,7 +110,7 @@ namespace mamba
|
||||||
throw std::invalid_argument("Only one query supported for 'depends'.");
|
throw std::invalid_argument("Only one query supported for 'depends'.");
|
||||||
}
|
}
|
||||||
auto res = Query::depends(
|
auto res = Query::depends(
|
||||||
pool,
|
db,
|
||||||
queries.front(),
|
queries.front(),
|
||||||
/* tree= */ format == QueryResultFormat::Tree
|
/* tree= */ format == QueryResultFormat::Tree
|
||||||
|| format == QueryResultFormat::RecursiveTable
|
|| format == QueryResultFormat::RecursiveTable
|
||||||
|
@ -135,7 +137,7 @@ namespace mamba
|
||||||
throw std::invalid_argument("Only one query supported for 'whoneeds'.");
|
throw std::invalid_argument("Only one query supported for 'whoneeds'.");
|
||||||
}
|
}
|
||||||
auto res = Query::whoneeds(
|
auto res = Query::whoneeds(
|
||||||
pool,
|
db,
|
||||||
queries.front(),
|
queries.front(),
|
||||||
/* tree= */ format == QueryResultFormat::Tree
|
/* tree= */ format == QueryResultFormat::Tree
|
||||||
|| format == QueryResultFormat::RecursiveTable
|
|| format == QueryResultFormat::RecursiveTable
|
||||||
|
@ -177,9 +179,9 @@ namespace mamba
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto& ctx = config.context();
|
auto& ctx = config.context();
|
||||||
auto pool = repoquery_init(ctx, config, format, use_local);
|
auto db = repoquery_init(ctx, config, format, use_local);
|
||||||
return make_repoquery(
|
return make_repoquery(
|
||||||
pool,
|
db,
|
||||||
type,
|
type,
|
||||||
format,
|
format,
|
||||||
queries,
|
queries,
|
||||||
|
|
|
@ -10,9 +10,11 @@
|
||||||
#include "mamba/api/update.hpp"
|
#include "mamba/api/update.hpp"
|
||||||
#include "mamba/core/channel_context.hpp"
|
#include "mamba/core/channel_context.hpp"
|
||||||
#include "mamba/core/context.hpp"
|
#include "mamba/core/context.hpp"
|
||||||
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/pinning.hpp"
|
#include "mamba/core/pinning.hpp"
|
||||||
#include "mamba/core/transaction.hpp"
|
#include "mamba/core/transaction.hpp"
|
||||||
#include "mamba/core/virtual_packages.hpp"
|
#include "mamba/core/virtual_packages.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/solver.hpp"
|
#include "mamba/solver/libsolv/solver.hpp"
|
||||||
#include "mamba/solver/request.hpp"
|
#include "mamba/solver/request.hpp"
|
||||||
|
|
||||||
|
@ -106,12 +108,12 @@ namespace mamba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database db{ channel_context.params() };
|
||||||
add_spdlog_logger_to_pool(pool);
|
add_spdlog_logger_to_database(db);
|
||||||
|
|
||||||
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||||
|
|
||||||
auto exp_loaded = load_channels(ctx, channel_context, pool, package_caches);
|
auto exp_loaded = load_channels(ctx, channel_context, db, package_caches);
|
||||||
if (!exp_loaded)
|
if (!exp_loaded)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(exp_loaded.error().what());
|
throw std::runtime_error(exp_loaded.error().what());
|
||||||
|
@ -131,7 +133,7 @@ namespace mamba
|
||||||
prefix_pkgs.push_back(it.first);
|
prefix_pkgs.push_back(it.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
load_installed_packages_in_database(ctx, db, prefix_data);
|
||||||
|
|
||||||
auto request = create_update_request(
|
auto request = create_update_request(
|
||||||
prefix_data,
|
prefix_data,
|
||||||
|
@ -157,13 +159,13 @@ namespace mamba
|
||||||
// Console stream prints on destrucion
|
// Console stream prints on destrucion
|
||||||
}
|
}
|
||||||
|
|
||||||
auto outcome = solver::libsolv::Solver().solve(pool, request).value();
|
auto outcome = solver::libsolv::Solver().solve(db, request).value();
|
||||||
if (auto* unsolvable = std::get_if<solver::libsolv::UnSolvable>(&outcome))
|
if (auto* unsolvable = std::get_if<solver::libsolv::UnSolvable>(&outcome))
|
||||||
{
|
{
|
||||||
if (ctx.output_params.json)
|
if (ctx.output_params.json)
|
||||||
{
|
{
|
||||||
Console::instance().json_write({ { "success", false },
|
Console::instance().json_write({ { "success", false },
|
||||||
{ "solver_problems", unsolvable->problems(pool) } });
|
{ "solver_problems", unsolvable->problems(db) } });
|
||||||
}
|
}
|
||||||
throw mamba_error(
|
throw mamba_error(
|
||||||
"Could not solve for environment specs",
|
"Could not solve for environment specs",
|
||||||
|
@ -174,7 +176,7 @@ namespace mamba
|
||||||
Console::instance().json_write({ { "success", true } });
|
Console::instance().json_write({ { "success", true } });
|
||||||
auto transaction = MTransaction(
|
auto transaction = MTransaction(
|
||||||
ctx,
|
ctx,
|
||||||
pool,
|
db,
|
||||||
request,
|
request,
|
||||||
std::get<solver::Solution>(outcome),
|
std::get<solver::Solution>(outcome),
|
||||||
package_caches
|
package_caches
|
||||||
|
|
|
@ -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/context.hpp"
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
#include "mamba/core/query.hpp"
|
#include "mamba/core/query.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/specs/conda_url.hpp"
|
#include "mamba/specs/conda_url.hpp"
|
||||||
#include "mamba/specs/package_info.hpp"
|
#include "mamba/specs/package_info.hpp"
|
||||||
#include "mamba/util/string.hpp"
|
#include "mamba/util/string.hpp"
|
||||||
|
@ -72,11 +73,11 @@ namespace mamba
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto pool_latest_package(MPool& pool, specs::MatchSpec spec)
|
auto database_latest_package(solver::libsolv::Database& db, specs::MatchSpec spec)
|
||||||
-> std::optional<specs::PackageInfo>
|
-> std::optional<specs::PackageInfo>
|
||||||
{
|
{
|
||||||
auto out = std::optional<specs::PackageInfo>();
|
auto out = std::optional<specs::PackageInfo>();
|
||||||
pool.for_each_package_matching(
|
db.for_each_package_matching(
|
||||||
spec,
|
spec,
|
||||||
[&](auto pkg)
|
[&](auto pkg)
|
||||||
{
|
{
|
||||||
|
@ -96,7 +97,7 @@ namespace mamba
|
||||||
using DepGraph = typename QueryResult::dependency_graph;
|
using DepGraph = typename QueryResult::dependency_graph;
|
||||||
using node_id = typename QueryResult::dependency_graph::node_id;
|
using node_id = typename QueryResult::dependency_graph::node_id;
|
||||||
|
|
||||||
PoolWalker(MPool& pool);
|
PoolWalker(solver::libsolv::Database& db);
|
||||||
|
|
||||||
void walk(specs::PackageInfo pkg, std::size_t max_depth);
|
void walk(specs::PackageInfo pkg, std::size_t max_depth);
|
||||||
void walk(specs::PackageInfo pkg);
|
void walk(specs::PackageInfo pkg);
|
||||||
|
@ -113,14 +114,14 @@ namespace mamba
|
||||||
DepGraph m_graph;
|
DepGraph m_graph;
|
||||||
VisitedMap m_visited;
|
VisitedMap m_visited;
|
||||||
NotFoundMap m_not_found;
|
NotFoundMap m_not_found;
|
||||||
MPool& m_pool;
|
solver::libsolv::Database& m_database;
|
||||||
|
|
||||||
void walk_impl(node_id id, std::size_t max_depth);
|
void walk_impl(node_id id, std::size_t max_depth);
|
||||||
void reverse_walk_impl(node_id id);
|
void reverse_walk_impl(node_id id);
|
||||||
};
|
};
|
||||||
|
|
||||||
PoolWalker::PoolWalker(MPool& pool)
|
PoolWalker::PoolWalker(solver::libsolv::Database& db)
|
||||||
: m_pool(pool)
|
: m_database(db)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ namespace mamba
|
||||||
// as taking any package matching a dependency recursively.
|
// as taking any package matching a dependency recursively.
|
||||||
// Package dependencies can appear mulitple time, further reducing its valid set.
|
// Package dependencies can appear mulitple time, further reducing its valid set.
|
||||||
// To do this properly, we should instanciate a solver and resolve the spec.
|
// To do this properly, we should instanciate a solver and resolve the spec.
|
||||||
if (auto child = pool_latest_package(m_pool, specs::MatchSpec::parse(dep)))
|
if (auto child = database_latest_package(m_database, specs::MatchSpec::parse(dep)))
|
||||||
{
|
{
|
||||||
if (auto it = m_visited.find(&(*child)); it != m_visited.cend())
|
if (auto it = m_visited.find(&(*child)); it != m_visited.cend())
|
||||||
{
|
{
|
||||||
|
@ -185,7 +186,7 @@ namespace mamba
|
||||||
|
|
||||||
void PoolWalker::reverse_walk_impl(node_id id)
|
void PoolWalker::reverse_walk_impl(node_id id)
|
||||||
{
|
{
|
||||||
m_pool.for_each_package_depending_on(
|
m_database.for_each_package_depending_on(
|
||||||
specs::MatchSpec::parse(m_graph.node(id).name),
|
specs::MatchSpec::parse(m_graph.node(id).name),
|
||||||
[&](specs::PackageInfo pkg)
|
[&](specs::PackageInfo pkg)
|
||||||
{
|
{
|
||||||
|
@ -210,12 +211,12 @@ namespace mamba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Query::find(MPool& mpool, const std::vector<std::string>& queries) -> QueryResult
|
auto Query::find(Database& db, const std::vector<std::string>& queries) -> QueryResult
|
||||||
{
|
{
|
||||||
QueryResult::dependency_graph g;
|
QueryResult::dependency_graph g;
|
||||||
for (const auto& query : queries)
|
for (const auto& query : queries)
|
||||||
{
|
{
|
||||||
mpool.for_each_package_matching(
|
db.for_each_package_matching(
|
||||||
specs::MatchSpec::parse(query),
|
specs::MatchSpec::parse(query),
|
||||||
[&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); }
|
[&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); }
|
||||||
);
|
);
|
||||||
|
@ -228,13 +229,13 @@ namespace mamba
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Query::whoneeds(MPool& mpool, std::string query, bool tree) -> QueryResult
|
auto Query::whoneeds(Database& db, std::string query, bool tree) -> QueryResult
|
||||||
{
|
{
|
||||||
if (tree)
|
if (tree)
|
||||||
{
|
{
|
||||||
if (auto pkg = pool_latest_package(mpool, specs::MatchSpec::parse(query)))
|
if (auto pkg = database_latest_package(db, specs::MatchSpec::parse(query)))
|
||||||
{
|
{
|
||||||
auto walker = PoolWalker(mpool);
|
auto walker = PoolWalker(db);
|
||||||
walker.reverse_walk(std::move(pkg).value());
|
walker.reverse_walk(std::move(pkg).value());
|
||||||
return { QueryType::WhoNeeds, std::move(query), std::move(walker).graph() };
|
return { QueryType::WhoNeeds, std::move(query), std::move(walker).graph() };
|
||||||
}
|
}
|
||||||
|
@ -242,7 +243,7 @@ namespace mamba
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QueryResult::dependency_graph g;
|
QueryResult::dependency_graph g;
|
||||||
mpool.for_each_package_depending_on(
|
db.for_each_package_depending_on(
|
||||||
specs::MatchSpec::parse(query),
|
specs::MatchSpec::parse(query),
|
||||||
[&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); }
|
[&](specs::PackageInfo&& pkg) { g.add_node(std::move(pkg)); }
|
||||||
);
|
);
|
||||||
|
@ -251,11 +252,11 @@ namespace mamba
|
||||||
return { QueryType::WhoNeeds, std::move(query), QueryResult::dependency_graph() };
|
return { QueryType::WhoNeeds, std::move(query), QueryResult::dependency_graph() };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Query::depends(MPool& mpool, std::string query, bool tree) -> QueryResult
|
auto Query::depends(Database& db, std::string query, bool tree) -> QueryResult
|
||||||
{
|
{
|
||||||
if (auto pkg = pool_latest_package(mpool, specs::MatchSpec::parse(query)))
|
if (auto pkg = database_latest_package(db, specs::MatchSpec::parse(query)))
|
||||||
{
|
{
|
||||||
auto walker = PoolWalker(mpool);
|
auto walker = PoolWalker(db);
|
||||||
if (tree)
|
if (tree)
|
||||||
{
|
{
|
||||||
walker.walk(std::move(pkg).value());
|
walker.walk(std::move(pkg).value());
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
#include "mamba/core/link.hpp"
|
#include "mamba/core/link.hpp"
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
#include "mamba/core/package_fetcher.hpp"
|
#include "mamba/core/package_fetcher.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
|
||||||
#include "mamba/core/thread_utils.hpp"
|
#include "mamba/core/thread_utils.hpp"
|
||||||
#include "mamba/core/transaction.hpp"
|
#include "mamba/core/transaction.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/specs/match_spec.hpp"
|
#include "mamba/specs/match_spec.hpp"
|
||||||
#include "mamba/util/variant_cmp.hpp"
|
#include "mamba/util/variant_cmp.hpp"
|
||||||
|
|
||||||
|
@ -47,10 +47,10 @@ namespace mamba
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO duplicated function, consider moving it to Pool
|
// TODO duplicated function, consider moving it to Pool
|
||||||
auto pool_has_package(MPool& pool, const specs::MatchSpec& spec) -> bool
|
auto database_has_package(solver::libsolv::Database& db, const specs::MatchSpec& spec) -> bool
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
pool.for_each_package_matching(
|
db.for_each_package_matching(
|
||||||
spec,
|
spec,
|
||||||
[&](const auto&)
|
[&](const auto&)
|
||||||
{
|
{
|
||||||
|
@ -76,13 +76,14 @@ namespace mamba
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto installed_python(const MPool& pool) -> std::optional<specs::PackageInfo>
|
auto installed_python(const solver::libsolv::Database& db)
|
||||||
|
-> std::optional<specs::PackageInfo>
|
||||||
{
|
{
|
||||||
// TODO combine Repo and MatchSpec search API in Pool
|
// TODO combine Repo and MatchSpec search API in Pool
|
||||||
auto out = std::optional<specs::PackageInfo>();
|
auto out = std::optional<specs::PackageInfo>();
|
||||||
if (auto repo = pool.installed_repo())
|
if (auto repo = db.installed_repo())
|
||||||
{
|
{
|
||||||
pool.for_each_package_in_repo(
|
db.for_each_package_in_repo(
|
||||||
*repo,
|
*repo,
|
||||||
[&](specs::PackageInfo&& pkg)
|
[&](specs::PackageInfo&& pkg)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +99,8 @@ namespace mamba
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto find_python_version(const solver::Solution& solution, const MPool& pool)
|
auto
|
||||||
|
find_python_version(const solver::Solution& solution, const solver::libsolv::Database& db)
|
||||||
-> std::pair<std::string, std::string>
|
-> std::pair<std::string, std::string>
|
||||||
{
|
{
|
||||||
// We need to find the python version that will be there after this
|
// We need to find the python version that will be there after this
|
||||||
|
@ -108,7 +110,7 @@ namespace mamba
|
||||||
// version but keeping the current one.
|
// version but keeping the current one.
|
||||||
// Could also be written in term of PrefixData.
|
// Could also be written in term of PrefixData.
|
||||||
std::string installed_py_ver = {};
|
std::string installed_py_ver = {};
|
||||||
if (auto pkg = installed_python(pool))
|
if (auto pkg = installed_python(db))
|
||||||
{
|
{
|
||||||
installed_py_ver = pkg->version;
|
installed_py_ver = pkg->version;
|
||||||
LOG_INFO << "Found python in installed packages " << installed_py_ver;
|
LOG_INFO << "Found python in installed packages " << installed_py_ver;
|
||||||
|
@ -132,7 +134,7 @@ namespace mamba
|
||||||
|
|
||||||
MTransaction::MTransaction(
|
MTransaction::MTransaction(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
std::vector<specs::PackageInfo> pkgs_to_remove,
|
std::vector<specs::PackageInfo> pkgs_to_remove,
|
||||||
std::vector<specs::PackageInfo> pkgs_to_install,
|
std::vector<specs::PackageInfo> pkgs_to_install,
|
||||||
MultiPackageCache& caches
|
MultiPackageCache& caches
|
||||||
|
@ -143,7 +145,7 @@ namespace mamba
|
||||||
for (const auto& pkg : pkgs_to_remove)
|
for (const auto& pkg : pkgs_to_remove)
|
||||||
{
|
{
|
||||||
auto spec = explicit_spec(pkg);
|
auto spec = explicit_spec(pkg);
|
||||||
if (!pool_has_package(pool, spec))
|
if (!database_has_package(db, spec))
|
||||||
{
|
{
|
||||||
not_found << "\n - " << spec.str();
|
not_found << "\n - " << spec.str();
|
||||||
}
|
}
|
||||||
|
@ -203,14 +205,14 @@ namespace mamba
|
||||||
ctx,
|
ctx,
|
||||||
ctx.prefix_params.target_prefix,
|
ctx.prefix_params.target_prefix,
|
||||||
ctx.prefix_params.relocate_prefix,
|
ctx.prefix_params.relocate_prefix,
|
||||||
find_python_version(m_solution, pool),
|
find_python_version(m_solution, db),
|
||||||
specs_to_install
|
specs_to_install
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTransaction::MTransaction(
|
MTransaction::MTransaction(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
const solver::Request& request,
|
const solver::Request& request,
|
||||||
solver::Solution solution,
|
solver::Solution solution,
|
||||||
MultiPackageCache& caches
|
MultiPackageCache& caches
|
||||||
|
@ -257,7 +259,7 @@ namespace mamba
|
||||||
ctx,
|
ctx,
|
||||||
ctx.prefix_params.target_prefix,
|
ctx.prefix_params.target_prefix,
|
||||||
ctx.prefix_params.relocate_prefix,
|
ctx.prefix_params.relocate_prefix,
|
||||||
find_python_version(m_solution, pool),
|
find_python_version(m_solution, db),
|
||||||
std::move(requested_specs)
|
std::move(requested_specs)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -273,7 +275,7 @@ namespace mamba
|
||||||
|
|
||||||
MTransaction::MTransaction(
|
MTransaction::MTransaction(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
std::vector<specs::PackageInfo> packages,
|
std::vector<specs::PackageInfo> packages,
|
||||||
MultiPackageCache& caches
|
MultiPackageCache& caches
|
||||||
)
|
)
|
||||||
|
@ -307,7 +309,7 @@ namespace mamba
|
||||||
ctx,
|
ctx,
|
||||||
ctx.prefix_params.target_prefix,
|
ctx.prefix_params.target_prefix,
|
||||||
ctx.prefix_params.relocate_prefix,
|
ctx.prefix_params.relocate_prefix,
|
||||||
find_python_version(m_solution, pool),
|
find_python_version(m_solution, db),
|
||||||
std::move(specs_to_install)
|
std::move(specs_to_install)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1112,7 +1114,7 @@ namespace mamba
|
||||||
}
|
}
|
||||||
|
|
||||||
MTransaction
|
MTransaction
|
||||||
create_explicit_transaction_from_urls(const Context& ctx, MPool& pool, const std::vector<std::string>& urls, MultiPackageCache& package_caches, std::vector<detail::other_pkg_mgr_spec>&)
|
create_explicit_transaction_from_urls(const Context& ctx, solver::libsolv::Database& db, const std::vector<std::string>& urls, MultiPackageCache& package_caches, std::vector<detail::other_pkg_mgr_spec>&)
|
||||||
{
|
{
|
||||||
std::vector<specs::PackageInfo> specs_to_install = {};
|
std::vector<specs::PackageInfo> specs_to_install = {};
|
||||||
specs_to_install.reserve(urls.size());
|
specs_to_install.reserve(urls.size());
|
||||||
|
@ -1122,12 +1124,12 @@ namespace mamba
|
||||||
std::back_insert_iterator(specs_to_install),
|
std::back_insert_iterator(specs_to_install),
|
||||||
[&](const auto& u) { return specs::PackageInfo::from_url(u); }
|
[&](const auto& u) { return specs::PackageInfo::from_url(u); }
|
||||||
);
|
);
|
||||||
return MTransaction(ctx, pool, {}, specs_to_install, package_caches);
|
return MTransaction(ctx, db, {}, specs_to_install, package_caches);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTransaction create_explicit_transaction_from_lockfile(
|
MTransaction create_explicit_transaction_from_lockfile(
|
||||||
const Context& ctx,
|
const Context& ctx,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
const fs::u8path& env_lockfile_path,
|
const fs::u8path& env_lockfile_path,
|
||||||
const std::vector<std::string>& categories,
|
const std::vector<std::string>& categories,
|
||||||
MultiPackageCache& package_caches,
|
MultiPackageCache& package_caches,
|
||||||
|
@ -1191,7 +1193,7 @@ namespace mamba
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MTransaction{ ctx, pool, std::move(conda_packages), package_caches };
|
return MTransaction{ ctx, db, std::move(conda_packages), package_caches };
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mamba
|
} // namespace mamba
|
||||||
|
|
|
@ -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 <solv/solver.h>
|
||||||
|
|
||||||
#include "mamba/core/channel_context.hpp"
|
|
||||||
#include "mamba/core/error_handling.hpp"
|
#include "mamba/core/error_handling.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/solver.hpp"
|
#include "mamba/solver/libsolv/solver.hpp"
|
||||||
#include "mamba/util/variant_cmp.hpp"
|
#include "mamba/util/variant_cmp.hpp"
|
||||||
#include "solv-cpp/solver.hpp"
|
#include "solv-cpp/solver.hpp"
|
||||||
|
@ -51,9 +50,9 @@ namespace mamba::solver::libsolv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Solver::solve_impl(MPool& mpool, const Request& request) -> expected_t<Outcome>
|
auto Solver::solve_impl(Database& mpool, const Request& request) -> expected_t<Outcome>
|
||||||
{
|
{
|
||||||
auto& pool = MPool::Impl::get(mpool);
|
auto& pool = Database::Impl::get(mpool);
|
||||||
const auto& chan_params = mpool.channel_params();
|
const auto& chan_params = mpool.channel_params();
|
||||||
const auto& flags = request.flags;
|
const auto& flags = request.flags;
|
||||||
|
|
||||||
|
@ -87,7 +86,7 @@ namespace mamba::solver::libsolv
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Solver::solve(MPool& mpool, Request&& request) -> expected_t<Outcome>
|
auto Solver::solve(Database& mpool, Request&& request) -> expected_t<Outcome>
|
||||||
{
|
{
|
||||||
if (request.flags.order_request)
|
if (request.flags.order_request)
|
||||||
{
|
{
|
||||||
|
@ -96,7 +95,7 @@ namespace mamba::solver::libsolv
|
||||||
return solve_impl(mpool, request);
|
return solve_impl(mpool, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Solver::solve(MPool& mpool, const Request& request) -> expected_t<Outcome>
|
auto Solver::solve(Database& mpool, const Request& request) -> expected_t<Outcome>
|
||||||
{
|
{
|
||||||
if (request.flags.order_request)
|
if (request.flags.order_request)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
#include "mamba/core/palette.hpp"
|
#include "mamba/core/palette.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/unsolvable.hpp"
|
#include "mamba/solver/libsolv/unsolvable.hpp"
|
||||||
#include "mamba/specs/match_spec.hpp"
|
#include "mamba/specs/match_spec.hpp"
|
||||||
#include "mamba/specs/package_info.hpp"
|
#include "mamba/specs/package_info.hpp"
|
||||||
|
@ -41,9 +41,9 @@ namespace mamba::solver::libsolv
|
||||||
return *m_solver;
|
return *m_solver;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto UnSolvable::problems(MPool& mpool) const -> std::vector<std::string>
|
auto UnSolvable::problems(Database& mpool) const -> std::vector<std::string>
|
||||||
{
|
{
|
||||||
auto& pool = MPool::Impl::get(mpool);
|
auto& pool = Database::Impl::get(mpool);
|
||||||
std::vector<std::string> problems;
|
std::vector<std::string> problems;
|
||||||
solver().for_each_problem_id([&](solv::ProblemId pb)
|
solver().for_each_problem_id([&](solv::ProblemId pb)
|
||||||
{ problems.emplace_back(solver().problem_to_string(pool, pb)); }
|
{ problems.emplace_back(solver().problem_to_string(pool, pb)); }
|
||||||
|
@ -51,9 +51,9 @@ namespace mamba::solver::libsolv
|
||||||
return problems;
|
return problems;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto UnSolvable::problems_to_str(MPool& mpool) const -> std::string
|
auto UnSolvable::problems_to_str(Database& mpool) const -> std::string
|
||||||
{
|
{
|
||||||
auto& pool = MPool::Impl::get(mpool);
|
auto& pool = Database::Impl::get(mpool);
|
||||||
std::stringstream problems;
|
std::stringstream problems;
|
||||||
problems << "Encountered problems while solving:\n";
|
problems << "Encountered problems while solving:\n";
|
||||||
solver().for_each_problem_id(
|
solver().for_each_problem_id(
|
||||||
|
@ -63,9 +63,9 @@ namespace mamba::solver::libsolv
|
||||||
return problems.str();
|
return problems.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto UnSolvable::all_problems_to_str(MPool& mpool) const -> std::string
|
auto UnSolvable::all_problems_to_str(Database& mpool) const -> std::string
|
||||||
{
|
{
|
||||||
auto& pool = MPool::Impl::get(mpool);
|
auto& pool = Database::Impl::get(mpool);
|
||||||
std::stringstream problems;
|
std::stringstream problems;
|
||||||
solver().for_each_problem_id(
|
solver().for_each_problem_id(
|
||||||
[&](solv::ProblemId pb)
|
[&](solv::ProblemId pb)
|
||||||
|
@ -467,13 +467,14 @@ namespace mamba::solver::libsolv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto UnSolvable::problems_graph(const MPool& pool) const -> ProblemsGraph
|
auto UnSolvable::problems_graph(const Database& pool) const -> ProblemsGraph
|
||||||
{
|
{
|
||||||
assert(m_solver != nullptr);
|
assert(m_solver != nullptr);
|
||||||
return ProblemsGraphCreator(MPool::Impl::get(pool), *m_solver).problem_graph();
|
return ProblemsGraphCreator(Database::Impl::get(pool), *m_solver).problem_graph();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto UnSolvable::explain_problems_to(MPool& pool, std::ostream& out, const Palette& palette) const
|
auto
|
||||||
|
UnSolvable::explain_problems_to(Database& pool, std::ostream& out, const Palette& palette) const
|
||||||
-> std::ostream&
|
-> std::ostream&
|
||||||
{
|
{
|
||||||
out << "Could not solve for environment specs\n";
|
out << "Could not solve for environment specs\n";
|
||||||
|
@ -491,7 +492,7 @@ namespace mamba::solver::libsolv
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto UnSolvable::explain_problems(MPool& pool, const Palette& palette) const -> std::string
|
auto UnSolvable::explain_problems(Database& pool, const Palette& palette) const -> std::string
|
||||||
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
#include "mamba/core/channel_context.hpp"
|
#include "mamba/core/channel_context.hpp"
|
||||||
#include "mamba/core/env_lockfile.hpp"
|
#include "mamba/core/env_lockfile.hpp"
|
||||||
#include "mamba/core/fsutil.hpp"
|
#include "mamba/core/fsutil.hpp"
|
||||||
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/transaction.hpp"
|
#include "mamba/core/transaction.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
|
|
||||||
#include "mambatests.hpp"
|
#include "mambatests.hpp"
|
||||||
|
|
||||||
|
@ -126,8 +128,8 @@ namespace mamba
|
||||||
const fs::u8path lockfile_path{ mambatests::test_data_dir
|
const fs::u8path lockfile_path{ mambatests::test_data_dir
|
||||||
/ "env_lockfile/good_multiple_categories-lock.yaml" };
|
/ "env_lockfile/good_multiple_categories-lock.yaml" };
|
||||||
auto channel_context = ChannelContext::make_conda_compatible(mambatests::context());
|
auto channel_context = ChannelContext::make_conda_compatible(mambatests::context());
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database db{ channel_context.params() };
|
||||||
add_spdlog_logger_to_pool(pool);
|
add_spdlog_logger_to_database(db);
|
||||||
mamba::MultiPackageCache pkg_cache({ "/tmp/" }, ctx.validation_params);
|
mamba::MultiPackageCache pkg_cache({ "/tmp/" }, ctx.validation_params);
|
||||||
|
|
||||||
ctx.platform = "linux-64";
|
ctx.platform = "linux-64";
|
||||||
|
@ -138,7 +140,7 @@ namespace mamba
|
||||||
std::vector<detail::other_pkg_mgr_spec> other_specs;
|
std::vector<detail::other_pkg_mgr_spec> other_specs;
|
||||||
auto transaction = create_explicit_transaction_from_lockfile(
|
auto transaction = create_explicit_transaction_from_lockfile(
|
||||||
ctx,
|
ctx,
|
||||||
pool,
|
db,
|
||||||
lockfile_path,
|
lockfile_path,
|
||||||
categories,
|
categories,
|
||||||
pkg_cache,
|
pkg_cache,
|
||||||
|
|
|
@ -14,11 +14,12 @@
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "mamba/core/channel_context.hpp"
|
#include "mamba/core/channel_context.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/prefix_data.hpp"
|
#include "mamba/core/prefix_data.hpp"
|
||||||
#include "mamba/core/subdirdata.hpp"
|
#include "mamba/core/subdirdata.hpp"
|
||||||
#include "mamba/core/util.hpp"
|
#include "mamba/core/util.hpp"
|
||||||
#include "mamba/fs/filesystem.hpp"
|
#include "mamba/fs/filesystem.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||||
#include "mamba/solver/libsolv/solver.hpp"
|
#include "mamba/solver/libsolv/solver.hpp"
|
||||||
#include "mamba/solver/libsolv/unsolvable.hpp"
|
#include "mamba/solver/libsolv/unsolvable.hpp"
|
||||||
|
@ -97,26 +98,26 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a solver and a pool of a conflict.
|
* Create a solver and a database of a conflict.
|
||||||
*
|
*
|
||||||
* The underlying packages do not exist, we are onl interested in the conflict.
|
* The underlying packages do not exist, we are onl interested in the conflict.
|
||||||
*/
|
*/
|
||||||
template <typename PkgRange>
|
template <typename PkgRange>
|
||||||
auto create_pkgs_pool(ChannelContext& channel_context, const PkgRange& packages)
|
auto create_pkgs_database(ChannelContext& channel_context, const PkgRange& packages)
|
||||||
{
|
{
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database db{ channel_context.params() };
|
||||||
pool.add_repo_from_packages(packages);
|
db.add_repo_from_packages(packages);
|
||||||
return pool;
|
return db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test create_pool utility")
|
TEST_CASE("Test create_pkgs_database utility")
|
||||||
{
|
{
|
||||||
auto& ctx = mambatests::context();
|
auto& ctx = mambatests::context();
|
||||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||||
auto pool = create_pkgs_pool(channel_context, std::array{ mkpkg("foo", "0.1.0", {}) });
|
auto db = create_pkgs_database(channel_context, std::array{ mkpkg("foo", "0.1.0", {}) });
|
||||||
auto request = Request{ {}, { Request::Install{ "foo"_ms } } };
|
auto request = Request{ {}, { Request::Install{ "foo"_ms } } };
|
||||||
const auto outcome = solver::libsolv::Solver().solve(pool, request).value();
|
const auto outcome = solver::libsolv::Solver().solve(db, request).value();
|
||||||
REQUIRE(std::holds_alternative<solver::Solution>(outcome));
|
REQUIRE(std::holds_alternative<solver::Solution>(outcome));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,12 +125,12 @@ TEST_CASE("Test empty specs")
|
||||||
{
|
{
|
||||||
auto& ctx = mambatests::context();
|
auto& ctx = mambatests::context();
|
||||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||||
auto pool = create_pkgs_pool(
|
auto db = create_pkgs_database(
|
||||||
channel_context,
|
channel_context,
|
||||||
std::array{ mkpkg("foo", "0.1.0", {}), mkpkg("", "", {}) }
|
std::array{ mkpkg("foo", "0.1.0", {}), mkpkg("", "", {}) }
|
||||||
);
|
);
|
||||||
auto request = Request{ {}, { Request::Install{ "foo"_ms } } };
|
auto request = Request{ {}, { Request::Install{ "foo"_ms } } };
|
||||||
const auto outcome = solver::libsolv::Solver().solve(pool, request).value();
|
const auto outcome = solver::libsolv::Solver().solve(db, request).value();
|
||||||
REQUIRE(std::holds_alternative<solver::Solution>(outcome));
|
REQUIRE(std::holds_alternative<solver::Solution>(outcome));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +139,7 @@ namespace
|
||||||
auto create_basic_conflict(Context&, ChannelContext& channel_context)
|
auto create_basic_conflict(Context&, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_pkgs_pool(
|
create_pkgs_database(
|
||||||
channel_context,
|
channel_context,
|
||||||
std::array{
|
std::array{
|
||||||
mkpkg("A", "0.1.0"),
|
mkpkg("A", "0.1.0"),
|
||||||
|
@ -159,7 +160,7 @@ namespace
|
||||||
auto create_pubgrub(Context&, ChannelContext& channel_context)
|
auto create_pubgrub(Context&, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_pkgs_pool(
|
create_pkgs_database(
|
||||||
channel_context,
|
channel_context,
|
||||||
std::array{
|
std::array{
|
||||||
mkpkg("menu", "1.5.0", { "dropdown=2.*" }),
|
mkpkg("menu", "1.5.0", { "dropdown=2.*" }),
|
||||||
|
@ -241,7 +242,7 @@ namespace
|
||||||
packages.push_back(mkpkg("dropdown", "2.9.0", { "libicons>10.0" }));
|
packages.push_back(mkpkg("dropdown", "2.9.0", { "libicons>10.0" }));
|
||||||
}
|
}
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_pkgs_pool(channel_context, packages),
|
create_pkgs_database(channel_context, packages),
|
||||||
Request{
|
Request{
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -287,7 +288,7 @@ namespace
|
||||||
auto load_channels(
|
auto load_channels(
|
||||||
Context& ctx,
|
Context& ctx,
|
||||||
ChannelContext& channel_context,
|
ChannelContext& channel_context,
|
||||||
MPool& pool,
|
solver::libsolv::Database& db,
|
||||||
MultiPackageCache& cache,
|
MultiPackageCache& cache,
|
||||||
std::vector<std::string>&& channels
|
std::vector<std::string>&& channels
|
||||||
)
|
)
|
||||||
|
@ -317,14 +318,14 @@ namespace
|
||||||
|
|
||||||
for (auto& sub_dir : sub_dirs)
|
for (auto& sub_dir : sub_dirs)
|
||||||
{
|
{
|
||||||
auto repo = load_subdir_in_pool(ctx, pool, sub_dir);
|
auto repo = load_subdir_in_database(ctx, db, sub_dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a solver and a pool of a conflict from conda-forge packages.
|
* Create a solver and a database of a conflict from conda-forge packages.
|
||||||
*/
|
*/
|
||||||
auto create_conda_forge_pool(
|
auto create_conda_forge_database(
|
||||||
Context& ctx,
|
Context& ctx,
|
||||||
ChannelContext& channel_context,
|
ChannelContext& channel_context,
|
||||||
const std::vector<specs::PackageInfo>& virtual_packages = { mkpkg("__glibc", "2.17.0") },
|
const std::vector<specs::PackageInfo>& virtual_packages = { mkpkg("__glibc", "2.17.0") },
|
||||||
|
@ -338,9 +339,9 @@ namespace
|
||||||
|
|
||||||
auto prefix_data = PrefixData::create(tmp_dir.path() / "prefix", channel_context).value();
|
auto prefix_data = PrefixData::create(tmp_dir.path() / "prefix", channel_context).value();
|
||||||
prefix_data.add_packages(virtual_packages);
|
prefix_data.add_packages(virtual_packages);
|
||||||
auto pool = MPool{ channel_context.params() };
|
auto db = solver::libsolv::Database{ channel_context.params() };
|
||||||
|
|
||||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
load_installed_packages_in_database(ctx, db, prefix_data);
|
||||||
|
|
||||||
auto cache = MultiPackageCache({ tmp_dir.path() / "cache" }, ctx.validation_params);
|
auto cache = MultiPackageCache({ tmp_dir.path() / "cache" }, ctx.validation_params);
|
||||||
create_cache_dir(cache.first_writable_path());
|
create_cache_dir(cache.first_writable_path());
|
||||||
|
@ -350,13 +351,13 @@ namespace
|
||||||
load_channels(
|
load_channels(
|
||||||
ctx,
|
ctx,
|
||||||
channel_context,
|
channel_context,
|
||||||
pool,
|
db,
|
||||||
cache,
|
cache,
|
||||||
make_platform_channels(std::move(channels), platforms)
|
make_platform_channels(std::move(channels), platforms)
|
||||||
);
|
);
|
||||||
ctx.graphics_params.no_progress_bars = prev_progress_bars_value;
|
ctx.graphics_params.no_progress_bars = prev_progress_bars_value;
|
||||||
|
|
||||||
return pool;
|
return db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,9 +365,9 @@ TEST_CASE("Test create_conda_forge utility")
|
||||||
{
|
{
|
||||||
auto& ctx = mambatests::context();
|
auto& ctx = mambatests::context();
|
||||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||||
auto pool = create_conda_forge_pool(ctx, channel_context);
|
auto db = create_conda_forge_database(ctx, channel_context);
|
||||||
auto request = Request{ {}, { Request::Install{ "xtensor>=0.7"_ms } } };
|
auto request = Request{ {}, { Request::Install{ "xtensor>=0.7"_ms } } };
|
||||||
const auto outcome = solver::libsolv::Solver().solve(pool, request).value();
|
const auto outcome = solver::libsolv::Solver().solve(db, request).value();
|
||||||
REQUIRE(std::holds_alternative<solver::Solution>(outcome));
|
REQUIRE(std::holds_alternative<solver::Solution>(outcome));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +376,7 @@ namespace
|
||||||
auto create_pytorch_cpu(Context& ctx, ChannelContext& channel_context)
|
auto create_pytorch_cpu(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(ctx, channel_context),
|
create_conda_forge_database(ctx, channel_context),
|
||||||
Request{
|
Request{
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -389,7 +390,7 @@ namespace
|
||||||
auto create_pytorch_cuda(Context& ctx, ChannelContext& channel_context)
|
auto create_pytorch_cuda(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(
|
create_conda_forge_database(
|
||||||
ctx,
|
ctx,
|
||||||
channel_context,
|
channel_context,
|
||||||
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "10.2.0") }
|
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "10.2.0") }
|
||||||
|
@ -407,7 +408,7 @@ namespace
|
||||||
auto create_cudatoolkit(Context& ctx, ChannelContext& channel_context)
|
auto create_cudatoolkit(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(
|
create_conda_forge_database(
|
||||||
ctx,
|
ctx,
|
||||||
channel_context,
|
channel_context,
|
||||||
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "11.1") }
|
{ mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "11.1") }
|
||||||
|
@ -428,7 +429,7 @@ namespace
|
||||||
auto create_jpeg9b(Context& ctx, ChannelContext& channel_context)
|
auto create_jpeg9b(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(ctx, channel_context),
|
create_conda_forge_database(ctx, channel_context),
|
||||||
Request{
|
Request{
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -442,7 +443,7 @@ namespace
|
||||||
auto create_r_base(Context& ctx, ChannelContext& channel_context)
|
auto create_r_base(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(ctx, channel_context),
|
create_conda_forge_database(ctx, channel_context),
|
||||||
Request{
|
Request{
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -459,7 +460,7 @@ namespace
|
||||||
auto create_scip(Context& ctx, ChannelContext& channel_context)
|
auto create_scip(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(ctx, channel_context),
|
create_conda_forge_database(ctx, channel_context),
|
||||||
Request{
|
Request{
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -473,7 +474,7 @@ namespace
|
||||||
auto create_double_python(Context& ctx, ChannelContext& channel_context)
|
auto create_double_python(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(ctx, channel_context),
|
create_conda_forge_database(ctx, channel_context),
|
||||||
Request{
|
Request{
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -487,7 +488,7 @@ namespace
|
||||||
auto create_numba(Context& ctx, ChannelContext& channel_context)
|
auto create_numba(Context& ctx, ChannelContext& channel_context)
|
||||||
{
|
{
|
||||||
return std::pair(
|
return std::pair(
|
||||||
create_conda_forge_pool(ctx, channel_context),
|
create_conda_forge_database(ctx, channel_context),
|
||||||
Request{
|
Request{
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -583,11 +584,11 @@ TEST_CASE("Create problem graph")
|
||||||
// Somehow the capture does not work directly on ``name``
|
// Somehow the capture does not work directly on ``name``
|
||||||
std::string_view name_copy = name;
|
std::string_view name_copy = name;
|
||||||
CAPTURE(name_copy);
|
CAPTURE(name_copy);
|
||||||
auto [pool, request] = factory(ctx, channel_context);
|
auto [db, request] = factory(ctx, channel_context);
|
||||||
auto outcome = solver::libsolv::Solver().solve(pool, request).value();
|
auto outcome = solver::libsolv::Solver().solve(db, request).value();
|
||||||
// REQUIRE(std::holds_alternative<solver::libsolv::UnSolvable>(outcome));
|
// REQUIRE(std::holds_alternative<solver::libsolv::UnSolvable>(outcome));
|
||||||
auto& unsolvable = std::get<solver::libsolv::UnSolvable>(outcome);
|
auto& unsolvable = std::get<solver::libsolv::UnSolvable>(outcome);
|
||||||
const auto pbs_init = unsolvable.problems_graph(pool);
|
const auto pbs_init = unsolvable.problems_graph(db);
|
||||||
const auto& graph_init = pbs_init.graph();
|
const auto& graph_init = pbs_init.graph();
|
||||||
|
|
||||||
REQUIRE_GE(graph_init.number_of_nodes(), 1);
|
REQUIRE_GE(graph_init.number_of_nodes(), 1);
|
||||||
|
|
|
@ -23,14 +23,15 @@
|
||||||
#include "mamba/core/download_progress_bar.hpp"
|
#include "mamba/core/download_progress_bar.hpp"
|
||||||
#include "mamba/core/execution.hpp"
|
#include "mamba/core/execution.hpp"
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/package_handling.hpp"
|
#include "mamba/core/package_handling.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
|
||||||
#include "mamba/core/prefix_data.hpp"
|
#include "mamba/core/prefix_data.hpp"
|
||||||
#include "mamba/core/query.hpp"
|
#include "mamba/core/query.hpp"
|
||||||
#include "mamba/core/subdirdata.hpp"
|
#include "mamba/core/subdirdata.hpp"
|
||||||
#include "mamba/core/transaction.hpp"
|
#include "mamba/core/transaction.hpp"
|
||||||
#include "mamba/core/util_os.hpp"
|
#include "mamba/core/util_os.hpp"
|
||||||
#include "mamba/core/virtual_packages.hpp"
|
#include "mamba/core/virtual_packages.hpp"
|
||||||
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||||
#include "mamba/solver/problems_graph.hpp"
|
#include "mamba/solver/problems_graph.hpp"
|
||||||
#include "mamba/validation/tools.hpp"
|
#include "mamba/validation/tools.hpp"
|
||||||
|
@ -379,12 +380,16 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
|
|
||||||
py::add_ostream_redirect(m, "ostream_redirect");
|
py::add_ostream_redirect(m, "ostream_redirect");
|
||||||
|
|
||||||
py::class_<MPool>(m, "Pool")
|
py::class_<solver::libsolv::Database>(m, "Pool")
|
||||||
.def(py::init<specs::ChannelResolveParams>(), py::arg("channel_params"))
|
.def(py::init<specs::ChannelResolveParams>(), py::arg("channel_params"))
|
||||||
.def("set_logger", &MPool::set_logger, py::call_guard<py::gil_scoped_acquire>())
|
.def(
|
||||||
|
"set_logger",
|
||||||
|
&solver::libsolv::Database::set_logger,
|
||||||
|
py::call_guard<py::gil_scoped_acquire>()
|
||||||
|
)
|
||||||
.def(
|
.def(
|
||||||
"add_repo_from_repodata_json",
|
"add_repo_from_repodata_json",
|
||||||
&MPool::add_repo_from_repodata_json,
|
&solver::libsolv::Database::add_repo_from_repodata_json,
|
||||||
py::arg("path"),
|
py::arg("path"),
|
||||||
py::arg("url"),
|
py::arg("url"),
|
||||||
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No,
|
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No,
|
||||||
|
@ -393,14 +398,14 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
)
|
)
|
||||||
.def(
|
.def(
|
||||||
"add_repo_from_native_serialization",
|
"add_repo_from_native_serialization",
|
||||||
&MPool::add_repo_from_native_serialization,
|
&solver::libsolv::Database::add_repo_from_native_serialization,
|
||||||
py::arg("path"),
|
py::arg("path"),
|
||||||
py::arg("expected"),
|
py::arg("expected"),
|
||||||
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No
|
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No
|
||||||
)
|
)
|
||||||
.def(
|
.def(
|
||||||
"add_repo_from_packages",
|
"add_repo_from_packages",
|
||||||
[](MPool& pool,
|
[](solver::libsolv::Database& db,
|
||||||
py::iterable packages,
|
py::iterable packages,
|
||||||
std::string_view name,
|
std::string_view name,
|
||||||
solver::libsolv::PipAsPythonDependency add)
|
solver::libsolv::PipAsPythonDependency add)
|
||||||
|
@ -411,7 +416,7 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
{
|
{
|
||||||
pkg_infos.push_back(pkg.cast<specs::PackageInfo>());
|
pkg_infos.push_back(pkg.cast<specs::PackageInfo>());
|
||||||
}
|
}
|
||||||
return pool.add_repo_from_packages(pkg_infos, name, add);
|
return db.add_repo_from_packages(pkg_infos, name, add);
|
||||||
},
|
},
|
||||||
py::arg("packages"),
|
py::arg("packages"),
|
||||||
py::arg("name") = "",
|
py::arg("name") = "",
|
||||||
|
@ -419,17 +424,22 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
)
|
)
|
||||||
.def(
|
.def(
|
||||||
"native_serialize_repo",
|
"native_serialize_repo",
|
||||||
&MPool::native_serialize_repo,
|
&solver::libsolv::Database::native_serialize_repo,
|
||||||
py::arg("repo"),
|
py::arg("repo"),
|
||||||
py::arg("path"),
|
py::arg("path"),
|
||||||
py::arg("metadata")
|
py::arg("metadata")
|
||||||
)
|
)
|
||||||
.def("set_installed_repo", &MPool::set_installed_repo, py::arg("repo"))
|
.def("set_installed_repo", &solver::libsolv::Database::set_installed_repo, py::arg("repo"))
|
||||||
.def("set_repo_priority", &MPool::set_repo_priority, py::arg("repo"), py::arg("priorities"));
|
.def(
|
||||||
|
"set_repo_priority",
|
||||||
|
&solver::libsolv::Database::set_repo_priority,
|
||||||
|
py::arg("repo"),
|
||||||
|
py::arg("priorities")
|
||||||
|
);
|
||||||
|
|
||||||
m.def(
|
m.def(
|
||||||
"load_subdir_in_pool",
|
"load_subdir_in_pool",
|
||||||
&load_subdir_in_pool,
|
&load_subdir_in_database,
|
||||||
py::arg("context"),
|
py::arg("context"),
|
||||||
py::arg("pool"),
|
py::arg("pool"),
|
||||||
py::arg("subdir")
|
py::arg("subdir")
|
||||||
|
@ -437,7 +447,7 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
|
|
||||||
m.def(
|
m.def(
|
||||||
"load_installed_packages_in_pool",
|
"load_installed_packages_in_pool",
|
||||||
&load_installed_packages_in_pool,
|
&load_installed_packages_in_database,
|
||||||
py::arg("context"),
|
py::arg("context"),
|
||||||
py::arg("pool"),
|
py::arg("pool"),
|
||||||
py::arg("prefix_data")
|
py::arg("prefix_data")
|
||||||
|
@ -457,7 +467,7 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
.def_property_readonly("first_writable_path", &MultiPackageCache::first_writable_path);
|
.def_property_readonly("first_writable_path", &MultiPackageCache::first_writable_path);
|
||||||
|
|
||||||
py::class_<MTransaction>(m, "Transaction")
|
py::class_<MTransaction>(m, "Transaction")
|
||||||
.def(py::init<const Context&, MPool&, const solver::Request&, solver::Solution, MultiPackageCache&>(
|
.def(py::init<const Context&, solver::libsolv::Database&, const solver::Request&, solver::Solution, MultiPackageCache&>(
|
||||||
))
|
))
|
||||||
.def("to_conda", &MTransaction::to_conda)
|
.def("to_conda", &MTransaction::to_conda)
|
||||||
.def("log_json", &MTransaction::log_json)
|
.def("log_json", &MTransaction::log_json)
|
||||||
|
@ -522,10 +532,10 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
py::class_<SubdirData>(m, "SubdirData")
|
py::class_<SubdirData>(m, "SubdirData")
|
||||||
.def(
|
.def(
|
||||||
"create_repo",
|
"create_repo",
|
||||||
[](SubdirData& subdir, MPool& pool) -> solver::libsolv::RepoInfo
|
[](SubdirData& subdir, solver::libsolv::Database& db) -> solver::libsolv::RepoInfo
|
||||||
{
|
{
|
||||||
deprecated("Use `load_subdir_in_pool` instead", "2.0");
|
deprecated("Use `load_subdir_in_pool` instead", "2.0");
|
||||||
return extract(load_subdir_in_pool(mambapy::singletons.context(), pool, subdir));
|
return extract(load_subdir_in_database(mambapy::singletons.context(), db, subdir));
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.def("loaded", &SubdirData::is_loaded)
|
.def("loaded", &SubdirData::is_loaded)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
#include "mamba/core/palette.hpp"
|
#include "mamba/core/palette.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/parameters.hpp"
|
#include "mamba/solver/libsolv/parameters.hpp"
|
||||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||||
#include "mamba/solver/libsolv/solver.hpp"
|
#include "mamba/solver/libsolv/solver.hpp"
|
||||||
|
@ -125,8 +125,8 @@ namespace mambapy
|
||||||
.def(py::init())
|
.def(py::init())
|
||||||
.def(
|
.def(
|
||||||
"solve",
|
"solve",
|
||||||
[](Solver& self, MPool& pool, const solver::Request& request)
|
[](Solver& self, Database& db, const solver::Request& request)
|
||||||
{ return self.solve(pool, request); }
|
{ return self.solve(db, request); }
|
||||||
)
|
)
|
||||||
.def("add_jobs", solver_job_v2_migrator)
|
.def("add_jobs", solver_job_v2_migrator)
|
||||||
.def("add_global_job", solver_job_v2_migrator)
|
.def("add_global_job", solver_job_v2_migrator)
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
using namespace mamba;
|
using namespace mamba;
|
||||||
|
|
||||||
MPool
|
Database
|
||||||
load_pool(
|
load_pool(
|
||||||
const std::vector<std::string>& channels,
|
const std::vector<std::string>& channels,
|
||||||
MultiPackageCache& package_caches,
|
MultiPackageCache& package_caches,
|
||||||
|
@ -40,7 +40,7 @@ load_pool(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ctx.channels = channels;
|
ctx.channels = channels;
|
||||||
mamba::MPool pool{ ctx, channel_context };
|
mamba::Database pool{ ctx, channel_context };
|
||||||
auto exp_load = load_channels(ctx, pool, package_caches, false);
|
auto exp_load = load_channels(ctx, pool, package_caches, false);
|
||||||
if (!exp_load)
|
if (!exp_load)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +59,7 @@ handle_solve_request(
|
||||||
{
|
{
|
||||||
struct cache
|
struct cache
|
||||||
{
|
{
|
||||||
std::optional<mamba::MPool> pool;
|
std::optional<mamba::Database> pool;
|
||||||
std::chrono::time_point<std::chrono::system_clock> last_update;
|
std::chrono::time_point<std::chrono::system_clock> last_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "mamba/api/update.hpp"
|
#include "mamba/api/update.hpp"
|
||||||
#include "mamba/core/channel_context.hpp"
|
#include "mamba/core/channel_context.hpp"
|
||||||
#include "mamba/core/context.hpp"
|
#include "mamba/core/context.hpp"
|
||||||
|
#include "mamba/core/package_database_loader.hpp"
|
||||||
#include "mamba/core/transaction.hpp"
|
#include "mamba/core/transaction.hpp"
|
||||||
#include "mamba/core/util_os.hpp"
|
#include "mamba/core/util_os.hpp"
|
||||||
#include "mamba/util/build.hpp"
|
#include "mamba/util/build.hpp"
|
||||||
|
@ -28,10 +29,10 @@ using namespace mamba; // NOLINT(build/namespaces)
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
auto pool_has_package(MPool& pool, specs::MatchSpec spec) -> bool
|
auto database_has_package(solver::libsolv::Database& database, specs::MatchSpec spec) -> bool
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
pool.for_each_package_matching(
|
database.for_each_package_matching(
|
||||||
spec,
|
spec,
|
||||||
[&](const auto&)
|
[&](const auto&)
|
||||||
{
|
{
|
||||||
|
@ -42,10 +43,11 @@ namespace
|
||||||
return found;
|
return found;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto pool_latest_package(MPool& pool, specs::MatchSpec spec) -> std::optional<specs::PackageInfo>
|
auto database_latest_package(solver::libsolv::Database& db, specs::MatchSpec spec)
|
||||||
|
-> std::optional<specs::PackageInfo>
|
||||||
{
|
{
|
||||||
auto out = std::optional<specs::PackageInfo>();
|
auto out = std::optional<specs::PackageInfo>();
|
||||||
pool.for_each_package_matching(
|
db.for_each_package_matching(
|
||||||
spec,
|
spec,
|
||||||
[&](auto pkg)
|
[&](auto pkg)
|
||||||
{
|
{
|
||||||
|
@ -72,12 +74,12 @@ update_self(Configuration& config, const std::optional<std::string>& version)
|
||||||
|
|
||||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||||
|
|
||||||
MPool pool{ channel_context.params() };
|
solver::libsolv::Database db{ channel_context.params() };
|
||||||
add_spdlog_logger_to_pool(pool);
|
add_spdlog_logger_to_database(db);
|
||||||
|
|
||||||
mamba::MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
mamba::MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||||
|
|
||||||
auto exp_loaded = load_channels(ctx, channel_context, pool, package_caches);
|
auto exp_loaded = load_channels(ctx, channel_context, db, package_caches);
|
||||||
if (!exp_loaded)
|
if (!exp_loaded)
|
||||||
{
|
{
|
||||||
throw exp_loaded.error();
|
throw exp_loaded.error();
|
||||||
|
@ -88,11 +90,11 @@ update_self(Configuration& config, const std::optional<std::string>& version)
|
||||||
: fmt::format("micromamba>{}", umamba::version())
|
: fmt::format("micromamba>{}", umamba::version())
|
||||||
);
|
);
|
||||||
|
|
||||||
auto latest_micromamba = pool_latest_package(pool, matchspec);
|
auto latest_micromamba = database_latest_package(db, matchspec);
|
||||||
|
|
||||||
if (!latest_micromamba.has_value())
|
if (!latest_micromamba.has_value())
|
||||||
{
|
{
|
||||||
if (pool_has_package(pool, specs::MatchSpec::parse("micromamba")))
|
if (database_has_package(db, specs::MatchSpec::parse("micromamba")))
|
||||||
{
|
{
|
||||||
Console::instance().print(
|
Console::instance().print(
|
||||||
fmt::format("\nYour micromamba version ({}) is already up to date.", umamba::version())
|
fmt::format("\nYour micromamba version ({}) is already up to date.", umamba::version())
|
||||||
|
@ -120,7 +122,7 @@ update_self(Configuration& config, const std::optional<std::string>& version)
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.download_only = true;
|
ctx.download_only = true;
|
||||||
MTransaction t(ctx, pool, { latest_micromamba.value() }, package_caches);
|
MTransaction t(ctx, db, { latest_micromamba.value() }, package_caches);
|
||||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.root_prefix, channel_context);
|
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.root_prefix, channel_context);
|
||||||
if (!exp_prefix_data)
|
if (!exp_prefix_data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -756,7 +756,7 @@ def test_channel_nodefaults(tmp_home, tmp_root_prefix, tmp_path):
|
||||||
def test_pin_applicable(tmp_home, tmp_root_prefix, tmp_path):
|
def test_pin_applicable(tmp_home, tmp_root_prefix, tmp_path):
|
||||||
pin_name = "xtensor"
|
pin_name = "xtensor"
|
||||||
pin_max_version = "0.20"
|
pin_max_version = "0.20"
|
||||||
# We add the channel to test a fragile behavior of ``MPool``
|
# We add the channel to test a fragile behavior of ``Database``
|
||||||
spec_name = "conda-forge::xtensor"
|
spec_name = "conda-forge::xtensor"
|
||||||
rc_file = tmp_path / "rc.yaml"
|
rc_file = tmp_path / "rc.yaml"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue