|
15 | 15 | #include "mamba/core/package_handling.hpp" |
16 | 16 | #include "mamba/core/util.hpp" |
17 | 17 | #include "mamba/fs/filesystem.hpp" |
| 18 | +#include "mamba/specs/archive.hpp" |
18 | 19 | #include "mamba/util/url_manip.hpp" |
19 | 20 |
|
20 | 21 | #include "mambatests.hpp" |
@@ -1300,4 +1301,79 @@ namespace |
1300 | 1301 | REQUIRE(repodata_record.contains("size")); |
1301 | 1302 | CHECK(repodata_record["size"] == tarball_size); |
1302 | 1303 | } |
| 1304 | + |
| 1305 | + // Non-regression for https://github.com/mamba-org/mamba/issues/4322 and |
| 1306 | + // https://github.com/mamba-org/mamba/issues/4331#issuecomment-4771693736 |
| 1307 | + // When the tarball uses the flat layout but extraction targets the hierarchical layout, |
| 1308 | + // clear_cache() must remove the hierarchical extracted directory. |
| 1309 | + TEST_CASE("PackageFetcher::clear_cache removes hierarchical extracted directory", "[regression][4322][4331]") |
| 1310 | + { |
| 1311 | + auto& ctx = mambatests::context(); |
| 1312 | + TemporaryDirectory temp_dir; |
| 1313 | + const fs::u8path pkgs_dir = temp_dir.path() / "pkgs"; |
| 1314 | + fs::create_directories(pkgs_dir); |
| 1315 | + MultiPackageCache package_caches({ pkgs_dir }, ctx.validation_params); |
| 1316 | + |
| 1317 | + specs::PackageInfo pkg; |
| 1318 | + pkg.name = "cuda-nvvp"; |
| 1319 | + pkg.version = "12.9.79"; |
| 1320 | + pkg.build_string = "he0c23c2_0"; |
| 1321 | + pkg.platform = "win-64"; |
| 1322 | + pkg.channel = "conda-forge"; |
| 1323 | + pkg.package_url = "https://conda.anaconda.org/conda-forge/win-64/cuda-nvvp-12.9.79-he0c23c2_0.conda"; |
| 1324 | + pkg.filename = "cuda-nvvp-12.9.79-he0c23c2_0.conda"; |
| 1325 | + |
| 1326 | + const auto cache_subdir = package_cache_folder_relative_path(pkg); |
| 1327 | + const std::string pkg_basename = std::string(specs::strip_archive_extension(pkg.filename)); |
| 1328 | + const fs::u8path hierarchical_extract = pkgs_dir / cache_subdir / pkg_basename; |
| 1329 | + const fs::u8path flat_tarball = pkgs_dir / pkg.filename; |
| 1330 | + |
| 1331 | + // Build a valid tarball at the flat cache location. |
| 1332 | + const fs::u8path build_dir = temp_dir.path() / "build"; |
| 1333 | + const fs::u8path info_dir = build_dir / "info"; |
| 1334 | + fs::create_directories(info_dir); |
| 1335 | + { |
| 1336 | + std::ofstream index_file((info_dir / "index.json").std_path()); |
| 1337 | + index_file << R"({"name":"cuda-nvvp","version":"12.9.79","build":"he0c23c2_0"})"; |
| 1338 | + } |
| 1339 | + { |
| 1340 | + std::ofstream paths_file((info_dir / "paths.json").std_path()); |
| 1341 | + paths_file << R"({"paths": [], "paths_version": 1})"; |
| 1342 | + } |
| 1343 | + create_archive( |
| 1344 | + build_dir, |
| 1345 | + flat_tarball, |
| 1346 | + compression_algorithm::bzip2, |
| 1347 | + /* compression_level= */ 1, |
| 1348 | + /* compression_threads= */ 1, |
| 1349 | + /* filter= */ nullptr |
| 1350 | + ); |
| 1351 | + REQUIRE(fs::exists(flat_tarball)); |
| 1352 | + |
| 1353 | + // Simulate a stale partial extraction at the hierarchical location. |
| 1354 | + fs::create_directories(hierarchical_extract / "info"); |
| 1355 | + { |
| 1356 | + auto out = open_ofstream(hierarchical_extract / "info" / "repodata_record.json"); |
| 1357 | + out << R"({"name":"cuda-nvvp","version":"12.9.79","build":"he0c23c2_0","url":")" |
| 1358 | + << pkg.package_url << R"(","channel":")" << pkg.channel << R"("})"; |
| 1359 | + } |
| 1360 | + { |
| 1361 | + std::ofstream paths_file((hierarchical_extract / "info" / "paths.json").std_path()); |
| 1362 | + paths_file << R"({ |
| 1363 | + "paths_version": 1, |
| 1364 | + "paths": [ |
| 1365 | + {"_path": "Library/missing-file.txt", "path_type": "hardlink", "size_in_bytes": 42} |
| 1366 | + ] |
| 1367 | +})"; |
| 1368 | + } |
| 1369 | + |
| 1370 | + PackageFetcher fetcher(pkg, package_caches); |
| 1371 | + REQUIRE(fetcher.needs_extract()); |
| 1372 | + |
| 1373 | + fetcher.clear_cache(); |
| 1374 | + |
| 1375 | + REQUIRE_FALSE(fs::exists(hierarchical_extract)); |
| 1376 | + REQUIRE_FALSE(fs::exists(flat_tarball)); |
| 1377 | + REQUIRE(package_caches.get_extracted_dir_path(pkg).empty()); |
| 1378 | + } |
1303 | 1379 | } |
0 commit comments