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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Text in SVG `<text>` elements now rendered in PNG sprites (see [#102])
- Support loading SVG files compressed with gzip (`*.svgz`; see [#107])
- Propagate errors in `get_svg_input_paths` (see [#108])
- Update Oxipng dependency from v9 to v10 (see [#106])
- Update thiserror dependency from v1 to v2 (see [#106])

Expand All @@ -12,6 +13,7 @@ The minimum supported version of Rust is now 1.85.1 (released March 2025).
[#102]: https://github.com/flother/spreet/pull/102
[#106]: https://github.com/flother/spreet/pull/106
[#107]: https://github.com/flother/spreet/pull/107
[#108]: https://github.com/flother/spreet/pull/108

## v0.13.1 (2025-12-24)

Expand Down
47 changes: 30 additions & 17 deletions src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,18 @@ fn is_useful_input(entry: &DirEntry) -> bool {
///
/// This function will return an error if Rust's underlying [`read_dir`] returns an error.
pub fn get_svg_input_paths<P: AsRef<Path>>(path: P, recursive: bool) -> SpreetResult<Vec<PathBuf>> {
Ok(read_dir(path)?
.filter_map(|entry| {
if let Ok(entry) = entry {
let path_buf = entry.path();
if recursive && path_buf.is_dir() {
get_svg_input_paths(path_buf, true).ok()
} else if is_useful_input(&entry) {
Some(vec![path_buf])
} else {
None
}
} else {
None
}
})
.flatten()
.collect())
let mut results = Vec::new();
for entry in read_dir(path)? {
let entry = entry?;
let path_buf = entry.path();
if recursive && path_buf.is_dir() {
let nested = get_svg_input_paths(path_buf, true)?;
results.extend(nested);
} else if is_useful_input(&entry) {
results.push(path_buf);
}
}
Ok(results)
}

/// Load an SVG image from a file path.
Expand Down Expand Up @@ -123,6 +118,8 @@ fn svg_data_to_text(data: &[u8]) -> Result<Cow<'_, str>, UsvgError> {
mod tests {
use super::*;
use assert_fs::prelude::*;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;

fn entry_for(temp: &assert_fs::TempDir, name: &str) -> DirEntry {
std::fs::read_dir(temp.path())
Expand Down Expand Up @@ -163,4 +160,20 @@ mod tests {
let dir_entry = entry_for(&tmp_dir, "icons.svg");
assert!(!is_svg_file(&dir_entry));
}

#[cfg(unix)]
#[test]
fn get_svg_input_paths_returns_error_on_unreadable_directory() {
let tmp_dir = assert_fs::TempDir::new().unwrap();
let restricted = tmp_dir.child("no-access");
restricted.create_dir_all().unwrap();
std::fs::set_permissions(restricted.path(), std::fs::Permissions::from_mode(0o000))
.unwrap();

let result = get_svg_input_paths(tmp_dir.path(), true);

std::fs::set_permissions(restricted.path(), std::fs::Permissions::from_mode(0o700))
.unwrap();
assert!(result.is_err());
}
}