From 7b7c33aa64a068db9175462d548b5e121f7403b1 Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Tue, 5 Mar 2024 17:48:42 +0100 Subject: [PATCH] fix: removal of multiple packages that clobber each other (#556) Fixes #554 --- Cargo.toml | 38 +++++------ .../rattler/src/install/clobber_registry.rs | 63 ++++++++++++++++++- crates/rattler_solve/tests/backends.rs | 4 +- 3 files changed, 83 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 852537132..3f6401631 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ tag-prefix = "" lto = true [workspace.dependencies] -anyhow = "1.0.79" +anyhow = "1.0.80" assert_matches = "1.5.0" async-compression = { version = "0.4.6", features = [ "gzip", @@ -44,12 +44,12 @@ bytes = "1.5.0" bzip2 = "0.4.4" cache_control = "0.2.0" cfg-if = "1.0" -chrono = { version = "0.4.33", default-features = false, features = [ +chrono = { version = "0.4.34", default-features = false, features = [ "std", "serde", "alloc", ] } -clap = { version = "4.4.18", features = ["derive"] } +clap = { version = "4.5.1", features = ["derive"] } cmake = "0.1.50" console = { version = "0.15.8", features = ["windows-console-colors"] } criterion = "0.5" @@ -70,16 +70,16 @@ hex = "0.4.3" hex-literal = "0.4.1" humansize = "2.1.3" humantime = "2.1.0" -indexmap = "2.2.2" -indicatif = "0.17.7" -insta = { version = "1.34.0" } +indexmap = "2.2.5" +indicatif = "0.17.8" +insta = { version = "1.36.1" } itertools = "0.12.1" json-patch = "1.2.0" keyring = "2.3.2" lazy-regex = "3.1.0" lazy_static = "1.4.0" libc = { version = "0.2" } -libloading = "0.8.1" +libloading = "0.8.2" libz-sys = { version = "1.1.15", default-features = false } md-5 = "0.10.6" memchr = "2.7.1" @@ -97,7 +97,7 @@ plist = "1" purl = { version = "0.1.2", features = ["serde"] } quote = "1.0.35" rand = "0.8.5" -reflink-copy = "0.1.14" +reflink-copy = "0.1.15" regex = "1.10.3" reqwest = { version = "0.11.24", default-features = false } reqwest-middleware = "0.2.4" @@ -105,12 +105,12 @@ resolvo = { version = "0.4.0" } retry-policies = { version = "0.2.1", default-features = false } rstest = { version = "0.18.2" } rstest_reuse = "0.6.0" -serde = { version = "1.0.196" } +serde = { version = "1.0.197" } serde-json-python-formatter = "0.1.0" -serde_json = { version = "1.0.113" } +serde_json = { version = "1.0.114" } serde_repr = "0.1" -serde_with = "3.6.0" -serde_yaml = "0.9.31" +serde_with = "3.6.1" +serde_yaml = "0.9.32" sha2 = "0.10.8" shlex = "1.3.0" similar-asserts = "1.5.0" @@ -122,26 +122,26 @@ smallvec = { version = "1.13.1", features = [ ] } strum = { version = "0.26.1", features = ["derive"] } superslice = "1.0.0" -syn = "2.0.48" -sysinfo = "0.30.5" +syn = "2.0.52" +sysinfo = "0.30.6" tar = "0.4.40" task-local-extensions = "0.1.4" tempdir = "0.3.7" -tempfile = "3.9.0" -test-log = "0.2.14" +tempfile = "3.10.1" +test-log = "0.2.15" thiserror = "1.0" -tokio = { version = "1.35.1", default-features = false } +tokio = { version = "1.36.0", default-features = false } tokio-stream = "0.1.14" tokio-util = "0.7.10" tower = { version = "0.4.13", default-features = false } -tower-http = { version = "0.5.1", default-features = false } +tower-http = { version = "0.5.2", default-features = false } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", default-features = false } tracing-test = { version = "0.2.4" } trybuild = { version = "1.0.89" } url = { version = "2.5.0" } uuid = { version = "1.7.0", default-features = false } -walkdir = "2.4.0" +walkdir = "2.5.0" windows-sys = { version = "0.52.0", default-features = false } zip = { version = "0.6.6", default-features = false } zstd = { version = "0.13.0", default-features = false } diff --git a/crates/rattler/src/install/clobber_registry.rs b/crates/rattler/src/install/clobber_registry.rs index c3166a8eb..8602a00e7 100644 --- a/crates/rattler/src/install/clobber_registry.rs +++ b/crates/rattler/src/install/clobber_registry.rs @@ -160,7 +160,12 @@ impl ClobberRegistry { .enumerate() .filter(|(_, n)| clobbered_by_names.contains(n)) .collect::>(); - let winner = sorted_clobbered_by.last().expect("No winner found"); + + let winner = match sorted_clobbered_by.last() { + Some(winner) => winner, + // In this case, all files have been removed and we can skip any unclobbering + None => continue, + }; if winner.1 == clobbered_by_names[0] { tracing::info!( @@ -1084,4 +1089,60 @@ mod tests { ); } } + + // This used to hit an expect in the clobbering code + #[tokio::test] + async fn test_transaction_with_clobber_remove_all() { + let operations = test_operations(); + + let transaction = transaction::Transaction:: { + operations, + python_info: None, + current_python_info: None, + platform: Platform::current(), + }; + + // execute transaction + let target_prefix = tempfile::tempdir().unwrap(); + + let packages_dir = tempfile::tempdir().unwrap(); + let cache = PackageCache::new(packages_dir.path()); + + execute_transaction( + transaction, + target_prefix.path(), + &reqwest_middleware::ClientWithMiddleware::from(reqwest::Client::new()), + &cache, + &InstallDriver::default(), + &InstallOptions::default(), + ) + .await; + + let prefix_records = PrefixRecord::collect_from_prefix(target_prefix.path()).unwrap(); + + // remove one of the clobbering files + let transaction = transaction::Transaction:: { + operations: prefix_records + .iter() + .map(|r| TransactionOperation::Remove(r.clone())) + .collect(), + python_info: None, + current_python_info: None, + platform: Platform::current(), + }; + + let install_driver = InstallDriver::new(100, Some(&prefix_records)); + + execute_transaction( + transaction, + target_prefix.path(), + &reqwest_middleware::ClientWithMiddleware::from(reqwest::Client::new()), + &cache, + &install_driver, + &InstallOptions::default(), + ) + .await; + + assert_check_files(target_prefix.path(), &[]); + } } diff --git a/crates/rattler_solve/tests/backends.rs b/crates/rattler_solve/tests/backends.rs index f1b9a0b7b..633b9ec2d 100644 --- a/crates/rattler_solve/tests/backends.rs +++ b/crates/rattler_solve/tests/backends.rs @@ -273,7 +273,7 @@ macro_rules! solver_backend_tests { assert!(result.is_err()); let err = result.err().unwrap(); - insta::assert_display_snapshot!(err); + insta::assert_snapshot!(err); } #[test] @@ -605,7 +605,7 @@ mod resolvo { ); // We expect an error here. `bors` is pinnend to 1, but we try to install `>=2`. - insta::assert_display_snapshot!(result.unwrap_err()); + insta::assert_snapshot!(result.unwrap_err()); } }