Skip to content

Commit

Permalink
PackageQuery: Add filter_duplicates() method
Browse files Browse the repository at this point in the history
  • Loading branch information
kontura committed Nov 29, 2022
1 parent d42c163 commit c0643a1
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
3 changes: 3 additions & 0 deletions include/libdnf/rpm/package_query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,9 @@ class PackageQuery : public PackageSet {

void swap(PackageQuery & other) noexcept;

/// Filter packages to keep only duplicates of installed packages. Packages are duplicate if they have the same `name` and `arch` but different `evr`.
void filter_duplicates();

private:
friend libdnf::Goal;
class PQImpl;
Expand Down
62 changes: 62 additions & 0 deletions libdnf/rpm/package_query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2148,6 +2148,30 @@ static void add_n_first_to_map(
}
}

static void add_duplicates_to_map(
libdnf::solv::Pool & pool,
libdnf::solv::SolvMap & result,
libdnf::solv::IdQueue & samename,
int start_block,
int stop_block) {
Solvable * s_first = nullptr;
Solvable * s_second = nullptr;
for (int pos_first = start_block; pos_first < stop_block; ++pos_first) {
Id id_first = samename[pos_first];
s_first = pool.id2solvable(id_first);
for (int pos_second = start_block; pos_second < stop_block; ++pos_second) {
Id id_second = samename[pos_second];
s_second = pool.id2solvable(id_second);
if ((s_first->evr == s_second->evr) && (s_first->arch != s_second->arch)) {
continue;
}

result.add_unsafe(id_first);
result.add_unsafe(id_second);
}
}
}

static int latest_cmp(const Id * ap, const Id * bp, libdnf::solv::Pool * pool) {
Solvable * sa = pool->id2solvable(*ap);
Solvable * sb = pool->id2solvable(*bp);
Expand Down Expand Up @@ -2349,4 +2373,42 @@ void PackageQuery::swap(PackageQuery & other) noexcept {
p_pq_impl.swap(other.p_pq_impl);
}

void PackageQuery::filter_duplicates() {
auto & pool = get_pool(p_impl->base);

filter_installed();

libdnf::solv::IdQueue samename;
for (Id candidate_id : *p_impl) {
samename.push_back(candidate_id);
}
samename.sort(latest_cmp, &pool);

p_impl->clear();
// Create blocks per name, arch
Solvable * highest = nullptr;
int start_block = -1;
int i;
for (i = 0; i < samename.size(); ++i) {
Solvable * considered = pool.id2solvable(samename[i]);
if (!highest || highest->name != considered->name || highest->arch != considered->arch) {
/* start of a new block */
if (start_block == -1) {
highest = considered;
start_block = i;
continue;
}
if (start_block != i - 1) {
add_duplicates_to_map(pool, *p_impl, samename, start_block, i);
}
highest = considered;
start_block = i;
}
}
if (start_block != i - 1) { // Add last block to the map if it is bigger than 1 (has duplicates)
add_duplicates_to_map(pool, *p_impl, samename, start_block, i);
}
}


} // namespace libdnf::rpm

0 comments on commit c0643a1

Please sign in to comment.