Skip to content

Commit f5c7aef

Browse files
committed
devenv: fix execing into a shell with devenv shell
The recent async-ification broke interactive shells here: something to do with tokio's Command differences. Switching to exec here to maximize compatibility with interactive shells.
1 parent c6df749 commit f5c7aef

File tree

3 files changed

+17
-23
lines changed

3 files changed

+17
-23
lines changed

devenv-run-tests/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ async fn run_tests_in_directory(args: &Args) -> Result<Vec<TestResult>> {
207207
if PathBuf::from(setup_script).exists() {
208208
eprintln!(" Running {setup_script}");
209209
let output = devenv
210-
.exec_in_shell(format!("./{setup_script}"), &[])
210+
.run_in_shell(format!("./{setup_script}"), &[])
211211
.await?;
212212
if !output.status.success() {
213213
return Err(miette::miette!(

devenv/src/devenv.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -380,21 +380,25 @@ impl Devenv {
380380
Ok(shell_cmd)
381381
}
382382

383-
/// Exec into the shell.
384-
/// This method does not return after calling `exec`.
385-
pub async fn shell(self) -> Result<()> {
386-
let shell_cmd = self.prepare_shell(&None, &[]).await?;
383+
/// Launch an interactive shell (uses exec, never returns).
384+
pub async fn shell(&self) -> Result<()> {
385+
self.exec_into_shell(None, &[]).await
386+
}
387+
388+
/// Execute a command by replacing the current process using exec.
389+
/// Only returns if exec fails.
390+
pub async fn exec_into_shell(&self, cmd: Option<String>, args: &[String]) -> Result<()> {
391+
let shell_cmd = self.prepare_shell(&cmd, args).await?;
387392
info!(devenv.is_user_message = true, "Entering shell");
388393
let err = shell_cmd.into_std().exec();
389-
bail!("Failed to execute shell: {}", err);
394+
bail!("Failed to exec into shell: {}", err);
390395
}
391396

392-
pub async fn exec_in_shell(&self, cmd: String, args: &[String]) -> Result<Output> {
397+
/// Run a command and return the output.
398+
/// Uses `spawn` + `wait_with_output` under the hood.
399+
pub async fn run_in_shell(&self, cmd: String, args: &[String]) -> Result<Output> {
393400
let mut shell_cmd = self.prepare_shell(&Some(cmd), args).await?;
394-
let span = info_span!(
395-
"executing_in_shell",
396-
devenv.user_message = "Executing in shell"
397-
);
401+
let span = info_span!("running_in_shell", devenv.user_message = "Running in shell");
398402
// Note that tokio's `output()` always configures stdout/stderr as pipes.
399403
// Use `spawn` + `wait_with_output` instead.
400404
let proc = shell_cmd

devenv/src/main.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ use devenv::{
44
config, log, Devenv,
55
};
66
use miette::{IntoDiagnostic, Result, WrapErr};
7-
use std::env;
8-
use std::{
9-
os::unix::process::CommandExt,
10-
process::{self, Command},
11-
};
7+
use std::{env, os::unix::process::CommandExt, process::Command};
128
use tempfile::TempDir;
139
use tracing::{info, warn};
1410

@@ -100,13 +96,7 @@ async fn main() -> Result<()> {
10096

10197
match command {
10298
Commands::Shell { cmd, ref args } => match cmd {
103-
Some(cmd) => {
104-
let output = devenv.exec_in_shell(cmd, args).await?;
105-
if !output.status.success() {
106-
process::exit(output.status.code().unwrap_or(1));
107-
}
108-
Ok(())
109-
}
99+
Some(cmd) => devenv.exec_into_shell(Some(cmd), args).await,
110100
None => devenv.shell().await,
111101
},
112102
Commands::Test { .. } => devenv.test().await,

0 commit comments

Comments
 (0)