Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Julien Jerphanion <[email protected]>
  • Loading branch information
jjerphan committed Feb 13, 2025
1 parent 304d2ae commit c698d33
Show file tree
Hide file tree
Showing 10 changed files with 775 additions and 46 deletions.
12 changes: 12 additions & 0 deletions libmamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ set(
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/matcher.cpp
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/solver.cpp
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/unsolvable.cpp
# Solver resolvo implementation
${LIBMAMBA_SOURCE_DIR}/solver/resolvo/database.cpp
${LIBMAMBA_SOURCE_DIR}/solver/resolvo/solver.cpp
${LIBMAMBA_SOURCE_DIR}/solver/resolvo/unsolvable.cpp
# Artifacts validation
${LIBMAMBA_SOURCE_DIR}/validation/errors.cpp
${LIBMAMBA_SOURCE_DIR}/validation/keys.cpp
Expand Down Expand Up @@ -348,6 +352,10 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/database.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/solver.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/unsolvable.hpp
# Solver resolvo implementation
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/resolvo/database.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/resolvo/solver.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/resolvo/unsolvable.hpp
# Artifacts validation
${LIBMAMBA_INCLUDE_DIR}/mamba/validation/errors.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/validation/keys.hpp
Expand Down Expand Up @@ -430,6 +438,8 @@ find_package(yaml-cpp CONFIG REQUIRED)
find_package(reproc CONFIG REQUIRED)
find_package(reproc++ CONFIG REQUIRED)
find_package(Libsolv MODULE REQUIRED)
find_package(Resolvo CONFIG REQUIRED)

add_subdirectory(ext/solv-cpp)

macro(libmamba_create_target target_name linkage output_name)
Expand Down Expand Up @@ -478,6 +488,7 @@ macro(libmamba_create_target target_name linkage output_name)
solv::libsolv_static
solv::libsolvext_static
solv::cpp
Resolvo::Resolvo
)

if(UNIX)
Expand Down Expand Up @@ -624,6 +635,7 @@ macro(libmamba_create_target target_name linkage output_name)
solv::libsolv
solv::libsolvext
solv::cpp
Resolvo::Resolvo
)
# CMake 3.17 provides a LibArchive::LibArchive target that could be used instead of
# LIBRARIES/INCLUDE_DIRS
Expand Down
13 changes: 13 additions & 0 deletions libmamba/include/mamba/api/channel_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ namespace mamba
{
class Database;
}

namespace solver::resolvo
{
class PackageDatabase;
}

class Context;
class ChannelContext;
class MultiPackageCache;
Expand All @@ -34,6 +40,13 @@ namespace mamba
MultiPackageCache& package_caches
) -> expected_t<void, mamba_aggregated_error>;

auto load_channels(
Context& ctx,
ChannelContext& channel_context,
solver::resolvo::PackageDatabase& pool,
MultiPackageCache& package_caches
) -> expected_t<void, mamba_aggregated_error>;

/* Brief Creates channels and mirrors objects,
* but does not load channels.
*
Expand Down
65 changes: 20 additions & 45 deletions libmamba/include/mamba/solver/resolvo/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
#include <resolvo/resolvo_dependency_provider.h>
#include <resolvo/resolvo_pool.h>

#include "mamba/core/error_handling.hpp"
#include "mamba/fs/filesystem.hpp"
#include "mamba/solver/parameters.hpp"
#include "mamba/solver/repo_info.hpp"
#include "mamba/specs/channel.hpp"
#include "mamba/specs/match_spec.hpp"
#include "mamba/specs/package_info.hpp"
#include "mamba/util/string.hpp"


using namespace mamba;
using namespace mamba::specs;

Expand Down Expand Up @@ -160,34 +163,29 @@ struct Mapping

namespace mamba::solver::resolvo
{
enum class LogLevel
{
Debug,
Warning,
Error,
Fatal,
};

class PackageDatabase : public DependencyProvider
class PackageDatabase final : public DependencyProvider
{
public:

using logger_type = std::function<void(LogLevel, std::string_view)>;

explicit PackageDatabase(specs::ChannelResolveParams channel_params)
: params(params)
: params(channel_params)
{
}

PackageDatabase(const PackageDatabase&) = delete;
PackageDatabase(PackageDatabase&&);
PackageDatabase(PackageDatabase&&) = delete;

virtual ~PackageDatabase() = default;
~PackageDatabase() = default;

auto operator=(const PackageDatabase&) -> PackageDatabase& = delete;
auto operator=(PackageDatabase&&) -> PackageDatabase&;
auto operator=(PackageDatabase&&) -> PackageDatabase& = delete;

[[nodiscard]] auto channel_params() const -> const specs::ChannelResolveParams&;
[[nodiscard]] auto channel_params() const -> const specs::ChannelResolveParams&
{
return params;
}

void set_logger(logger_type callback);

Expand Down Expand Up @@ -223,11 +221,9 @@ namespace mamba::solver::resolvo
PipAsPythonDependency add = PipAsPythonDependency::No
) -> RepoInfo;

auto native_serialize_repo(
const RepoInfo& repo,
const fs::u8path& path,
const RepodataOrigin& metadata
) -> expected_t<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>;

Expand Down Expand Up @@ -320,32 +316,6 @@ namespace mamba::solver::resolvo
return VersionSetId{ 0 };
}

// NOTE: This works around some improperly encoded `constrains` in the test data, e.g.:
// `openmpi-4.1.4-ha1ae619_102`'s improperly encoded `constrains`: "cudatoolkit
// >= 10.2" `pytorch-1.13.0-cpu_py310h02c325b_0.conda`'s improperly encoded
// `constrains`: "pytorch-cpu = 1.13.0", "pytorch-gpu = 99999999"
// `fipy-3.4.2.1-py310hff52083_3.tar.bz2`'s improperly encoded `constrains` or
// `dep`:
// ">=4.5.2"
// Remove any with space after the binary operators
for (const std::string& op : { ">=", "<=", "==", ">", "<", "!=", "=", "==" })
{
const std::string& bad_op = op + " ";
while (raw_match_spec_str.find(bad_op) != std::string::npos)
{
raw_match_spec_str = raw_match_spec_str.substr(0, raw_match_spec_str.find(bad_op))
+ op
+ raw_match_spec_str.substr(
raw_match_spec_str.find(bad_op) + bad_op.size()
);
}
// If start with binary operator, prepend NONE
if (raw_match_spec_str.find(op) == 0)
{
raw_match_spec_str = "NONE " + raw_match_spec_str;
}
}

const MatchSpec match_spec = MatchSpec::parse(raw_match_spec_str).value();
// Add the version set to the version set pool
auto id = version_set_pool.alloc(match_spec);
Expand Down Expand Up @@ -711,6 +681,11 @@ namespace mamba::solver::resolvo
return dependencies;
}

const PackageInfo& get_solvable(SolvableId solvable_id)
{
return solvable_pool[solvable_id];
}

private:

const ChannelResolveParams& params;
Expand Down
27 changes: 27 additions & 0 deletions libmamba/include/mamba/solver/resolvo/solver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include "mamba/core/error_handling.hpp"
#include "mamba/solver/request.hpp"
#include "mamba/solver/resolvo/database.hpp"
#include "mamba/solver/resolvo/unsolvable.hpp"
#include "mamba/solver/solution.hpp"
#include "mamba/util/variant_cmp.hpp"

namespace mamba::solver::resolvo
{

class Solver
{
public:

using Outcome = std::variant<Solution, UnSolvable>;

[[nodiscard]] auto solve(PackageDatabase& pool, Request&& request) -> expected_t<Outcome>;
[[nodiscard]] auto
solve(PackageDatabase& pool, const Request& request) -> expected_t<Outcome>;

private:

auto solve_impl(PackageDatabase& pool, const Request& request) -> expected_t<Outcome>;
};
}
61 changes: 61 additions & 0 deletions libmamba/include/mamba/solver/resolvo/unsolvable.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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.

#pragma once

#include <iosfwd>
#include <memory>
#include <string>
#include <vector>

#include "mamba/solver/problems_graph.hpp"

namespace mamba
{
class Palette;
}

namespace mamba::solver::resolvo
{
class Solver;
class PackageDatabase;

class UnSolvable
{
public:

UnSolvable(std::string reason);

UnSolvable(UnSolvable&&);

~UnSolvable();

auto operator=(UnSolvable&&) -> UnSolvable&;

[[nodiscard]] auto problems(PackageDatabase& pool) const -> std::vector<std::string>;

[[nodiscard]] auto problems_to_str(PackageDatabase& pool) const -> std::string;

[[nodiscard]] auto all_problems_to_str(PackageDatabase& pool) const -> std::string;

[[nodiscard]] auto problems_graph(const PackageDatabase& pool) const -> ProblemsGraph;

auto explain_problems_to( //
PackageDatabase& pool,
std::ostream& out,
const ProblemsMessageFormat& format
) const -> std::ostream&;

[[nodiscard]] auto
explain_problems(PackageDatabase& pool, const ProblemsMessageFormat& format) const -> std::string;

private:

std::string m_reason;

friend class Solver;
};
}
11 changes: 10 additions & 1 deletion libmamba/src/api/channel_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,16 @@ namespace mamba
return load_channels_impl(ctx, channel_context, pool, package_caches, false);
}

auto load_channels(
Context& ctx,
ChannelContext& channel_context,
solver::resolvo::PackageDatabase& pool,
MultiPackageCache& package_caches
) -> expected_t<void, mamba_aggregated_error>
{
return load_channels_impl(ctx, channel_context, pool, package_caches, false);
}

void init_channels(Context& context, ChannelContext& channel_context)
{
for (const auto& mirror : context.mirrored_channels)
Expand Down Expand Up @@ -513,5 +523,4 @@ namespace mamba
}
}
}

}
69 changes: 69 additions & 0 deletions libmamba/src/api/install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "mamba/download/downloader.hpp"
#include "mamba/fs/filesystem.hpp"
#include "mamba/solver/libsolv/solver.hpp"
#include "mamba/solver/resolvo/solver.hpp"
#include "mamba/util/path_manip.hpp"
#include "mamba/util/string.hpp"

Expand Down Expand Up @@ -379,6 +380,59 @@ namespace mamba

namespace
{
void install_specs_resolvo_impl(
Context& ctx,
ChannelContext& channel_context,
const Configuration& config,
const std::vector<std::string>& specs,
bool create_env,
bool remove_prefix_on_failure,
bool is_retry
)
{
assert(&config.context() == &ctx);

auto& no_pin = config.at("no_pin").value<bool>();
auto& no_py_pin = config.at("no_py_pin").value<bool>();
auto& freeze_installed = config.at("freeze_installed").value<bool>();
auto& retry_clean_cache = config.at("retry_clean_cache").value<bool>();

if (ctx.prefix_params.target_prefix.empty())
{
throw std::runtime_error("No active target prefix");
}
if (!fs::exists(ctx.prefix_params.target_prefix) && create_env == false)
{
throw std::runtime_error(fmt::format(
"Prefix does not exist at: {}",
ctx.prefix_params.target_prefix.string()
));
}

MultiPackageCache package_caches{ ctx.pkgs_dirs, ctx.validation_params };

// add channels from specs
for (const auto& s : specs)
{
if (auto ms = specs::MatchSpec::parse(s); ms && ms->channel().has_value())
{
ctx.channels.push_back(ms->channel()->str());
}
}

if (ctx.channels.empty() && !ctx.offline)
{
LOG_WARNING << "No 'channels' specified";
}

solver::resolvo::PackageDatabase db{ channel_context.params() };
auto exp_load = load_channels(ctx, channel_context, db, package_caches);
if (!exp_load)
{
throw std::runtime_error(exp_load.error().what());
}
}

void install_specs_impl(
Context& ctx,
ChannelContext& channel_context,
Expand Down Expand Up @@ -574,6 +628,21 @@ namespace mamba
bool remove_prefix_on_failure
)
{
// Check if the MAMBA_USE_RESOLVO env var is set
if (const char* use_resolvo = std::getenv("MAMBA_USE_RESOLVO");
use_resolvo && std::string(use_resolvo) == "1")
{
return install_specs_resolvo_impl(
ctx,
channel_context,
config,
specs,
create_env,
remove_prefix_on_failure,
false
);
}

return install_specs_impl(
ctx,
channel_context,
Expand Down
Loading

0 comments on commit c698d33

Please sign in to comment.