Skip to content

Commit 05e89c6

Browse files
committed
csm env deactivate: Add command
1 parent 9e1482b commit 05e89c6

File tree

4 files changed

+132
-1
lines changed

4 files changed

+132
-1
lines changed

Cargo.lock

Lines changed: 48 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ tar = "0.4.44"
2828
assert_cmd = "2.0"
2929
predicates = { version = "3.0", features = ["regex"] }
3030
regex = "1.12.2"
31+
temp-env = "0.3.6"
3132
tempfile = "3.0"
3233
which = "8.0.0"

src/env.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub enum Subcommand {
1515
/// Activate an environment
1616
Activate(CommonEnvArgs),
1717
/// Deactivate an environment
18-
Deactivate(CommonEnvArgs),
18+
Deactivate,
1919
/// Run an executable in an environment
2020
Run(RunArgs),
2121
/// ???
@@ -190,6 +190,18 @@ pub fn run(config: Config, subcommand: Subcommand) -> ExitCode {
190190

191191
ExitCode::SUCCESS
192192
}
193+
Subcommand::Deactivate => {
194+
let Some(shell) = SupportedShell::from_csm_hook() else {
195+
error!("Your shell does not appear to have the csm hook enabled");
196+
error!("See 'csm init' for information on how to set up the hook");
197+
return ExitCode::FAILURE;
198+
};
199+
println!("{}", shell.restore_and_unset_env_var("PATH"));
200+
println!("{}", shell.restore_and_unset_env_var("CONDA_DEFAULT_ENV"));
201+
println!("{}", shell.restore_and_unset_env_var("CONDA_PREFIX"));
202+
println!("{}", shell.restore_and_unset_env_var("CONDA_SHLVL"));
203+
ExitCode::SUCCESS
204+
}
193205
_ => {
194206
println!("{:?}", config);
195207
println!("{:?}", subcommand);

src/shell.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,52 @@ impl SupportedShell {
151151
out.push_str(&self.env_var_codegen(key, new_value));
152152
out
153153
}
154+
155+
pub fn unset_env_var(&self, key: &str) -> String {
156+
match self {
157+
Self::Bash | Self::Zsh => format!("unset {};", key),
158+
Self::Fish => format!("set -e {};", key),
159+
Self::Powershell => format!("Remove-Item Env:{};", key),
160+
}
161+
}
162+
163+
/// Emit the shell code to restore an environment variable that was backed
164+
/// up to $_CSM_<name>_ORIG by `set_env_var()`. If there was no matching
165+
/// backup variable found, return None.
166+
///
167+
/// Invalid utf-8 backup variables are treated as not present.
168+
pub fn restore_env_var(&self, key: &str) -> Option<String> {
169+
let backup_key = format!("_CSM_{}_ORIG", key);
170+
match std::env::var(&backup_key) {
171+
Ok(orig_value) => {
172+
debug!("Restoring original value of ${} from ${}", key, backup_key);
173+
Some(self.set_env_var(key, &orig_value))
174+
}
175+
Err(std::env::VarError::NotPresent) => {
176+
debug!("No original value for ${} found in ${}", key, backup_key);
177+
None
178+
}
179+
Err(std::env::VarError::NotUnicode(_)) => {
180+
warn!(
181+
"Original value for ${} in ${} was not valid utf-8",
182+
key, backup_key
183+
);
184+
None
185+
}
186+
}
187+
}
188+
189+
/// Emit the shell code to restore an environment variable that was backed
190+
/// up, and then unset the backup variable.
191+
pub fn restore_and_unset_env_var(&self, key: &str) -> String {
192+
let mut out = String::new();
193+
if let Some(code) = self.restore_env_var(key) {
194+
out.push_str(&code);
195+
}
196+
let backup_key = format!("_CSM_{}_ORIG", key);
197+
out.push_str(&self.unset_env_var(&backup_key));
198+
out
199+
}
154200
}
155201

156202
pub struct ShellConfiguration {
@@ -235,4 +281,28 @@ mod tests {
235281
.ends_with(";$env:PATH = \"/tmp/testing$([IO.Path]::PathSeparator)$env:PATH\";")
236282
);
237283
}
284+
285+
#[test]
286+
fn test_supportedshell_restore_env_var() {
287+
temp_env::with_var("_CSM_TEST_VAR_ORIG", Some("a value"), || {
288+
assert_eq!(
289+
SupportedShell::Bash.restore_env_var("TEST_VAR").unwrap(),
290+
"export TEST_VAR=\"a value\";"
291+
);
292+
assert_eq!(
293+
SupportedShell::Fish.restore_env_var("TEST_VAR").unwrap(),
294+
"set -g TEST_VAR \"a value\";"
295+
);
296+
assert_eq!(
297+
SupportedShell::Zsh.restore_env_var("TEST_VAR").unwrap(),
298+
"export TEST_VAR=\"a value\";"
299+
);
300+
assert_eq!(
301+
SupportedShell::Powershell
302+
.restore_env_var("TEST_VAR")
303+
.unwrap(),
304+
"$env:TEST_VAR = \"a value\";"
305+
);
306+
});
307+
}
238308
}

0 commit comments

Comments
 (0)