diff --git a/README.md b/README.md index adf12e7..6785b8b 100644 --- a/README.md +++ b/README.md @@ -102,11 +102,11 @@ The installation provides a new `siz` executable on your system PATH. `siz` acc ### Default file filtering behavior -- Ignore all dotfiles (toggleable as of v0.1.0) -- Ignore all recursive traversal paths under dot directories (toggleable as of v0.1.0) +- Ignore all dotfiles (option available to toggle as of v0.1.0) +- Ignore all recursive traversal paths under dot directories (option available to toggle as of v0.1.0) - Use .gitignore file glob pattern definitions to filter output *when executed on a git repository path*. By default, the tool respects .gitignore files in the parent directories of each file path. - Respect a local .ignore file. This file supports the same glob syntax as the .gitignore file. It allows you to define different sets of includes/excludes than those defined in .gitignore, and use this file-based ignore syntax outside of a git repository. -- Will not follow symbolic links ([#17](https://github.com/chrissimpkins/siz/issues/17)) +- Will not follow symbolic links (option available to toggle as of v0.4.0) ## Changes diff --git a/src/lib/args.rs b/src/lib/args.rs index b358299..086f9d7 100644 --- a/src/lib/args.rs +++ b/src/lib/args.rs @@ -26,6 +26,8 @@ fn styles() -> Styles { /// /// * `depth`: An optional `usize` that represents the maximum directory traversal depth. /// +/// * `follow`: A boolean that indicates whether to follow symbolic links. +/// /// * `glob`: An optional vector of `String` that represents path glob patterns to filter the output. /// /// * `hidden`: A boolean that indicates whether to show hidden dot files and dot directories. @@ -66,6 +68,10 @@ pub struct Args { #[arg(short, long, help_heading = "Filters")] pub depth: Option, + /// Follow symbolic links + #[arg(short = 'L', long, default_value_t = false, help_heading = "Filters")] + pub follow: bool, + /// Filter the output by gitignore syntax glob patterns #[arg( short, @@ -162,6 +168,7 @@ mod tests { assert_eq!(args.binary_units, false); assert_eq!(args.color, false); assert_eq!(args.depth, None); + assert_eq!(args.follow, false); assert_eq!(args.glob, None); assert_eq!(args.hidden, false); assert_eq!(args.highlow, false); @@ -182,6 +189,7 @@ mod tests { assert_eq!(args.binary_units, true); assert_eq!(args.color, true); assert_eq!(args.depth, None); + assert_eq!(args.follow, false); assert_eq!(args.glob, None); assert_eq!(args.hidden, false); assert_eq!(args.highlow, false); diff --git a/src/lib/walk.rs b/src/lib/walk.rs index 3ccaf8a..93cc947 100644 --- a/src/lib/walk.rs +++ b/src/lib/walk.rs @@ -72,7 +72,7 @@ impl Walker { .max_depth(args.depth) .git_global(false) .git_exclude(false) - .follow_links(false); + .follow_links(args.follow); // sort by file path string if args.name { @@ -288,7 +288,7 @@ impl ParallelWalker { .max_depth(args.depth) .git_global(false) .git_exclude(false) - .follow_links(false); + .follow_links(args.follow); // filter files on user-defined default types // Note: This is not compatible with the glob option defined below. @@ -975,4 +975,35 @@ mod tests { Ok(()) } + + #[cfg(unix)] + #[test] + fn test_walker_symbolic_links() -> Result<()> { + use std::os::unix::fs::symlink; + + let td = tmpdir(); + let td_path = td.path().to_str().unwrap(); + + mkdir_on_path(td.path().join("x/y")); + symlink(td.path().join("x/y"), td.path().join("z"))?; + write_file(td.path().join("x/y/test.txt"), ""); + + let args_no_sym = Args::parse_from(vec!["siz", td_path]); + let args_sym = Args::parse_from(vec!["siz", "--follow", td_path]); + + // test sequential without symbolic link follow + assert_file_paths_sequential_sorted(td.path(), &args_no_sym, &["x/y/test.txt"])?; + // test sequential with symbolic link follow + assert_file_paths_sequential_sorted(td.path(), &args_sym, &["x/y/test.txt", "z/test.txt"])?; + // test parallel without symbolic link follow + assert_paths_parallel_sorted(td.path(), &args_no_sym, &["x", "x/y", "x/y/test.txt", "z"])?; + // test parallel with symbolic link follow + assert_paths_parallel_sorted( + td.path(), + &args_sym, + &["x", "x/y", "x/y/test.txt", "z", "z/test.txt"], + )?; + + Ok(()) + } }