Skip to content

Commit

Permalink
System package manager install set of equivalent packages (#11367)
Browse files Browse the repository at this point in the history
* wip

* wip

* minor changes

* minor changes

* fix test

* fix test

* extend test

* review
  • Loading branch information
czoido authored Jun 1, 2022
1 parent ab6f8be commit d02459c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 9 deletions.
15 changes: 15 additions & 0 deletions conan/tools/system/package_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def run(self, method, *args, **kwargs):
if self._active_tool == self.__class__.tool_name:
return method(*args, **kwargs)

def install_substitutes(self, *args, **kwargs):
return self.run(self._install_substitutes, *args, **kwargs)

def install(self, *args, **kwargs):
return self.run(self._install, *args, **kwargs)

Expand All @@ -70,6 +73,18 @@ def update(self, *args, **kwargs):
def check(self, *args, **kwargs):
return self.run(self._check, *args, **kwargs)

def _install_substitutes(self, *packages_substitutes, update=False, check=True, **kwargs):
errors = []
for packages in packages_substitutes:
try:
return self.install(packages, update, check, **kwargs)
except ConanException as e:
errors.append(e)

for error in errors:
self._conanfile.output.warn(str(error))
raise ConanException("None of the installs for the package substitutes succeeded.")

def _install(self, packages, update=False, check=True, **kwargs):
if update:
self.update()
Expand Down
54 changes: 45 additions & 9 deletions conans/test/functional/tools/system/package_manager_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@

@pytest.mark.tool_apt_get
@pytest.mark.skipif(platform.system() != "Linux", reason="Requires apt")
@pytest.mark.skipif(six.PY2, reason="Does not pass on Py2 with Pytest")
def test_apt_check():
client = TestClient()
client.save({"conanfile.py": textwrap.dedent("""
from conans import ConanFile
from conan import ConanFile
from conan.tools.system.package_manager import Apt
class MyPkg(ConanFile):
settings = "arch", "os"
Expand All @@ -30,11 +29,49 @@ def system_requirements(self):

@pytest.mark.tool_apt_get
@pytest.mark.skipif(platform.system() != "Linux", reason="Requires apt")
@pytest.mark.skipif(six.PY2, reason="Does not pass on Py2 with Pytest")
def test_apt_install_substitutes():
client = TestClient()
conanfile_py = textwrap.dedent("""
from conan import ConanFile
from conan.tools.system.package_manager import Apt
class MyPkg(ConanFile):
settings = "arch", "os"
def system_requirements(self):
# FIXME this is needed because the ci-functional apt-get update fails
try:
self.run("sudo apt-get update")
except Exception:
pass
apt = Apt(self)
{}
""")

installs = 'apt.install_substitutes(["non-existing1", "non-existing2"], ["non-existing3", "non-existing4"])'
client.save({"conanfile.py": conanfile_py.format(installs)})
client.run("create . test/1.0@ -c tools.system.package_manager:mode=install "
"-c tools.system.package_manager:sudo=True", assert_error=True)

assert "dpkg-query: no packages found matching non-existing1:amd64" in client.out
assert "dpkg-query: no packages found matching non-existing2:amd64" in client.out
assert "dpkg-query: no packages found matching non-existing3:amd64" in client.out
assert "dpkg-query: no packages found matching non-existing4:amd64" in client.out
assert "ERROR: while executing system_requirements(): " \
"None of the installs for the package substitutes succeeded." in client.out

client.run_command("sudo apt remove nano -yy")
installs = 'apt.install_substitutes(["non-existing1", "non-existing2"], ["nano"], ["non-existing3"])'
client.save({"conanfile.py": conanfile_py.format(installs)})
client.run("create . test/1.0@ -c tools.system.package_manager:mode=install "
"-c tools.system.package_manager:sudo=True")
assert "1 newly installed" in client.out


@pytest.mark.tool_apt_get
@pytest.mark.skipif(platform.system() != "Linux", reason="Requires apt")
def test_build_require():
client = TestClient()
client.save({"tool_require.py": textwrap.dedent("""
from conans import ConanFile
from conan import ConanFile
from conan.tools.system.package_manager import Apt
class MyPkg(ConanFile):
settings = "arch", "os"
Expand All @@ -45,7 +82,7 @@ def system_requirements(self):
""")})
client.run("export tool_require.py tool_require/1.0@")
client.save({"consumer.py": textwrap.dedent("""
from conans import ConanFile
from conan import ConanFile
class consumer(ConanFile):
settings = "arch", "os"
tool_requires = "tool_require/1.0"
Expand All @@ -58,11 +95,10 @@ class consumer(ConanFile):

@pytest.mark.tool_brew
@pytest.mark.skipif(platform.system() != "Darwin", reason="Requires brew")
@pytest.mark.skipif(six.PY2, reason="Does not pass on Py2 with Pytest")
def test_brew_check():
client = TestClient()
client.save({"conanfile.py": textwrap.dedent("""
from conans import ConanFile
from conan import ConanFile
from conan.tools.system.package_manager import Brew
class MyPkg(ConanFile):
settings = "arch"
Expand All @@ -81,7 +117,7 @@ def system_requirements(self):
def test_brew_install_check_mode():
client = TestClient()
client.save({"conanfile.py": textwrap.dedent("""
from conans import ConanFile
from conan import ConanFile
from conan.tools.system.package_manager import Brew
class MyPkg(ConanFile):
settings = "arch"
Expand All @@ -100,7 +136,7 @@ def system_requirements(self):
def test_brew_install_install_mode():
client = TestClient()
client.save({"conanfile.py": textwrap.dedent("""
from conans import ConanFile
from conan import ConanFile
from conan.tools.system.package_manager import Brew
class MyPkg(ConanFile):
settings = "arch"
Expand Down

0 comments on commit d02459c

Please sign in to comment.