Skip to main content

recurse/ops/
io.rs

1use std::path::Path;
2
3use walkdir::{IntoIter, WalkDir};
4
5pub(crate) fn walk<P>(
6    path: P,
7    mindepth: &Option<usize>,
8    maxdepth: &Option<usize>,
9    symlinks: &bool,
10) -> IntoIter
11where
12    P: AsRef<Path>,
13{
14    let mut wd = WalkDir::new(path);
15    // Max directory traversal depth
16    // default: no max
17    if maxdepth.is_some() {
18        wd = wd.max_depth(maxdepth.unwrap());
19    }
20    // Min directory traversal depth
21    // default: no min
22    if mindepth.is_some() {
23        wd = wd.min_depth(mindepth.unwrap());
24    }
25    // Follow symbolic links and include in returned paths
26    // default: false
27    if *symlinks {
28        wd = wd.follow_links(true);
29    }
30    wd.into_iter()
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36    use std::path::PathBuf;
37
38    #[test]
39    fn test_walk_func_with_dir_default_depth() {
40        let mut dirpaths = walk("./tests/testfiles/io/stablepaths", &None, &None, &false);
41        let dirpaths_len_check = walk("./tests/testfiles/io/stablepaths", &None, &None, &false);
42        let expected_list = [
43            Path::new("./tests/testfiles/io/stablepaths"),
44            Path::new("./tests/testfiles/io/stablepaths/test"),
45            Path::new("./tests/testfiles/io/stablepaths/README.md"),
46            Path::new("./tests/testfiles/io/stablepaths/test.txt"),
47        ];
48        // run through all expected files in iterator and check against
49        // contents of expected list.
50        // Cannot test order directly because order differs across
51        // macOS, Win, GNU/Linux platforms based on CI testing results
52        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
53        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
54        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
55        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
56
57        let mut index = 0;
58        for _ in dirpaths_len_check {
59            index += 1;
60        }
61        assert_eq!(index, 4);
62    }
63
64    #[test]
65    fn test_walk_func_with_file_default_depth() {
66        let mut filepaths = walk(
67            "./tests/testfiles/io/stablepaths/README.md",
68            &None,
69            &None,
70            &false,
71        );
72        let filepaths_len_check = walk(
73            "./tests/testfiles/io/stablepaths/README.md",
74            &None,
75            &None,
76            &false,
77        );
78
79        assert_eq!(
80            filepaths.next().unwrap().unwrap().path(),
81            Path::new("./tests/testfiles/io/stablepaths/README.md")
82        );
83
84        let mut index = 0;
85        for _ in filepaths_len_check {
86            index += 1;
87        }
88        assert_eq!(index, 1);
89    }
90
91    #[test]
92    fn test_walk_func_with_filter_map_default_depth() {
93        let expected_list = [
94            PathBuf::from("./tests/testfiles/io/stablepaths/test"),
95            PathBuf::from("./tests/testfiles/io/stablepaths/README.md"),
96            PathBuf::from("./tests/testfiles/io/stablepaths/test.txt"),
97        ];
98        // filter_map to filter out directories that process does not have permission
99        // to access
100        let mut file_entries = walk("./tests/testfiles/io/stablepaths", &None, &None, &false)
101            .filter_map(|f| f.ok())
102            .filter_map(|f| {
103                if f.path().is_file() {
104                    Some(f.path().to_owned())
105                } else {
106                    None
107                }
108            });
109        assert!(expected_list.contains(&file_entries.next().unwrap()));
110        assert!(expected_list.contains(&file_entries.next().unwrap()));
111        assert!(expected_list.contains(&file_entries.next().unwrap()));
112        assert_eq!(file_entries.next(), None); // the above should have exhausted the file paths in the test
113    }
114
115    #[test]
116    fn test_walk_func_with_dir_set_max_depth() {
117        let mut dirpaths = walk("./tests/testfiles/io/depthtests", &None, &Some(1), &false);
118        let dirpaths_len_check = walk("./tests/testfiles/io/depthtests", &None, &Some(1), &false);
119        let expected_list = [
120            Path::new("./tests/testfiles/io/depthtests"),
121            Path::new("./tests/testfiles/io/depthtests/test.txt"),
122            Path::new("./tests/testfiles/io/depthtests/depth2"),
123        ];
124        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
125        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
126        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
127        let mut index = 0;
128        for _ in dirpaths_len_check {
129            index += 1;
130        }
131        assert_eq!(index, 3);
132    }
133
134    #[test]
135    fn test_walk_func_with_dir_set_min_depth() {
136        let mut dirpaths = walk("./tests/testfiles/io/depthtests", &Some(3), &None, &false);
137        let dirpaths_len_check = walk("./tests/testfiles/io/depthtests", &Some(3), &None, &false);
138        let expected_list = [Path::new(
139            "./tests/testfiles/io/depthtests/depth2/depth3/test3.txt",
140        )];
141        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
142        let mut index = 0;
143        for _ in dirpaths_len_check {
144            index += 1;
145        }
146        assert_eq!(index, 1);
147    }
148
149    #[test]
150    fn test_walk_func_with_dir_default_depth_and_follow_symlinks() {
151        let mut dirpaths = walk("./tests/testfiles/io/stablepaths", &None, &None, &true);
152        let dirpaths_len_check = walk("./tests/testfiles/io/stablepaths", &None, &None, &true);
153        let expected_list = [
154            Path::new("./tests/testfiles/io/stablepaths"),
155            Path::new("./tests/testfiles/io/stablepaths/test"),
156            Path::new("./tests/testfiles/io/stablepaths/README.md"),
157            Path::new("./tests/testfiles/io/stablepaths/test.txt"),
158        ];
159        // run through all expected files in iterator and check against
160        // contents of expected list.
161        // Cannot test order directly because order differs across
162        // macOS, Win, GNU/Linux platforms based on CI testing results
163        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
164        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
165        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
166        assert!(expected_list.contains(&dirpaths.next().unwrap().unwrap().path()));
167
168        let mut index = 0;
169        for _ in dirpaths_len_check {
170            index += 1;
171        }
172        assert_eq!(index, 4);
173    }
174}