Merge pull request #3063 from Vogtinator/smartfileconflicts

osclib/repochecks.py: Use libsolv for checking conflicts between packages
This commit is contained in:
Fabian Vogt 2024-02-22 16:41:53 +01:00 committed by GitHub
commit 1748b2024e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 4 deletions

View File

@ -446,8 +446,8 @@ for my $tc (sort keys %tocheck) {
my @sp1 = split(' ', $p1);
my @sp2 = split(' ', $p2);
print "- between:\n";
print " - [$sp1[0], $sp1[1], $sp1[2], $sp1[3]]\n";
print " - [$sp2[0], $sp2[1], $sp2[2], $sp2[3]]\n";
print " - [$sp1[0], '$sp1[1]', '$sp1[2]', $sp1[3]]\n";
print " - [$sp2[0], '$sp2[1]', '$sp2[2]', $sp2[3]]\n";
print " conflicts: |-\n";
print " $_\n" for (@con);
}

View File

@ -2,6 +2,7 @@ import logging
import os
import re
import requests
import solv
import subprocess
import tempfile
import glob
@ -63,12 +64,40 @@ def _check_conflicts_whitelist(sp1, sp2, whitelist):
return True
def _fileconflicts(pfile, target_packages, whitelist):
def _do_packages_conflict(pool, pkgs):
logger.debug("Checking whether %s can be installed at once", pkgs)
jobs = []
for pkg in pkgs:
sel = pool.select(pkg, solv.Selection.SELECTION_CANON | solv.Selection.SELECTION_DOTARCH)
if sel.isempty():
raise RuntimeError(f"{pkg} not found in pool")
jobs += sel.jobs(solv.Job.SOLVER_INSTALL)
solver = pool.Solver()
problems = solver.solve(jobs)
if not problems:
return False
for problem in problems:
logger.debug("Problem: %s", str(problem))
return True
def _fileconflicts(pfile, arch, target_packages, whitelist):
script = os.path.join(SCRIPT_PATH, '..', 'findfileconflicts')
p = subprocess.run(['perl', script, pfile], stdout=subprocess.PIPE)
if p.returncode or len(p.stdout):
output = ''
conflicts = yaml.safe_load(p.stdout)
pool = solv.Pool()
pool.setarch(arch)
repo = pool.add_repo("packages")
repo.add_susetags(solv.xfopen(pfile), pool.lookup_id(solv.SOLVID_META, solv.SUSETAGS_DEFAULTVENDOR), "en")
pool.createwhatprovides()
for conflict in conflicts:
sp1 = conflict['between'][0]
sp2 = conflict['between'][1]
@ -79,6 +108,12 @@ def _fileconflicts(pfile, target_packages, whitelist):
if _check_conflicts_whitelist(sp1, sp2, whitelist):
continue
pkgcanon1 = _format_pkg(sp1)
pkgcanon2 = _format_pkg(sp2)
if _do_packages_conflict(pool, [pkgcanon1, pkgcanon2]):
logger.debug("Packages %s and %s with conflicting files conflict", pkgcanon1, pkgcanon2)
continue
output += "found conflict of {} with {}\n".format(_format_pkg(sp1), _format_pkg(sp2))
for file in conflict['conflicts'].split('\n'):
output += " {}\n".format(file)
@ -159,7 +194,7 @@ def installcheck(directories, arch, whitelist, ignore_conflicts):
target_packages = catalog.get(directories[0], [])
parts = []
output = _fileconflicts(pfile, target_packages, ignore_conflicts)
output = _fileconflicts(pfile, arch, target_packages, ignore_conflicts)
if output:
parts.append(output)