Skip to content

Commit a3f0c4b

Browse files
Merge pull request #108 from theseus-rs/improve-windows-commands
fix: improve commands on windows to return stdout and stderr
2 parents 282e75f + 14863d5 commit a3f0c4b

File tree

2 files changed

+40
-73
lines changed

2 files changed

+40
-73
lines changed

.github/workflows/clear-caches.yml

Lines changed: 0 additions & 22 deletions
This file was deleted.

postgresql_commands/src/traits.rs

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use crate::error::{Error, Result};
2+
use std::env::consts::OS;
23
use std::ffi::{OsStr, OsString};
34
use std::fmt::Debug;
45
use std::path::PathBuf;
6+
use std::process::ExitStatus;
57
use std::time::Duration;
68
use tracing::debug;
79

@@ -140,46 +142,37 @@ impl CommandExecutor for std::process::Command {
140142
/// Execute the command and return the stdout and stderr
141143
fn execute(&mut self) -> Result<(String, String)> {
142144
debug!("Executing command: {}", self.to_command_string());
143-
#[cfg(not(target_os = "windows"))]
144-
{
145-
let output = self.output()?;
146-
let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
147-
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
148-
149-
debug!(
150-
"Result: {}\nstdout: {}\nstderr: {}",
151-
output
152-
.status
153-
.code()
154-
.map_or("None".to_string(), |c| c.to_string()),
155-
stdout,
156-
stderr
157-
);
158-
159-
if output.status.success() {
160-
Ok((stdout, stderr))
161-
} else {
162-
Err(Error::CommandError { stdout, stderr })
163-
}
164-
}
145+
let program = self.get_program().to_string_lossy().to_string();
146+
let stdout: String;
147+
let stderr: String;
148+
let status: ExitStatus;
165149

166-
// TODO: Processes can hang on Windows when attempting to get stdout/stderr using code
167-
// that works for Linux/MacOS; this implementation should be updated to retrieve the
168-
// values of stdout/stderr without hanging
169-
#[cfg(target_os = "windows")]
170-
{
150+
if OS == "windows" && program.as_str().ends_with("pg_ctl") {
151+
// The pg_ctl process can hang on Windows when attempting to get stdout/stderr.
171152
let mut process = self
172153
.stdout(std::process::Stdio::piped())
173154
.stderr(std::process::Stdio::piped())
174155
.spawn()?;
175-
let status = process.wait()?;
176-
let stdout = String::new();
177-
let stderr = String::new();
178-
if status.success() {
179-
Ok((stdout, stderr))
180-
} else {
181-
Err(Error::CommandError { stdout, stderr })
182-
}
156+
stdout = String::new();
157+
stderr = String::new();
158+
status = process.wait()?;
159+
} else {
160+
let output = self.output()?;
161+
stdout = String::from_utf8_lossy(&output.stdout).into_owned();
162+
stderr = String::from_utf8_lossy(&output.stderr).into_owned();
163+
status = output.status;
164+
}
165+
debug!(
166+
"Result: {}\nstdout: {}\nstderr: {}",
167+
status.code().map_or("None".to_string(), |c| c.to_string()),
168+
stdout,
169+
stderr
170+
);
171+
172+
if status.success() {
173+
Ok((stdout, stderr))
174+
} else {
175+
Err(Error::CommandError { stdout, stderr })
183176
}
184177
}
185178
}
@@ -194,19 +187,18 @@ impl AsyncCommandExecutor for tokio::process::Command {
194187
Some(duration) => tokio::time::timeout(duration, self.output()).await?,
195188
None => self.output().await,
196189
}?;
197-
198-
#[cfg(not(target_os = "windows"))]
199-
let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
200-
#[cfg(not(target_os = "windows"))]
201-
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
202-
203-
// TODO: Processes can hang on Windows when attempting to get stdout/stderr using code
204-
// that works for Linux/MacOS; this implementation should be updated to retrieve the
205-
// values of stdout/stderr without hanging
206-
#[cfg(target_os = "windows")]
207-
let stdout = String::new();
208-
#[cfg(target_os = "windows")]
209-
let stderr = String::new();
190+
let program = self.as_std().get_program().to_string_lossy().to_string();
191+
let stdout: String;
192+
let stderr: String;
193+
194+
if OS == "windows" && program.as_str().ends_with("pg_ctl") {
195+
// The pg_ctl process can hang on Windows when attempting to get stdout/stderr.
196+
stdout = String::new();
197+
stderr = String::new();
198+
} else {
199+
stdout = String::from_utf8_lossy(&output.stdout).into_owned();
200+
stderr = String::from_utf8_lossy(&output.stderr).into_owned();
201+
}
210202

211203
debug!(
212204
"Result: {}\nstdout: {}\nstderr: {}",
@@ -371,10 +363,7 @@ mod test {
371363
command.args(["/C", "echo foo"]);
372364

373365
let (stdout, stderr) = command.execute()?;
374-
#[cfg(not(target_os = "windows"))]
375366
assert!(stdout.starts_with("foo"));
376-
#[cfg(target_os = "windows")]
377-
assert!(stdout.is_empty());
378367
assert!(stderr.is_empty());
379368
Ok(())
380369
}

0 commit comments

Comments
 (0)