diff --git a/src/activation.rs b/src/activation.rs index 5c1bed1eb..79b37af3c 100644 --- a/src/activation.rs +++ b/src/activation.rs @@ -285,6 +285,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 f5e5b4b91..3fb6da5f4 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, } @@ -79,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") @@ -93,6 +100,7 @@ async fn generate_activation_script( conda_prefix, path, path_modification_behavior: PathModificationBehavior::default(), + current_env, }) .into_diagnostic()?; @@ -117,6 +125,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 +199,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 +210,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