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

fix [system_tools] version range resolution #13667

Merged
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions conans/client/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def propagate_downstream(self, require, node, src_node=None):
return True
require.aggregate(existing.require)

assert not require.version_range # No ranges slip into transitive_deps definitions
# TODO: Might need to move to an update() for performance
self.transitive_deps.pop(require, None)
self.transitive_deps[require] = TransitiveRequirement(require, node)
Expand Down
8 changes: 6 additions & 2 deletions conans/client/graph/graph_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def _resolve_recipe(self, ref, graph_lock):

@staticmethod
def _resolved_system_tool(node, require, profile_build, profile_host, resolve_prereleases):
if node.context == CONTEXT_HOST and not require.build: # Only for tool_requires
if node.context == CONTEXT_HOST and not require.build: # Only for DIRECT tool_requires
return
system_tool = profile_build.system_tools if node.context == CONTEXT_BUILD \
else profile_host.system_tools
Expand All @@ -229,9 +229,13 @@ def _resolved_system_tool(node, require, profile_build, profile_host, resolve_pr
if require.ref.name == d.name:
if version_range:
if version_range.contains(d.version, resolve_prereleases):
require.ref.version = d.version # resolved range is replaced by exact
return d, ConanFile(str(d)), RECIPE_SYSTEM_TOOL, None
elif require.ref.version == d.version:
return d, ConanFile(str(d)), RECIPE_SYSTEM_TOOL, None
if d.revision is None or require.ref.revision is None or \
d.revision == require.ref.revision:
require.ref.revision = d.revision
return d, ConanFile(str(d)), RECIPE_SYSTEM_TOOL, None

def _create_new_node(self, node, require, graph, profile_host, profile_build, graph_lock):
resolved = self._resolved_system_tool(node, require, profile_build, profile_host,
Expand Down
67 changes: 67 additions & 0 deletions conans/test/integration/graph/test_system_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,73 @@ def test_graph_info_system_tool_require_range(self):
client.run("graph info . -pr=profile")
assert "tool/1.1 - System tool" in client.out

def test_consumer_resolved_version(self):
client = TestClient()
conanfile = textwrap.dedent("""
from conan import ConanFile
class Pkg(ConanFile):
tool_requires = "tool/[>=1.0]"

def generate(self):
for r, _ in self.dependencies.items():
self.output.info(f"DEPENDENCY {r.ref}")
""")
client.save({"conanfile.py": conanfile,
"profile": "[system_tools]\ntool/1.1"})
client.run("install . -pr=profile")
assert "tool/1.1 - System tool" in client.out
assert "conanfile.py: DEPENDENCY tool/1.1" in client.out

def test_consumer_resolved_revision(self):
client = TestClient()
conanfile = textwrap.dedent("""
from conan import ConanFile
class Pkg(ConanFile):
tool_requires = "tool/1.1"

def generate(self):
for r, _ in self.dependencies.items():
self.output.info(f"DEPENDENCY {repr(r.ref)}")
""")
client.save({"conanfile.py": conanfile,
"profile": "[system_tools]\ntool/1.1#rev1"})
client.run("install . -pr=profile")
assert "tool/1.1 - System tool" in client.out
assert "conanfile.py: DEPENDENCY tool/1.1#rev1" in client.out

conanfile = textwrap.dedent("""
from conan import ConanFile
class Pkg(ConanFile):
tool_requires = "tool/1.1#rev1"

def generate(self):
for r, _ in self.dependencies.items():
self.output.info(f"DEPENDENCY {repr(r.ref)}")
""")
client.save({"conanfile.py": conanfile})
client.run("install . -pr=profile")
assert "tool/1.1 - System tool" in client.out
assert "conanfile.py: DEPENDENCY tool/1.1#rev1" in client.out

def test_consumer_unresolved_revision(self):
""" if a recipe specifies an exact revision and so does the profiñe
and it doesn't match, it is an error
"""
client = TestClient()
conanfile = textwrap.dedent("""
from conan import ConanFile
class Pkg(ConanFile):
tool_requires = "tool/1.1#rev2"

def generate(self):
for r, _ in self.dependencies.items():
self.output.info(f"DEPENDENCY {repr(r.ref)}")
""")
client.save({"conanfile.py": conanfile,
"profile": "[system_tools]\ntool/1.1#rev1"})
client.run("install . -pr=profile", assert_error=True)
assert "ERROR: Package 'tool/1.1' not resolved" in client.out


class TestToolRequiresLock:

Expand Down