use std::io;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
pub fn create_file_list(inputs: &[&Path]) -> io::Result<Vec<PathBuf>> {
let mut result = Vec::new();
for input in inputs {
if input.is_dir() {
for entry in WalkDir::new(input) {
let entry = entry.map_err(|e| {
e.io_error()
.map(|io| io::Error::new(io.kind(), io.to_string()))
.unwrap_or_else(|| io::Error::other(e.to_string()))
})?;
if entry.file_type().is_file() {
result.push(entry.into_path());
}
}
} else {
result.push(input.to_path_buf());
}
}
Ok(result)
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
fn make_tree() -> TempDir {
let dir = TempDir::new().unwrap();
let root = dir.path();
fs::create_dir(root.join("sub")).unwrap();
fs::write(root.join("a.txt"), b"a").unwrap();
fs::write(root.join("sub/b.txt"), b"b").unwrap();
dir
}
#[test]
fn expands_directory_recursively() {
let dir = make_tree();
let root = dir.path();
let inputs = vec![root];
let list = create_file_list(&inputs).unwrap();
assert_eq!(list.len(), 2);
}
#[test]
fn passes_regular_file_through() {
let dir = make_tree();
let file = dir.path().join("a.txt");
let inputs = vec![file.as_path()];
let list = create_file_list(&inputs).unwrap();
assert_eq!(list.len(), 1);
assert_eq!(list[0], file);
}
#[test]
fn empty_inputs_returns_empty_list() {
let list = create_file_list(&[]).unwrap();
assert!(list.is_empty());
}
#[cfg(unix)]
#[test]
fn symlink_to_regular_file_in_direct_input_passes_through() {
use std::os::unix::fs::symlink;
let dir = make_tree();
let root = dir.path();
let target = root.join("a.txt");
let link = root.join("link_to_a.txt");
symlink(&target, &link).unwrap();
let inputs = vec![link.as_path()];
let list = create_file_list(&inputs).unwrap();
assert_eq!(list.len(), 1);
assert_eq!(list[0], link);
}
#[cfg(unix)]
#[test]
fn symlink_to_file_inside_directory_is_excluded() {
use std::os::unix::fs::symlink;
let dir = make_tree();
let root = dir.path();
let target = root.join("a.txt");
let link = root.join("sub/link_to_a.txt");
symlink(&target, &link).unwrap();
let inputs = vec![root];
let list = create_file_list(&inputs).unwrap();
assert_eq!(list.len(), 2);
}
#[cfg(unix)]
#[test]
fn symlink_to_directory_is_not_recursed_into() {
use std::os::unix::fs::symlink;
let dir = make_tree();
let root = dir.path();
let other = TempDir::new().unwrap();
fs::write(other.path().join("c.txt"), b"c").unwrap();
let link = root.join("link_to_other");
symlink(other.path(), &link).unwrap();
let inputs = vec![root];
let list = create_file_list(&inputs).unwrap();
assert_eq!(list.len(), 2);
}
#[test]
fn mixed_inputs() {
let dir = make_tree();
let root = dir.path();
let file = root.join("a.txt");
let inputs = vec![file.as_path(), root];
let list = create_file_list(&inputs).unwrap();
assert_eq!(list.len(), 3);
}
}