mirror of https://github.com/mamba-org/mamba.git
Simplify MPool Interface (#3177)
* Remove some use to MPool::ChannelContext * Explicit palette in UnSolvable * Explicit option for use_only_tar_bz2 in Pool * Remove context from Pool * Remove Context capture in Pool * Remove ChannelContext capture in Pool * Silence warnings * Chane Unsolvable to use solv::ObjPool * Fine grain control of MPoll raw access * Remove MPool::id2pkginfo * Remove MPool::matchspec2id and select_solvables * Remove MPool::dep2str * Auto create_whatprovides in repoquery * Remove MPool::create_whatprovides * Change MPool::remove_repo API * Private libsolv
This commit is contained in:
parent
b3cb456764
commit
a2a2d26445
|
@ -446,13 +446,13 @@ macro(libmamba_create_target target_name linkage output_name)
|
|||
|
||||
target_link_libraries(
|
||||
${target_name}
|
||||
PUBLIC
|
||||
fmt::fmt-header-only
|
||||
spdlog::spdlog_header_only
|
||||
yaml-cpp::yaml-cpp
|
||||
PUBLIC fmt::fmt-header-only spdlog::spdlog_header_only yaml-cpp::yaml-cpp
|
||||
PRIVATE
|
||||
reproc
|
||||
reproc++
|
||||
simdjson::simdjson_static
|
||||
solv::libsolv_static
|
||||
solv::libsolvext_static
|
||||
PRIVATE reproc reproc++ simdjson::simdjson_static
|
||||
)
|
||||
|
||||
if(UNIX)
|
||||
|
@ -589,8 +589,6 @@ macro(libmamba_create_target target_name linkage output_name)
|
|||
# only version to avoid chasing after the correct fmt version mathching the one used
|
||||
# in the bundle
|
||||
spdlog::spdlog_header_only
|
||||
solv::libsolv
|
||||
solv::libsolvext
|
||||
PRIVATE
|
||||
${LibArchive_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
|
@ -600,6 +598,8 @@ macro(libmamba_create_target target_name linkage output_name)
|
|||
reproc++
|
||||
simdjson::simdjson
|
||||
zstd::libzstd_shared
|
||||
solv::libsolv
|
||||
solv::libsolvext
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -749,8 +749,6 @@ install(
|
|||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
DESTINATION ${LIBMAMBA_CMAKECONFIG_INSTALL_DIR}
|
||||
)
|
||||
# Need to install the FindLibsolv for the installed target to work
|
||||
install(FILES "../cmake/modules/FindLibsolv.cmake" DESTINATION ${LIBMAMBA_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
|
|
|
@ -12,10 +12,15 @@
|
|||
namespace mamba
|
||||
{
|
||||
class Context;
|
||||
class ChannelContext;
|
||||
class MPool;
|
||||
class MultiPackageCache;
|
||||
|
||||
expected_t<void, mamba_aggregated_error>
|
||||
load_channels(Context& ctx, MPool& pool, MultiPackageCache& package_caches);
|
||||
auto load_channels( //
|
||||
Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
MultiPackageCache& package_caches
|
||||
) -> expected_t<void, mamba_aggregated_error>;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
namespace mamba
|
||||
{
|
||||
|
||||
struct Palette
|
||||
{
|
||||
/** Something that is possible or exsists. */
|
||||
|
@ -45,21 +44,21 @@ namespace mamba
|
|||
fmt::text_style progress_bar_extracted;
|
||||
|
||||
/** A Palette with no colors at all. */
|
||||
static constexpr Palette no_color();
|
||||
static constexpr auto no_color() -> Palette;
|
||||
/** A Palette with terminal 4 bit colors. */
|
||||
static constexpr Palette terminal();
|
||||
static constexpr auto terminal() -> Palette;
|
||||
};
|
||||
|
||||
/*******************************
|
||||
* Implementation of Palette *
|
||||
*******************************/
|
||||
|
||||
inline constexpr Palette Palette::no_color()
|
||||
inline constexpr auto Palette::no_color() -> Palette
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
inline constexpr Palette Palette::terminal()
|
||||
inline constexpr auto Palette::terminal() -> Palette
|
||||
{
|
||||
return {
|
||||
/* .success= */ fmt::fg(fmt::terminal_color::green),
|
||||
|
|
|
@ -7,20 +7,19 @@
|
|||
#ifndef MAMBA_CORE_POOL_HPP
|
||||
#define MAMBA_CORE_POOL_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <solv/pooltypes.h>
|
||||
|
||||
#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 ChannelContext;
|
||||
class Context;
|
||||
class PrefixData;
|
||||
class SubdirData;
|
||||
|
@ -40,6 +39,12 @@ namespace mamba
|
|||
class MatchSpec;
|
||||
}
|
||||
|
||||
namespace solver::libsolv
|
||||
{
|
||||
class Solver;
|
||||
class UnSolvable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pool of solvable involved in resolving en environment.
|
||||
*
|
||||
|
@ -52,26 +57,20 @@ namespace mamba
|
|||
{
|
||||
public:
|
||||
|
||||
MPool(Context& ctx, ChannelContext& channel_context);
|
||||
using logger_type = std::function<void(solver::libsolv::LogLevel, std::string_view)>;
|
||||
|
||||
MPool(specs::ChannelResolveParams channel_params);
|
||||
~MPool();
|
||||
|
||||
void set_debuglevel();
|
||||
void create_whatprovides();
|
||||
[[nodiscard]] auto channel_params() const -> const specs::ChannelResolveParams&;
|
||||
|
||||
std::vector<Id> select_solvables(Id id, bool sorted = false) const;
|
||||
Id matchspec2id(const specs::MatchSpec& ms);
|
||||
|
||||
std::optional<specs::PackageInfo> id2pkginfo(Id solv_id) const;
|
||||
std::optional<std::string> dep2str(Id dep_id) const;
|
||||
|
||||
// TODO: (TMP) This is not meant to be public but is needed for a transition period
|
||||
solv::ObjPool& pool();
|
||||
const solv::ObjPool& pool() const;
|
||||
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>;
|
||||
|
||||
|
@ -109,7 +108,7 @@ namespace mamba
|
|||
void
|
||||
set_repo_priority(solver::libsolv::RepoInfo repo, solver::libsolv::Priorities priorities);
|
||||
|
||||
void remove_repo(::Id repo_id, bool reuse_ids);
|
||||
void remove_repo(solver::libsolv::RepoInfo repo);
|
||||
|
||||
template <typename Func>
|
||||
void for_each_package_in_repo(solver::libsolv::RepoInfo repo, Func&&) const;
|
||||
|
@ -120,14 +119,20 @@ namespace mamba
|
|||
template <typename Func>
|
||||
void for_each_package_depending_on(const specs::MatchSpec& ms, Func&&);
|
||||
|
||||
ChannelContext& channel_context() const;
|
||||
const Context& context() const;
|
||||
/** 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).
|
||||
*
|
||||
|
@ -142,6 +147,10 @@ namespace mamba
|
|||
*/
|
||||
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,
|
||||
|
@ -167,6 +176,8 @@ namespace mamba
|
|||
};
|
||||
|
||||
// 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>;
|
||||
|
||||
|
|
|
@ -25,6 +25,20 @@ namespace mamba::solver::libsolv
|
|||
Yes = true,
|
||||
};
|
||||
|
||||
enum class UseOnlyTarBz2
|
||||
{
|
||||
No = false,
|
||||
Yes = true,
|
||||
};
|
||||
|
||||
enum class LogLevel
|
||||
{
|
||||
Debug,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal,
|
||||
};
|
||||
|
||||
struct Priorities
|
||||
{
|
||||
using value_type = int;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
namespace mamba
|
||||
{
|
||||
class MPool;
|
||||
class Palette;
|
||||
|
||||
namespace solv
|
||||
{
|
||||
|
@ -46,8 +47,13 @@ namespace mamba::solver::libsolv
|
|||
|
||||
[[nodiscard]] auto problems_graph(const MPool& pool) const -> ProblemsGraph;
|
||||
|
||||
auto explain_problems_to(MPool& pool, std::ostream& out) const -> std::ostream&;
|
||||
[[nodiscard]] auto explain_problems(MPool& pool) const -> std::string;
|
||||
auto explain_problems_to( //
|
||||
MPool& pool,
|
||||
std::ostream& out,
|
||||
const Palette& palette
|
||||
) const -> std::ostream&;
|
||||
|
||||
[[nodiscard]] auto explain_problems(MPool& pool, const Palette& palette) const -> std::string;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ find_dependency(tl-expected)
|
|||
find_dependency(nlohmann_json)
|
||||
find_dependency(yaml-cpp)
|
||||
find_dependency(reproc++)
|
||||
find_dependency(Libsolv MODULE)
|
||||
|
||||
if(NOT (TARGET libmamba-dyn OR TARGET libmamba-static))
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/core/prefix_data.hpp"
|
||||
#include "mamba/core/subdirdata.hpp"
|
||||
#include "mamba/download/downloader.hpp"
|
||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||
#include "mamba/specs/package_info.hpp"
|
||||
|
||||
|
@ -19,15 +18,19 @@ namespace mamba
|
|||
{
|
||||
namespace
|
||||
{
|
||||
solver::libsolv::RepoInfo
|
||||
create_repo_from_pkgs_dir(const Context& ctx, MPool& pool, const fs::u8path& pkgs_dir)
|
||||
auto create_repo_from_pkgs_dir(
|
||||
const Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
const fs::u8path& pkgs_dir
|
||||
) -> solver::libsolv::RepoInfo
|
||||
{
|
||||
if (!fs::exists(pkgs_dir))
|
||||
{
|
||||
// TODO : us tl::expected mechanis
|
||||
throw std::runtime_error("Specified pkgs_dir does not exist\n");
|
||||
}
|
||||
auto sprefix_data = PrefixData::create(pkgs_dir, pool.channel_context());
|
||||
auto sprefix_data = PrefixData::create(pkgs_dir, channel_context);
|
||||
if (!sprefix_data)
|
||||
{
|
||||
throw std::runtime_error("Specified pkgs_dir does not exist\n");
|
||||
|
@ -106,8 +109,13 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
|
||||
expected_t<void, mamba_aggregated_error>
|
||||
load_channels_impl(Context& ctx, MPool& pool, MultiPackageCache& package_caches, bool is_retry)
|
||||
auto load_channels_impl(
|
||||
Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
MultiPackageCache& package_caches,
|
||||
bool is_retry
|
||||
) -> expected_t<void, mamba_aggregated_error>
|
||||
{
|
||||
std::vector<SubdirData> subdirs;
|
||||
|
||||
|
@ -121,12 +129,12 @@ namespace mamba
|
|||
|
||||
for (const auto& mirror : ctx.mirrored_channels)
|
||||
{
|
||||
for (auto channel : pool.channel_context().make_channel(mirror.first, mirror.second))
|
||||
for (auto channel : channel_context.make_channel(mirror.first, mirror.second))
|
||||
{
|
||||
create_mirrors(channel, ctx.mirrors);
|
||||
create_subdirs(
|
||||
ctx,
|
||||
pool.channel_context(),
|
||||
channel_context,
|
||||
channel,
|
||||
package_caches,
|
||||
subdirs,
|
||||
|
@ -145,7 +153,7 @@ namespace mamba
|
|||
// TODO: C++20, replace with contains
|
||||
if (ctx.mirrored_channels.find(location) == ctx.mirrored_channels.end())
|
||||
{
|
||||
for (auto channel : pool.channel_context().make_channel(location))
|
||||
for (auto channel : channel_context.make_channel(location))
|
||||
{
|
||||
if (channel.is_package())
|
||||
{
|
||||
|
@ -157,7 +165,7 @@ namespace mamba
|
|||
create_mirrors(channel, ctx.mirrors);
|
||||
create_subdirs(
|
||||
ctx,
|
||||
pool.channel_context(),
|
||||
channel_context,
|
||||
channel,
|
||||
package_caches,
|
||||
subdirs,
|
||||
|
@ -203,7 +211,7 @@ namespace mamba
|
|||
LOG_INFO << "Creating repo from pkgs_dir for offline";
|
||||
for (const auto& c : ctx.pkgs_dirs)
|
||||
{
|
||||
create_repo_from_pkgs_dir(ctx, pool, c);
|
||||
create_repo_from_pkgs_dir(ctx, channel_context, pool, c);
|
||||
}
|
||||
}
|
||||
std::string prev_channel;
|
||||
|
@ -255,12 +263,12 @@ namespace mamba
|
|||
if (!ctx.offline && !is_retry)
|
||||
{
|
||||
LOG_WARNING << "Encountered malformed repodata.json cache. Redownloading.";
|
||||
return load_channels_impl(ctx, pool, package_caches, true);
|
||||
return load_channels_impl(ctx, channel_context, pool, package_caches, true);
|
||||
}
|
||||
error_list.push_back(mamba_error(
|
||||
error_list.emplace_back(
|
||||
"Could not load repodata. Cache corrupted?",
|
||||
mamba_error_code::repodata_not_loaded
|
||||
));
|
||||
);
|
||||
}
|
||||
using return_type = expected_t<void, mamba_aggregated_error>;
|
||||
return error_list.empty() ? return_type()
|
||||
|
@ -268,9 +276,10 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
|
||||
expected_t<void, mamba_aggregated_error>
|
||||
load_channels(Context& ctx, MPool& pool, MultiPackageCache& package_caches)
|
||||
auto
|
||||
load_channels(Context& ctx, ChannelContext& channel_context, MPool& pool, MultiPackageCache& package_caches)
|
||||
-> expected_t<void, mamba_aggregated_error>
|
||||
{
|
||||
return load_channels_impl(ctx, pool, package_caches, false);
|
||||
return load_channels_impl(ctx, channel_context, pool, package_caches, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -530,7 +530,8 @@ namespace mamba
|
|||
LOG_WARNING << "No 'channels' specified";
|
||||
}
|
||||
|
||||
MPool pool{ ctx, channel_context };
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
// functions implied in 'and_then' coding-styles must return the same type
|
||||
// which limits this syntax
|
||||
/*auto exp_prefix_data = load_channels(pool, package_caches)
|
||||
|
@ -538,16 +539,13 @@ namespace mamba
|
|||
PrefixData::create(ctx.prefix_params.target_prefix); } ) .map_error([](const
|
||||
mamba_error& err) { throw std::runtime_error(err.what());
|
||||
});*/
|
||||
auto exp_load = load_channels(ctx, pool, package_caches);
|
||||
auto exp_load = load_channels(ctx, channel_context, pool, package_caches);
|
||||
if (!exp_load)
|
||||
{
|
||||
throw std::runtime_error(exp_load.error().what());
|
||||
}
|
||||
|
||||
auto exp_prefix_data = PrefixData::create(
|
||||
ctx.prefix_params.target_prefix,
|
||||
pool.channel_context()
|
||||
);
|
||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!exp_prefix_data)
|
||||
{
|
||||
throw std::runtime_error(exp_prefix_data.error().what());
|
||||
|
@ -571,7 +569,7 @@ namespace mamba
|
|||
|
||||
if (auto* unsolvable = std::get_if<solver::libsolv::UnSolvable>(&outcome))
|
||||
{
|
||||
unsolvable->explain_problems_to(pool, LOG_ERROR);
|
||||
unsolvable->explain_problems_to(pool, LOG_ERROR, ctx.graphics_params.palette);
|
||||
if (retry_clean_cache && !is_retry)
|
||||
{
|
||||
ctx.local_repodata_ttl = 2;
|
||||
|
@ -686,7 +684,9 @@ namespace mamba
|
|||
bool remove_prefix_on_failure
|
||||
)
|
||||
{
|
||||
MPool pool{ ctx, channel_context };
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
|
||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
||||
if (!exp_prefix_data)
|
||||
{
|
||||
|
|
|
@ -127,8 +127,8 @@ namespace mamba
|
|||
}
|
||||
PrefixData& prefix_data = exp_prefix_data.value();
|
||||
|
||||
MPool pool{ ctx, channel_context };
|
||||
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
||||
|
||||
const fs::u8path pkgs_dirs(ctx.prefix_params.root_prefix / "pkgs");
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include <solv/solver.h>
|
||||
|
||||
#include "mamba/api/channel_loader.hpp"
|
||||
#include "mamba/api/configuration.hpp"
|
||||
#include "mamba/api/repoquery.hpp"
|
||||
|
@ -30,7 +28,8 @@ namespace mamba
|
|||
config.load();
|
||||
|
||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||
MPool pool{ ctx, channel_context };
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
|
||||
// bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds);
|
||||
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||
|
@ -66,13 +65,12 @@ namespace mamba
|
|||
{
|
||||
Console::stream() << "Getting repodata from channels..." << std::endl;
|
||||
}
|
||||
auto exp_load = load_channels(ctx, pool, package_caches);
|
||||
auto exp_load = load_channels(ctx, channel_context, pool, package_caches);
|
||||
if (!exp_load)
|
||||
{
|
||||
throw std::runtime_error(exp_load.error().what());
|
||||
}
|
||||
}
|
||||
pool.create_whatprovides();
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,10 +106,12 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
|
||||
MPool pool{ ctx, channel_context };
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
|
||||
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||
|
||||
auto exp_loaded = load_channels(ctx, pool, package_caches);
|
||||
auto exp_loaded = load_channels(ctx, channel_context, pool, package_caches);
|
||||
if (!exp_loaded)
|
||||
{
|
||||
throw std::runtime_error(exp_loaded.error().what());
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
//
|
||||
// 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>
|
||||
|
@ -33,138 +36,100 @@ namespace mamba
|
|||
{
|
||||
struct MPool::MPoolData
|
||||
{
|
||||
MPoolData(Context& ctx, ChannelContext& cc)
|
||||
: context(ctx)
|
||||
, channel_context(cc)
|
||||
MPoolData(specs::ChannelResolveParams p_channel_params)
|
||||
: channel_params(std::move(p_channel_params))
|
||||
{
|
||||
}
|
||||
|
||||
specs::ChannelResolveParams channel_params;
|
||||
solv::ObjPool pool = {};
|
||||
Context& context;
|
||||
ChannelContext& channel_context;
|
||||
};
|
||||
|
||||
MPool::MPool(Context& ctx, ChannelContext& channel_context)
|
||||
: m_data(std::make_shared<MPoolData>(ctx, channel_context))
|
||||
MPool::MPool(specs::ChannelResolveParams channel_params)
|
||||
: m_data(std::make_unique<MPoolData>(std::move(channel_params)))
|
||||
{
|
||||
pool().set_disttype(DISTTYPE_CONDA);
|
||||
set_debuglevel();
|
||||
// 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;
|
||||
|
||||
ChannelContext& MPool::channel_context() const
|
||||
{
|
||||
return m_data->channel_context;
|
||||
}
|
||||
|
||||
const Context& MPool::context() const
|
||||
{
|
||||
return m_data->context;
|
||||
}
|
||||
|
||||
solv::ObjPool& MPool::pool()
|
||||
auto MPool::pool() -> solv::ObjPool&
|
||||
{
|
||||
return m_data->pool;
|
||||
}
|
||||
|
||||
const solv::ObjPool& MPool::pool() const
|
||||
auto MPool::pool() const -> const solv::ObjPool&
|
||||
{
|
||||
return m_data->pool;
|
||||
}
|
||||
|
||||
void MPool::set_debuglevel()
|
||||
auto MPool::Impl::get(MPool& pool) -> solv::ObjPool&
|
||||
{
|
||||
// ensure that debug logging goes to stderr as to not interfere with stdout json output
|
||||
pool().raw()->debugmask |= SOLV_DEBUG_TO_STDERR;
|
||||
const auto& ctx = context();
|
||||
if (ctx.output_params.verbosity > 2)
|
||||
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
|
||||
{
|
||||
pool_setdebuglevel(pool().raw(), ctx.output_params.verbosity - 1);
|
||||
pool().set_debug_callback(
|
||||
[logger = spdlog::get("libsolv"), &ctx](::Pool*, int type, std::string_view msg) noexcept
|
||||
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
|
||||
{
|
||||
if (msg.size() == 0 || msg.back() != '\n')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto log = Console::hide_secrets(msg);
|
||||
if (type & SOLV_FATAL || type & SOLV_ERROR)
|
||||
{
|
||||
logger->error(log);
|
||||
}
|
||||
else if (type & SOLV_WARN)
|
||||
{
|
||||
logger->warn(log);
|
||||
}
|
||||
else if (ctx.output_params.verbosity > 2)
|
||||
{
|
||||
logger->info(log);
|
||||
}
|
||||
logger(libsolv_to_log_level(type), msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MPool::create_whatprovides()
|
||||
{
|
||||
pool().create_whatprovides();
|
||||
}
|
||||
|
||||
std::vector<Id> MPool::select_solvables(Id matchspec, bool sorted) const
|
||||
{
|
||||
auto solvables = pool().select_solvables({ SOLVER_SOLVABLE_PROVIDES, matchspec });
|
||||
|
||||
if (sorted)
|
||||
{
|
||||
std::sort(
|
||||
solvables.begin(),
|
||||
solvables.end(),
|
||||
[pool_ptr = pool().raw()](Id a, Id b)
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
Solvable* sa = pool_id2solvable(pool_ptr, a);
|
||||
Solvable* sb = pool_id2solvable(pool_ptr, b);
|
||||
return (pool_evrcmp(pool_ptr, sa->evr, sb->evr, EVRCMP_COMPARE) > 0);
|
||||
std::cerr << "Developer error: error in libsolv logging function: \n"
|
||||
<< e.what();
|
||||
}
|
||||
);
|
||||
}
|
||||
return solvables.as<std::vector>();
|
||||
}
|
||||
|
||||
auto MPool::matchspec2id(const specs::MatchSpec& ms) -> ::Id
|
||||
{
|
||||
return solver::libsolv::pool_add_matchspec(pool(), ms, channel_context().params())
|
||||
.or_else([](mamba_error&& error) { throw std::move(error); })
|
||||
.value_or(0);
|
||||
}
|
||||
|
||||
std::optional<specs::PackageInfo> MPool::id2pkginfo(Id solv_id) const
|
||||
{
|
||||
if (const auto solv = pool().get_solvable(solv_id))
|
||||
{
|
||||
return { solver::libsolv::make_package_info(pool(), solv.value()) };
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> MPool::dep2str(Id dep_id) const
|
||||
{
|
||||
if (!dep_id)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
// Not const because might alloctmp space
|
||||
return pool_dep2str(const_cast<::Pool*>(pool().raw()), dep_id);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
|
@ -184,29 +149,29 @@ namespace mamba
|
|||
repo,
|
||||
path,
|
||||
std::string(url),
|
||||
context().use_only_tar_bz2
|
||||
use_only_tar_bz2
|
||||
);
|
||||
}
|
||||
return solver::libsolv::libsolv_read_json(repo, path, context().use_only_tar_bz2)
|
||||
return solver::libsolv::libsolv_read_json(repo, path, use_only_tar_bz2)
|
||||
.transform(
|
||||
[&url](solv::ObjRepoView repo)
|
||||
[&url](solv::ObjRepoView p_repo)
|
||||
{
|
||||
solver::libsolv::set_solvables_url(repo, std::string(url));
|
||||
return repo;
|
||||
solver::libsolv::set_solvables_url(p_repo, std::string(url));
|
||||
return p_repo;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return make_repo()
|
||||
.transform(
|
||||
[&](solv::ObjRepoView repo) -> solver::libsolv::RepoInfo
|
||||
[&](solv::ObjRepoView p_repo) -> solver::libsolv::RepoInfo
|
||||
{
|
||||
if (add == solver::libsolv::PipAsPythonDependency::Yes)
|
||||
{
|
||||
solver::libsolv::add_pip_as_python_dependency(pool(), repo);
|
||||
solver::libsolv::add_pip_as_python_dependency(pool(), p_repo);
|
||||
}
|
||||
repo.internalize();
|
||||
return solver::libsolv::RepoInfo{ repo.raw() };
|
||||
p_repo.internalize();
|
||||
return solver::libsolv::RepoInfo{ p_repo.raw() };
|
||||
}
|
||||
)
|
||||
.or_else([&](const auto&) { pool().remove_repo(repo.id(), /* reuse_ids= */ true); });
|
||||
|
@ -222,16 +187,16 @@ namespace mamba
|
|||
|
||||
return solver::libsolv::read_solv(pool(), repo, path, expected, static_cast<bool>(add))
|
||||
.transform(
|
||||
[&](solv::ObjRepoView repo) -> solver::libsolv::RepoInfo
|
||||
[&](solv::ObjRepoView p_repo) -> solver::libsolv::RepoInfo
|
||||
{
|
||||
repo.set_url(expected.url);
|
||||
solver::libsolv::set_solvables_url(repo, expected.url);
|
||||
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(), repo);
|
||||
solver::libsolv::add_pip_as_python_dependency(pool(), p_repo);
|
||||
}
|
||||
repo.internalize();
|
||||
return solver::libsolv::RepoInfo(repo.raw());
|
||||
p_repo.internalize();
|
||||
return solver::libsolv::RepoInfo(p_repo.raw());
|
||||
}
|
||||
)
|
||||
.or_else([&](const auto&) { pool().remove_repo(repo.id(), /* reuse_ids= */ true); });
|
||||
|
@ -279,12 +244,13 @@ namespace mamba
|
|||
{
|
||||
assert(repo.m_ptr != nullptr);
|
||||
return solver::libsolv::write_solv(solv::ObjRepoView(*repo.m_ptr), path, metadata)
|
||||
.transform([](solv::ObjRepoView repo) { return solver::libsolv::RepoInfo(repo.raw()); });
|
||||
.transform([](solv::ObjRepoView solv_repo)
|
||||
{ return solver::libsolv::RepoInfo(solv_repo.raw()); });
|
||||
}
|
||||
|
||||
void MPool::remove_repo(::Id repo_id, bool reuse_ids)
|
||||
void MPool::remove_repo(solver::libsolv::RepoInfo repo)
|
||||
{
|
||||
pool().remove_repo(repo_id, reuse_ids);
|
||||
pool().remove_repo(repo.id(), /* reuse_ids= */ true);
|
||||
}
|
||||
|
||||
auto MPool::installed_repo() const -> std::optional<solver::libsolv::RepoInfo>
|
||||
|
@ -316,8 +282,9 @@ namespace mamba
|
|||
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>);
|
||||
// Safe because the ID is coming from libsolv
|
||||
return id2pkginfo(static_cast<solv::SolvableId>(id)).value();
|
||||
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>
|
||||
|
@ -330,12 +297,26 @@ namespace mamba
|
|||
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(ms);
|
||||
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(
|
||||
|
@ -352,7 +333,7 @@ namespace mamba
|
|||
static_assert(std::is_same_v<std::underlying_type_t<PackageId>, solv::SolvableId>);
|
||||
|
||||
pool().ensure_whatprovides();
|
||||
const auto ms_id = matchspec2id(ms);
|
||||
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(
|
||||
|
@ -365,6 +346,31 @@ namespace mamba
|
|||
}
|
||||
|
||||
// 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>
|
||||
{
|
||||
|
@ -408,6 +414,7 @@ namespace mamba
|
|||
repodata_json,
|
||||
util::rsplit(subdir.metadata().url(), "/", 1).front(),
|
||||
add_pip,
|
||||
static_cast<solver::libsolv::UseOnlyTarBz2>(ctx.use_only_tar_bz2),
|
||||
json_parser
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,18 +6,14 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <solv/conda.h>
|
||||
#include <solv/pool.h>
|
||||
#include <solv/poolid.h>
|
||||
#include <solv/pooltypes.h>
|
||||
#include <solv/repo.h>
|
||||
#include <solv/selection.h>
|
||||
extern "C" // Incomplete header
|
||||
{
|
||||
#include <solv/conda.h>
|
||||
}
|
||||
|
||||
#include "solv-cpp/pool.hpp"
|
||||
|
||||
|
|
|
@ -622,7 +622,7 @@ namespace mamba::solver::libsolv
|
|||
}
|
||||
|
||||
// conda_build_form does **NOT** contain the channel info
|
||||
const solv::DependencyId match = pool_conda_matchspec(
|
||||
const solv::DependencyId match_id = pool_conda_matchspec(
|
||||
pool.raw(),
|
||||
ms.conda_build_form().c_str()
|
||||
);
|
||||
|
@ -632,7 +632,7 @@ namespace mamba::solver::libsolv
|
|||
solv::ObjQueue selected_pkgs = {};
|
||||
auto other_subdir_match = std::string();
|
||||
pool.for_each_whatprovides(
|
||||
match,
|
||||
match_id,
|
||||
[&](solv::ObjSolvableViewConst s)
|
||||
{
|
||||
if (s.installed())
|
||||
|
@ -1021,7 +1021,7 @@ namespace mamba::solver::libsolv
|
|||
|
||||
auto installed_python(const solv::ObjPool& pool) -> std::optional<solv::ObjSolvableViewConst>
|
||||
{
|
||||
auto py_id = solv::SolvableId(0);
|
||||
auto py_id = solv::SolvableId{ 0 };
|
||||
pool.for_each_installed_solvable(
|
||||
[&](solv::ObjSolvableViewConst s)
|
||||
{
|
||||
|
|
|
@ -53,8 +53,8 @@ namespace mamba::solver::libsolv
|
|||
|
||||
auto Solver::solve_impl(MPool& mpool, const Request& request) -> expected_t<Outcome>
|
||||
{
|
||||
auto& pool = mpool.pool();
|
||||
const auto& chan_params = mpool.channel_context().params();
|
||||
auto& pool = MPool::Impl::get(mpool);
|
||||
const auto& chan_params = mpool.channel_params();
|
||||
const auto& flags = request.flags;
|
||||
|
||||
return solver::libsolv::request_to_decision_queue(request, pool, chan_params, flags.force_reinstall)
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
#include <vector>
|
||||
|
||||
#include <solv/problems.h>
|
||||
#include <solv/solver.h>
|
||||
|
||||
#include "mamba/core/context.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/palette.hpp"
|
||||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/solver/libsolv/unsolvable.hpp"
|
||||
#include "mamba/specs/match_spec.hpp"
|
||||
|
@ -19,6 +20,8 @@
|
|||
#include "solv-cpp/pool.hpp"
|
||||
#include "solv-cpp/solver.hpp"
|
||||
|
||||
#include "solver/libsolv/helpers.hpp"
|
||||
|
||||
namespace mamba::solver::libsolv
|
||||
{
|
||||
UnSolvable::UnSolvable(std::unique_ptr<solv::ObjSolver>&& solver)
|
||||
|
@ -38,37 +41,39 @@ namespace mamba::solver::libsolv
|
|||
return *m_solver;
|
||||
}
|
||||
|
||||
auto UnSolvable::problems(MPool& pool) const -> std::vector<std::string>
|
||||
auto UnSolvable::problems(MPool& mpool) const -> std::vector<std::string>
|
||||
{
|
||||
auto& pool = MPool::Impl::get(mpool);
|
||||
std::vector<std::string> problems;
|
||||
solver().for_each_problem_id(
|
||||
[&](solv::ProblemId pb)
|
||||
{ problems.emplace_back(solver().problem_to_string(pool.pool(), pb)); }
|
||||
solver().for_each_problem_id([&](solv::ProblemId pb)
|
||||
{ problems.emplace_back(solver().problem_to_string(pool, pb)); }
|
||||
);
|
||||
return problems;
|
||||
}
|
||||
|
||||
auto UnSolvable::problems_to_str(MPool& pool) const -> std::string
|
||||
auto UnSolvable::problems_to_str(MPool& mpool) const -> std::string
|
||||
{
|
||||
auto& pool = MPool::Impl::get(mpool);
|
||||
std::stringstream problems;
|
||||
problems << "Encountered problems while solving:\n";
|
||||
solver().for_each_problem_id(
|
||||
[&](solv::ProblemId pb)
|
||||
{ problems << " - " << solver().problem_to_string(pool.pool(), pb) << "\n"; }
|
||||
{ problems << " - " << solver().problem_to_string(pool, pb) << "\n"; }
|
||||
);
|
||||
return problems.str();
|
||||
}
|
||||
|
||||
auto UnSolvable::all_problems_to_str(MPool& pool) const -> std::string
|
||||
auto UnSolvable::all_problems_to_str(MPool& mpool) const -> std::string
|
||||
{
|
||||
auto& pool = MPool::Impl::get(mpool);
|
||||
std::stringstream problems;
|
||||
solver().for_each_problem_id(
|
||||
[&](solv::ProblemId pb)
|
||||
{
|
||||
for (solv::RuleId const rule : solver().problem_rules(pb))
|
||||
{
|
||||
auto const info = solver().get_rule_info(pool.pool(), rule);
|
||||
problems << " - " << solver().rule_info_to_string(pool.pool(), info) << "\n";
|
||||
auto const info = solver().get_rule_info(pool, rule);
|
||||
problems << " - " << solver().rule_info_to_string(pool, info) << "\n";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -77,6 +82,28 @@ namespace mamba::solver::libsolv
|
|||
|
||||
namespace
|
||||
{
|
||||
auto pool_id_to_package_info( //
|
||||
const solv::ObjPool& pool,
|
||||
solv::SolvableId id
|
||||
) -> std::optional<specs::PackageInfo>
|
||||
{
|
||||
if (const auto solv = pool.get_solvable(id))
|
||||
{
|
||||
return { solver::libsolv::make_package_info(pool, solv.value()) };
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto pool_dependency_to_string(const solv::ObjPool& pool, solv::SolvableId id)
|
||||
-> std::optional<std::string>
|
||||
{
|
||||
if (!id)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
return { pool.dependency_to_string(id) };
|
||||
}
|
||||
|
||||
struct SolverProblem
|
||||
{
|
||||
SolverRuleinfo type;
|
||||
|
@ -89,14 +116,13 @@ namespace mamba::solver::libsolv
|
|||
std::string description;
|
||||
};
|
||||
|
||||
// TODO change MSolver problem
|
||||
auto make_solver_problem(
|
||||
const solv::ObjSolver& solver,
|
||||
const MPool& pool,
|
||||
SolverRuleinfo type,
|
||||
Id source_id,
|
||||
Id target_id,
|
||||
Id dep_id
|
||||
const solv::ObjPool& pool,
|
||||
::SolverRuleinfo type,
|
||||
solv::SolvableId source_id,
|
||||
solv::SolvableId target_id,
|
||||
solv::DependencyId dep_id
|
||||
) -> SolverProblem
|
||||
{
|
||||
return {
|
||||
|
@ -104,9 +130,9 @@ namespace mamba::solver::libsolv
|
|||
/* .source_id= */ source_id,
|
||||
/* .target_id= */ target_id,
|
||||
/* .dep_id= */ dep_id,
|
||||
/* .source= */ pool.id2pkginfo(source_id),
|
||||
/* .target= */ pool.id2pkginfo(target_id),
|
||||
/* .dep= */ pool.dep2str(dep_id),
|
||||
/* .source= */ pool_id_to_package_info(pool, source_id),
|
||||
/* .target= */ pool_id_to_package_info(pool, target_id),
|
||||
/* .dep= */ pool_dependency_to_string(pool, dep_id),
|
||||
/* .description= */
|
||||
::solver_problemruleinfo2str(
|
||||
const_cast<::Solver*>(solver.raw()), // Not const because might alloctmp space
|
||||
|
@ -118,7 +144,7 @@ namespace mamba::solver::libsolv
|
|||
};
|
||||
}
|
||||
|
||||
auto all_problems_structured(const MPool& pool, const solv::ObjSolver& solver)
|
||||
auto all_problems_structured(const solv::ObjPool& pool, const solv::ObjSolver& solver)
|
||||
-> std::vector<SolverProblem>
|
||||
{
|
||||
std::vector<SolverProblem> res = {};
|
||||
|
@ -128,7 +154,7 @@ namespace mamba::solver::libsolv
|
|||
{
|
||||
for (solv::RuleId const rule : solver.problem_rules(pb))
|
||||
{
|
||||
auto info = solver.get_rule_info(pool.pool(), rule);
|
||||
auto info = solver.get_rule_info(pool, rule);
|
||||
res.push_back(make_solver_problem(
|
||||
/* solver= */ solver,
|
||||
/* pool= */ pool,
|
||||
|
@ -165,14 +191,14 @@ namespace mamba::solver::libsolv
|
|||
using edge_t = ProblemsGraph::edge_t;
|
||||
using conflicts_t = ProblemsGraph::conflicts_t;
|
||||
|
||||
ProblemsGraphCreator(const MPool& pool, const solv::ObjSolver& solver);
|
||||
ProblemsGraphCreator(const solv::ObjPool& pool, const solv::ObjSolver& solver);
|
||||
|
||||
auto problem_graph() && -> ProblemsGraph;
|
||||
|
||||
private:
|
||||
|
||||
const solv::ObjSolver& m_solver;
|
||||
const MPool& m_pool;
|
||||
const solv::ObjPool& m_pool;
|
||||
graph_t m_graph;
|
||||
conflicts_t m_conflicts;
|
||||
std::map<solv::SolvableId, node_id> m_solv2node;
|
||||
|
@ -201,7 +227,7 @@ namespace mamba::solver::libsolv
|
|||
void parse_problems();
|
||||
};
|
||||
|
||||
ProblemsGraphCreator::ProblemsGraphCreator(const MPool& pool, const solv::ObjSolver& solver)
|
||||
ProblemsGraphCreator::ProblemsGraphCreator(const solv::ObjPool& pool, const solv::ObjSolver& solver)
|
||||
: m_solver{ solver }
|
||||
, m_pool{ pool }
|
||||
{
|
||||
|
@ -246,10 +272,10 @@ namespace mamba::solver::libsolv
|
|||
) -> bool
|
||||
{
|
||||
bool added = false;
|
||||
for (const auto& solv_id : m_pool.select_solvables(dep_id))
|
||||
for (const auto& solv_id : m_pool.select_solvables({ SOLVER_SOLVABLE_PROVIDES, dep_id }))
|
||||
{
|
||||
added = true;
|
||||
auto pkg_info = m_pool.id2pkginfo(solv_id);
|
||||
auto pkg_info = pool_id_to_package_info(m_pool, solv_id);
|
||||
assert(pkg_info.has_value());
|
||||
node_id to_id = add_solvable(solv_id, PackageNode{ std::move(pkg_info).value() }, false);
|
||||
m_graph.add_edge(from_id, to_id, edge);
|
||||
|
@ -420,8 +446,8 @@ namespace mamba::solver::libsolv
|
|||
// dependency.
|
||||
auto edge = specs::MatchSpec::parse(source.value().name);
|
||||
// The package cannot exist without its name in the pool
|
||||
assert(m_pool.pool().find_string(edge.name().str()).has_value());
|
||||
const auto dep_id = m_pool.pool().find_string(edge.name().str()).value();
|
||||
assert(m_pool.find_string(edge.name().str()).has_value());
|
||||
const auto dep_id = m_pool.find_string(edge.name().str()).value();
|
||||
const bool added = add_expanded_deps_edges(m_root_node, dep_id, edge);
|
||||
if (!added)
|
||||
{
|
||||
|
@ -444,12 +470,12 @@ namespace mamba::solver::libsolv
|
|||
auto UnSolvable::problems_graph(const MPool& pool) const -> ProblemsGraph
|
||||
{
|
||||
assert(m_solver != nullptr);
|
||||
return ProblemsGraphCreator(pool, *m_solver).problem_graph();
|
||||
return ProblemsGraphCreator(MPool::Impl::get(pool), *m_solver).problem_graph();
|
||||
}
|
||||
|
||||
auto UnSolvable::explain_problems_to(MPool& pool, std::ostream& out) const -> std::ostream&
|
||||
auto UnSolvable::explain_problems_to(MPool& pool, std::ostream& out, const Palette& palette) const
|
||||
-> std::ostream&
|
||||
{
|
||||
const auto& ctx = pool.context();
|
||||
out << "Could not solve for environment specs\n";
|
||||
const auto pbs = problems_graph(pool);
|
||||
const auto pbs_simplified = simplify_conflicts(pbs);
|
||||
|
@ -457,16 +483,19 @@ namespace mamba::solver::libsolv
|
|||
print_problem_tree_msg(
|
||||
out,
|
||||
cp_pbs,
|
||||
{ /* .unavailable= */ ctx.graphics_params.palette.failure,
|
||||
/* .available= */ ctx.graphics_params.palette.success }
|
||||
{
|
||||
/* .unavailable= */ palette.failure,
|
||||
/* .available= */ palette.success,
|
||||
}
|
||||
);
|
||||
return out;
|
||||
}
|
||||
|
||||
auto UnSolvable::explain_problems(MPool& pool) const -> std::string
|
||||
auto UnSolvable::explain_problems(MPool& pool, const Palette& palette) const -> std::string
|
||||
|
||||
{
|
||||
std::stringstream ss;
|
||||
explain_problems_to(pool, ss);
|
||||
explain_problems_to(pool, ss, palette);
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,11 +104,12 @@ target_include_directories(
|
|||
|
||||
find_package(doctest REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(Libsolv REQUIRED)
|
||||
|
||||
target_link_libraries(
|
||||
test_libmamba
|
||||
PUBLIC mamba::libmamba reproc reproc++
|
||||
PRIVATE doctest::doctest Threads::Threads
|
||||
PRIVATE doctest::doctest Threads::Threads solv::libsolv solv::libsolvext
|
||||
)
|
||||
|
||||
# Copy data directory into binary dir to avoid modifications
|
||||
|
|
|
@ -126,7 +126,8 @@ namespace mamba
|
|||
const fs::u8path lockfile_path{ mambatests::test_data_dir
|
||||
/ "env_lockfile/good_multiple_categories-lock.yaml" };
|
||||
auto channel_context = ChannelContext::make_conda_compatible(mambatests::context());
|
||||
MPool pool{ ctx, channel_context };
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
mamba::MultiPackageCache pkg_cache({ "/tmp/" }, ctx.validation_params);
|
||||
|
||||
ctx.platform = "linux-64";
|
||||
|
|
|
@ -102,9 +102,9 @@ namespace
|
|||
* The underlying packages do not exist, we are onl interested in the conflict.
|
||||
*/
|
||||
template <typename PkgRange>
|
||||
auto create_pkgs_pool(Context& ctx, ChannelContext& channel_context, const PkgRange& packages)
|
||||
auto create_pkgs_pool(ChannelContext& channel_context, const PkgRange& packages)
|
||||
{
|
||||
auto pool = MPool{ ctx, channel_context };
|
||||
MPool pool{ channel_context.params() };
|
||||
pool.add_repo_from_packages(packages);
|
||||
return pool;
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ TEST_CASE("Test create_pool utility")
|
|||
{
|
||||
auto& ctx = mambatests::context();
|
||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||
auto pool = create_pkgs_pool(ctx, channel_context, std::array{ mkpkg("foo", "0.1.0", {}) });
|
||||
auto pool = create_pkgs_pool(channel_context, std::array{ mkpkg("foo", "0.1.0", {}) });
|
||||
auto request = Request{ {}, { Request::Install{ "foo"_ms } } };
|
||||
const auto outcome = solver::libsolv::Solver().solve(pool, request).value();
|
||||
REQUIRE(std::holds_alternative<solver::Solution>(outcome));
|
||||
|
@ -125,7 +125,6 @@ TEST_CASE("Test empty specs")
|
|||
auto& ctx = mambatests::context();
|
||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||
auto pool = create_pkgs_pool(
|
||||
ctx,
|
||||
channel_context,
|
||||
std::array{ mkpkg("foo", "0.1.0", {}), mkpkg("", "", {}) }
|
||||
);
|
||||
|
@ -136,11 +135,10 @@ TEST_CASE("Test empty specs")
|
|||
|
||||
namespace
|
||||
{
|
||||
auto create_basic_conflict(Context& ctx, ChannelContext& channel_context)
|
||||
auto create_basic_conflict(Context&, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_pkgs_pool(
|
||||
ctx,
|
||||
channel_context,
|
||||
std::array{
|
||||
mkpkg("A", "0.1.0"),
|
||||
|
@ -158,11 +156,10 @@ namespace
|
|||
* The example given by Natalie Weizenbaum
|
||||
* (credits https://nex3.medium.com/pubgrub-2fb6470504f).
|
||||
*/
|
||||
auto create_pubgrub(Context& ctx, ChannelContext& channel_context)
|
||||
auto create_pubgrub(Context&, ChannelContext& channel_context)
|
||||
{
|
||||
return std::pair(
|
||||
create_pkgs_pool(
|
||||
ctx,
|
||||
channel_context,
|
||||
std::array{
|
||||
mkpkg("menu", "1.5.0", { "dropdown=2.*" }),
|
||||
|
@ -194,7 +191,7 @@ namespace
|
|||
);
|
||||
}
|
||||
|
||||
auto create_pubgrub_hard_(Context& ctx, ChannelContext& channel_context, bool missing_package)
|
||||
auto create_pubgrub_hard_(Context&, ChannelContext& channel_context, bool missing_package)
|
||||
{
|
||||
auto packages = std::vector{
|
||||
mkpkg("menu", "2.1.0", { "dropdown>=2.1", "emoji" }),
|
||||
|
@ -244,7 +241,7 @@ namespace
|
|||
packages.push_back(mkpkg("dropdown", "2.9.0", { "libicons>10.0" }));
|
||||
}
|
||||
return std::pair(
|
||||
create_pkgs_pool(ctx, channel_context, packages),
|
||||
create_pkgs_pool(channel_context, packages),
|
||||
Request{
|
||||
{},
|
||||
{
|
||||
|
@ -287,19 +284,24 @@ namespace
|
|||
/**
|
||||
* Mock of channel_loader.hpp:load_channels that takes a list of channels.
|
||||
*/
|
||||
auto
|
||||
load_channels(Context& ctx, MPool& pool, MultiPackageCache& cache, std::vector<std::string>&& channels)
|
||||
auto load_channels(
|
||||
Context& ctx,
|
||||
ChannelContext& channel_context,
|
||||
MPool& pool,
|
||||
MultiPackageCache& cache,
|
||||
std::vector<std::string>&& channels
|
||||
)
|
||||
{
|
||||
auto sub_dirs = std::vector<SubdirData>();
|
||||
for (const auto& location : channels)
|
||||
{
|
||||
for (const auto& chan : pool.channel_context().make_channel(location))
|
||||
for (const auto& chan : channel_context.make_channel(location))
|
||||
{
|
||||
for (const auto& platform : chan.platforms())
|
||||
{
|
||||
auto sub_dir = SubdirData::create(
|
||||
ctx,
|
||||
pool.channel_context(),
|
||||
channel_context,
|
||||
chan,
|
||||
platform,
|
||||
chan.platform_url(platform).str(),
|
||||
|
@ -336,7 +338,7 @@ namespace
|
|||
|
||||
auto prefix_data = PrefixData::create(tmp_dir.path() / "prefix", channel_context).value();
|
||||
prefix_data.add_packages(virtual_packages);
|
||||
auto pool = MPool{ ctx, channel_context };
|
||||
auto pool = MPool{ channel_context.params() };
|
||||
|
||||
load_installed_packages_in_pool(ctx, pool, prefix_data);
|
||||
|
||||
|
@ -345,7 +347,13 @@ namespace
|
|||
|
||||
bool prev_progress_bars_value = ctx.graphics_params.no_progress_bars;
|
||||
ctx.graphics_params.no_progress_bars = true;
|
||||
load_channels(ctx, pool, cache, make_platform_channels(std::move(channels), platforms));
|
||||
load_channels(
|
||||
ctx,
|
||||
channel_context,
|
||||
pool,
|
||||
cache,
|
||||
make_platform_channels(std::move(channels), platforms)
|
||||
);
|
||||
ctx.graphics_params.no_progress_bars = prev_progress_bars_value;
|
||||
|
||||
return pool;
|
||||
|
|
|
@ -380,25 +380,15 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
py::add_ostream_redirect(m, "ostream_redirect");
|
||||
|
||||
py::class_<MPool>(m, "Pool")
|
||||
.def(
|
||||
py::init<>(
|
||||
[](ChannelContext& channel_context) {
|
||||
return MPool{ mambapy::singletons.context(), channel_context };
|
||||
}
|
||||
),
|
||||
py::arg("channel_context")
|
||||
)
|
||||
.def("set_debuglevel", &MPool::set_debuglevel)
|
||||
.def("create_whatprovides", &MPool::create_whatprovides)
|
||||
.def("select_solvables", &MPool::select_solvables, py::arg("id"), py::arg("sorted") = false)
|
||||
.def("matchspec2id", &MPool::matchspec2id, py::arg("spec"))
|
||||
.def("id2pkginfo", &MPool::id2pkginfo, py::arg("id"))
|
||||
.def(py::init<specs::ChannelResolveParams>(), py::arg("channel_params"))
|
||||
.def("set_logger", &MPool::set_logger, py::call_guard<py::gil_scoped_acquire>())
|
||||
.def(
|
||||
"add_repo_from_repodata_json",
|
||||
&MPool::add_repo_from_repodata_json,
|
||||
py::arg("path"),
|
||||
py::arg("url"),
|
||||
py::arg("add_pip_as_python_dependency") = solver::libsolv::PipAsPythonDependency::No,
|
||||
py::arg("use_only_tar_bz2") = solver::libsolv::UseOnlyTarBz2::No,
|
||||
py::arg("repodata_parsers") = solver::libsolv::RepodataParser::Mamba
|
||||
)
|
||||
.def(
|
||||
|
@ -655,6 +645,10 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
.def("params", &ChannelContext::params)
|
||||
.def("has_zst", &ChannelContext::has_zst);
|
||||
|
||||
py::class_<Palette>(m, "Palette")
|
||||
.def_static("no_color", &Palette::no_color)
|
||||
.def_static("terminal", &Palette::terminal);
|
||||
|
||||
py::class_<Context, std::unique_ptr<Context, py::nodelete>> ctx(m, "Context");
|
||||
ctx //
|
||||
.def_static(
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <pybind11/operators.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include "mamba/core/palette.hpp"
|
||||
#include "mamba/core/pool.hpp"
|
||||
#include "mamba/solver/libsolv/parameters.hpp"
|
||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||
|
@ -37,6 +38,20 @@ namespace mambapy
|
|||
.def(py::init([](bool val) { return static_cast<PipAsPythonDependency>(val); }));
|
||||
py::implicitly_convertible<py::bool_, PipAsPythonDependency>();
|
||||
|
||||
py::enum_<UseOnlyTarBz2>(m, "UseOnlyTarBz2")
|
||||
.value("No", UseOnlyTarBz2::No)
|
||||
.value("Yes", UseOnlyTarBz2::Yes)
|
||||
.def(py::init([](bool val) { return static_cast<UseOnlyTarBz2>(val); }));
|
||||
py::implicitly_convertible<py::bool_, UseOnlyTarBz2>();
|
||||
|
||||
py::enum_<LogLevel>(m, "LogLevel")
|
||||
.value("Debug", LogLevel::Debug)
|
||||
.value("Warning", LogLevel::Warning)
|
||||
.value("Error", LogLevel::Error)
|
||||
.value("Fatal", LogLevel::Fatal)
|
||||
.def(py::init(&enum_from_str<LogLevel>));
|
||||
py::implicitly_convertible<py::bool_, LogLevel>();
|
||||
|
||||
py::class_<Priorities>(m, "Priorities")
|
||||
.def(
|
||||
py::init(
|
||||
|
|
|
@ -36,6 +36,26 @@ def test_PipASPythonDependency():
|
|||
assert libsolv.PipAsPythonDependency(True) == libsolv.PipAsPythonDependency.Yes
|
||||
|
||||
|
||||
def test_UseOnlyTarBz2():
|
||||
assert libsolv.UseOnlyTarBz2.No.name == "No"
|
||||
assert libsolv.UseOnlyTarBz2.Yes.name == "Yes"
|
||||
|
||||
assert libsolv.UseOnlyTarBz2(True) == libsolv.UseOnlyTarBz2.Yes
|
||||
|
||||
|
||||
def test_Platform():
|
||||
assert libsolv.LogLevel.Debug.name == "Debug"
|
||||
assert libsolv.LogLevel.Warning.name == "Warning"
|
||||
assert libsolv.LogLevel.Error.name == "Error"
|
||||
assert libsolv.LogLevel.Fatal.name == "Fatal"
|
||||
|
||||
assert libsolv.LogLevel("Error") == libsolv.LogLevel.Error
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
# No parsing, explicit name
|
||||
libsolv.LogLevel("Unicorn")
|
||||
|
||||
|
||||
def test_Priorities():
|
||||
p = libsolv.Priorities(priority=-1, subpriority=-2)
|
||||
|
||||
|
|
|
@ -71,16 +71,18 @@ update_self(Configuration& config, const std::optional<std::string>& version)
|
|||
ctx.prefix_params.target_prefix = ctx.prefix_params.root_prefix;
|
||||
|
||||
auto channel_context = ChannelContext::make_conda_compatible(ctx);
|
||||
mamba::MPool pool{ ctx, channel_context };
|
||||
|
||||
MPool pool{ channel_context.params() };
|
||||
add_spdlog_logger_to_pool(pool);
|
||||
|
||||
mamba::MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||
|
||||
auto exp_loaded = load_channels(ctx, pool, package_caches);
|
||||
auto exp_loaded = load_channels(ctx, channel_context, pool, package_caches);
|
||||
if (!exp_loaded)
|
||||
{
|
||||
throw exp_loaded.error();
|
||||
}
|
||||
|
||||
pool.create_whatprovides();
|
||||
auto matchspec = specs::MatchSpec::parse(
|
||||
version ? fmt::format("micromamba={}", version.value())
|
||||
: fmt::format("micromamba>{}", umamba::version())
|
||||
|
|
Loading…
Reference in New Issue