Skip to content

Commit d8c1354

Browse files
committed
devenv: rework up to support env reuse
1 parent a881e21 commit d8c1354

File tree

3 files changed

+57
-119
lines changed

3 files changed

+57
-119
lines changed

devenv/src/devenv.rs

+42-111
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::os::unix::{fs::PermissionsExt, process::CommandExt};
1616
use std::{
1717
fs::{self, File},
1818
path::{Path, PathBuf},
19+
process,
1920
};
2021
use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument};
2122

@@ -42,14 +43,25 @@ pub static DIRENVRC_VERSION: Lazy<u8> = Lazy::new(|| {
4243
// project vars
4344
const DEVENV_FLAKE: &str = ".devenv.flake.nix";
4445

45-
#[derive(Default)]
46+
#[derive(Default, Debug)]
4647
pub struct DevenvOptions {
4748
pub config: config::Config,
4849
pub global_options: Option<cli::GlobalOptions>,
4950
pub devenv_root: Option<PathBuf>,
5051
pub devenv_dotfile: Option<PathBuf>,
5152
}
5253

54+
#[derive(Default, Debug)]
55+
pub struct ProcessOptions<'a> {
56+
/// An optional environment map to pass to the process.
57+
/// If not provided, the process will be executed inside a freshly evaluated shell.
58+
pub envs: Option<&'a HashMap<String, String>>,
59+
/// Whether the process should be detached from the current process.
60+
pub detach: bool,
61+
/// Whether the process should be logged to a file.
62+
pub log_to_file: bool,
63+
}
64+
5365
pub struct Devenv {
5466
pub config: config::Config,
5567
pub global_options: cli::GlobalOptions,
@@ -683,7 +695,7 @@ impl Devenv {
683695
.expect("Failed to wait for script");
684696

685697
// Parse the environment variables
686-
let file = File::open(&script_path).into_diagnostic()?;
698+
let file = File::open(&env_path).into_diagnostic()?;
687699
let reader = BufReader::new(file);
688700
let shell_envs = reader
689701
.lines()
@@ -716,7 +728,12 @@ impl Devenv {
716728
}
717729

718730
if self.has_processes().await? {
719-
self.launch_processes(vec![], &envs, &true, &false).await?;
731+
let options = ProcessOptions {
732+
envs: Some(&envs),
733+
detach: true,
734+
log_to_file: false,
735+
};
736+
self.up(vec![], &options).await?;
720737
}
721738

722739
let span = info_span!("test", devenv.user_message = "Running tests");
@@ -746,96 +763,6 @@ impl Devenv {
746763
}
747764
}
748765

749-
pub async fn launch_processes(
750-
&mut self,
751-
processes: Vec<String>,
752-
envs: &std::collections::HashMap<String, String>,
753-
detach: &bool,
754-
log_to_file: &bool,
755-
) -> Result<()> {
756-
self.assemble(false).await?;
757-
if !self.has_processes().await? {
758-
error!("No 'processes' option defined: https://devenv.sh/processes/");
759-
bail!("No processes defined");
760-
}
761-
762-
let span = info_span!(
763-
"build_processes",
764-
devenv.user_message = "Building processes"
765-
);
766-
let proc_script_string = async {
767-
let proc_script = self.nix.build(&["procfileScript"], None).await?;
768-
let proc_script_string = proc_script[0]
769-
.to_str()
770-
.expect("Failed to get proc script path")
771-
.to_string();
772-
self.nix.add_gc("procfilescript", &proc_script[0]).await?;
773-
Ok::<String, miette::Report>(proc_script_string)
774-
}
775-
.instrument(span)
776-
.await?;
777-
778-
let span = info_span!("up", devenv.user_message = "Starting processes");
779-
async {
780-
let processes = processes.join("");
781-
782-
let processes_script = self.devenv_dotfile.join("processes");
783-
// we force disable process compose tui if detach is enabled
784-
let tui = if *detach {
785-
"export PC_TUI_ENABLED=0"
786-
} else {
787-
""
788-
};
789-
fs::write(
790-
&processes_script,
791-
indoc::formatdoc! {"
792-
#!/usr/bin/env bash
793-
{tui}
794-
exec {proc_script_string} {processes}
795-
"},
796-
)
797-
.expect("Failed to write PROCESSES_SCRIPT");
798-
799-
std::fs::set_permissions(&processes_script, std::fs::Permissions::from_mode(0o755))
800-
.expect("Failed to set permissions");
801-
802-
let mut cmd = std::process::Command::new("bash");
803-
cmd.arg(processes_script.to_string_lossy().to_string())
804-
.env_clear()
805-
.envs(envs);
806-
807-
if *detach {
808-
let log_file = std::fs::File::create(self.processes_log())
809-
.expect("Failed to create PROCESSES_LOG");
810-
let process = if !*log_to_file {
811-
cmd.stdout(std::process::Stdio::inherit())
812-
.stderr(std::process::Stdio::inherit())
813-
.spawn()
814-
.expect("Failed to spawn process")
815-
} else {
816-
cmd.stdout(log_file.try_clone().expect("Failed to clone Stdio"))
817-
.stderr(log_file)
818-
.spawn()
819-
.expect("Failed to spawn process")
820-
};
821-
822-
std::fs::write(self.processes_pid(), process.id().to_string())
823-
.expect("Failed to write PROCESSES_PID");
824-
info!("PID is {}", process.id());
825-
if *log_to_file {
826-
info!("See logs: $ tail -f {}", self.processes_log().display());
827-
}
828-
info!("Stop: $ devenv processes stop");
829-
} else {
830-
let err = cmd.exec();
831-
bail!(err);
832-
}
833-
Ok(())
834-
}
835-
.instrument(span)
836-
.await
837-
}
838-
839766
pub async fn info(&mut self) -> Result<()> {
840767
self.assemble(false).await?;
841768
let output = self.nix.metadata().await?;
@@ -892,11 +819,10 @@ impl Devenv {
892819
.await
893820
}
894821

895-
pub async fn up(
822+
pub async fn up<'a>(
896823
&mut self,
897824
processes: Vec<String>,
898-
detach: &bool,
899-
log_to_file: &bool,
825+
options: &'a ProcessOptions<'a>,
900826
) -> Result<()> {
901827
self.assemble(false).await?;
902828
if !self.has_processes().await? {
@@ -926,7 +852,7 @@ impl Devenv {
926852

927853
let processes_script = self.devenv_dotfile.join("processes");
928854
// we force disable process compose tui if detach is enabled
929-
let tui = if *detach {
855+
let tui = if options.detach {
930856
"export PC_TUI_ENABLED=0"
931857
} else {
932858
""
@@ -941,21 +867,26 @@ impl Devenv {
941867
)
942868
.expect("Failed to write PROCESSES_SCRIPT");
943869

944-
std::fs::set_permissions(&processes_script, std::fs::Permissions::from_mode(0o755))
870+
fs::set_permissions(&processes_script, std::fs::Permissions::from_mode(0o755))
945871
.expect("Failed to set permissions");
946872

947-
let span = info_span!("Entering shell");
948-
let mut cmd = self
949-
.prepare_shell(&Some(processes_script.to_string_lossy().to_string()), &[])
950-
.instrument(span)
951-
.await?;
873+
let mut cmd = if let Some(envs) = options.envs {
874+
let mut cmd = process::Command::new("bash");
875+
cmd.arg(processes_script.to_string_lossy().to_string())
876+
.env_clear()
877+
.envs(envs);
878+
cmd
879+
} else {
880+
self.prepare_shell(&Some(processes_script.to_string_lossy().to_string()), &[])
881+
.await?
882+
};
952883

953-
if *detach {
954-
let log_file = std::fs::File::create(self.processes_log())
955-
.expect("Failed to create PROCESSES_LOG");
956-
let process = if !*log_to_file {
957-
cmd.stdout(std::process::Stdio::inherit())
958-
.stderr(std::process::Stdio::inherit())
884+
if options.detach {
885+
let log_file =
886+
fs::File::create(self.processes_log()).expect("Failed to create PROCESSES_LOG");
887+
let process = if !options.log_to_file {
888+
cmd.stdout(process::Stdio::inherit())
889+
.stderr(process::Stdio::inherit())
959890
.spawn()
960891
.expect("Failed to spawn process")
961892
} else {
@@ -965,10 +896,10 @@ impl Devenv {
965896
.expect("Failed to spawn process")
966897
};
967898

968-
std::fs::write(self.processes_pid(), process.id().to_string())
899+
fs::write(self.processes_pid(), process.id().to_string())
969900
.expect("Failed to write PROCESSES_PID");
970901
info!("PID is {}", process.id());
971-
if *log_to_file {
902+
if options.log_to_file {
972903
info!("See logs: $ tail -f {}", self.processes_log().display());
973904
}
974905
info!("Stop: $ devenv processes stop");

devenv/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ pub mod log;
66
mod util;
77

88
pub use cli::{default_system, GlobalOptions};
9-
pub use devenv::{Devenv, DevenvOptions, DIRENVRC, DIRENVRC_VERSION};
9+
pub use devenv::{Devenv, DevenvOptions, ProcessOptions, DIRENVRC, DIRENVRC_VERSION};
1010
pub use devenv_tasks as tasks;

devenv/src/main.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,20 @@ async fn main() -> Result<()> {
184184
Commands::Repl {} => devenv.repl().await,
185185
Commands::Build { attributes } => devenv.build(&attributes).await,
186186
Commands::Update { name } => devenv.update(&name).await,
187-
Commands::Up { processes, detach } => devenv.up(processes, &detach, &detach).await,
188-
Commands::Processes { command } => match command {
189-
ProcessesCommand::Up { processes, detach } => {
190-
devenv.up(processes, &detach, &detach).await
191-
}
192-
ProcessesCommand::Down {} => devenv.down(),
193-
},
187+
Commands::Up { processes, detach }
188+
| Commands::Processes {
189+
command: ProcessesCommand::Up { processes, detach },
190+
} => {
191+
let options = devenv::ProcessOptions {
192+
detach,
193+
log_to_file: detach,
194+
..Default::default()
195+
};
196+
devenv.up(processes, &options).await
197+
}
198+
Commands::Processes {
199+
command: ProcessesCommand::Down {},
200+
} => devenv.down(),
194201
Commands::Tasks { command } => match command {
195202
TasksCommand::Run { tasks } => devenv.tasks_run(tasks).await,
196203
},

0 commit comments

Comments
 (0)