Skip to content

Commit

Permalink
ignore: add support for WASI
Browse files Browse the repository at this point in the history
Add support for compiling to `wasm32-wasip2`. For this target `WalkParallel` becomes single threaded. This allows projects that depend on `ignore` to be compiled for WASI without having to modify their code.
  • Loading branch information
Timmmm committed Feb 20, 2025
1 parent e2362d4 commit fddbd40
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 27 deletions.
3 changes: 3 additions & 0 deletions crates/ignore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ See the documentation for `WalkBuilder` for many other options.
*/

#![deny(missing_docs)]
// https://github.com/rust-lang/rust/issues/130323
#![cfg_attr(all(target_os = "wasi", target_env = "p2"), feature(wasip2))]
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]

use std::path::{Path, PathBuf};

Expand Down
70 changes: 43 additions & 27 deletions crates/ignore/src/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl DirEntry {
/// Returns the underlying inode number if one exists.
///
/// If this entry doesn't have an inode number, then `None` is returned.
#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
pub fn ino(&self) -> Option<u64> {
self.dent.ino()
}
Expand Down Expand Up @@ -212,7 +212,7 @@ impl DirEntryInner {
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
fn ino(&self) -> Option<u64> {
use self::DirEntryInner::*;
use walkdir::DirEntryExt;
Expand Down Expand Up @@ -244,7 +244,7 @@ struct DirEntryRaw {
/// The depth at which this entry was generated relative to the root.
depth: usize,
/// The underlying inode number (Unix only).
#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
ino: u64,
/// The underlying metadata (Windows only). We store this on Windows
/// because this comes for free while reading a directory.
Expand Down Expand Up @@ -314,7 +314,7 @@ impl DirEntryRaw {
self.depth
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
fn ino(&self) -> u64 {
self.ino
}
Expand Down Expand Up @@ -349,13 +349,16 @@ impl DirEntryRaw {
})
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
fn from_entry_os(
depth: usize,
ent: &fs::DirEntry,
ty: fs::FileType,
) -> Result<DirEntryRaw, Error> {
#[cfg(unix)]
use std::os::unix::fs::DirEntryExt;
#[cfg(target_os = "wasi")]
use std::os::wasi::fs::DirEntryExt;

Ok(DirEntryRaw {
path: ent.path(),
Expand All @@ -368,7 +371,7 @@ impl DirEntryRaw {

// Placeholder implementation to allow compiling on non-standard platforms
// (e.g. wasm32).
#[cfg(not(any(windows, unix)))]
#[cfg(not(any(windows, unix, target_os = "wasi")))]
fn from_entry_os(
depth: usize,
ent: &fs::DirEntry,
Expand Down Expand Up @@ -397,13 +400,16 @@ impl DirEntryRaw {
})
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
fn from_path(
depth: usize,
pb: PathBuf,
link: bool,
) -> Result<DirEntryRaw, Error> {
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
#[cfg(target_os = "wasi")]
use std::os::wasi::fs::MetadataExt;

let md =
fs::metadata(&pb).map_err(|err| Error::Io(err).with_path(&pb))?;
Expand All @@ -418,7 +424,7 @@ impl DirEntryRaw {

// Placeholder implementation to allow compiling on non-standard platforms
// (e.g. wasm32).
#[cfg(not(any(windows, unix)))]
#[cfg(not(any(windows, unix, target_os = "wasi")))]
fn from_path(
depth: usize,
pb: PathBuf,
Expand Down Expand Up @@ -1277,30 +1283,40 @@ impl WalkParallel {
return;
}
}

// Create the workers and then wait for them to finish.
let quit_now = Arc::new(AtomicBool::new(false));
let active_workers = Arc::new(AtomicUsize::new(threads));
let stacks = Stack::new_for_each_thread(threads, stack);
std::thread::scope(|s| {
let handles: Vec<_> = stacks
.into_iter()
.map(|stack| Worker {
visitor: builder.build(),
stack,
quit_now: quit_now.clone(),
active_workers: active_workers.clone(),
max_depth: self.max_depth,
max_filesize: self.max_filesize,
follow_links: self.follow_links,
skip: self.skip.clone(),
filter: self.filter.clone(),
})
.map(|worker| s.spawn(|| worker.run()))
.collect();
for handle in handles {
handle.join().unwrap();
let mut make_worker = |stack| Worker {
visitor: builder.build(),
stack,
quit_now: quit_now.clone(),
active_workers: active_workers.clone(),
max_depth: self.max_depth,
max_filesize: self.max_filesize,
follow_links: self.follow_links,
skip: self.skip.clone(),
filter: self.filter.clone(),
};
if cfg!(target_os = "wasi") {
for stack in stacks.into_iter() {
make_worker(stack).run();
}
});
} else {
std::thread::scope(|s| {
let handles: Vec<_> = stacks
.into_iter()
.map(|stack| {
let worker = make_worker(stack);
s.spawn(|| worker.run())
})
.collect();
for handle in handles {
handle.join().unwrap();
}
});
}
}

fn threads(&self) -> usize {
Expand Down

0 comments on commit fddbd40

Please sign in to comment.