Skip to content

Commit

Permalink
Fix conan cache restore when restoring the same cache multiple times
Browse files Browse the repository at this point in the history
Fixes: #15949
  • Loading branch information
obnyis committed Mar 26, 2024
1 parent 077ec0c commit 09c8d9b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
6 changes: 6 additions & 0 deletions conan/api/subapi/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
45 changes: 45 additions & 0 deletions conans/test/integration/command_v2/test_cache_save_restore.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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")
Expand All @@ -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():
Expand Down

0 comments on commit 09c8d9b

Please sign in to comment.