Skip to content

Commit

Permalink
dir+utf8: Add filenames and filenames_filtered
Browse files Browse the repository at this point in the history
More convenience helpers, particularly for the use case where
one wants to gather a list of filenames (possibly filtered)
and sort them.

(We don't do sorting here, but it's trivial to do after calling
 `filenames_filtered()`)
  • Loading branch information
cgwalters committed Jul 11, 2024
1 parent 5885ac2 commit 2476728
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ rustix = { version = "0.38", features = ["fs", "procfs", "process", "pipe"] }

[dev-dependencies]
anyhow = "1.0"
uuid = "1.10"

[features]
default = []
Expand Down
25 changes: 25 additions & 0 deletions src/dirext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ pub trait CapStdExtDirExtUtf8 {
contents: impl AsRef<[u8]>,
perms: cap_std::fs::Permissions,
) -> Result<()>;

/// Read all filenames in this directory
fn filenames(&self) -> Result<Vec<String>> {
self.filenames_filtered(|_, _| true)
}

/// Read all filenames in this directory, applying a filter
fn filenames_filtered<F>(&self, f: F) -> Result<Vec<String>>
where
F: FnMut(&fs_utf8::DirEntry, &str) -> bool;
}

fn map_optional<R>(r: Result<R>) -> Result<Option<R>> {
Expand Down Expand Up @@ -496,4 +506,19 @@ impl CapStdExtDirExtUtf8 for cap_std::fs_utf8::Dir {
self.as_cap_std()
.atomic_write_with_perms(destname.as_ref().as_std_path(), contents, perms)
}

fn filenames_filtered<F>(&self, mut f: F) -> Result<Vec<String>>
where
F: FnMut(&fs_utf8::DirEntry, &str) -> bool,
{
self.entries()?
.try_fold(Vec::new(), |mut acc, ent| -> Result<Vec<String>> {
let ent = ent?;
let name = ent.file_name()?;
if f(&ent, name.as_str()) {
acc.push(name);
}
Ok(acc)
})
}
}
44 changes: 44 additions & 0 deletions tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,47 @@ fn ensuredir_utf8() -> Result<()> {

Ok(())
}

#[test]
#[cfg(feature = "fs_utf8")]
fn filenames_utf8() -> Result<()> {
use std::collections::BTreeSet;

use cap_std_ext::dirext::CapStdExtDirExtUtf8;
let td = &cap_tempfile::utf8::TempDir::new(cap_std::ambient_authority())?;

let mut expected = BTreeSet::new();
const N: usize = 20;
(0..N).try_for_each(|_| -> Result<()> {
let fname = uuid::Uuid::new_v4().to_string();

td.write(&fname, &fname)?;
expected.insert(fname);
Ok(())
})?;
let names = td.filenames().unwrap();
assert_eq!(names.len(), N);
for name in names.iter() {
assert!(expected.contains(name));
}
for (a, b) in expected.iter().zip(names.iter()) {
if a != b {
// This is totally normal, just interesting to see if it happens.
// It usually should on Linux.
println!("order differs: {a} {b}");
return Ok(());
}
}
println!("filesystem order is sorted");

td.create_dir(".foo").unwrap();

let names = td
.filenames_filtered(|_ent, name| !name.starts_with('.'))
.unwrap();
assert_eq!(names.len(), N);
for name in names.iter() {
assert!(!name.starts_with('.'));
}
Ok(())
}

0 comments on commit 2476728

Please sign in to comment.