Skip to content

Commit a881e21

Browse files
committed
wip: pass around env for testing
1 parent 1a45c76 commit a881e21

File tree

1 file changed

+62
-27
lines changed

1 file changed

+62
-27
lines changed

devenv/src/devenv.rs

+62-27
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ use clap::crate_version;
33
use cli_table::Table;
44
use cli_table::{print_stderr, WithTitle};
55
use include_dir::{include_dir, Dir};
6-
use miette::{bail, IntoDiagnostic, Result};
6+
use miette::{bail, Context, IntoDiagnostic, Result};
77
use nix::sys::signal;
88
use nix::unistd::Pid;
99
use once_cell::sync::Lazy;
1010
use serde::Deserialize;
1111
use sha2::Digest;
1212
use similar::{ChangeTag, TextDiff};
13-
use std::collections::BTreeMap;
14-
use std::io::Write;
13+
use std::collections::{BTreeMap, HashMap};
14+
use std::io::{BufRead, BufReader, Write};
1515
use std::os::unix::{fs::PermissionsExt, process::CommandExt};
1616
use std::{
17-
fs,
17+
fs::{self, File},
1818
path::{Path, PathBuf},
1919
};
2020
use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument};
@@ -301,17 +301,18 @@ impl Devenv {
301301

302302
let config_clean = self.config.clean.clone().unwrap_or_default();
303303
if self.global_options.clean.is_some() || config_clean.enabled {
304-
shell_cmd.env_clear();
305-
306304
let keep = match &self.global_options.clean {
307305
Some(clean) => clean,
308306
None => &config_clean.keep,
309307
};
310308

311309
let filtered_env = std::env::vars().filter(|(k, _)| keep.contains(k));
312310

313-
shell_cmd.envs(filtered_env);
314-
shell_cmd.arg("--norc").arg("--noprofile");
311+
shell_cmd
312+
.env_clear()
313+
.envs(filtered_env)
314+
.arg("--norc")
315+
.arg("--noprofile");
315316
}
316317

317318
shell_cmd.env("SHELL", &bash);
@@ -655,43 +656,75 @@ impl Devenv {
655656
};
656657
let test_script = test_script[0].to_string_lossy().to_string();
657658

659+
let temp_dir = tempfile::TempDir::with_prefix("devenv-test").into_diagnostic()?;
660+
661+
let script_path = temp_dir.path().join("script");
662+
let env_path = temp_dir.path().join("env");
663+
664+
let script = format!("env > {}", env_path.to_string_lossy());
665+
fs::write(&script_path, script)
666+
.into_diagnostic()
667+
.wrap_err(format!(
668+
"Failed to write script to {}",
669+
script_path.display()
670+
))?;
671+
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755))
672+
.into_diagnostic()
673+
.wrap_err("Change permissions")?;
674+
658675
// Run script and capture its environment exports
659-
let output = self
660-
.prepare_shell(&Some("env".to_string()), &[])
676+
self.prepare_shell(&Some(script_path.to_string_lossy().into()), &[])
661677
.await?
662-
.env("CLICOLOR_FORCE", "1")
663678
.stderr(std::process::Stdio::inherit())
664-
.stdout(std::process::Stdio::piped())
679+
.stdout(std::process::Stdio::inherit())
665680
.spawn()
666681
.expect("Failed to execute script")
667-
.wait_with_output()
682+
.wait()
668683
.expect("Failed to wait for script");
669684

670-
let stdout = String::from_utf8_lossy(&output.stdout);
671685
// Parse the environment variables
672-
let env_vars = stdout.lines().filter_map(|line| {
673-
let parts: Vec<&str> = line.splitn(2, '=').collect();
674-
if parts.len() == 2 {
675-
Some((parts[0], parts[1]))
686+
let file = File::open(&script_path).into_diagnostic()?;
687+
let reader = BufReader::new(file);
688+
let shell_envs = reader
689+
.lines()
690+
.map_while(Result::ok)
691+
.filter_map(|line| {
692+
let mut parts = line.splitn(2, '=');
693+
match (parts.next(), parts.next()) {
694+
(Some(key), Some(value)) => Some((key.to_string(), value.to_string())),
695+
_ => None,
696+
}
697+
})
698+
.collect::<Vec<_>>();
699+
700+
let config_clean = self.config.clean.clone().unwrap_or_default();
701+
let mut envs: HashMap<String, String> = {
702+
let vars = std::env::vars();
703+
if self.global_options.clean.is_some() || config_clean.enabled {
704+
let keep = match &self.global_options.clean {
705+
Some(clean) => clean,
706+
None => &config_clean.keep,
707+
};
708+
vars.filter(|(key, _)| !keep.contains(key)).collect()
676709
} else {
677-
None
710+
vars.collect()
678711
}
679-
});
712+
};
680713

681-
// TODO: clean && keep
682-
// Set environment variables for current process
683-
for (key, value) in env_vars {
684-
std::env::set_var(key, value);
714+
for (key, value) in shell_envs {
715+
envs.insert(key, value);
685716
}
686717

687718
if self.has_processes().await? {
688-
self.launch_processes(vec![], &true, &false).await?;
719+
self.launch_processes(vec![], &envs, &true, &false).await?;
689720
}
690721

691722
let span = info_span!("test", devenv.user_message = "Running tests");
692723
let result = async {
693724
debug!("Running command: {test_script}");
694725
std::process::Command::new(test_script)
726+
.env_clear()
727+
.envs(envs)
695728
.spawn()
696729
.unwrap()
697730
.wait_with_output()
@@ -716,6 +749,7 @@ impl Devenv {
716749
pub async fn launch_processes(
717750
&mut self,
718751
processes: Vec<String>,
752+
envs: &std::collections::HashMap<String, String>,
719753
detach: &bool,
720754
log_to_file: &bool,
721755
) -> Result<()> {
@@ -765,9 +799,10 @@ impl Devenv {
765799
std::fs::set_permissions(&processes_script, std::fs::Permissions::from_mode(0o755))
766800
.expect("Failed to set permissions");
767801

768-
// let span = info_span!("Entering shell");
769802
let mut cmd = std::process::Command::new("bash");
770-
cmd.arg(processes_script.to_string_lossy().to_string());
803+
cmd.arg(processes_script.to_string_lossy().to_string())
804+
.env_clear()
805+
.envs(envs);
771806

772807
if *detach {
773808
let log_file = std::fs::File::create(self.processes_log())

0 commit comments

Comments
 (0)