Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid reinstalling installonly packages marked for ERASE #1625

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions libdnf/goal/Goal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,12 @@ erase_flags2libsolv(int flags)
return ret;
}

static bool
NameSolvableComparator(const Solvable * first, const Solvable * second)
{
return first->name < second->name;
}

Goal::Goal(const Goal & goal_src) : pImpl(new Impl(*goal_src.pImpl)) {}

Goal::Impl::Impl(const Goal::Impl & goal_src)
Expand Down Expand Up @@ -1436,10 +1442,24 @@ Goal::Impl::limitInstallonlyPackages(Solver *solv, Queue *job)
for (int i = 0; i < onlies->count; ++i) {
Id p, pp;
IdQueue q, installing;
std::vector<Solvable *> available_unused_providers;

// Add all providers of installonly provides that are marked for install
// to `q` IdQueue those that are not marked for install and are not already
// installed are added to available_unused_providers.
FOR_PKG_PROVIDES(p, pp, onlies->elements[i])
if (solver_get_decisionlevel(solv, p) > 0)
// According to libsolv-bindings the decision level is positive for installs
// and negative for conflicts (conflicts with another package or dependency
// conflicts = dependencies cannot be met).
if (solver_get_decisionlevel(solv, p) > 0) {
q.pushBack(p);
} else {
Solvable *s = pool_id2solvable(pool, p);
if (s->repo != pool->installed) {
available_unused_providers.push_back(s);
}
}

if (q.size() <= (int) dnf_sack_get_installonly_limit(sack)) {
continue;
}
Expand All @@ -1457,6 +1477,7 @@ Goal::Impl::limitInstallonlyPackages(Solver *solv, Queue *job)

struct InstallonliesSortCallback s_cb = {pool, dnf_sack_running_kernel(sack)};
solv_sort(q.data(), q.size(), sizeof(q[0]), sort_packages, &s_cb);
std::sort(available_unused_providers.begin(), available_unused_providers.end(), NameSolvableComparator);
IdQueue same_names;
while (q.size() > 0) {
same_name_subqueue(pool, q.getQueue(), same_names.getQueue());
Expand All @@ -1466,8 +1487,18 @@ Goal::Impl::limitInstallonlyPackages(Solver *solv, Queue *job)
for (int j = 0; j < same_names.size(); ++j) {
Id id = same_names[j];
Id action = SOLVER_ERASE;
if (j < (int) dnf_sack_get_installonly_limit(sack))
if (j < (int) dnf_sack_get_installonly_limit(sack)) {
action = SOLVER_INSTALL;
} else {
// We want to avoid reinstalling packages marked for ERASE, therefore
// if some unused provider is also available we need to mark it ERASE as well.
Solvable *s = pool_id2solvable(pool, id);
auto low = std::lower_bound(available_unused_providers.begin(), available_unused_providers.end(), s, NameSolvableComparator);
while (low != available_unused_providers.end() && (*low)->name == s->name) {
queue_push2(job, SOLVER_ERASE | SOLVER_SOLVABLE, pool_solvable2id(pool, *low));
++low;
}
}
queue_push2(job, action | SOLVER_SOLVABLE, id);
}
}
Expand Down
Loading