Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions scripts/benchmark.sh
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ bench "env --show-all" "env" "$RTK env --show-all"
# ===================
section "err"
if command -v cargo &>/dev/null; then
bench "err cargo build" "cargo build 2>&1 || true" "$RTK err cargo build"
bench "err cargo build" "cargo build 2>&1 || true" "$RTK err cargo build 2>&1"
else
echo "⏭️ err cargo build (cargo not in PATH, skipped)"
fi
Expand All @@ -265,7 +265,7 @@ fi
# ===================
section "test"
if command -v cargo &>/dev/null; then
bench "test cargo test" "cargo test 2>&1 || true" "$RTK test cargo test"
bench "test cargo test" "cargo test 2>&1 || true" "$RTK test cargo test 2>&1"
else
echo "⏭️ test cargo test (cargo not in PATH, skipped)"
fi
Expand Down Expand Up @@ -313,10 +313,10 @@ fi
# ===================
section "cargo"
if command -v cargo &>/dev/null; then
bench "cargo build" "cargo build 2>&1 || true" "$RTK cargo build"
bench "cargo test" "cargo test 2>&1 || true" "$RTK cargo test"
bench "cargo clippy" "cargo clippy 2>&1 || true" "$RTK cargo clippy"
bench "cargo check" "cargo check 2>&1 || true" "$RTK cargo check"
bench "cargo build" "cargo build 2>&1 || true" "$RTK cargo build 2>&1"
bench "cargo test" "cargo test 2>&1 || true" "$RTK cargo test 2>&1"
bench "cargo clippy" "cargo clippy 2>&1 || true" "$RTK cargo clippy 2>&1"
bench "cargo check" "cargo check 2>&1 || true" "$RTK cargo check 2>&1"
else
echo "⏭️ cargo build/test/clippy/check (cargo not in PATH, skipped)"
fi
Expand Down Expand Up @@ -366,7 +366,7 @@ if [ -f "package.json" ]; then
section "modern JS stack"

if command -v tsc &> /dev/null || [ -f "node_modules/.bin/tsc" ]; then
bench "tsc" "tsc --noEmit 2>&1 || true" "$RTK tsc --noEmit"
bench "tsc" "tsc --noEmit 2>&1 || true" "$RTK tsc --noEmit 2>&1"
fi

if command -v prettier &> /dev/null || [ -f "node_modules/.bin/prettier" ]; then
Expand Down
42 changes: 28 additions & 14 deletions src/core/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ pub fn run_streaming(
let mut capped_out = false;
let mut capped_err = false;
let mut saved_filter: Option<Box<dyn StreamFilter + '_>> = None;
let mut filter_fd_is_stderr = false;

if is_streaming {
enum StreamLine {
Expand Down Expand Up @@ -333,11 +334,13 @@ pub fn run_streaming(
if let FilterMode::Streaming(mut filter) = stdout_mode {
let stdout_handle = io::stdout();
let mut out = stdout_handle.lock();
let stderr_handle = io::stderr();
let mut err_out = stderr_handle.lock();

for msg in rx {
let (line, is_stderr) = match msg {
StreamLine::Stdout(l) => (l, false),
StreamLine::Stderr(l) => (l, true),
StreamLine::Stdout(l) => (l, false),
};
if is_stderr {
if !capped_err {
Expand All @@ -358,9 +361,11 @@ pub fn run_streaming(
eprintln!("[rtk] warning: stdout exceeds 10 MiB — filter input truncated");
}
}
filter_fd_is_stderr = is_stderr;
if let Some(output) = filter.feed_line(&line) {
filtered.push_str(&output);
match write!(out, "{}", output) {
let dest: &mut dyn Write = if is_stderr { &mut err_out } else { &mut out };
match write!(dest, "{}", output) {
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => break,
Err(e) => return Err(e.into()),
Ok(_) => {}
Expand All @@ -369,7 +374,12 @@ pub fn run_streaming(
}
let tail = filter.flush();
filtered.push_str(&tail);
match write!(io::stdout(), "{}", tail) {
let flush_dest: &mut dyn Write = if filter_fd_is_stderr {
&mut err_out
} else {
&mut out
};
match write!(flush_dest, "{}", tail) {
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => {}
Err(e) => return Err(e.into()),
Ok(_) => {}
Expand Down Expand Up @@ -459,7 +469,12 @@ pub fn run_streaming(
if let Some(mut f) = saved_filter {
if let Some(post) = f.on_exit(exit_code, &raw) {
filtered.push_str(&post);
match write!(io::stdout(), "{}", post) {
let mut dest: Box<dyn Write> = if filter_fd_is_stderr {
Box::new(io::stderr().lock())
} else {
Box::new(io::stdout().lock())
};
match write!(dest, "{}", post) {
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => {}
Err(e) => return Err(e.into()),
Ok(_) => {}
Expand Down Expand Up @@ -904,8 +919,7 @@ pub(crate) mod tests {

#[cfg(not(windows))]
#[test]
fn test_streaming_merges_stderr_through_filter() {
// nosemgrep: interpreter-execution
fn test_streaming_filters_both_fds_and_routes_to_correct_fd() {
let mut cmd = Command::new("sh");
cmd.args(["-c", "echo 'error[E0308]: type mismatch'; echo ' Compiling foo v1.0' >&2; echo ' Downloading bar v2.0' >&2; echo ' Finished dev' >&2; echo 'real error on stderr' >&2"]);

Expand Down Expand Up @@ -937,27 +951,27 @@ pub(crate) mod tests {
.unwrap();

assert!(
!result.filtered.contains("Compiling"),
"filtered output should not contain cargo noise, got: {}",
result.filtered.contains("error[E0308]"),
"filtered should contain stdout errors, got: {}",
result.filtered
);
assert!(
!result.filtered.contains("Downloading"),
"filtered output should not contain cargo noise, got: {}",
!result.filtered.contains("Compiling"),
"cargo noise should be filtered out, got: {}",
result.filtered
);
assert!(
result.filtered.contains("error[E0308]"),
"filtered output should contain real errors, got: {}",
!result.filtered.contains("Downloading"),
"cargo noise should be filtered out, got: {}",
result.filtered
);
assert!(
result.raw_stderr.contains("Compiling"),
"raw_stderr should still capture noise for tracking"
"raw_stderr should capture all stderr lines"
);
assert!(
result.raw_stderr.contains("real error on stderr"),
"raw_stderr should capture real errors"
"raw_stderr should capture all stderr lines"
);
}
}
Loading