Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
69 changes: 69 additions & 0 deletions crates/pixi_build_r/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,75 @@ Imports:
});
}

#[tokio::test]
async fn test_recommended_packages_are_dependencies() {
let temp_dir = TempDir::new().unwrap();

fs::write(
temp_dir.path().join("DESCRIPTION"),
r#"Package: nlraa
Version: 1.9.11
Imports:
boot,
MASS,
Matrix,
mgcv,
nlme,
stats
"#,
)
.await
.unwrap();

let project_model = project_fixture!({
"name": "r-nlraa",
"version": "1.9.11",
"targets": {
"defaultTarget": {}
}
});

let generated_recipe = RGenerator::default()
.generate_recipe(
&project_model,
&RBackendConfig::default(),
temp_dir.path().to_path_buf(),
Platform::Linux64,
None,
&HashSet::new(),
vec![],
None,
None,
None,
None,
)
.await
.expect("Failed to generate recipe");

let host_reqs = &generated_recipe.recipe.requirements.host;
let run_reqs = &generated_recipe.recipe.requirements.run;

for package in ["r-boot", "r-mass", "r-matrix", "r-mgcv", "r-nlme"] {
assert!(
host_reqs.iter().any(|req| req.to_string() == package),
"{package} should be in host requirements"
);
assert!(
run_reqs.iter().any(|req| req.to_string() == package),
"{package} should be in run requirements"
);
}

assert!(
host_reqs.iter().all(|req| req.to_string() != "r-stats"),
"base packages should not be separate host requirements"
);
assert!(
run_reqs.iter().all(|req| req.to_string() != "r-stats"),
"base packages should not be separate run requirements"
);
}

#[tokio::test]
async fn test_package_name_derived_from_description_is_r_prefixed() {
// When the model carries no name (the inline source-dependency flow),
Expand Down
31 changes: 6 additions & 25 deletions crates/pixi_build_r/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,8 @@ static CRAN_SPDX_MAP: LazyLock<HashMap<String, String>> = LazyLock::new(|| {

/// R packages that are built into r-base and should not be listed as separate dependencies.
///
/// This includes:
/// - Base packages (14): ship with every R installation
/// - Recommended packages (15): included in all binary distributions of R
///
/// See: <https://cran.r-project.org/doc/FAQ/R-FAQ.html>
/// Recommended packages are not listed because conda-forge packages them
/// separately from r-base.
pub const R_BUILTIN_PACKAGES: &[&str] = &[
// Base packages (Priority: base)
"base",
Expand All @@ -36,23 +33,6 @@ pub const R_BUILTIN_PACKAGES: &[&str] = &[
"tcltk",
"tools",
"utils",
// Recommended packages (Priority: recommended)
// These are included in all binary distributions of R
"KernSmooth",
"MASS",
"Matrix",
"boot",
"class",
"cluster",
"codetools",
"foreign",
"lattice",
"mgcv",
"nlme",
"nnet",
"rpart",
"spatial",
"survival",
];

/// Check if an R package is built into r-base
Expand Down Expand Up @@ -715,10 +695,11 @@ Imports:
}

#[test]
fn test_is_builtin_package() {
fn test_only_base_packages_are_builtin() {
assert!(is_builtin_package("stats"));
assert!(is_builtin_package("MASS"));
assert!(is_builtin_package("mass")); // case insensitive
assert!(is_builtin_package("STATS"));
assert!(!is_builtin_package("MASS"));
assert!(!is_builtin_package("boot"));
assert!(!is_builtin_package("curl"));
assert!(!is_builtin_package("ggplot2"));
}
Expand Down
Loading