diff --git a/src/cli/add.rs b/src/cli/add.rs index afcca3c53..1fde21b17 100644 --- a/src/cli/add.rs +++ b/src/cli/add.rs @@ -1,9 +1,12 @@ +use crate::environment::update_prefix; +use crate::prefix::Prefix; use crate::{ environment::{load_lock_file, update_lock_file}, project::Project, virtual_packages::get_minimal_virtual_packages, }; use clap::Parser; +use console::style; use indexmap::IndexMap; use itertools::Itertools; use miette::{IntoDiagnostic, WrapErr}; @@ -48,6 +51,10 @@ pub struct Args { /// This is a build dependency #[arg(long, conflicts_with = "host")] pub build: bool, + + /// Don't install the package to the environment, only add the package to the lock-file. + #[arg(long)] + pub no_install: bool, } #[derive(Debug, Copy, Clone)] @@ -72,13 +79,14 @@ impl SpecType { pub async fn execute(args: Args) -> miette::Result<()> { let mut project = Project::load_or_else_discover(args.manifest_path.as_deref())?; let spec_type = SpecType::from_args(&args); - add_specs_to_project(&mut project, args.specs, spec_type).await + add_specs_to_project(&mut project, args.specs, spec_type, args.no_install).await } pub async fn add_specs_to_project( project: &mut Project, specs: Vec<MatchSpec>, spec_type: SpecType, + no_install: bool, ) -> miette::Result<()> { // Split the specs into package name and version specifier let new_specs = specs @@ -160,7 +168,7 @@ pub async fn add_specs_to_project( } // Update the lock file and write to disk - update_lock_file( + let lock_file = update_lock_file( project, load_lock_file(project).await?, Some(sparse_repo_data), @@ -168,6 +176,20 @@ pub async fn add_specs_to_project( .await?; project.save()?; + if !no_install { + let platform = Platform::current(); + if project.platforms().contains(&platform) { + // Get the currently installed packages + let prefix = Prefix::new(project.root().join(".pixi/env"))?; + let installed_packages = prefix.find_installed_packages(None).await?; + + // Update the prefix + update_prefix(&prefix, installed_packages, &lock_file, platform).await?; + } else { + eprintln!("{} skipping installation of environment because your platform ({platform}) is not supported by this project.", style("!").yellow().bold()) + } + } + for spec in added_specs { eprintln!( "{}Added {}", diff --git a/src/environment.rs b/src/environment.rs index 80f101669..43f70cba3 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -68,10 +68,29 @@ pub async fn get_up_to_date_prefix(project: &Project) -> miette::Result<Prefix> lock_file }; + // Update the environment + update_prefix( + &prefix, + installed_packages_future.await.into_diagnostic()??, + &lock_file, + platform, + ) + .await?; + + Ok(prefix) +} + +/// Updates the environment to contain the packages from the specified lock-file +pub async fn update_prefix( + prefix: &Prefix, + installed_packages: Vec<PrefixRecord>, + lock_file: &CondaLock, + platform: Platform, +) -> miette::Result<()> { // Construct a transaction to bring the environment up to date with the lock-file content let transaction = Transaction::from_current_and_desired( - installed_packages_future.await.into_diagnostic()??, - get_required_packages(&lock_file, platform)?, + installed_packages, + get_required_packages(lock_file, platform)?, platform, ) .into_diagnostic()?; @@ -91,8 +110,7 @@ pub async fn get_up_to_date_prefix(project: &Project) -> miette::Result<Prefix> ) .await?; } - - Ok(prefix) + Ok(()) } /// Loads the lockfile for the specified project or returns a dummy one if none could be found. diff --git a/tests/common/builders.rs b/tests/common/builders.rs index 8ee47f003..bcdeddc5e 100644 --- a/tests/common/builders.rs +++ b/tests/common/builders.rs @@ -92,6 +92,13 @@ impl AddBuilder { } self } + + /// Set whether or not to also install the environment. By default the environment is NOT + /// installed to reduce test times. + pub fn with_install(mut self, install: bool) -> Self { + self.args.no_install = !install; + self + } } impl IntoFuture for AddBuilder { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 597181ca4..88bbe747c 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -119,6 +119,7 @@ impl PixiControl { host: false, specs: vec![spec.into()], build: false, + no_install: true, }, } } diff --git a/tests/install_tests.rs b/tests/install_tests.rs index 46ced883d..31af5d27b 100644 --- a/tests/install_tests.rs +++ b/tests/install_tests.rs @@ -13,7 +13,7 @@ use tempfile::TempDir; async fn install_run_python() { let pixi = PixiControl::new().unwrap(); pixi.init().await.unwrap(); - pixi.add("python==3.11.0").await.unwrap(); + pixi.add("python==3.11.0").with_install(true).await.unwrap(); // Check if lock has python version let lock = pixi.lock_file().await.unwrap();