mirror of https://github.com/mamba-org/mamba.git
311 lines
8.1 KiB
C++
311 lines
8.1 KiB
C++
/*
|
|
<%
|
|
cfg['compiler_args'] = ['-std=c++17', '-march=native']
|
|
cfg['libraries'] = ['solv']
|
|
setup_pybind11(cfg)
|
|
%>
|
|
*/
|
|
|
|
#include "thirdparty/simdjson/simdjson.h"
|
|
#include "thirdparty/simdjson/simdjson.cpp"
|
|
|
|
extern "C"
|
|
{
|
|
#include "solv/pool.h"
|
|
#include "solv/repo.h"
|
|
#include "solv/queue.h"
|
|
#include "solv/solver.h"
|
|
#include "solv/solverdebug.h"
|
|
}
|
|
|
|
static Pool* global_pool;
|
|
|
|
#include <iostream>
|
|
|
|
#include "parsing.hpp"
|
|
|
|
struct package {
|
|
std::string name;
|
|
std::string version;
|
|
std::string build_string;
|
|
int build_number;
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream& os, package& pkg)
|
|
{
|
|
return os << pkg.name << " -> " << pkg.version << ", " << pkg.build_string;
|
|
}
|
|
|
|
struct repo_package {
|
|
std::string name;
|
|
std::string version;
|
|
std::string build_string;
|
|
int build_number;
|
|
std::vector<std::string> dependencies;
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream& os, repo_package& pkg)
|
|
{
|
|
return os << pkg.name << " -> " << pkg.version << ", " << pkg.build_string;
|
|
}
|
|
|
|
void parse_repo(ParsedJson::iterator &i, Repo* repo) {
|
|
package pkg;
|
|
|
|
if (!i.move_to_key("packages"))
|
|
{
|
|
throw std::runtime_error("Could not find packages key!");
|
|
}
|
|
|
|
std::string_view version, build_string, features, name;
|
|
int build_number = 0; // change to char* as well
|
|
|
|
i.down();
|
|
|
|
do {
|
|
Id s_id = repo_add_solvable(repo);
|
|
auto& s = global_pool->solvables[s_id];
|
|
i.next(); i.down();
|
|
do {
|
|
if (strcmp(i.get_string(), "name") == 0)
|
|
{
|
|
i.next();
|
|
pkg.name = i.get_string();
|
|
name = i.get_string();
|
|
Id name_id = pool_str2id(global_pool, i.get_string(), 1);
|
|
s.name = name_id;
|
|
}
|
|
else if (strcmp(i.get_string(), "build_number") == 0)
|
|
{
|
|
i.next();
|
|
build_number = i.get_integer();
|
|
}
|
|
else if (strcmp(i.get_string(), "build") == 0)
|
|
{
|
|
i.next();
|
|
build_string = i.get_string();
|
|
}
|
|
else if (strcmp(i.get_string(), "features") == 0)
|
|
{
|
|
i.next();
|
|
features = i.get_string();
|
|
}
|
|
else if (strcmp(i.get_string(), "version") == 0)
|
|
{
|
|
i.next();
|
|
version = i.get_string();
|
|
}
|
|
else if (strcmp(i.get_string(), "depends") == 0)
|
|
{
|
|
i.next();
|
|
if (i.down())
|
|
{
|
|
do {
|
|
Id rel = parse_to_relation(i.get_string(), global_pool);
|
|
solvable_add_deparray(
|
|
&s,
|
|
SOLVABLE_REQUIRES,
|
|
rel, -1);
|
|
|
|
} while (i.next());
|
|
i.up();
|
|
}
|
|
}
|
|
else {
|
|
i.next(); // skip value?
|
|
}
|
|
} while (i.next());
|
|
|
|
s.evr = pool_str2id(global_pool, normalize_version(version, build_number, build_string).c_str(), 1);
|
|
|
|
solvable_add_deparray(&s, SOLVABLE_PROVIDES,
|
|
pool_rel2id(global_pool, s.name, s.evr, REL_EQ, 1), -1);
|
|
|
|
if (features.size())
|
|
{
|
|
std::stringstream os;
|
|
os << name << "[" << features << "]";
|
|
std::string feature_name = os.str();
|
|
auto feat_id = pool_strn2id(global_pool, feature_name.c_str(), feature_name.size(), 1);
|
|
|
|
solvable_add_deparray(&s, SOLVABLE_PROVIDES,
|
|
pool_rel2id(global_pool, feat_id, s.evr, REL_EQ, 1), -1);
|
|
}
|
|
|
|
if (build_string.size())
|
|
{
|
|
std::stringstream os;
|
|
os << name << "[" << build_string << "]";
|
|
std::string feature_name = os.str();
|
|
auto feat_id = pool_strn2id(global_pool, feature_name.c_str(), feature_name.size(), 1);
|
|
|
|
solvable_add_deparray(&s, SOLVABLE_PROVIDES,
|
|
pool_rel2id(global_pool, feat_id, s.evr, REL_EQ, 1), -1);
|
|
}
|
|
|
|
i.up();
|
|
} while (i.next());
|
|
}
|
|
|
|
|
|
void installed_packages(Repo* repo, ParsedJson::iterator &i) {
|
|
package pkg;
|
|
switch (i.get_type()) {
|
|
case '{':
|
|
{
|
|
package pkg;
|
|
i.down();
|
|
do {
|
|
if (strcmp(i.get_string(), "name") == 0)
|
|
{
|
|
i.next();
|
|
pkg.name = i.get_string();
|
|
}
|
|
else if (strcmp(i.get_string(), "build_number") == 0)
|
|
{
|
|
i.next();
|
|
pkg.build_number = i.get_integer();
|
|
}
|
|
else if (strcmp(i.get_string(), "build_string") == 0)
|
|
{
|
|
i.next();
|
|
pkg.build_string = i.get_string();
|
|
}
|
|
else if (strcmp(i.get_string(), "version") == 0)
|
|
{
|
|
i.next();
|
|
pkg.version = i.get_string();
|
|
}
|
|
else {
|
|
i.next(); // skip value?
|
|
}
|
|
} while (i.next());
|
|
i.up();
|
|
|
|
Id s_id = repo_add_solvable(repo);
|
|
auto& s = global_pool->solvables[s_id];
|
|
|
|
s.name = pool_str2id(global_pool, pkg.name.c_str(), 1);
|
|
s.evr = pool_str2id(global_pool, normalize_version(pkg.version, pkg.build_number, pkg.build_string).c_str(), 1);
|
|
solvable_add_deparray(&s, SOLVABLE_PROVIDES,
|
|
pool_rel2id(global_pool, s.name, s.evr, REL_EQ, 1), -1);
|
|
break;
|
|
}
|
|
case '[':
|
|
if (i.down()) {
|
|
do {
|
|
if (i.is_object_or_array()) {
|
|
installed_packages(repo, i);
|
|
}
|
|
} while (i.next());
|
|
i.up();
|
|
}
|
|
break;
|
|
case 'l':
|
|
case 'd':
|
|
case 'n':
|
|
case 't':
|
|
case 'f':
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::string solve(std::vector<std::string> repos,
|
|
std::string installed,
|
|
std::string look_for)
|
|
{
|
|
Pool* pool = pool_create();
|
|
global_pool = pool;
|
|
|
|
if (installed.size())
|
|
{
|
|
Repo* repo = repo_create(pool, "installed");
|
|
pool_set_installed(pool, repo);
|
|
std::string_view p = get_corpus(installed);
|
|
ParsedJson pj = build_parsed_json(p);
|
|
ParsedJson::iterator pjh(pj);
|
|
installed_packages(repo, pjh);
|
|
}
|
|
for (auto& fn : repos)
|
|
{
|
|
std::string_view p = get_corpus(fn);
|
|
|
|
Repo* repo = repo_create(pool, fn.c_str());
|
|
|
|
ParsedJson pj = build_parsed_json(p);
|
|
if (!pj.isValid())
|
|
{
|
|
std::cout << "Found invalid json!";
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Parsing " << fn << std::endl;
|
|
}
|
|
ParsedJson::iterator pjh(pj);
|
|
parse_repo(pjh, repo);
|
|
std::cout << "Packages in " << fn << ": " << repo->nsolvables << std::endl;
|
|
repo_internalize(repo);
|
|
}
|
|
|
|
pool_createwhatprovides(global_pool);
|
|
Solver* solvy = solver_create(global_pool);
|
|
solver_set_flag(solvy, SOLVER_FLAG_ALLOW_DOWNGRADE, 1);
|
|
|
|
std::cout << "ALLOW DOWNGRADE? : " << solver_get_flag(solvy, SOLVER_FLAG_ALLOW_DOWNGRADE);
|
|
|
|
std::cout << "\nCreating the solver." << std::endl;
|
|
|
|
Queue q;
|
|
queue_init(&q);
|
|
int rel = parse_to_relation(look_for, pool);
|
|
std::cout << "Dep 2 str: " << pool_dep2str(pool, rel);
|
|
|
|
queue_push2(&q, SOLVER_INSTALL | SOLVER_SOLVABLE_NAME, rel);
|
|
|
|
solver_solve(solvy, &q);
|
|
Transaction* transy = solver_create_transaction(solvy);
|
|
int cnt = solver_problem_count(solvy);
|
|
Queue problem_queue;
|
|
queue_init(&problem_queue);
|
|
|
|
std::cout << "Encountered " << cnt << " problems.\n\n";
|
|
for (int i = 1; i <= cnt; i++)
|
|
{
|
|
queue_push(&problem_queue, i);
|
|
std::cout << "PROBLEM: " << solver_problem2str(solvy, i);
|
|
}
|
|
|
|
transaction_print(transy);
|
|
|
|
Queue q2;
|
|
int cut;
|
|
queue_init(&q2);
|
|
cut = transaction_installedresult(transy, &q2);
|
|
queue_truncate(&q2, cut);
|
|
|
|
std::cout << "Solution: " << std::endl;
|
|
|
|
std::vector<std::string> to_install;
|
|
for (int i = 0; i < q2.count; ++i)
|
|
{
|
|
to_install.emplace_back(pool_id2str(global_pool, global_pool->solvables[q2.elements[i]].name));
|
|
to_install.back() += " ==";
|
|
std::string version = pool_id2str(global_pool, global_pool->solvables[q2.elements[i]].evr);
|
|
|
|
auto vsplit = pystring::split(version, ".");
|
|
vsplit.pop_back();
|
|
version = pystring::join(".", vsplit);
|
|
to_install.back() += version;
|
|
}
|
|
|
|
std::sort(to_install.begin(), to_install.end());
|
|
|
|
std::string result;
|
|
for (auto& line : to_install)
|
|
{
|
|
result += "- " + line + "\n";
|
|
}
|
|
|
|
return result;
|
|
} |