aboutsummaryrefslogtreecommitdiff
path: root/src/file_finder.rs
blob: 08e86c4251d780345b0616fba1c39676984ce67e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use crate::file_handler::{File, FileHandler};
use std::fs::read_dir;
use std::path::PathBuf;

pub fn find_files(directory_path: &PathBuf) -> Vec<File> {
    find_files_recursively(directory_path, directory_path)
}

fn find_files_recursively(root_path: &PathBuf, directory_path: &PathBuf) -> Vec<File> {
    let mut result: Vec<File> = vec![];
    let file_handler = FileHandler::default();
    if let Ok(entries) = read_dir(directory_path) {
        for entry in entries.flatten() {
            let path = entry.path();
            if let Ok(relative_path) = path.strip_prefix(root_path) {
                if relative_path.starts_with(".git") || relative_path.starts_with(".gitignore") {
                    continue;
                }
                if path.is_dir() {
                    result.append(&mut find_files_recursively(root_path, &path));
                } else {
                    let file_type = file_handler.identify(&path);
                    result.push(File { path, file_type });
                }
            }
        }
    }
    result
}

#[cfg(test)]
mod tests {
    use std::collections::HashSet;
    use std::fs::create_dir_all;
    use std::path::PathBuf;

    use super::*;

    use crate::file_handler::File;
    use crate::file_handler::FileType;
    use test_utilities::*;

    fn get_paths(root_directory: &PathBuf, files: &[File]) -> HashSet<String> {
        files
            .iter()
            .map(|file| {
                file.path
                    .strip_prefix(root_directory)
                    .unwrap()
                    .to_string_lossy()
                    .to_string()
            })
            .collect()
    }

    #[test]
    fn finds_all_files() {
        let test_dir = setup_test_dir();
        create_dir_all(test_dir.join("nested")).expect("Could not create nested test directory");
        create_dir_all(test_dir.join("assets")).expect("Could not create assets test directory");
        create_test_file(&test_dir.join("test1.gmi"), "");
        create_test_file(&test_dir.join("_layout.html"), "");
        create_test_file(&test_dir.join("nested/nested.gmi"), "");
        create_test_file(&test_dir.join("assets/style.css"), "");
        create_test_file(&test_dir.join("image.png"), "");

        let files = find_files(&test_dir);
        let paths = get_paths(&test_dir, &files);

        assert!(paths.contains("test1.gmi"));
        assert!(paths.contains("_layout.html"));
        assert!(paths.contains("nested/nested.gmi"));
        assert!(paths.contains("assets/style.css"));
        assert!(paths.contains("image.png"));
    }

    #[test]
    fn identifies_correct_file_types() {
        let test_dir = setup_test_dir();
        create_dir_all(test_dir.join("nested")).expect("Could not create nested test directory");
        create_dir_all(test_dir.join("assets")).expect("Could not create assets test directory");
        create_test_file(&test_dir.join("_layout.html"), "");
        create_test_file(&test_dir.join("notalayout.html"), "");
        create_test_file(&test_dir.join("nested/nested.gmi"), "");
        create_test_file(&test_dir.join("assets/style.css"), "");
        create_test_file(&test_dir.join("image.png"), "");
        let files = find_files(&test_dir);

        for file in files {
            let extension = file.path.extension().and_then(|e| e.to_str());
            match extension {
                Some("gmi") => assert_eq!(file.file_type, FileType::Gemini),
                Some("html") => {
                    if file.path.ends_with("_layout.html") {
                        assert_eq!(file.file_type, FileType::Layout);
                    } else {
                        assert_eq!(file.file_type, FileType::File);
                    }
                }
                _ => assert_eq!(file.file_type, FileType::File),
            }
        }
    }

    #[test]
    fn ignores_git_directory() {
        let test_dir = setup_test_dir();
        create_dir_all(test_dir.join("nested")).expect("Could not create nested test directory");
        create_dir_all(test_dir.join("assets")).expect("Could not create assets test directory");
        create_dir_all(test_dir.join(".git")).expect("Could not create git test directory");
        create_test_file(&test_dir.join("_layout.html"), "");
        create_test_file(&test_dir.join("nested/nested.gmi"), "");
        create_test_file(&test_dir.join("assets/style.css"), "");
        create_test_file(&test_dir.join("image.png"), "");
        create_test_file(&test_dir.join(".git/config"), "");
        let files = find_files(&test_dir);

        let paths = get_paths(&test_dir, &files);

        assert!(!paths.iter().any(|p| p.starts_with(".git/")));
        assert!(!paths.contains(".gitignore"));
    }

    #[test]
    fn returns_empty_for_empty_directory() {
        let test_dir = setup_test_dir();
        let files = find_files(&test_dir);
        assert!(files.is_empty());
    }
}