cosmwasm_schema/
remove.rs

1use std::{fs, io, path};
2
3fn is_regular_file(path: &path::Path) -> Result<bool, io::Error> {
4    Ok(path.symlink_metadata()?.is_file())
5}
6
7fn is_hidden(path: &path::Path) -> bool {
8    match path.file_name() {
9        Some(name) => name.to_os_string().to_string_lossy().starts_with('.'),
10        None => false, // a path without filename is no .*
11    }
12}
13
14fn is_json(path: &path::Path) -> bool {
15    match path.file_name() {
16        Some(name) => name.to_os_string().to_string_lossy().ends_with(".json"),
17        None => false, // a path without filename is no *.json
18    }
19}
20
21pub fn remove_schemas(schemas_dir: &path::Path) -> Result<(), io::Error> {
22    let file_paths = fs::read_dir(schemas_dir)?
23        .filter_map(Result::ok) // skip read errors on entries
24        .map(|entry| entry.path())
25        .filter(|path| is_regular_file(path).unwrap_or(false)) // skip directories and symlinks
26        .filter(|path| !is_hidden(path)) // skip hidden
27        .filter(|path| is_json(path)) // skip non JSON
28        ;
29
30    for file_path in file_paths {
31        println!("Removing {file_path:?} …");
32        fs::remove_file(file_path)?;
33    }
34    Ok(())
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    use std::path::Path;
41
42    #[test]
43    fn is_hidden_works() {
44        assert!(!is_hidden(Path::new("/foo")));
45        assert!(!is_hidden(Path::new("/foo/bar")));
46        assert!(!is_hidden(Path::new("/foo/bar.txt")));
47        assert!(!is_hidden(Path::new("~foo")));
48        assert!(!is_hidden(Path::new("foo")));
49
50        assert!(is_hidden(Path::new("/.foo")));
51        assert!(is_hidden(Path::new("/foo/.bar")));
52        assert!(is_hidden(Path::new("/foo/.bar.txt")));
53        assert!(is_hidden(Path::new(".foo")));
54
55        // no filename
56        assert!(!is_hidden(Path::new("/")));
57        assert!(!is_hidden(Path::new("")));
58
59        // invalid UTF-8
60        #[cfg(any(unix, target_os = "redox"))]
61        {
62            use std::ffi::OsStr;
63            use std::os::unix::ffi::OsStrExt;
64            let non_hidden = OsStr::from_bytes(&[0x66, 0x6f, 0x80, 0x6f]); // fo�o // spellchecker:disable-line
65            assert!(!is_hidden(Path::new(non_hidden)));
66            let hidden = OsStr::from_bytes(&[0x2e, 0x66, 0x6f, 0x80, 0x6f]); // .fo�o // spellchecker:disable-line
67            assert!(is_hidden(Path::new(hidden)));
68        }
69    }
70
71    #[test]
72    fn is_json_works() {
73        assert!(!is_json(Path::new("/foo")));
74        assert!(!is_json(Path::new("/foo/bar")));
75        assert!(!is_json(Path::new("/foo/bar.txt")));
76        assert!(!is_json(Path::new("~foo")));
77        assert!(!is_json(Path::new("foo")));
78        assert!(!is_json(Path::new("foo.json5")));
79
80        assert!(is_json(Path::new("/.json")));
81        assert!(is_json(Path::new("/foo/.bar.json")));
82        assert!(is_json(Path::new("/foo/bar.json")));
83        assert!(is_json(Path::new("foo.json")));
84
85        // no filename
86        assert!(!is_json(Path::new("/")));
87        assert!(!is_json(Path::new("")));
88
89        // invalid UTF-8
90        #[cfg(any(unix, target_os = "redox"))]
91        {
92            use std::ffi::OsStr;
93            use std::os::unix::ffi::OsStrExt;
94            let non_hidden = OsStr::from_bytes(&[0x66, 0x6f, 0x80, 0x6f]); // fo�o // spellchecker:disable-line
95            assert!(!is_json(Path::new(non_hidden)));
96            let hidden = OsStr::from_bytes(&[0x66, 0x6f, 0x80, 0x6f, 0x2e, 0x6a, 0x73, 0x6f, 0x6e]); // fo�o.json // spellchecker:disable-line
97            assert!(is_json(Path::new(hidden)));
98        }
99    }
100}