Skip to content

Commit 09144b1

Browse files
committed
update usages
1 parent 1109308 commit 09144b1

File tree

6 files changed

+86
-85
lines changed

6 files changed

+86
-85
lines changed

crates/fspy/examples/cli.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{env::args_os, ffi::OsStr, path::PathBuf, pin::Pin};
22

3-
use fspy::{AccessMode, TrackedChild};
3+
use fspy::AccessMode;
44
use tokio::{
55
fs::File,
66
io::{AsyncWrite, stdout},
@@ -21,19 +21,16 @@ async fn main() -> anyhow::Result<()> {
2121
let mut command = spy.new_command(program);
2222
command.envs(std::env::vars_os()).args(args);
2323

24-
let TrackedChild { mut tokio_child, accesses_future } = command.spawn().await?;
25-
26-
let output = tokio_child.wait().await?;
27-
28-
let accesses = accesses_future.await?;
24+
let child = command.spawn().await?;
25+
let termination = child.wait_handle.await?;
2926

3027
let mut path_count = 0usize;
3128
let out_file: Pin<Box<dyn AsyncWrite>> =
3229
if out_path == "-" { Box::pin(stdout()) } else { Box::pin(File::create(out_path).await?) };
3330

3431
let mut csv_writer = csv_async::AsyncWriter::from_writer(out_file);
3532

36-
for acc in accesses.iter() {
33+
for acc in termination.path_accesses.iter() {
3734
path_count += 1;
3835
csv_writer
3936
.write_record(&[
@@ -49,6 +46,6 @@ async fn main() -> anyhow::Result<()> {
4946
}
5047
csv_writer.flush().await?;
5148

52-
eprintln!("\nfspy: {path_count} paths accessed. {output}");
49+
eprintln!("\nfspy: {path_count} paths accessed. status: {}", termination.status);
5350
Ok(())
5451
}

crates/fspy/src/unix/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ pub(crate) async fn spawn_impl(mut command: Command) -> Result<TrackedChild, Spa
140140
stdin: child.stdin.take(),
141141
stdout: child.stdout.take(),
142142
stderr: child.stderr.take(),
143+
// Keep polling for the child to exit in the background even if `wait_handle` is not awaited,
144+
// because we need to stop the supervisor and lock the channel as soon as the child exits.
143145
wait_handle: tokio::spawn(async move {
144146
let status = child.wait().await?;
145147

crates/fspy/tests/node_fs.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod test_utils;
22

33
use std::env::{current_dir, vars_os};
44

5-
use fspy::{AccessMode, PathAccessIterable, TrackedChild};
5+
use fspy::{AccessMode, PathAccessIterable};
66
use test_utils::assert_contains;
77

88
async fn track_node_script(script: &str) -> anyhow::Result<PathAccessIterable> {
@@ -11,11 +11,10 @@ async fn track_node_script(script: &str) -> anyhow::Result<PathAccessIterable> {
1111
.arg("-e")
1212
.envs(vars_os()) // https://github.com/jdx/mise/discussions/5968
1313
.arg(script);
14-
let TrackedChild { mut tokio_child, accesses_future } = command.spawn().await?;
15-
let status = tokio_child.wait().await?;
16-
let accesses = accesses_future.await?;
17-
assert!(status.success());
18-
Ok(accesses)
14+
let child = command.spawn().await?;
15+
let termination = child.wait_handle.await?;
16+
assert!(termination.status.success());
17+
Ok(termination.path_accesses)
1918
}
2019

2120
#[tokio::test]

crates/fspy/tests/test_utils.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::path::{Path, PathBuf, StripPrefixError};
22

3-
use fspy::{AccessMode, PathAccessIterable, TrackedChild};
3+
use fspy::{AccessMode, PathAccessIterable};
44

55
#[track_caller]
66
pub fn assert_contains(
@@ -55,10 +55,7 @@ macro_rules! track_child {
5555
pub async fn _spawn_with_id(id: &str) -> anyhow::Result<PathAccessIterable> {
5656
let mut command = fspy::Spy::global()?.new_command(::std::env::current_exe()?);
5757
command.arg(id);
58-
let TrackedChild { mut tokio_child, accesses_future } = command.spawn().await?;
59-
60-
let status = tokio_child.wait().await?;
61-
let accesses = accesses_future.await?;
62-
assert!(status.success());
63-
Ok(accesses)
58+
let termination = command.spawn().await?.wait_handle.await?;
59+
assert!(termination.status.success());
60+
Ok(termination.path_accesses)
6461
}

crates/fspy_e2e/src/main.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::{
99

1010
use fspy::{AccessMode, PathAccess};
1111
use serde::{Deserialize, Serialize};
12+
use tokio::io::AsyncReadExt;
1213

1314
#[derive(Serialize, Deserialize)]
1415
struct Config {
@@ -86,25 +87,30 @@ async fn main() {
8687
.stderr(Stdio::piped())
8788
.current_dir(&dir);
8889

89-
let tracked_child = cmd.spawn().await.unwrap();
90+
let mut tracked_child = cmd.spawn().await.unwrap();
9091

91-
let output = tracked_child.tokio_child.wait_with_output().await.unwrap();
92-
let accesses = tracked_child.accesses_future.await.unwrap();
92+
let mut stdout_bytes = Vec::<u8>::new();
93+
tracked_child.stdout.take().unwrap().read_to_end(&mut stdout_bytes).await.unwrap();
9394

94-
if !output.status.success() {
95+
let mut stderr_bytes = Vec::<u8>::new();
96+
tracked_child.stderr.take().unwrap().read_to_end(&mut stderr_bytes).await.unwrap();
97+
98+
let termination = tracked_child.wait_handle.await.unwrap();
99+
100+
if !termination.status.success() {
95101
eprintln!("----- stdout begin -----");
96-
stderr().write_all(&output.stdout).unwrap();
102+
stderr().write_all(&stdout_bytes).unwrap();
97103
eprintln!("----- stdout end -----");
98104
eprintln!("----- stderr begin-----");
99-
stderr().write_all(&output.stderr).unwrap();
105+
stderr().write_all(&stderr_bytes).unwrap();
100106
eprintln!("----- stderr end -----");
101107

102-
eprintln!("Case `{}` failed with status: {}", name, output.status);
108+
eprintln!("Case `{}` failed with status: {}", name, termination.status);
103109
process::exit(1);
104110
}
105111

106112
let mut collector = AccessCollector::new(dir);
107-
for access in accesses.iter() {
113+
for access in termination.path_accesses.iter() {
108114
collector.add(access);
109115
}
110116
let snap_file = File::create(manifest_dir.join(format!("snaps/{name}.txt"))).unwrap();

crates/vite_task/src/execute.rs

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{
99
};
1010

1111
use bincode::{Decode, Encode};
12-
use fspy::{AccessMode, Spy, TrackedChild};
12+
use fspy::{AccessMode, Spy};
1313
use futures_util::future::try_join3;
1414
use serde::{Deserialize, Serialize};
1515
use sha2::{Digest, Sha256};
@@ -402,87 +402,87 @@ pub async fn execute_task(
402402
cmd.current_dir(base_dir.join(&resolved_command.fingerprint.cwd))
403403
.stdout(Stdio::piped())
404404
.stderr(Stdio::piped());
405-
let TrackedChild { tokio_child: mut child, accesses_future } = cmd.spawn().await?;
405+
let mut child = cmd.spawn().await?;
406406

407407
let child_stdout = child.stdout.take().unwrap();
408408
let child_stderr = child.stderr.take().unwrap();
409409

410410
let outputs = Mutex::new(Vec::<StdOutput>::new());
411411

412-
let path_accesses_fut = async move {
413-
let path_accesses = accesses_future.await?;
414-
let mut path_reads = HashMap::<RelativePathBuf, PathRead>::new();
415-
let mut path_writes = HashMap::<RelativePathBuf, PathWrite>::new();
416-
for access in path_accesses.iter() {
417-
let relative_path = access
418-
.path
419-
.strip_path_prefix(base_dir, |strip_result| {
420-
let Ok(stripped_path) = strip_result else {
421-
return None;
422-
};
423-
Some(RelativePathBuf::new(stripped_path).map_err(|err| {
424-
Error::InvalidRelativePath { path: stripped_path.into(), reason: err }
425-
}))
426-
})
427-
.transpose()?;
428-
429-
let Some(relative_path) = relative_path else {
430-
// ignore accesses outside the workspace
431-
continue;
432-
};
433-
if relative_path.as_path().strip_prefix(".git").is_ok() {
434-
// temp workaround for oxlint reading inside .git
435-
continue;
436-
}
437-
match access.mode {
438-
AccessMode::Read => {
439-
path_reads.entry(relative_path).or_insert(PathRead { read_dir_entries: false });
440-
}
441-
AccessMode::Write => {
442-
path_writes.insert(relative_path, PathWrite);
443-
}
444-
AccessMode::ReadWrite => {
445-
path_reads
446-
.entry(relative_path.clone())
447-
.or_insert(PathRead { read_dir_entries: false });
448-
path_writes.insert(relative_path, PathWrite);
449-
}
450-
AccessMode::ReadDir => match path_reads.entry(relative_path) {
451-
Entry::Occupied(mut occupied) => occupied.get_mut().read_dir_entries = true,
452-
Entry::Vacant(vacant) => {
453-
vacant.insert(PathRead { read_dir_entries: true });
454-
}
455-
},
456-
}
457-
}
458-
Ok::<_, Error>((path_reads, path_writes))
459-
};
460-
461-
let ((), (), (exit_status, duration)) = try_join3(
412+
let ((), (), (termination, duration)) = try_join3(
462413
collect_std_outputs(&outputs, child_stdout, OutputKind::StdOut),
463414
collect_std_outputs(&outputs, child_stderr, OutputKind::StdErr),
464415
async move {
465416
let start = Instant::now();
466-
let exit_status = child.wait().await?;
417+
let exit_status = child.wait_handle.await?;
467418
Ok((exit_status, start.elapsed()))
468419
},
469420
)
470421
.await?;
471422

472-
let (path_reads, path_writes) = path_accesses_fut.await?;
423+
let mut path_reads = HashMap::<RelativePathBuf, PathRead>::new();
424+
let mut path_writes = HashMap::<RelativePathBuf, PathWrite>::new();
425+
for access in termination.path_accesses.iter() {
426+
let relative_path = access
427+
.path
428+
.strip_path_prefix(base_dir, |strip_result| {
429+
let Ok(stripped_path) = strip_result else {
430+
return None;
431+
};
432+
Some(RelativePathBuf::new(stripped_path).map_err(|err| {
433+
Error::InvalidRelativePath { path: stripped_path.into(), reason: err }
434+
}))
435+
})
436+
.transpose()?;
437+
438+
let Some(relative_path) = relative_path else {
439+
// ignore accesses outside the workspace
440+
continue;
441+
};
442+
if relative_path.as_path().strip_prefix(".git").is_ok() {
443+
// temp workaround for oxlint reading inside .git
444+
continue;
445+
}
446+
match access.mode {
447+
AccessMode::Read => {
448+
path_reads.entry(relative_path).or_insert(PathRead { read_dir_entries: false });
449+
}
450+
AccessMode::Write => {
451+
path_writes.insert(relative_path, PathWrite);
452+
}
453+
AccessMode::ReadWrite => {
454+
path_reads
455+
.entry(relative_path.clone())
456+
.or_insert(PathRead { read_dir_entries: false });
457+
path_writes.insert(relative_path, PathWrite);
458+
}
459+
AccessMode::ReadDir => match path_reads.entry(relative_path) {
460+
Entry::Occupied(mut occupied) => occupied.get_mut().read_dir_entries = true,
461+
Entry::Vacant(vacant) => {
462+
vacant.insert(PathRead { read_dir_entries: true });
463+
}
464+
},
465+
}
466+
}
473467

474468
let outputs = outputs.into_inner().unwrap();
475469
tracing::debug!(
476470
"executed task finished, path_reads: {}, path_writes: {}, outputs: {}, exit_status: {}",
477471
path_reads.len(),
478472
path_writes.len(),
479473
outputs.len(),
480-
exit_status
474+
termination.status,
481475
);
482476

483477
// let input_paths = gather_inputs(task, base_dir)?;
484478

485-
Ok(ExecutedTask { std_outputs: outputs.into(), exit_status, path_reads, path_writes, duration })
479+
Ok(ExecutedTask {
480+
std_outputs: outputs.into(),
481+
exit_status: termination.status,
482+
path_reads,
483+
path_writes,
484+
duration,
485+
})
486486
}
487487

488488
#[expect(dead_code)]

0 commit comments

Comments
 (0)