Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/rattler/src/install/installer/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ pub enum InstallerError {
/// Failed to create the prefix
#[error("failed to create the prefix")]
FailedToCreatePrefix(PathBuf, #[source] std::io::Error),

/// Attempted to install platform-specific packages when target platform is noarch
#[error("cannot install platform-specific packages with noarch as the target platform. The following packages have non-noarch subdirs: {}", .0.join(", "))]
PlatformSpecificPackagesWithNoarchPlatform(Vec<String>),
}

impl From<Cancelled> for InstallerError {
Expand Down
88 changes: 88 additions & 0 deletions crates/rattler/src/install/installer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,30 @@ impl Installer {

let transaction = transaction.to_owned();

// Validate that if the target platform is NoArch, all packages to be installed
// must also be noarch (subdir == "noarch")
if target_platform == Platform::NoArch {
let non_noarch_packages: Vec<String> = transaction
.installed_packages()
.filter(|record| record.package_record.subdir != "noarch")
.map(|record| {
format!(
"{}-{}-{} (subdir: {})",
record.package_record.name.as_normalized(),
record.package_record.version,
record.package_record.build,
record.package_record.subdir
)
})
.collect();

if !non_noarch_packages.is_empty() {
return Err(InstallerError::PlatformSpecificPackagesWithNoarchPlatform(
non_noarch_packages,
));
}
}

// Create a mapping from package names to requested specs
let spec_mapping = self
.requested_specs
Expand Down Expand Up @@ -1355,4 +1379,68 @@ mod tests {
"Migrated specs should match the original spec"
);
}

#[tokio::test]
async fn test_noarch_platform_rejects_platform_specific_packages() {
use rattler_conda_types::Platform;

let (_temp_dir, target_prefix) = create_test_environment();

// Create a platform-specific package (with subdir != "noarch")
let mut platform_specific_package = create_dummy_repo_record();
platform_specific_package.package_record.subdir = "osx-arm64".to_string();

// Try to install this platform-specific package with Platform::NoArch
let installer = Installer::new().with_target_platform(Platform::NoArch);
let result = installer
.install(&target_prefix, vec![platform_specific_package.clone()])
.await;

// Should fail with PlatformSpecificPackagesWithNoarchPlatform error
assert!(
result.is_err(),
"Installation should fail when installing platform-specific packages with noarch platform"
);

match result {
Err(InstallerError::PlatformSpecificPackagesWithNoarchPlatform(packages)) => {
assert!(
!packages.is_empty(),
"Error should list the problematic packages"
);
assert!(
packages[0].contains("osx-arm64"),
"Error message should include the subdir of the platform-specific package"
);
}
_ => {
panic!("Expected PlatformSpecificPackagesWithNoarchPlatform error, got: {result:?}")
}
}
}

#[tokio::test]
async fn test_noarch_platform_accepts_noarch_packages() {
use rattler_conda_types::{NoArchType, Platform};

let (_temp_dir, target_prefix) = create_test_environment();

// Create a noarch package (with subdir == "noarch")
let mut noarch_package = create_dummy_repo_record();
noarch_package.package_record.subdir = "noarch".to_string();
noarch_package.package_record.noarch = NoArchType::generic();

// Try to install this noarch package with Platform::NoArch
let installer = Installer::new().with_target_platform(Platform::NoArch);
let result = installer
.install(&target_prefix, vec![noarch_package.clone()])
.await;

// Should succeed
assert!(
result.is_ok(),
"Installation should succeed when installing noarch packages with noarch platform: {:?}",
result.err()
);
}
}
2 changes: 1 addition & 1 deletion crates/rattler_libsolv_c/libsolv
Submodule libsolv updated 122 files
Loading