Skip to content

feat: Add generate_deactivation_script() function in the shell_hook.rs #3670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
3 changes: 3 additions & 0 deletions src/activation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down
47 changes: 42 additions & 5 deletions src/cli/shell_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -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::<HashMap<String, String>>();

let activator = get_activator(environment, shell.clone()).into_diagnostic()?;

let path = std::env::var("PATH")
Expand All @@ -93,6 +100,7 @@ async fn generate_activation_script(
conda_prefix,
path,
path_modification_behavior: PathModificationBehavior::default(),
current_env,
})
.into_diagnostic()?;

Expand All @@ -117,6 +125,29 @@ async fn generate_activation_script(
}
}

/// Generates the deactivation script.
async fn generate_deactivation_script(
shell: Option<ShellEnum>,
environment: &Environment<'_>,
_project: &Workspace,
) -> miette::Result<String> {
// 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(
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down
Loading