From bf6d246facf8da7baa430dab0978e88e4fecab3e Mon Sep 17 00:00:00 2001 From: Swastik Patel Date: Thu, 24 Apr 2025 00:40:06 +0530 Subject: [PATCH 1/3] feat: Add generate_deactivation_script function --- src/cli/shell_hook.rs | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/cli/shell_hook.rs b/src/cli/shell_hook.rs index 4195266e4e..0918a82e41 100644 --- a/src/cli/shell_hook.rs +++ b/src/cli/shell_hook.rs @@ -57,6 +57,10 @@ pub struct Args { #[clap(long, default_value = "false", conflicts_with = "shell")] json: bool, + /// Generate a deactivation script instead of an activation script + #[clap(long, default_value = "false", conflicts_with = "json")] + deactivate: bool, + #[clap(flatten)] prompt_config: ConfigCliPrompt, } @@ -117,6 +121,29 @@ async fn generate_activation_script( } } +/// Generates the deactivation script. +async fn generate_deactivation_script( + shell: Option, + environment: &Environment<'_>, + _project: &Workspace, +) -> miette::Result { + // Get shell from the arguments or from the current process or use default if + // all fails + let shell = shell.unwrap_or_else(|| { + ShellEnum::from_parent_process() + .unwrap_or_else(|| ShellEnum::from_env().unwrap_or_default()) + }); + + let activator = get_activator(environment, shell.clone()).into_diagnostic()?; + + // Use the deactivation method + let result = activator.deactivation().into_diagnostic()?; + + let script = result.script.contents().into_diagnostic()?; + + Ok(script.to_string()) +} + /// Generates a JSON object describing the changes to the shell environment when /// activating the provided pixi environment. async fn generate_environment_json( @@ -168,8 +195,9 @@ pub async fn execute(args: Args) -> miette::Result<()> { ) .await?; - let output = match args.json { - true => { + let output = match (args.json, args.deactivate) { + (true, _) => { + // JSON mode takes precedence over deactivate (they are mutually exclusive anyway) generate_environment_json( &environment, &lock_file_data.lock_file, @@ -178,9 +206,14 @@ pub async fn execute(args: Args) -> miette::Result<()> { ) .await? } - // Skipping the activated environment caching for the script. - // As it can still run scripts. - false => generate_activation_script(args.shell, &environment, &workspace).await?, + (_, true) => { + // Deactivation script + generate_deactivation_script(args.shell, &environment, &workspace).await? + } + _ => { + // Default: activation script + generate_activation_script(args.shell, &environment, &workspace).await? + } }; // Print the output - either a JSON object or a shell script From 62c5571aff2e004dcc159b243a8080931d52fb5a Mon Sep 17 00:00:00 2001 From: Swastik Patel Date: Tue, 29 Apr 2025 02:48:36 +0530 Subject: [PATCH 2/3] refactor: allow env_vars to restore to pre-activation state --- src/activation.rs | 3 +++ src/cli/shell_hook.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/activation.rs b/src/activation.rs index 0307546b6e..714c8de218 100644 --- a/src/activation.rs +++ b/src/activation.rs @@ -293,6 +293,9 @@ pub async fn run_activation( // Prepending environment paths so they get found first. path_modification_behavior, + + // Current environment variables + current_env: HashMap::new(), }, None, ) diff --git a/src/cli/shell_hook.rs b/src/cli/shell_hook.rs index 0918a82e41..bcdadc1aac 100644 --- a/src/cli/shell_hook.rs +++ b/src/cli/shell_hook.rs @@ -83,6 +83,9 @@ async fn generate_activation_script( .unwrap_or_else(|| ShellEnum::from_env().unwrap_or_default()) }); + // Read current environment variables + let current_env = std::env::vars().collect::>(); + let activator = get_activator(environment, shell.clone()).into_diagnostic()?; let path = std::env::var("PATH") @@ -97,6 +100,7 @@ async fn generate_activation_script( conda_prefix, path, path_modification_behavior: PathModificationBehavior::default(), + current_env, }) .into_diagnostic()?; From 4c8aec7f31fe341f2059883fd78c9c2a26cb0a27 Mon Sep 17 00:00:00 2001 From: Swastik Patel Date: Wed, 4 Jun 2025 20:27:09 +0530 Subject: [PATCH 3/3] refactor: send ActionVariables as argument to the deactivation() function in rattler --- src/cli/shell_hook.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/cli/shell_hook.rs b/src/cli/shell_hook.rs index bcdadc1aac..eb93759a9d 100644 --- a/src/cli/shell_hook.rs +++ b/src/cli/shell_hook.rs @@ -140,8 +140,23 @@ async fn generate_deactivation_script( let activator = get_activator(environment, shell.clone()).into_diagnostic()?; - // Use the deactivation method - let result = activator.deactivation().into_diagnostic()?; + let current_env = std::env::vars().collect::>(); + + let path = std::env::var("PATH") + .ok() + .map(|p| std::env::split_paths(&p).collect::>()); + + let conda_prefix = std::env::var("CONDA_PREFIX").ok().map(|p| p.into()); + + // Use the deactivation method with environment variables + let result = activator + .deactivation(ActivationVariables { + conda_prefix, + path, + path_modification_behavior: PathModificationBehavior::default(), + current_env, + }) + .into_diagnostic()?; let script = result.script.contents().into_diagnostic()?;