diff --git a/conan/api/subapi/cache.py b/conan/api/subapi/cache.py index 36068942d28..8c8db46a87e 100644 --- a/conan/api/subapi/cache.py +++ b/conan/api/subapi/cache.py @@ -181,13 +181,19 @@ def restore(self, path): pkg_folder = pref_bundle["package_folder"] out.info(f"Restore: {pref} in {pkg_folder}") # We need to put the package in the final location in the cache + if os.path.exists(pkg_layout.package()) and pkg_layout.package() != os.path.join(cache.cache_folder, pkg_folder): + shutil.rmtree(pkg_layout.package()) shutil.move(os.path.join(cache.cache_folder, pkg_folder), pkg_layout.package()) + pref_bundle["package_folder"] = os.path.relpath(pkg_layout.package(), cache.cache_folder) metadata_folder = pref_bundle.get("metadata_folder") if metadata_folder: out.info(f"Restore: {pref} metadata in {metadata_folder}") # We need to put the package in the final location in the cache + if os.path.exists(pkg_layout.metadata()) and pkg_layout.metadata() != os.path.join(cache.cache_folder, metadata_folder): + shutil.rmtree(pkg_layout.metadata()) shutil.move(os.path.join(cache.cache_folder, metadata_folder), pkg_layout.metadata()) + pref_bundle["metadata_folder"] = os.path.relpath(pkg_layout.metadata(), cache.cache_folder) return package_list diff --git a/conans/test/integration/command_v2/test_cache_save_restore.py b/conans/test/integration/command_v2/test_cache_save_restore.py index e178cf240b2..046e0fb0e96 100644 --- a/conans/test/integration/command_v2/test_cache_save_restore.py +++ b/conans/test/integration/command_v2/test_cache_save_restore.py @@ -30,6 +30,36 @@ def test_cache_save_restore(): assert "\\" not in package_list +def test_cache_save_restore_with_package_file(): + """If we have some sources in the root (like the CMakeLists.txt) + we don't declare folders.source""" + conan_file = GenConanfile() \ + .with_settings("os") \ + .with_package_file("bin/file.txt", "content!!") + + client = TestClient() + client.save({"conanfile.py": conan_file}) + client.run("create . --name=pkg --version=1.0 -s os=Linux") + client.run("cache save pkg/*:* ") + cache_path = os.path.join(client.current_folder, "conan_cache_save.tgz") + assert os.path.exists(cache_path) + + c2 = TestClient() + shutil.copy2(cache_path, c2.current_folder) + c2.run("cache restore conan_cache_save.tgz") + c2.run("list *:*#*") + assert "pkg/1.0" in c2.out + tree = _get_directory_tree(c2.base_folder) + + # Restore again, expect the tree to be unchanged + c2.run("cache restore conan_cache_save.tgz") + c2.run("list *:*#*") + assert "pkg/1.0" in c2.out + tree2 = _get_directory_tree(c2.base_folder) + + assert tree2 == tree + + def test_cache_save_downloaded_restore(): """ what happens if we save packages downloaded from server, not created @@ -49,6 +79,18 @@ def test_cache_save_downloaded_restore(): _validate_restore(cache_path) +def _get_directory_tree(base_folder): + tree = [] + for d, _, fs in os.walk(base_folder): + rel_d = os.path.relpath(d, base_folder) if d != base_folder else "" + if rel_d: + tree.append(rel_d) + for f in fs: + tree.append(os.path.join(rel_d, f)) + tree.sort() + return tree + + def _validate_restore(cache_path): c2 = TestClient() # Create a package in the cache to check put doesn't interact badly @@ -61,6 +103,7 @@ def _validate_restore(cache_path): assert "pkg/1.0" in c2.out assert "pkg/1.1" in c2.out assert "other/2.0" not in c2.out + tree = _get_directory_tree(c2.base_folder) # Restore again, just in case c2.run("cache restore conan_cache_save.tgz") @@ -69,6 +112,8 @@ def _validate_restore(cache_path): assert "pkg/1.0" in c2.out assert "pkg/1.1" in c2.out assert "other/2.0" not in c2.out + tree2 = _get_directory_tree(c2.base_folder) + assert tree2 == tree def test_cache_save_restore_metadata():