Isolate PackageInfo from libsolv (#2340)

* Isolate libsolv from PackageInfo
This commit is contained in:
Antoine Prouvost 2023-03-08 09:15:46 +01:00 committed by GitHub
parent 66c721c220
commit 8c5841cbfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 473 additions and 467 deletions

View File

@ -12,10 +12,6 @@
#include <vector> #include <vector>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <solv/pool.h>
#include <solv/poolid.h>
#include <solv/repo.h>
#include <solv/solvable.h>
namespace mamba namespace mamba
{ {
@ -26,20 +22,14 @@ namespace mamba
using field_getter = std::function<std::string(const PackageInfo&)>; using field_getter = std::function<std::string(const PackageInfo&)>;
using compare_fun = std::function<bool(const PackageInfo&, const PackageInfo&)>; using compare_fun = std::function<bool(const PackageInfo&, const PackageInfo&)>;
static field_getter get_field_getter(const std::string& name); static field_getter get_field_getter(std::string_view field_name);
static compare_fun less(const std::string& member); static compare_fun less(std::string_view member);
static compare_fun equal(const std::string& member); static compare_fun equal(std::string_view member);
PackageInfo(Solvable* s); PackageInfo() = default;
PackageInfo(nlohmann::json&& j); explicit PackageInfo(nlohmann::json&& j);
PackageInfo(const std::string& name); explicit PackageInfo(std::string name);
PackageInfo(std::string&& name); PackageInfo(std::string name, std::string version, std::string build_string, std::size_t build_number);
PackageInfo(
const std::string& name,
const std::string& version,
const std::string build_string,
std::size_t build_number
);
bool operator==(const PackageInfo& other) const; bool operator==(const PackageInfo& other) const;
@ -48,26 +38,26 @@ namespace mamba
std::string str() const; std::string str() const;
std::string long_str() const; std::string long_str() const;
std::string name; std::string name = {};
std::string version; std::string version = {};
std::string build_string; std::string build_string = {};
std::string noarch; std::string noarch = {};
std::size_t build_number = 0; std::size_t build_number = 0;
std::string channel; std::string channel = {};
std::string url; std::string url = {};
std::string subdir; std::string subdir = {};
std::string fn; std::string fn = {};
std::string license; std::string license = {};
std::size_t size = 0; std::size_t size = 0;
std::size_t timestamp = 0; std::size_t timestamp = 0;
std::string md5; std::string md5 = {};
std::string sha256; std::string sha256 = {};
std::string track_features; std::string track_features = {};
std::vector<std::string> depends; std::vector<std::string> depends = {};
std::vector<std::string> constrains; std::vector<std::string> constrains = {};
std::string signatures; std::string signatures = {};
std::string extra_metadata; std::string extra_metadata = {};
std::set<std::string> defaulted_keys; std::set<std::string> defaulted_keys = {};
}; };
} // namespace mamba } // namespace mamba

View File

@ -32,13 +32,16 @@ namespace mamba
MPool(); MPool();
~MPool(); ~MPool();
std::size_t n_solvables() const;
void set_debuglevel(); void set_debuglevel();
void create_whatprovides(); void create_whatprovides();
std::vector<Id> select_solvables(Id id, bool sorted = false) const; std::vector<Id> select_solvables(Id id, bool sorted = false) const;
Id matchspec2id(const std::string& ms); Id matchspec2id(const std::string& ms);
std::optional<PackageInfo> id2pkginfo(Id id); std::optional<PackageInfo> id2pkginfo(Id solv_id) const;
std::optional<std::string> dep2str(Id dep_id) const;
operator Pool*(); operator Pool*();
operator const Pool*() const; operator const Pool*() const;

View File

@ -19,6 +19,7 @@
extern "C" extern "C"
{ {
typedef struct s_Repo Repo; typedef struct s_Repo Repo;
typedef struct s_Repodata Repodata;
} }
namespace mamba namespace mamba

View File

@ -95,7 +95,7 @@ namespace mamba
[[nodiscard]] const std::vector<MatchSpec>& neuter_specs() const; [[nodiscard]] const std::vector<MatchSpec>& neuter_specs() const;
[[nodiscard]] const std::vector<MatchSpec>& pinned_specs() const; [[nodiscard]] const std::vector<MatchSpec>& pinned_specs() const;
operator const Solver*() const;
operator Solver*(); operator Solver*();
bool only_deps = false; bool only_deps = false;

View File

@ -35,14 +35,10 @@
namespace mamba namespace mamba
{ {
void try_add(nlohmann::json& j, const char* key, const char* val);
nlohmann::json solvable_to_json(Solvable* s);
class PackageDownloadExtractTarget class PackageDownloadExtractTarget
{ {
public: public:
PackageDownloadExtractTarget(Solvable* solvable);
PackageDownloadExtractTarget(const PackageInfo& pkg_info); PackageDownloadExtractTarget(const PackageInfo& pkg_info);
void write_repodata_record(const fs::u8path& base_path); void write_repodata_record(const fs::u8path& base_path);
@ -126,7 +122,7 @@ namespace mamba
const std::vector<MatchSpec>& specs_to_install, const std::vector<MatchSpec>& specs_to_install,
MultiPackageCache& caches MultiPackageCache& caches
); );
MTransaction(MSolver& solver, MultiPackageCache& caches); MTransaction(MPool& pool, MSolver& solver, MultiPackageCache& caches);
// Only use if the packages have been solved previously already. // Only use if the packages have been solved previously already.
MTransaction(MPool& pool, const std::vector<PackageInfo>& packages, MultiPackageCache& caches); MTransaction(MPool& pool, const std::vector<PackageInfo>& packages, MultiPackageCache& caches);
@ -157,6 +153,8 @@ namespace mamba
private: private:
MPool m_pool;
FilterType m_filter_type = FilterType::none; FilterType m_filter_type = FilterType::none;
std::set<Id> m_filter_name_ids; std::set<Id> m_filter_name_ids;

View File

@ -493,10 +493,12 @@ namespace mamba
MRepo::create(pool, prefix_data); MRepo::create(pool, prefix_data);
MSolver solver( MSolver solver(
std::move(pool), pool,
{ { SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall }, {
{ SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall },
{ SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade }, { SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY, ctx.channel_priority == ChannelPriority::kStrict } } { SOLVER_FLAG_STRICT_REPO_PRIORITY, ctx.channel_priority == ChannelPriority::kStrict },
}
); );
solver.set_postsolve_flags({ { MAMBA_NO_DEPS, no_deps }, solver.set_postsolve_flags({ { MAMBA_NO_DEPS, no_deps },
@ -560,7 +562,7 @@ namespace mamba
); );
} }
MTransaction trans(solver, package_caches); MTransaction trans(pool, solver, package_caches);
if (ctx.json) if (ctx.json)
{ {

View File

@ -111,11 +111,13 @@ namespace mamba
else else
{ {
MSolver solver( MSolver solver(
std::move(pool), pool,
{ { SOLVER_FLAG_ALLOW_DOWNGRADE, 1 }, {
{ SOLVER_FLAG_ALLOW_DOWNGRADE, 1 },
{ SOLVER_FLAG_ALLOW_UNINSTALL, 1 }, { SOLVER_FLAG_ALLOW_UNINSTALL, 1 },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY, { SOLVER_FLAG_STRICT_REPO_PRIORITY,
ctx.channel_priority == ChannelPriority::kStrict } } ctx.channel_priority == ChannelPriority::kStrict },
}
); );
History history(ctx.target_prefix); History history(ctx.target_prefix);
@ -138,7 +140,7 @@ namespace mamba
solver.add_jobs(specs, solver_flag); solver.add_jobs(specs, solver_flag);
solver.must_solve(); solver.must_solve();
MTransaction transaction(solver, package_caches); MTransaction transaction(pool, solver, package_caches);
execute_transaction(transaction); execute_transaction(transaction);
} }
} }

View File

@ -70,10 +70,12 @@ namespace mamba
MRepo::create(pool, prefix_data); MRepo::create(pool, prefix_data);
MSolver solver( MSolver solver(
std::move(pool), pool,
{ { SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade }, {
{ SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade },
{ SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall }, { SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall },
{ SOLVER_FLAG_STRICT_REPO_PRIORITY, ctx.channel_priority == ChannelPriority::kStrict } } { SOLVER_FLAG_STRICT_REPO_PRIORITY, ctx.channel_priority == ChannelPriority::kStrict },
}
); );
if (update_all) if (update_all)
@ -140,7 +142,7 @@ namespace mamba
} }
}; };
MTransaction transaction(solver, package_caches); MTransaction transaction(pool, solver, package_caches);
execute_transaction(transaction); execute_transaction(transaction);
config.operation_teardown(); config.operation_teardown();

View File

@ -15,8 +15,6 @@
#include "mamba/core/channel.hpp" #include "mamba/core/channel.hpp"
#include "mamba/core/util_string.hpp" #include "mamba/core/util_string.hpp"
#include "solv-cpp/queue.hpp"
namespace mamba namespace mamba
{ {
namespace namespace
@ -43,7 +41,7 @@ namespace mamba
return std::bind(get_package_info_field<T>, std::placeholders::_1, field); return std::bind(get_package_info_field<T>, std::placeholders::_1, field);
} }
using field_getter_map = std::map<std::string, PackageInfo::field_getter>; using field_getter_map = std::map<std::string_view, PackageInfo::field_getter>;
field_getter_map build_field_getter_map() field_getter_map build_field_getter_map()
{ {
@ -62,16 +60,16 @@ namespace mamba
return res; return res;
} }
field_getter_map& get_field_getter_map() const field_getter_map& get_field_getter_map()
{ {
static field_getter_map m = build_field_getter_map(); static field_getter_map m = build_field_getter_map();
return m; return m;
} }
} // namespace } // namespace
PackageInfo::field_getter PackageInfo::get_field_getter(const std::string& name) PackageInfo::field_getter PackageInfo::get_field_getter(std::string_view field_name)
{ {
auto it = get_field_getter_map().find(name); auto it = get_field_getter_map().find(field_name);
if (it == get_field_getter_map().end()) if (it == get_field_getter_map().end())
{ {
throw std::runtime_error("field_getter function not found"); throw std::runtime_error("field_getter function not found");
@ -79,169 +77,20 @@ namespace mamba
return it->second; return it->second;
} }
PackageInfo::compare_fun PackageInfo::less(const std::string& member) PackageInfo::compare_fun PackageInfo::less(std::string_view member)
{ {
auto getter = get_field_getter(member); auto getter = get_field_getter(member);
return [getter](const PackageInfo& lhs, const PackageInfo& rhs) return [getter](const PackageInfo& lhs, const PackageInfo& rhs)
{ return getter(lhs) < getter(rhs); }; { return getter(lhs) < getter(rhs); };
} }
PackageInfo::compare_fun PackageInfo::equal(const std::string& member) PackageInfo::compare_fun PackageInfo::equal(std::string_view member)
{ {
auto getter = get_field_getter(member); auto getter = get_field_getter(member);
return [getter](const PackageInfo& lhs, const PackageInfo& rhs) return [getter](const PackageInfo& lhs, const PackageInfo& rhs)
{ return getter(lhs) == getter(rhs); }; { return getter(lhs) == getter(rhs); };
} }
PackageInfo::PackageInfo(Solvable* s)
{
// Note: this function (especially the checksum part) is NOT YET threadsafe!
Pool* pool = s->repo->pool;
Id check_type;
name = pool_id2str(pool, s->name);
version = pool_id2str(pool, s->evr);
const char* str = solvable_lookup_str(s, SOLVABLE_BUILDFLAVOR);
if (str)
{
build_string = str;
}
str = solvable_lookup_str(s, SOLVABLE_BUILDVERSION);
if (str)
{
build_number = std::stoull(str);
}
static Id real_repo_key = pool_str2id(pool, "solvable:real_repo_url", 1);
if (solvable_lookup_str(s, real_repo_key))
{
url = solvable_lookup_str(s, real_repo_key);
channel = make_channel(url).canonical_name();
}
else
{
if (!s->repo || strcmp(s->repo->name, "__explicit_specs__") == 0)
{
url = solvable_lookup_location(s, 0);
channel = make_channel(url).canonical_name();
}
else
{
channel = s->repo->name; // note this can and should be <unknown> when e.g.
// installing from a tarball
url = channel + "/" + raw_str_or_empty(solvable_lookup_str(s, SOLVABLE_MEDIAFILE));
}
}
subdir = raw_str_or_empty(solvable_lookup_str(s, SOLVABLE_MEDIADIR));
fn = raw_str_or_empty(solvable_lookup_str(s, SOLVABLE_MEDIAFILE));
str = raw_str_or_empty(solvable_lookup_str(s, SOLVABLE_LICENSE));
if (str)
{
license = str;
}
size = solvable_lookup_num(s, SOLVABLE_DOWNLOADSIZE, 0);
timestamp = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0);
str = solvable_lookup_checksum(s, SOLVABLE_PKGID, &check_type);
if (str)
{
md5 = str;
}
str = solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &check_type);
if (str)
{
sha256 = str;
}
signatures = raw_str_or_empty(solvable_lookup_str(s, SIGNATURE_DATA));
if (signatures.empty())
{
signatures = "{}";
}
solv::ObjQueue q = {};
if (!solvable_lookup_deparray(s, SOLVABLE_REQUIRES, q.raw(), -1))
{
defaulted_keys.insert("depends");
}
depends.reserve(q.size());
std::transform(
q.begin(),
q.end(),
std::back_inserter(depends),
[&pool](Id id) { return pool_dep2str(pool, id); }
);
q.clear();
if (!solvable_lookup_deparray(s, SOLVABLE_CONSTRAINS, q.raw(), -1))
{
defaulted_keys.insert("constrains");
}
constrains.reserve(q.size());
std::transform(
q.begin(),
q.end(),
std::back_inserter(constrains),
[&pool](Id id) { return pool_dep2str(pool, id); }
);
q.clear();
solvable_lookup_idarray(s, SOLVABLE_TRACK_FEATURES, q.raw());
for (auto iter = q.begin(), end = q.end(); iter < end; ++iter)
{
track_features += pool_id2str(pool, *iter);
if (iter < end - 1)
{
track_features += ",";
}
}
Id extra_keys_id = pool_str2id(pool, "solvable:extra_keys", 0);
Id extra_values_id = pool_str2id(pool, "solvable:extra_values", 0);
if (extra_keys_id && extra_values_id)
{
// Get extra signed keys
q.clear();
solvable_lookup_idarray(s, extra_keys_id, q.raw());
std::vector<std::string> extra_keys = {};
extra_keys.reserve(q.size());
std::transform(
q.begin(),
q.end(),
std::back_inserter(extra_keys),
[&pool](Id id) { return pool_dep2str(pool, id); }
);
// Get extra signed values
q.clear();
solvable_lookup_idarray(s, extra_values_id, q.raw());
std::vector<std::string> extra_values = {};
extra_values.reserve(q.size());
std::transform(
q.begin(),
q.end(),
std::back_inserter(extra_values),
[&pool](Id id) { return pool_dep2str(pool, id); }
);
// Build a JSON string for extra signed metadata
if (!extra_keys.empty() && (extra_keys.size() == extra_values.size()))
{
std::vector<std::string> extra;
for (std::size_t i = 0; i < extra_keys.size(); ++i)
{
extra.push_back("\"" + extra_keys[i] + "\":" + extra_values[i]);
}
extra_metadata = "{" + join(",", extra) + "}";
}
}
else
{
extra_metadata = "{}";
}
}
PackageInfo::PackageInfo(nlohmann::json&& j) PackageInfo::PackageInfo(nlohmann::json&& j)
{ {
using namespace std::string_literals; // NOLINT(build/namespaces) using namespace std::string_literals; // NOLINT(build/namespaces)
@ -289,21 +138,16 @@ namespace mamba
} }
} }
PackageInfo::PackageInfo(const std::string& n) PackageInfo::PackageInfo(std::string n)
: name(n)
{
}
PackageInfo::PackageInfo(std::string&& n)
: name(std::move(n)) : name(std::move(n))
{ {
} }
PackageInfo::PackageInfo(const std::string& n, const std::string& v, const std::string b, std::size_t bn) PackageInfo::PackageInfo(std::string n, std::string v, std::string b, std::size_t bn)
: name(n) : name(std::move(n))
, version(v) , version(std::move(v))
, build_string(b) , build_string(std::move(b))
, build_number(bn) , build_number(std::move(bn))
{ {
} }

View File

@ -6,6 +6,7 @@
#include <list> #include <list>
#include <fmt/format.h>
#include <solv/evr.h> #include <solv/evr.h>
#include <solv/pool.h> #include <solv/pool.h>
#include <solv/selection.h> #include <solv/selection.h>
@ -19,6 +20,9 @@ extern "C" // Incomplete header
#include "mamba/core/context.hpp" #include "mamba/core/context.hpp"
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"
#include "mamba/core/pool.hpp" #include "mamba/core/pool.hpp"
#include "mamba/core/util_cast.hpp"
#include "mamba/core/util_compare.hpp"
#include "mamba/core/util_string.hpp"
#include "solv-cpp/queue.hpp" #include "solv-cpp/queue.hpp"
@ -90,6 +94,11 @@ namespace mamba
return m_data->pool.get(); return m_data->pool.get();
} }
std::size_t MPool::n_solvables() const
{
return util::safe_num_cast<std::size_t>(pool()->nsolvables);
}
void MPool::set_debuglevel() void MPool::set_debuglevel()
{ {
// ensure that debug logging goes to stderr as to not interfere with stdout json output // ensure that debug logging goes to stderr as to not interfere with stdout json output
@ -150,13 +159,147 @@ namespace mamba
return id; return id;
} }
std::optional<PackageInfo> MPool::id2pkginfo(Id id) namespace
{ {
if (id == 0 || id >= pool()->nsolvables) auto make_package_info(::Solvable& s) -> PackageInfo
{
// Note: this function (especially the checksum part) is NOT YET threadsafe!
Pool* pool = s.repo->pool;
Id check_type;
PackageInfo out = {};
out.name = pool_id2str(pool, s.name);
out.version = pool_id2str(pool, s.evr);
out.build_string = raw_str_or_empty(solvable_lookup_str(&s, SOLVABLE_BUILDFLAVOR));
if (const char* str = solvable_lookup_str(&s, SOLVABLE_BUILDVERSION); str != nullptr)
{
out.build_number = std::stoull(str);
}
static ::Id real_repo_key = pool_str2id(pool, "solvable:real_repo_url", 1);
if (const char* str = solvable_lookup_str(&s, real_repo_key); str != nullptr)
{
out.url = str;
out.channel = make_channel(out.url).canonical_name();
}
else
{
if (!s.repo || strcmp(s.repo->name, "__explicit_specs__") == 0)
{
out.url = solvable_lookup_location(&s, 0);
out.channel = make_channel(out.url).canonical_name();
}
else
{
out.channel = s.repo->name; // note this can and should be <unknown> when e.g.
// installing from a tarball
out.url = fmt::format(
"{}/{}",
out.channel,
raw_str_or_empty(solvable_lookup_str(&s, SOLVABLE_MEDIAFILE))
);
}
}
out.subdir = raw_str_or_empty(solvable_lookup_str(&s, SOLVABLE_MEDIADIR));
out.fn = raw_str_or_empty(solvable_lookup_str(&s, SOLVABLE_MEDIAFILE));
out.license = raw_str_or_empty(solvable_lookup_str(&s, SOLVABLE_LICENSE));
out.size = solvable_lookup_num(&s, SOLVABLE_DOWNLOADSIZE, 0);
out.timestamp = solvable_lookup_num(&s, SOLVABLE_BUILDTIME, 0);
out.md5 = raw_str_or_empty(solvable_lookup_checksum(&s, SOLVABLE_PKGID, &check_type));
out.sha256 = raw_str_or_empty(solvable_lookup_checksum(&s, SOLVABLE_CHECKSUM, &check_type)
);
out.signatures = raw_str_or_empty(solvable_lookup_str(&s, SIGNATURE_DATA));
if (out.signatures.empty())
{
out.signatures = "{}";
}
solv::ObjQueue q = {};
auto dep2str = [&pool](Id id) { return pool_dep2str(pool, id); };
if (!solvable_lookup_deparray(&s, SOLVABLE_REQUIRES, q.raw(), -1))
{
out.defaulted_keys.insert("depends");
}
out.depends.reserve(q.size());
std::transform(q.begin(), q.end(), std::back_inserter(out.depends), dep2str);
q.clear();
if (!solvable_lookup_deparray(&s, SOLVABLE_CONSTRAINS, q.raw(), -1))
{
out.defaulted_keys.insert("constrains");
}
out.constrains.reserve(q.size());
std::transform(q.begin(), q.end(), std::back_inserter(out.constrains), dep2str);
q.clear();
solvable_lookup_idarray(&s, SOLVABLE_TRACK_FEATURES, q.raw());
for (::Id const id : q)
{
out.track_features += pool_id2str(pool, id);
out.track_features += ',';
}
if (!out.track_features.empty())
{
out.track_features.pop_back();
}
const ::Id extra_keys_id = pool_str2id(pool, "solvable:extra_keys", 0);
const ::Id extra_values_id = pool_str2id(pool, "solvable:extra_values", 0);
if (extra_keys_id && extra_values_id)
{
// Get extra signed keys
q.clear();
solvable_lookup_idarray(&s, extra_keys_id, q.raw());
std::vector<std::string> extra_keys = {};
extra_keys.reserve(q.size());
std::transform(q.begin(), q.end(), std::back_inserter(extra_keys), dep2str);
// Get extra signed values
q.clear();
solvable_lookup_idarray(&s, extra_values_id, q.raw());
std::vector<std::string> extra_values = {};
extra_values.reserve(q.size());
std::transform(q.begin(), q.end(), std::back_inserter(extra_values), dep2str);
// Build a JSON string for extra signed metadata
if (!extra_keys.empty() && (extra_keys.size() == extra_values.size()))
{
std::vector<std::string> extra = {};
extra.reserve(extra_keys.size());
for (std::size_t i = 0; i < extra_keys.size(); ++i)
{
extra.push_back(fmt::format(R"("{}":{})", extra_keys[i], extra_values[i]));
}
out.extra_metadata = fmt::format("{{{}}}", fmt::join(extra, ","));
}
}
else
{
out.extra_metadata = "{}";
}
return out;
}
}
std::optional<PackageInfo> MPool::id2pkginfo(Id solv_id) const
{
if (solv_id == 0 || util::cmp_greater_equal(solv_id, n_solvables()))
{ {
return std::nullopt; return std::nullopt;
} }
return pool_id2solvable(pool(), id); return { make_package_info(*pool_id2solvable(pool(), solv_id)) };
}
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()), dep_id);
} }
MRepo& MPool::add_repo(MRepo&& repo) MRepo& MPool::add_repo(MRepo&& repo)

View File

@ -6,6 +6,8 @@
#include "mamba/core/prefix_data.hpp" #include "mamba/core/prefix_data.hpp"
#include <solv/pool.h>
#include <solv/repo.h>
#include <solv/transaction.h> #include <solv/transaction.h>
#include "mamba/core/output.hpp" #include "mamba/core/output.hpp"

View File

@ -26,8 +26,11 @@
#include "solv-cpp/queue.hpp" #include "solv-cpp/queue.hpp"
namespace mamba namespace mamba
{
namespace
{ {
void walk_graph( void walk_graph(
MPool pool,
query_result::dependency_graph& dep_graph, query_result::dependency_graph& dep_graph,
query_result::dependency_graph::node_id parent, query_result::dependency_graph::node_id parent,
Solvable* s, Solvable* s,
@ -44,8 +47,6 @@ namespace mamba
if (s && s->requires) if (s && s->requires)
{ {
auto* pool = s->repo->pool;
Id* reqp = s->repo->idarraydata + s->requires; Id* reqp = s->repo->idarraydata + s->requires;
Id req = *reqp; Id req = *reqp;
@ -70,10 +71,12 @@ namespace mamba
auto it = visited.find(rs); auto it = visited.find(rs);
if (it == visited.end()) if (it == visited.end())
{ {
auto dep_id = dep_graph.add_node(PackageInfo(rs)); auto pkg_info = pool.id2pkginfo(pool_solvable2id(pool, rs));
assert(pkg_info.has_value());
auto dep_id = dep_graph.add_node(std::move(pkg_info).value());
dep_graph.add_edge(parent, dep_id); dep_graph.add_edge(parent, dep_id);
visited.insert(std::make_pair(rs, dep_id)); visited.insert(std::make_pair(rs, dep_id));
walk_graph(dep_graph, dep_id, rs, visited, not_found, depth); walk_graph(pool, dep_graph, dep_id, rs, visited, not_found, depth);
} }
else else
{ {
@ -104,6 +107,7 @@ namespace mamba
} }
void reverse_walk_graph( void reverse_walk_graph(
MPool& pool,
query_result::dependency_graph& dep_graph, query_result::dependency_graph& dep_graph,
query_result::dependency_graph::node_id parent, query_result::dependency_graph::node_id parent,
Solvable* s, Solvable* s,
@ -112,7 +116,6 @@ namespace mamba
{ {
if (s) if (s)
{ {
auto* pool = s->repo->pool;
// figure out who requires `s` // figure out who requires `s`
solv::ObjQueue solvables = {}; solv::ObjQueue solvables = {};
@ -120,17 +123,18 @@ namespace mamba
if (solvables.size() != 0) if (solvables.size() != 0)
{ {
Solvable* rs;
for (auto& el : solvables) for (auto& el : solvables)
{ {
rs = pool_id2solvable(pool, el); ::Solvable* rs = pool_id2solvable(pool, el);
auto it = visited.find(rs); auto it = visited.find(rs);
if (it == visited.end()) if (it == visited.end())
{ {
auto dep_id = dep_graph.add_node(PackageInfo(rs)); auto pkg_info = pool.id2pkginfo(el);
assert(pkg_info.has_value());
auto dep_id = dep_graph.add_node(std::move(pkg_info).value());
dep_graph.add_edge(parent, dep_id); dep_graph.add_edge(parent, dep_id);
visited.insert(std::make_pair(rs, dep_id)); visited.insert(std::make_pair(rs, dep_id));
reverse_walk_graph(dep_graph, dep_id, rs, visited); reverse_walk_graph(pool, dep_graph, dep_id, rs, visited);
} }
else else
{ {
@ -140,6 +144,7 @@ namespace mamba
} }
} }
} }
}
/************************ /************************
* Query implementation * * Query implementation *
@ -236,8 +241,9 @@ namespace mamba
for (auto& el : solvables) for (auto& el : solvables)
{ {
Solvable* s = pool_id2solvable(m_pool.get(), el); auto pkg_info = m_pool.get().id2pkginfo(el);
g.add_node(PackageInfo(s)); assert(pkg_info.has_value());
g.add_node(std::move(pkg_info).value());
} }
return query_result(QueryType::kSEARCH, query, std::move(g)); return query_result(QueryType::kSEARCH, query, std::move(g));
@ -245,35 +251,38 @@ namespace mamba
query_result Query::whoneeds(const std::string& query, bool tree) const query_result Query::whoneeds(const std::string& query, bool tree) const
{ {
solv::ObjQueue job, solvables;
const Id id = pool_conda_matchspec(m_pool.get(), query.c_str()); const Id id = pool_conda_matchspec(m_pool.get(), query.c_str());
if (!id) if (!id)
{ {
throw std::runtime_error("Could not generate query for " + query); throw std::runtime_error("Could not generate query for " + query);
} }
job.push_back(SOLVER_SOLVABLE_PROVIDES, id);
solv::ObjQueue job = { SOLVER_SOLVABLE_PROVIDES, id };
query_result::dependency_graph g; query_result::dependency_graph g;
if (tree) if (tree)
{ {
solv::ObjQueue solvables = {};
selection_solvables(m_pool.get(), job.raw(), solvables.raw()); selection_solvables(m_pool.get(), job.raw(), solvables.raw());
if (solvables.size() > 0) if (!solvables.empty())
{ {
Solvable* latest = pool_id2solvable(m_pool.get(), solvables[0]); auto pkg_info = m_pool.get().id2pkginfo(solvables.front());
const auto node_id = g.add_node(PackageInfo(latest)); assert(pkg_info.has_value());
const auto node_id = g.add_node(std::move(pkg_info).value());
Solvable* const latest = pool_id2solvable(m_pool.get(), solvables.front());
std::map<Solvable*, size_t> visited = { { latest, node_id } }; std::map<Solvable*, size_t> visited = { { latest, node_id } };
reverse_walk_graph(g, node_id, latest, visited); reverse_walk_graph(m_pool, g, node_id, latest, visited);
} }
} }
else else
{ {
solv::ObjQueue solvables = {};
pool_whatmatchesdep(m_pool.get(), SOLVABLE_REQUIRES, id, solvables.raw(), -1); pool_whatmatchesdep(m_pool.get(), SOLVABLE_REQUIRES, id, solvables.raw(), -1);
for (auto& el : solvables) for (auto& el : solvables)
{ {
Solvable* s = pool_id2solvable(m_pool.get(), el); auto pkg_info = m_pool.get().id2pkginfo(el);
g.add_node(PackageInfo(s)); assert(pkg_info.has_value());
g.add_node(std::move(pkg_info).value());
} }
} }
return query_result(QueryType::kWHONEEDS, query, std::move(g)); return query_result(QueryType::kWHONEEDS, query, std::move(g));
@ -297,8 +306,8 @@ namespace mamba
auto find_latest_in_non_empty = [&](solv::ObjQueue& lsolvables) -> Solvable* auto find_latest_in_non_empty = [&](solv::ObjQueue& lsolvables) -> Solvable*
{ {
Solvable* latest = pool_id2solvable(m_pool.get(), lsolvables.front()); ::Solvable* latest = pool_id2solvable(m_pool.get(), lsolvables.front());
for (Id const solv : lsolvables) for (Id const solv : solvables)
{ {
Solvable* s = pool_id2solvable(m_pool.get(), solv); Solvable* s = pool_id2solvable(m_pool.get(), solv);
if (pool_evrcmp(m_pool.get(), s->evr, latest->evr, 0) > 0) if (pool_evrcmp(m_pool.get(), s->evr, latest->evr, 0) > 0)
@ -309,13 +318,16 @@ namespace mamba
return latest; return latest;
}; };
if (solvables.size() > 0) if (!solvables.empty())
{ {
Solvable* latest = find_latest_in_non_empty(solvables); ::Solvable* const latest = find_latest_in_non_empty(solvables);
const auto node_id = g.add_node(PackageInfo(latest)); auto pkg_info = m_pool.get().id2pkginfo(pool_solvable2id(m_pool.get(), latest));
assert(pkg_info.has_value());
const auto node_id = g.add_node(std::move(pkg_info).value());
std::map<Solvable*, size_t> visited = { { latest, node_id } }; std::map<Solvable*, size_t> visited = { { latest, node_id } };
std::map<std::string, size_t> not_found; std::map<std::string, size_t> not_found;
walk_graph(g, node_id, latest, visited, not_found, depth); walk_graph(m_pool, g, node_id, latest, visited, not_found, depth);
} }
return query_result(QueryType::kDEPENDS, query, std::move(g)); return query_result(QueryType::kDEPENDS, query, std::move(g));

View File

@ -126,8 +126,9 @@ namespace mamba
for (const auto& solv_id : m_pool.select_solvables(dep_id)) for (const auto& solv_id : m_pool.select_solvables(dep_id))
{ {
added = true; added = true;
PackageInfo pkg_info(pool_id2solvable(m_pool, solv_id)); auto pkg_info = m_pool.id2pkginfo(solv_id);
node_id to_id = add_solvable(solv_id, PackageNode{ std::move(pkg_info) }, false); 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); m_graph.add_edge(from_id, to_id, edge);
} }
return added; return added;

View File

@ -171,47 +171,32 @@ namespace mamba
} }
} }
std::optional<PackageInfo> make_solver_problem_source(::Pool* pool, Id source_id) MSolverProblem make_solver_problem(
{ const MSolver& solver,
if (source_id == 0 || source_id >= pool->nsolvables) const MPool& pool,
{ SolverRuleinfo type,
return std::nullopt; Id source_id,
} Id target_id,
return pool_id2solvable(pool, source_id); Id dep_id
} )
std::optional<PackageInfo> make_solver_problem_target(::Pool* pool, Id target_id)
{
if (target_id == 0 || target_id >= pool->nsolvables)
{
return std::nullopt;
}
return pool_id2solvable(pool, target_id);
}
std::optional<std::string> make_solver_problem_dep(::Pool* pool, Id dep_id)
{
if (!dep_id)
{
return std::nullopt;
}
return pool_dep2str(pool, dep_id);
}
MSolverProblem
make_solver_problem(::Solver* solver, SolverRuleinfo type, Id source_id, Id target_id, Id dep_id)
{ {
const ::Solver* const solver_ptr = solver;
return { return {
/* .type= */ type, /* .type= */ type,
/* .source_id= */ source_id, /* .source_id= */ source_id,
/* .target_id= */ target_id, /* .target_id= */ target_id,
/* .dep_id= */ dep_id, /* .dep_id= */ dep_id,
/* .source= */ make_solver_problem_source(solver->pool, source_id), /* .source= */ pool.id2pkginfo(source_id),
/* .target= */ make_solver_problem_target(solver->pool, target_id), /* .target= */ pool.id2pkginfo(target_id),
/* .dep= */ make_solver_problem_dep(solver->pool, dep_id), /* .dep= */ pool.dep2str(dep_id),
/* .description= */ /* .description= */
solver_problemruleinfo2str(solver, type, source_id, target_id, dep_id), solver_problemruleinfo2str(
const_cast<::Solver*>(solver_ptr), // Not const because might alloctmp space
type,
source_id,
target_id,
dep_id
),
}; };
} }
} }
@ -623,7 +608,8 @@ namespace mamba
Id source, target, dep; Id source, target, dep;
const SolverRuleinfo type = solver_ruleinfo(m_solver.get(), r, &source, &target, &dep); const SolverRuleinfo type = solver_ruleinfo(m_solver.get(), r, &source, &target, &dep);
res.push_back(make_solver_problem( res.push_back(make_solver_problem(
/* solver= */ m_solver.get(), /* solver= */ *this,
/* pool= */ m_pool,
/* type= */ type, /* type= */ type,
/* source_id= */ source, /* source_id= */ source,
/* target_id= */ target, /* target_id= */ target,
@ -713,6 +699,11 @@ namespace mamba
return problems; return problems;
} }
MSolver::operator const Solver*() const
{
return m_solver.get();
}
MSolver::operator Solver*() MSolver::operator Solver*()
{ {
return m_solver.get(); return m_solver.get();

View File

@ -32,20 +32,29 @@ extern "C" // Incomplete header
#include "progress_bar_impl.hpp" #include "progress_bar_impl.hpp"
namespace mamba
{
namespace namespace
{ {
bool need_pkg_download(const mamba::PackageInfo& pkg_info, mamba::MultiPackageCache& caches) bool need_pkg_download(const PackageInfo& pkg_info, MultiPackageCache& caches)
{ {
return caches.get_extracted_dir_path(pkg_info).empty() return caches.get_extracted_dir_path(pkg_info).empty()
&& caches.get_tarball_path(pkg_info).empty(); && caches.get_tarball_path(pkg_info).empty();
} }
} // anonymouse namspace
namespace mamba auto mk_pkginfo(const MPool& pool, Solvable* s) -> PackageInfo
{ {
nlohmann::json solvable_to_json(Solvable* s) assert(s != nullptr);
const auto pkginfo = pool.id2pkginfo(pool_solvable2id(pool, s));
assert(pkginfo.has_value()); // There is Solvable so the optional must no be empty
return std::move(pkginfo).value();
};
}
nlohmann::json solvable_to_json(const MPool& pool, Solvable* s)
{ {
return PackageInfo(s).json_record(); return mk_pkginfo(pool, s).json_record();
} }
/******************************** /********************************
@ -64,11 +73,6 @@ namespace mamba
DownloadExtractSemaphore::semaphore.set_max(value); DownloadExtractSemaphore::semaphore.set_max(value);
} }
PackageDownloadExtractTarget::PackageDownloadExtractTarget(Solvable* solvable)
: PackageDownloadExtractTarget(PackageInfo(solvable))
{
}
PackageDownloadExtractTarget::PackageDownloadExtractTarget(const PackageInfo& pkg_info) PackageDownloadExtractTarget::PackageDownloadExtractTarget(const PackageInfo& pkg_info)
: m_finished(false) : m_finished(false)
, m_package_info(pkg_info) , m_package_info(pkg_info)
@ -474,7 +478,8 @@ namespace mamba
const std::vector<MatchSpec>& specs_to_install, const std::vector<MatchSpec>& specs_to_install,
MultiPackageCache& caches MultiPackageCache& caches
) )
: m_multi_cache(caches) : m_pool(pool)
, m_multi_cache(caches)
{ {
// auto& ctx = Context::instance(); // auto& ctx = Context::instance();
std::vector<PackageInfo> pi_result; std::vector<PackageInfo> pi_result;
@ -499,9 +504,9 @@ namespace mamba
pi_result.push_back(p); pi_result.push_back(p);
} }
MRepo& mrepo = MRepo::create(pool, "__explicit_specs__", pi_result); MRepo& mrepo = MRepo::create(m_pool, "__explicit_specs__", pi_result);
pool.create_whatprovides(); m_pool.create_whatprovides();
// Just add the packages we want to remove directly to the transaction // Just add the packages we want to remove directly to the transaction
solv::ObjQueue q, job, decision; solv::ObjQueue q, job, decision;
@ -512,12 +517,12 @@ namespace mamba
job.clear(); job.clear();
q.clear(); q.clear();
const Id id = pool_conda_matchspec(pool, s.conda_build_form().c_str()); const Id id = pool_conda_matchspec(m_pool, s.conda_build_form().c_str());
if (id) if (id)
{ {
job.push_back(SOLVER_SOLVABLE_PROVIDES, id); job.push_back(SOLVER_SOLVABLE_PROVIDES, id);
} }
selection_solvables(pool, job.raw(), q.raw()); selection_solvables(m_pool, job.raw(), q.raw());
if (q.size() == 0) if (q.size() == 0)
{ {
@ -536,8 +541,8 @@ namespace mamba
throw std::runtime_error("Could not find packages to remove:" + join("", not_found)); throw std::runtime_error("Could not find packages to remove:" + join("", not_found));
} }
selection_solvables(pool, job.raw(), q.raw()); selection_solvables(m_pool, job.raw(), q.raw());
const bool remove_success = q.size() >= specs_to_remove.size(); const bool remove_success = size_t(q.size()) >= specs_to_remove.size();
Console::instance().json_write({ { "success", remove_success } }); Console::instance().json_write({ { "success", remove_success } });
Id pkg_id; Id pkg_id;
Solvable* solvable; Solvable* solvable;
@ -548,7 +553,7 @@ namespace mamba
decision.push_back(pkg_id); decision.push_back(pkg_id);
} }
m_transaction = transaction_create_decisionq(pool, decision.raw(), nullptr); m_transaction = transaction_create_decisionq(m_pool, decision.raw(), nullptr);
init(); init();
m_history_entry = History::UserRequest::prefilled(); m_history_entry = History::UserRequest::prefilled();
@ -577,9 +582,10 @@ namespace mamba
); );
} }
MTransaction::MTransaction(MPool& pool, MSolver& solver, MultiPackageCache& caches)
MTransaction::MTransaction(MSolver& solver, MultiPackageCache& caches) : m_pool(pool)
: m_multi_cache(caches) , m_multi_cache(caches)
{ {
if (!solver.is_solved()) if (!solver.is_solved())
{ {
@ -590,8 +596,6 @@ namespace mamba
m_transaction = solver_create_transaction(solver); m_transaction = solver_create_transaction(solver);
transaction_order(m_transaction, 0); transaction_order(m_transaction, 0);
auto* pool = static_cast<Solver*>(solver)->pool;
m_history_entry = History::UserRequest::prefilled(); m_history_entry = History::UserRequest::prefilled();
if (solver.no_deps || solver.only_deps) if (solver.no_deps || solver.only_deps)
@ -599,11 +603,11 @@ namespace mamba
m_filter_type = solver.only_deps ? FilterType::keep_only : FilterType::ignore; m_filter_type = solver.only_deps ? FilterType::keep_only : FilterType::ignore;
for (auto& s : solver.install_specs()) for (auto& s : solver.install_specs())
{ {
m_filter_name_ids.insert(pool_str2id(pool, s.name.c_str(), 0)); m_filter_name_ids.insert(pool_str2id(m_pool, s.name.c_str(), 0));
} }
for (auto& s : solver.remove_specs()) for (auto& s : solver.remove_specs())
{ {
m_filter_name_ids.insert(pool_str2id(pool, s.name.c_str(), 0)); m_filter_name_ids.insert(pool_str2id(m_pool, s.name.c_str(), 0));
} }
if (solver.only_deps) if (solver.only_deps)
@ -612,15 +616,15 @@ namespace mamba
transaction_installedresult(m_transaction, q.raw()); transaction_installedresult(m_transaction, q.raw());
for (const Id r : q) for (const Id r : q)
{ {
Solvable* s = pool_id2solvable(pool, r); Solvable* s = pool_id2solvable(m_pool, r);
if (m_filter_name_ids.count(s->name)) if (m_filter_name_ids.count(s->name))
{ {
// add the dependencies of this selected package to the added specs // add the dependencies of this selected package to the added specs
Id* reqp; Id* reqp;
for (reqp = s->repo->idarraydata + s->requires; *reqp; reqp++) for (reqp = s->repo->idarraydata + s->requires; *reqp; reqp++)
{ {
const char* depname = pool_id2str(pool, *reqp); const char* depname = pool_id2str(m_pool, *reqp);
const char* depevr = pool_id2evr(pool, *reqp); const char* depevr = pool_id2evr(m_pool, *reqp);
std::string add_spec; std::string add_spec;
if (depname) if (depname)
{ {
@ -670,7 +674,8 @@ namespace mamba
solver.install_specs() solver.install_specs()
); );
if (m_transaction_context.relink_noarch && pool->installed != nullptr) ::Pool* const pool_ptr = static_cast<::Pool* const>(m_pool);
if (m_transaction_context.relink_noarch && pool_ptr->installed != nullptr)
{ {
Id p = 0; Id p = 0;
Solvable* s = nullptr; Solvable* s = nullptr;
@ -678,9 +683,9 @@ namespace mamba
solver_get_decisionqueue(solver, decision.raw()); solver_get_decisionqueue(solver, decision.raw());
const Id noarch_repo_key = pool_str2id(pool, "solvable:noarch_type", 1); const Id noarch_repo_key = pool_str2id(m_pool, "solvable:noarch_type", 1);
FOR_REPO_SOLVABLES(pool->installed, p, s) FOR_REPO_SOLVABLES(pool_ptr->installed, p, s)
{ {
const char* noarch_type = solvable_lookup_str(s, noarch_repo_key); const char* noarch_type = solvable_lookup_str(s, noarch_repo_key);
@ -714,11 +719,12 @@ namespace mamba
continue; continue;
} }
PackageInfo pi(s);
const auto pkg_info = mk_pkginfo(m_pool, s);
const Id id = pool_conda_matchspec( const Id id = pool_conda_matchspec(
pool, m_pool,
fmt::format("{} {} {}", pi.name, pi.version, pi.build_string).c_str() fmt::format("{} {} {}", pkg_info.name, pkg_info.version, pkg_info.build_string)
.c_str()
); );
if (id) if (id)
@ -726,13 +732,13 @@ namespace mamba
job.push_back(SOLVER_SOLVABLE_PROVIDES, id); job.push_back(SOLVER_SOLVABLE_PROVIDES, id);
} }
selection_solvables(pool, job.raw(), q.raw()); selection_solvables(m_pool, job.raw(), q.raw());
Id reinstall_id = -1; Id reinstall_id = -1;
for (const Id r : q) for (const Id r : q)
{ {
auto* xid = pool_id2solvable(pool, r); auto* xid = pool_id2solvable(m_pool, r);
if (xid->repo != pool->installed) if (xid->repo != pool_ptr->installed)
{ {
reinstall_id = r; reinstall_id = r;
break; break;
@ -747,9 +753,9 @@ namespace mamba
"To upgrade python we need to reinstall noarch", "To upgrade python we need to reinstall noarch",
" package {} {} {} but we could not find it in", " package {} {} {} but we could not find it in",
" any of the loaded channels.", " any of the loaded channels.",
pi.name, pkg_info.name,
pi.version, pkg_info.version,
pi.build_string pkg_info.build_string
); );
continue; continue;
} }
@ -763,7 +769,7 @@ namespace mamba
} }
transaction_free(m_transaction); transaction_free(m_transaction);
m_transaction = transaction_create_decisionq(pool, decision.raw(), nullptr); m_transaction = transaction_create_decisionq(m_pool, decision.raw(), nullptr);
transaction_order(m_transaction, 0); transaction_order(m_transaction, 0);
// init everything again... // init everything again...
@ -776,11 +782,12 @@ namespace mamba
const std::vector<PackageInfo>& packages, const std::vector<PackageInfo>& packages,
MultiPackageCache& caches MultiPackageCache& caches
) )
: m_multi_cache(caches) : m_pool(pool)
, m_multi_cache(caches)
{ {
LOG_INFO << "MTransaction::MTransaction - packages already resolved (lockfile)"; LOG_INFO << "MTransaction::MTransaction - packages already resolved (lockfile)";
MRepo& mrepo = MRepo::create(pool, "__explicit_specs__", packages); MRepo& mrepo = MRepo::create(m_pool, "__explicit_specs__", packages);
pool.create_whatprovides(); m_pool.create_whatprovides();
solv::ObjQueue decision = {}; solv::ObjQueue decision = {};
@ -792,7 +799,7 @@ namespace mamba
decision.push_back(pkg_id); decision.push_back(pkg_id);
} }
m_transaction = transaction_create_decisionq(pool, decision.raw(), nullptr); m_transaction = transaction_create_decisionq(m_pool, decision.raw(), nullptr);
transaction_order(m_transaction, 0); transaction_order(m_transaction, 0);
init(); init();
@ -828,7 +835,7 @@ namespace mamba
{ {
Id p = m_transaction->steps.elements[i]; Id p = m_transaction->steps.elements[i];
Id ttype = transaction_type(m_transaction, p, SOLVER_TRANSACTION_SHOW_ALL); Id ttype = transaction_type(m_transaction, p, SOLVER_TRANSACTION_SHOW_ALL);
Solvable* s = pool_id2solvable(m_transaction->pool, p); Solvable* s = pool_id2solvable(m_pool, p);
if (filter(s)) if (filter(s))
{ {
continue; continue;
@ -842,7 +849,7 @@ namespace mamba
{ {
m_to_remove.push_back(s); m_to_remove.push_back(s);
m_to_install.push_back( m_to_install.push_back(
m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p) static_cast<::Pool*>(m_pool)->solvables + transaction_obs_pkg(m_transaction, p)
); );
break; break;
} }
@ -871,31 +878,31 @@ namespace mamba
// 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
// Transaction is finished in order to compile the noarch packages correctly, // Transaction is finished in order to compile the noarch packages correctly,
// for example // for example
Pool* pool = m_transaction->pool;
assert(pool != nullptr);
std::string installed_py_ver, new_py_ver; std::string installed_py_ver, new_py_ver;
Id python = pool_str2id(pool, "python", 0); Id python = pool_str2id(m_pool, "python", 0);
for (Solvable* s : m_to_install) for (Solvable* s : m_to_install)
{ {
if (s->name == python) if (s->name == python)
{ {
new_py_ver = pool_id2str(pool, s->evr); new_py_ver = pool_id2str(m_pool, s->evr);
LOG_INFO << "Found python version in packages to be installed " << new_py_ver; LOG_INFO << "Found python version in packages to be installed " << new_py_ver;
break; break;
} }
} }
if (pool->installed != nullptr)
::Pool* const pool_ptr = m_pool;
if (pool_ptr->installed != nullptr)
{ {
Id p; Id p;
Solvable* s; Solvable* s;
FOR_REPO_SOLVABLES(pool->installed, p, s) FOR_REPO_SOLVABLES(pool_ptr->installed, p, s)
{ {
if (s->name == python) if (s->name == python)
{ {
installed_py_ver = pool_id2str(pool, s->evr); installed_py_ver = pool_id2str(m_pool, s->evr);
LOG_INFO << "Found python in installed packages " << installed_py_ver; LOG_INFO << "Found python in installed packages " << installed_py_ver;
break; break;
} }
@ -985,13 +992,11 @@ namespace mamba
TransactionRollback rollback; TransactionRollback rollback;
auto* pool = m_transaction->pool;
for (int i = 0; i < m_transaction->steps.count && !is_sig_interrupted(); i++) for (int i = 0; i < m_transaction->steps.count && !is_sig_interrupted(); i++)
{ {
Id p = m_transaction->steps.elements[i]; Id p = m_transaction->steps.elements[i];
Id ttype = transaction_type(m_transaction, p, SOLVER_TRANSACTION_SHOW_ALL); Id ttype = transaction_type(m_transaction, p, SOLVER_TRANSACTION_SHOW_ALL);
Solvable* s = pool_id2solvable(pool, p); Solvable* s = pool_id2solvable(m_pool, p);
if (filter(s)) if (filter(s))
{ {
@ -1005,17 +1010,19 @@ namespace mamba
case SOLVER_TRANSACTION_CHANGED: case SOLVER_TRANSACTION_CHANGED:
case SOLVER_TRANSACTION_REINSTALLED: case SOLVER_TRANSACTION_REINSTALLED:
{ {
Solvable* s2 = m_transaction->pool->solvables Solvable* s2 = static_cast<::Pool*>(m_pool)->solvables
+ transaction_obs_pkg(m_transaction, p); + transaction_obs_pkg(m_transaction, p);
Console::stream()
<< "Changing " << PackageInfo(s).str() << " ==> " << PackageInfo(s2).str();
PackageInfo package_to_unlink(s); const PackageInfo package_to_unlink = mk_pkginfo(m_pool, s);
const PackageInfo package_to_link = mk_pkginfo(m_pool, s2);
Console::stream() << "Changing " << package_to_unlink.str() << " ==> "
<< package_to_link.str();
const fs::u8path ul_cache_path( const fs::u8path ul_cache_path(
m_multi_cache.get_extracted_dir_path(package_to_unlink) m_multi_cache.get_extracted_dir_path(package_to_unlink)
); );
PackageInfo package_to_link(s2);
const fs::u8path l_cache_path( const fs::u8path l_cache_path(
m_multi_cache.get_extracted_dir_path(package_to_link, false) m_multi_cache.get_extracted_dir_path(package_to_link, false)
); );
@ -1035,7 +1042,7 @@ namespace mamba
} }
case SOLVER_TRANSACTION_ERASE: case SOLVER_TRANSACTION_ERASE:
{ {
PackageInfo package_info(s); PackageInfo package_info = mk_pkginfo(m_pool, s);
Console::stream() << "Unlinking " << package_info.str(); Console::stream() << "Unlinking " << package_info.str();
const fs::u8path cache_path(m_multi_cache.get_extracted_dir_path(package_info)); const fs::u8path cache_path(m_multi_cache.get_extracted_dir_path(package_info));
UnlinkPackage up(package_info, cache_path, &m_transaction_context); UnlinkPackage up(package_info, cache_path, &m_transaction_context);
@ -1046,7 +1053,7 @@ namespace mamba
} }
case SOLVER_TRANSACTION_INSTALL: case SOLVER_TRANSACTION_INSTALL:
{ {
PackageInfo package_info(s); PackageInfo package_info = mk_pkginfo(m_pool, s);
Console::stream() << "Linking " << package_info.str(); Console::stream() << "Linking " << package_info.str();
const fs::u8path cache_path( const fs::u8path cache_path(
m_multi_cache.get_extracted_dir_path(package_info, false) m_multi_cache.get_extracted_dir_path(package_info, false)
@ -1083,7 +1090,7 @@ namespace mamba
auto MTransaction::to_conda() -> to_conda_type auto MTransaction::to_conda() -> to_conda_type
{ {
Id real_repo_key = pool_str2id(m_transaction->pool, "solvable:real_repo_url", 1); const Id real_repo_key = pool_str2id(m_pool, "solvable:real_repo_url", 1);
to_install_type to_install_structured; to_install_type to_install_structured;
to_remove_type to_remove_structured; to_remove_type to_remove_structured;
@ -1097,7 +1104,7 @@ namespace mamba
for (Solvable* s : m_to_install) for (Solvable* s : m_to_install)
{ {
const char* mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE); const char* mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
std::string s_json = solvable_to_json(s).dump(4); std::string s_json = solvable_to_json(m_pool, s).dump(4);
std::string channel; std::string channel;
if (solvable_lookup_str(s, real_repo_key)) if (solvable_lookup_str(s, real_repo_key))
@ -1126,20 +1133,20 @@ namespace mamba
for (Solvable* s : m_to_install) for (Solvable* s : m_to_install)
{ {
if (!need_pkg_download(s, m_multi_cache)) if (!need_pkg_download(mk_pkginfo(m_pool, s), m_multi_cache))
{ {
to_link.push_back(solvable_to_json(s)); to_link.push_back(solvable_to_json(m_pool, s));
} }
else else
{ {
to_fetch.push_back(solvable_to_json(s)); to_fetch.push_back(solvable_to_json(m_pool, s));
to_link.push_back(solvable_to_json(s)); to_link.push_back(solvable_to_json(m_pool, s));
} }
} }
for (Solvable* s : m_to_remove) for (Solvable* s : m_to_remove)
{ {
to_unlink.push_back(solvable_to_json(s)); to_unlink.push_back(solvable_to_json(m_pool, s));
} }
auto add_json = [](const auto& jlist, const char* s) auto add_json = [](const auto& jlist, const char* s)
@ -1184,9 +1191,7 @@ namespace mamba
if (ctx.experimental && ctx.verify_artifacts) if (ctx.experimental && ctx.verify_artifacts)
{ {
const auto& repo_checker = make_channel(mamba_repo->url()).repo_checker(m_multi_cache); const auto& repo_checker = make_channel(mamba_repo->url()).repo_checker(m_multi_cache);
const auto pkg_info = mk_pkginfo(m_pool, s);
auto pkg_info = PackageInfo(s);
repo_checker.verify_package( repo_checker.verify_package(
pkg_info.json_signable(), pkg_info.json_signable(),
nlohmann::json::parse(pkg_info.signatures) nlohmann::json::parse(pkg_info.signatures)
@ -1195,7 +1200,8 @@ namespace mamba
LOG_DEBUG << "'" << pkg_info.name << "' trusted from '" << mamba_repo->url() << "'"; LOG_DEBUG << "'" << pkg_info.name << "' trusted from '" << mamba_repo->url() << "'";
} }
targets.emplace_back(std::make_unique<PackageDownloadExtractTarget>(s)); targets.emplace_back(std::make_unique<PackageDownloadExtractTarget>(mk_pkginfo(m_pool, s))
);
DownloadTarget* download_target = targets.back()->target(m_multi_cache); DownloadTarget* download_target = targets.back()->target(m_multi_cache);
if (download_target != nullptr) if (download_target != nullptr)
{ {
@ -1450,7 +1456,6 @@ namespace mamba
rows downgraded, upgraded, changed, reinstalled, erased, installed, ignored; rows downgraded, upgraded, changed, reinstalled, erased, installed, ignored;
std::size_t total_size = 0; std::size_t total_size = 0;
auto* pool = m_transaction->pool;
enum struct Status enum struct Status
{ {
@ -1459,7 +1464,7 @@ namespace mamba
remove remove
}; };
auto format_row = auto format_row =
[this, &ctx, pool, &total_size](rows& r, Solvable* s, Status status, std::string diff) [this, &ctx, &total_size](rows& r, Solvable* s, Status status, std::string diff)
{ {
std::size_t dlsize = solvable_lookup_num(s, SOLVABLE_DOWNLOADSIZE, SIZE_MAX); std::size_t dlsize = solvable_lookup_num(s, SOLVABLE_DOWNLOADSIZE, SIZE_MAX);
printers::FormattedString dlsize_s; printers::FormattedString dlsize_s;
@ -1471,7 +1476,7 @@ namespace mamba
} }
else else
{ {
if (!need_pkg_download(s, m_multi_cache)) if (!need_pkg_download(mk_pkginfo(m_pool, s), m_multi_cache))
{ {
dlsize_s.s = "Cached"; dlsize_s.s = "Cached";
dlsize_s.style = ctx.palette.addition; dlsize_s.style = ctx.palette.addition;
@ -1490,7 +1495,7 @@ namespace mamba
} }
} }
printers::FormattedString name; printers::FormattedString name;
name.s = fmt::format("{} {}", diff, pool_id2str(pool, s->name)); name.s = fmt::format("{} {}", diff, pool_id2str(m_pool, s->name));
if (status == Status::install) if (status == Status::install)
{ {
name.style = ctx.palette.addition; name.style = ctx.palette.addition;
@ -1506,7 +1511,7 @@ namespace mamba
const char* build_string = solvable_lookup_str(s, SOLVABLE_BUILDFLAVOR); const char* build_string = solvable_lookup_str(s, SOLVABLE_BUILDFLAVOR);
std::string channel; std::string channel;
Id real_repo_key = pool_str2id(pool, "solvable:real_repo_url", 1); Id real_repo_key = pool_str2id(m_pool, "solvable:real_repo_url", 1);
if (solvable_lookup_str(s, real_repo_key)) if (solvable_lookup_str(s, real_repo_key))
{ {
std::string repo_key = solvable_lookup_str(s, real_repo_key); std::string repo_key = solvable_lookup_str(s, real_repo_key);
@ -1529,12 +1534,14 @@ namespace mamba
} }
r.push_back({ name, r.push_back({ name,
printers::FormattedString(pool_id2str(pool, s->evr)), printers::FormattedString(pool_id2str(m_pool, s->evr)),
printers::FormattedString(build_string ? build_string : ""), printers::FormattedString(build_string ? build_string : ""),
printers::FormattedString(cut_repo_name(channel)), printers::FormattedString(cut_repo_name(channel)),
dlsize_s }); dlsize_s });
}; };
::Solvable* const solvables = static_cast<::Pool*>(m_pool)->solvables;
int mode = SOLVER_TRANSACTION_SHOW_OBSOLETES | SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE; int mode = SOLVER_TRANSACTION_SHOW_OBSOLETES | SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
transaction_classify(m_transaction, mode, classes.raw()); transaction_classify(m_transaction, mode, classes.raw());
for (std::size_t n_classes = classes.size(), i = 0; i < n_classes; i += 4) for (std::size_t n_classes = classes.size(), i = 0; i < n_classes; i += 4)
@ -1551,7 +1558,7 @@ namespace mamba
for (const Id p : pkgs) for (const Id p : pkgs)
{ {
Solvable* s = m_transaction->pool->solvables + p; Solvable* s = solvables + p;
if (filter(s)) if (filter(s))
{ {
@ -1564,7 +1571,7 @@ namespace mamba
format_row(upgraded, s, Status::remove, "-"); format_row(upgraded, s, Status::remove, "-");
format_row( format_row(
upgraded, upgraded,
m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p), solvables + transaction_obs_pkg(m_transaction, p),
Status::install, Status::install,
"+" "+"
); );
@ -1573,7 +1580,7 @@ namespace mamba
format_row(changed, s, Status::remove, "-"); format_row(changed, s, Status::remove, "-");
format_row( format_row(
changed, changed,
m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p), solvables + transaction_obs_pkg(m_transaction, p),
Status::install, Status::install,
"+" "+"
); );
@ -1585,7 +1592,7 @@ namespace mamba
format_row(downgraded, s, Status::remove, "-"); format_row(downgraded, s, Status::remove, "-");
format_row( format_row(
downgraded, downgraded,
m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p), solvables + transaction_obs_pkg(m_transaction, p),
Status::install, Status::install,
"+" "+"
); );

View File

@ -844,8 +844,6 @@ class MultiPackageCache:
pass pass
class PackageInfo: class PackageInfo:
@typing.overload
def __init__(self, arg0: s_Solvable) -> None: ...
@typing.overload @typing.overload
def __init__(self, name: str) -> None: ... def __init__(self, name: str) -> None: ...
@typing.overload @typing.overload
@ -1398,6 +1396,9 @@ class SubdirData:
pass pass
class Transaction: class Transaction:
@typing.overload
def __init__(self, arg0: Pool, arg1: Solver, arg2: MultiPackageCache) -> None: ...
@typing.overload
def __init__(self, arg0: Solver, arg1: MultiPackageCache) -> None: ... def __init__(self, arg0: Solver, arg1: MultiPackageCache) -> None: ...
def execute(self, arg0: PrefixData) -> bool: ... def execute(self, arg0: PrefixData) -> bool: ...
def fetch_extract_packages(self) -> bool: ... def fetch_extract_packages(self) -> bool: ...

View File

@ -210,7 +210,14 @@ PYBIND11_MODULE(bindings, m)
.def("clear", &MRepo::clear); .def("clear", &MRepo::clear);
py::class_<MTransaction>(m, "Transaction") py::class_<MTransaction>(m, "Transaction")
.def(py::init<MSolver&, MultiPackageCache&>()) .def(py::init<>(
[](MSolver& solver, MultiPackageCache& mpc)
{
deprecated("Use Transaction(Pool, Solver, MultiPackageCache) instead");
return std::make_unique<MTransaction>(solver.pool(), solver, mpc);
}
))
.def(py::init<MPool&, MSolver&, 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)
.def("print", &MTransaction::print) .def("print", &MTransaction::print)
@ -565,7 +572,7 @@ PYBIND11_MODULE(bindings, m)
.def_property_readonly("package_records", &PrefixData::records) .def_property_readonly("package_records", &PrefixData::records)
.def("add_packages", &PrefixData::add_packages); .def("add_packages", &PrefixData::add_packages);
pyPackageInfo.def(py::init<Solvable*>()) pyPackageInfo //
.def(py::init<const std::string&>(), py::arg("name")) .def(py::init<const std::string&>(), py::arg("name"))
.def( .def(
py::init<const std::string&, const std::string&, const std::string&, std::size_t>(), py::init<const std::string&, const std::string&, const std::string&, std::size_t>(),

View File

@ -224,7 +224,7 @@ def remove(args, parser):
return exit_code return exit_code
package_cache = api.MultiPackageCache(context.pkgs_dirs) package_cache = api.MultiPackageCache(context.pkgs_dirs)
transaction = api.Transaction(solver, package_cache) transaction = api.Transaction(pool, solver, package_cache)
if not transaction.prompt(): if not transaction.prompt():
exit(0) exit(0)
@ -562,7 +562,7 @@ def install(args, parser, command="install"):
return exit_code return exit_code
package_cache = api.MultiPackageCache(context.pkgs_dirs) package_cache = api.MultiPackageCache(context.pkgs_dirs)
transaction = api.Transaction(solver, package_cache) transaction = api.Transaction(pool, solver, package_cache)
mmb_specs, to_link, to_unlink = transaction.to_conda() mmb_specs, to_link, to_unlink = transaction.to_conda()
specs_to_add = [MatchSpec(m) for m in mmb_specs[0]] specs_to_add = [MatchSpec(m) for m in mmb_specs[0]]

View File

@ -141,7 +141,7 @@ def mamba_install(prefix, specs, args, env, dry_run=False, *_, **kwargs):
exit(1) exit(1)
package_cache = api.MultiPackageCache(context.pkgs_dirs) package_cache = api.MultiPackageCache(context.pkgs_dirs)
transaction = api.Transaction(solver, package_cache) transaction = api.Transaction(pool, solver, package_cache)
mmb_specs, to_link, to_unlink = transaction.to_conda() mmb_specs, to_link, to_unlink = transaction.to_conda()
specs_to_add = [MatchSpec(m) for m in mmb_specs[0]] specs_to_add = [MatchSpec(m) for m in mmb_specs[0]]