Browse Source

We have dependency resolution failure explanations!

default_compile_flags
vector-of-bool 5 years ago
parent
commit
17ecc2b652
5 changed files with 116 additions and 3 deletions
  1. +7
    -0
      catalog.json
  2. +1
    -1
      package.dds
  3. +45
    -0
      src/dds/deps.cpp
  4. +2
    -0
      src/dds/deps.hpp
  5. +61
    -2
      src/dds/solve/solve.cpp

+ 7
- 0
catalog.json View File

@@ -73,6 +73,13 @@
"ref": "0.1.2"
},
"depends": {}
},
"0.2.0": {
"git": {
"url": "https://github.com/vector-of-bool/pubgrub.git",
"ref": "0.2.0"
},
"depends": {}
}
}
}

+ 1
- 1
package.dds View File

@@ -8,6 +8,6 @@ Depends: nlohmann-json 3.7.1
Depends: neo-sqlite3 0.2.2
Depends: neo-fun 0.1.0
Depends: semver 0.2.1
Depends: pubgrub 0.1.2
Depends: pubgrub 0.2.0

Test-Driver: Catch-Main

+ 45
- 0
src/dds/deps.cpp View File

@@ -56,4 +56,49 @@ dependency_manifest dependency_manifest::from_file(path_ref fpath) {
},
lm::reject_unknown());
return ret;
}

namespace {

std::string iv_string(const pubgrub::interval_set<semver::version>::interval_type& iv) {
if (iv.high == semver::version::max_version()) {
return ">=" + iv.low.to_string();
}
if (iv.low == semver::version()) {
return "<" + iv.high.to_string();
}
return iv.low.to_string() + " < " + iv.high.to_string();
}

} // namespace

std::string dependency::to_string() const noexcept {
std::stringstream strm;
strm << name << "@";
if (versions.num_intervals() == 1) {
auto iv = *versions.iter_intervals().begin();
if (iv.high == iv.low.next_after()) {
strm << iv.low.to_string();
return strm.str();
}
if (iv.low == semver::version() && iv.high == semver::version::max_version()) {
return name;
}
strm << "[" << iv_string(iv) << "]";
return strm.str();
}

strm << "[";
auto iv_it = versions.iter_intervals();
auto it = iv_it.begin();
const auto stop = iv_it.end();
while (it != stop) {
strm << "(" << iv_string(*it) << ")";
++it;
if (it != stop) {
strm << " || ";
}
}
strm << "]";
return strm.str();
}

+ 2
- 0
src/dds/deps.hpp View File

@@ -17,6 +17,8 @@ struct dependency {
version_range_set versions;

static dependency parse_depends_string(std::string_view str);

std::string to_string() const noexcept;
};

/**

+ 61
- 2
src/dds/solve/solve.cpp View File

@@ -4,6 +4,9 @@

#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
#include <spdlog/spdlog.h>

#include <sstream>

using namespace dds;

@@ -51,6 +54,11 @@ struct req_type {
friend bool operator==(req_ref lhs, req_ref rhs) noexcept {
return lhs.dep.name == rhs.dep.name && lhs.dep.versions == rhs.dep.versions;
}

friend std::ostream& operator<<(std::ostream& out, req_ref self) noexcept {
out << self.dep.to_string();
return out;
}
};

auto as_pkg_id(const req_type& req) {
@@ -89,6 +97,51 @@ struct solver_provider {
}
};

using solve_fail_exc = pubgrub::solve_failure_type_t<req_type>;

struct explainer {
std::stringstream strm;
bool at_head = true;

void put(pubgrub::explain::no_solution) { strm << "Dependencies cannot be satisfied"; }

void put(pubgrub::explain::dependency<req_type> dep) {
strm << dep.dependent << " requires " << dep.dependency << '.';
}

void put(pubgrub::explain::unavailable<req_type> un) {
strm << un.requirement << " is not available";
}

void put(pubgrub::explain::conflict<req_type> cf) {
strm << cf.a << " conflicts with " << cf.b;
}

void put(pubgrub::explain::needed<req_type> req) { strm << req.requirement << " is required"; }

void put(pubgrub::explain::disallowed<req_type> dis) {
strm << dis.requirement << " cannot be used";
}

template <typename T>
void operator()(pubgrub::explain::premise<T> pr) {
strm.str("");
put(pr.value);
spdlog::error("{} {},", at_head ? "┌─ Given that" : "│ and", strm.str());
at_head = false;
}

template <typename T>
void operator()(pubgrub::explain::conclusion<T> cncl) {
at_head = true;
strm.str("");
put(cncl.value);
spdlog::error("╘═ Then: {}.", strm.str());
}

void operator()(pubgrub::explain::separator) { spdlog::error(""); }
};

} // namespace

std::vector<package_id> dds::solve(const std::vector<dependency>& deps,
@@ -97,6 +150,12 @@ std::vector<package_id> dds::solve(const std::vector<dependency>& deps,
auto wrap_req
= deps | ranges::v3::views::transform([](const dependency& dep) { return req_type{dep}; });

auto solution = pubgrub::solve(wrap_req, solver_provider{pkgs_prov, deps_prov});
return solution | ranges::views::transform(as_pkg_id) | ranges::to_vector;
try {
auto solution = pubgrub::solve(wrap_req, solver_provider{pkgs_prov, deps_prov});
return solution | ranges::views::transform(as_pkg_id) | ranges::to_vector;
} catch (const solve_fail_exc& failure) {
spdlog::error("Dependency resolution has failed! Explanation:");
pubgrub::generate_explaination(failure, explainer());
throw;
}
}

Loading…
Cancel
Save