Skip to content

Commit

Permalink
Simple MSolver::add_pin to play along all_problems_structured
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoinePrv committed Mar 30, 2023
1 parent c90533d commit 75caca0
Showing 1 changed file with 16 additions and 72 deletions.
88 changes: 16 additions & 72 deletions libmamba/src/core/solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,78 +417,22 @@ namespace mamba

void MSolver::add_pin(const std::string& pin)
{
// if we pin a package, we need to remove all packages that don't match the
// pin from being available for installation! This is done by adding
// SOLVER_LOCK to the packages, so that they are prevented from being
// installed A lock basically says: keep the state of the package. I.e.
// uninstalled packages stay uninstalled, installed packages stay installed.
// A lock is a hard requirement, we could also use SOLVER_FAVOR for soft
// requirements

// First we need to check if the pin is OK given the currently installed
// packages
Pool* pool = m_pool;
MatchSpec ms(pin);

// TODO
// if (m_prefix_data)
// {
// for (auto& [name, record] : m_prefix_data->records())
// {
// LOG_ERROR << "NAME " << name;
// if (name == ms.name)
// {
// LOG_ERROR << "Found pinned package in installed packages, need
// to check pin now."; LOG_ERROR << record.version << " vs " <<
// ms.version;
// }
// }
// }

Id match = pool_conda_matchspec(pool, ms.conda_build_form().c_str());

std::set<Id> matching_solvables;
const Channel& c = make_channel(ms.channel);

for (Id* wp = pool_whatprovides_ptr(pool, match); *wp; wp++)
{
if (!ms.channel.empty())
{
if (!channel_match(pool_id2solvable(pool, *wp), c))
{
continue;
}
}
matching_solvables.insert(*wp);
}

std::set<Id> all_solvables;
Id name_id = pool_str2id(pool, ms.name.c_str(), 1);
for (Id* wp = pool_whatprovides_ptr(pool, name_id); *wp; wp++)
{
all_solvables.insert(*wp);
}

if (all_solvables.size() != 0 && matching_solvables.size() == 0)
{
throw std::runtime_error(fmt::format("No package can be installed for pin: {}", pin));
}
m_pinned_specs.push_back(ms);

solv::ObjQueue selected_pkgs;

for (auto& id : all_solvables)
{
if (matching_solvables.find(id) == matching_solvables.end())
{
// the solvable is _NOT_ matched by our pinning expression! So we have to
// lock it to make it un-installable
selected_pkgs.push_back(id);
}
}

Id d = pool_queuetowhatprovides(pool, selected_pkgs.raw());
m_jobs->push_back(SOLVER_LOCK | SOLVER_SOLVABLE_ONE_OF, d);
// A previous version of this function would use ``SOLVER_LOCK`` to lock all packages not
// matching the pin.
// In libsolv, locking means that a package keep the same state: if it is installed,
// it remains installed, if not it remains uninstalled.
// Locking on a spec applies the lock to all packages matching the spec.
// In mamba, we do not want to lock the package because we want to allow other variants
// (mathcing the same spec) to unlock more solutions.
// For instance we may pin ``libfmt=8.*`` but allow it to be swaped with a version built
// by a more recent compiler.
// To achieve that, the previous version was locking (out) all solvables not matching the
// spec.
//
// Given that in Mamba, only a single version of a package can be installed at a time,
// and that libsolv knows which packages are already installed, it seems that one can
// simply add the pin as an extra job in order for it to be treated as a constraint.
return add_jobs({ pin }, SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES);
}

void MSolver::add_pins(const std::vector<std::string>& pins)
Expand Down

0 comments on commit 75caca0

Please sign in to comment.