From 7b46fdcbd8077e0d829a64d37a6d4888ca062813 Mon Sep 17 00:00:00 2001 From: Dan Callaghan Date: Oct 16 2017 05:51:50 +0000 Subject: ensure we check at least one conflict candidate from the repos Bug: 1502458 Change-Id: Ic359b9fa32b510bbdc56c07d3389a29028cbb41d --- diff --git a/acceptance_tests/test_check_conflicts.py b/acceptance_tests/test_check_conflicts.py index 7783a19..c1fa7c7 100644 --- a/acceptance_tests/test_check_conflicts.py +++ b/acceptance_tests/test_check_conflicts.py @@ -189,9 +189,15 @@ def test_conflict_not_ignored_if_contents_match_but_perms_differ(request, dir_se different_group.get_built_rpm('i386')]) assert exitcode == 3 assert err == ('Undeclared file conflicts:\n' + 'x-0.1-1.i386 provides /usr/share/thing which is also provided by b-0.1-1.i386\n' 'x-0.1-1.i386 provides /usr/share/thing which is also provided by y-0.1-1.i386\n' + 'x-0.1-1.i386 provides /usr/share/thing which is also provided by z-0.1-1.i386\n' + 'y-0.1-1.i386 provides /usr/share/thing which is also provided by b-0.1-1.i386\n' 'y-0.1-1.i386 provides /usr/share/thing which is also provided by x-0.1-1.i386\n' + 'y-0.1-1.i386 provides /usr/share/thing which is also provided by z-0.1-1.i386\n' + 'z-0.1-1.i386 provides /usr/share/thing which is also provided by b-0.1-1.i386\n' 'z-0.1-1.i386 provides /usr/share/thing which is also provided by x-0.1-1.i386\n' + 'z-0.1-1.i386 provides /usr/share/thing which is also provided by y-0.1-1.i386\n' ) @@ -333,6 +339,47 @@ def test_finds_conflicts_in_installonly_packages(request, dir_server): 'which is also provided by kernel-core-0.1-1.i386\n') +# https://bugzilla.redhat.com/show_bug.cgi?id=1502458 +def test_finds_conflict_against_older_subpackage(request, dir_server): + conflicting_path = 'usr/share/man/man1/vim.1.gz' + oldvim = rpmfluff.SimpleRpmBuild('vim', '7.4.1989', '2', ['x86_64']) + oldvim.add_subpackage('common') + oldvim.add_subpackage('minimal') + oldvim.add_installed_file(installPath=conflicting_path, + sourceFile=rpmfluff.SourceFile('vim.1', 'oldcontent\n'), + subpackageSuffix='common') + oldvim.get_subpackage('minimal').section_files += '/%s\n' % conflicting_path + baserepo = rpmfluff.YumRepoBuild([oldvim]) + baserepo.make('x86_64') + dir_server.basepath = baserepo.repoDir + + newvim = rpmfluff.SimpleRpmBuild('vim', '8.0.118', '1', ['x86_64']) + newvim.add_subpackage('common') + newvim.add_subpackage('minimal') + newvim.add_installed_file(installPath=conflicting_path, + sourceFile=rpmfluff.SourceFile('vim.1', 'newcontent\n'), + subpackageSuffix='common') + newvim.get_subpackage('minimal').section_files += '/%s\n' % conflicting_path + newvim.make() + + def cleanUp(): + shutil.rmtree(baserepo.repoDir) + shutil.rmtree(oldvim.get_base_dir()) + shutil.rmtree(newvim.get_base_dir()) + request.addfinalizer(cleanUp) + + exitcode, out, err = run_rpmdeplint(['rpmdeplint', 'check-conflicts', + '--repo=base,{}'.format(dir_server.url), + newvim.get_built_rpm('x86_64', name='vim-common'), + newvim.get_built_rpm('x86_64', name='vim-minimal')]) + assert exitcode == 3 + assert err == ('Undeclared file conflicts:\n' + 'vim-common-8.0.118-1.x86_64 provides /usr/share/man/man1/vim.1.gz ' + 'which is also provided by vim-minimal-7.4.1989-2.x86_64\n' + 'vim-minimal-8.0.118-1.x86_64 provides /usr/share/man/man1/vim.1.gz ' + 'which is also provided by vim-common-7.4.1989-2.x86_64\n') + + # https://bugzilla.redhat.com/show_bug.cgi?id=1448768 def test_obeys_xml_base_when_downloading_packages(request, tmpdir, dir_server): p2 = rpmfluff.SimpleRpmBuild('b', '0.1', '1', ['x86_64']) diff --git a/rpmdeplint/__init__.py b/rpmdeplint/__init__.py index 5cba623..c9d9c94 100644 --- a/rpmdeplint/__init__.py +++ b/rpmdeplint/__init__.py @@ -384,22 +384,34 @@ class DependencyAnalyzer(object): logger.debug('Checking all files in %s for conflicts', solvable) for filename in self._files_in_solvable(solvable): conflict_candidates = self._solvables_with_file(filename) - for i, conflicting in enumerate(conflict_candidates, 1): + checked_one_remote_candidate = False + for conflicting in conflict_candidates: if conflicting == solvable: continue if not self._packages_can_be_installed_together(solvable, conflicting): continue + if conflicting not in self.solvables and checked_one_remote_candidate: + # For each filename we are checking, we only want to + # check at most *one* package from the remote + # repositories. This is purely an optimization to save + # network bandwidth and time. We *are* potentially + # missing some real conflicts by doing this, but the + # cost of downloading every package in the distro for + # common directories like /usr/lib/debug is too high. + # Note however that we do always ensure at least one + # *remote* candidate is checked (that is, not from the + # set of packages under test) to catch problems like + # bug 1502458. + logger.debug('Skipping conflict check on %s with %s ' + 'to save network bandwidth', filename, conflicting) + continue logger.debug('Considering conflict on %s with %s', filename, conflicting) - conflicting_amount = len(conflict_candidates) - i if not self._file_conflict_is_permitted(solvable, conflicting, filename): msg = u'{} provides {} which is also provided by {}'.format( six.text_type(solvable), filename, six.text_type(conflicting)) problems.append(msg) - - if conflicting_amount: - logger.debug('Skipping %s further conflict checks on %s for %s', - conflicting_amount, solvable, filename) - break + if conflicting not in self.solvables: + checked_one_remote_candidate = True return sorted(problems) def find_upgrade_problems(self):