From 0309171ae95a282589d5f04bb8e34a7b18700f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abril=20Rinc=C3=B3n=20Blanco?= Date: Fri, 24 Oct 2025 13:51:09 +0200 Subject: [PATCH 1/2] Add tests for 2 asserts that are now triggering --- .../package_id/test_cache_compatibles.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/integration/package_id/test_cache_compatibles.py b/test/integration/package_id/test_cache_compatibles.py index 2642915f4df..4cd34264dcc 100644 --- a/test/integration/package_id/test_cache_compatibles.py +++ b/test/integration/package_id/test_cache_compatibles.py @@ -180,6 +180,15 @@ def compatibility(conanfile): c.assert_listed_binary({"dep/0.1": ("ce92fac7c26ace631e30875ddbb3a58a190eb601", "Download (default)")}) + # Now what happens if we have it in cache already + c.run(f"install consumer {base_settings} -s compiler.cppstd=17 --update") + assert "dep/0.1: Checking 3 compatible configurations" in c.out + assert "dep/0.1: Main binary package '6179018ccb6b15e6443829bf3640e25f2718b931' missing" in c.out + assert "Found compatible package 'ce92fac7c26ace631e30875ddbb3a58a190eb601': " \ + "compiler.cppstd=14" in c.out + c.assert_listed_binary({"dep/0.1": ("ce92fac7c26ace631e30875ddbb3a58a190eb601", + "Cache")}) + class TestDefaultCompat: @@ -475,3 +484,12 @@ def test_remove_plugin_file(self): c.save({"conanfile.txt": ""}) c.run("install .", assert_error=True) assert "ERROR: The 'compatibility.py' plugin file doesn't exist" in c.out + + +def test_compatible_prev_from_cache(): + tc = TestClient() + tc.save({"conanfile.py": GenConanfile("pkg", "0.1").with_settings("compiler")}) + tc.run("create . -s=compiler.cppstd=17") + tc.run("install --requires=pkg/0.1 -s=compiler.cppstd=14 -u") + c.assert_listed_binary({"pkg/0.1": ("13c50710eea8d3ed1a7db623b9ac330f0a2ee2b4", + "Cache")}) From 2db6a7f0b25ea34235800b00a1f0c36b8a0fe764 Mon Sep 17 00:00:00 2001 From: memsharded Date: Sat, 25 Oct 2025 10:18:00 +0200 Subject: [PATCH 2/2] fix regression --- conan/internal/graph/graph_binaries.py | 31 ++++++++++--------- .../package_id/test_cache_compatibles.py | 10 +++--- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/conan/internal/graph/graph_binaries.py b/conan/internal/graph/graph_binaries.py index 16569e2c4f1..98b750544d1 100644 --- a/conan/internal/graph/graph_binaries.py +++ b/conan/internal/graph/graph_binaries.py @@ -164,8 +164,9 @@ def _compatible_find_existing_binaries(self, node, compatibles, remotes, update) for package_id, compatible_package in compatibles.items(): node._package_id = package_id # Modifying package id under the hood, FIXME node.binary = None # Invalidate it - self._compatible_process_node_cache(node) # Doesn't check remotes - if node.binary == BINARY_CACHE: + cache_latest_prev = self._compatible_cache_latest_prev(node) # not check remotes + if cache_latest_prev: + self._binary_in_cache(node, cache_latest_prev) self._compatible_found(conanfile, package_id, compatible_package) return # If not found in the cache, then look first one in servers @@ -185,9 +186,9 @@ def _compatible_find_existing_binaries(self, node, compatibles, remotes, update) f"{conanfile.info.dump_diff(compatible_package)}") node._package_id = package_id # Modifying package id under the hood, FIXME node.binary = None # Invalidate it - self._compatible_process_node_cache(node) # Doesn't check remotes - if node.binary == BINARY_CACHE: - self._evaluate_cache_update(node.pref, node, remotes, update) + cache_latest_prev = self._compatible_cache_latest_prev(node) # Not check remotes + if cache_latest_prev: + self._evaluate_cache_update(cache_latest_prev, node, remotes, update) else: self._evaluate_download(node, remotes, update) if node.binary in (BINARY_CACHE, BINARY_UPDATE, BINARY_DOWNLOAD): @@ -198,7 +199,7 @@ def _compatible_find_existing_binaries(self, node, compatibles, remotes, update) node.binary = original_binary node._package_id = original_package_id - def _compatible_process_node_cache(self, node): + def _compatible_cache_latest_prev(self, node): """ simplified checking of compatible_packages, that should be found existing, but will never be built, for example. They cannot be editable either at this point. """ @@ -220,14 +221,16 @@ def _compatible_process_node_cache(self, node): if not self._evaluate_clean_pkg_folder_dirty(node, package_layout): break - if cache_latest_prev is not None: - # This binary already exists in the cache, maybe can be updated - assert cache_latest_prev.revision - assert node.binary is None - node.binary = BINARY_CACHE - node.binary_remote = None - node.prev = cache_latest_prev.revision - node.pref_timestamp = cache_latest_prev.timestamp + return cache_latest_prev + + @staticmethod + def _binary_in_cache(node, cache_latest_prev): + assert cache_latest_prev.revision + assert node.binary is None + node.binary = BINARY_CACHE + node.binary_remote = None + node.prev = cache_latest_prev.revision + node.pref_timestamp = cache_latest_prev.timestamp def _compatible_find_build_binary(self, node, compatibles): original_binary = node.binary diff --git a/test/integration/package_id/test_cache_compatibles.py b/test/integration/package_id/test_cache_compatibles.py index 4cd34264dcc..0241a3c8683 100644 --- a/test/integration/package_id/test_cache_compatibles.py +++ b/test/integration/package_id/test_cache_compatibles.py @@ -489,7 +489,9 @@ def test_remove_plugin_file(self): def test_compatible_prev_from_cache(): tc = TestClient() tc.save({"conanfile.py": GenConanfile("pkg", "0.1").with_settings("compiler")}) - tc.run("create . -s=compiler.cppstd=17") - tc.run("install --requires=pkg/0.1 -s=compiler.cppstd=14 -u") - c.assert_listed_binary({"pkg/0.1": ("13c50710eea8d3ed1a7db623b9ac330f0a2ee2b4", - "Cache")}) + settings = ("-s os=Linux -s arch=x86_64 -s compiler=gcc -s compiler.version=8 " + "-s compiler.libcxx=libstdc++11") + tc.run(f"create . {settings} -s=compiler.cppstd=17") + tc.run(f"install --requires=pkg/0.1 {settings} -s=compiler.cppstd=14 -u") + tc.assert_listed_binary({"pkg/0.1": ("6179018ccb6b15e6443829bf3640e25f2718b931", + "Cache")})