provenant/utils/file/
path.rs1use std::fs;
8use std::path::Path;
9
10use chrono::{TimeZone, Utc};
11use glob::Pattern;
12
13pub(super) const PLAIN_TEXT_EXTENSIONS: &[&str] = &[
14 "rst", "rest", "md", "txt", "log", "json", "xml", "yaml", "yml", "toml", "ini",
15];
16
17pub fn get_creation_date(metadata: &fs::Metadata) -> Option<String> {
19 let time = metadata.modified().ok()?;
20 let seconds_since_epoch = time.duration_since(std::time::UNIX_EPOCH).ok()?.as_secs() as i64;
21
22 Some(
23 Utc.timestamp_opt(seconds_since_epoch, 0)
24 .single()
25 .unwrap_or_else(Utc::now)
26 .format("%Y-%m-%d")
27 .to_string(),
28 )
29}
30
31pub fn is_path_excluded(path: &Path, exclude_patterns: &[Pattern]) -> bool {
33 let path_str = path.to_string_lossy();
34 let file_name = path
35 .file_name()
36 .map(|name| name.to_string_lossy())
37 .unwrap_or_default();
38
39 for pattern in exclude_patterns {
40 if pattern.matches(&path_str) {
42 return true;
43 }
44
45 if pattern.matches(&file_name) {
47 return true;
48 }
49 }
50
51 false
52}
53
54pub(super) fn extension(path: &Path) -> Option<&str> {
55 path.extension().and_then(|ext| ext.to_str())
56}
57
58pub(super) fn lower_extension(path: &Path) -> Option<String> {
59 extension(path).map(|ext| ext.to_ascii_lowercase())
60}
61
62pub(super) fn lower_file_name(path: &Path) -> String {
63 path.file_name()
64 .and_then(|name| name.to_str())
65 .map(|name| name.to_ascii_lowercase())
66 .unwrap_or_default()
67}
68
69pub(super) fn is_plain_text(path: &Path) -> bool {
70 lower_extension(path)
71 .as_deref()
72 .is_some_and(|ext| PLAIN_TEXT_EXTENSIONS.contains(&ext))
73}
74
75pub(super) fn is_makefile(path: &Path) -> bool {
76 matches!(lower_file_name(path).as_str(), "makefile" | "makefile.inc")
77}
78
79pub(super) fn is_source_map(path: &Path) -> bool {
80 let path_lower = path.to_string_lossy().to_ascii_lowercase();
81 path_lower.ends_with(".js.map") || path_lower.ends_with(".css.map")
82}
83
84pub(super) fn is_c_like_source(path: &Path) -> bool {
85 lower_extension(path).as_deref().is_some_and(|ext| {
86 matches!(
87 ext,
88 "c" | "cc"
89 | "cp"
90 | "cpp"
91 | "cxx"
92 | "c++"
93 | "h"
94 | "hh"
95 | "hpp"
96 | "hxx"
97 | "h++"
98 | "i"
99 | "ii"
100 | "m"
101 | "s"
102 | "asm"
103 )
104 })
105}
106
107pub(super) fn is_java_like_source(path: &Path) -> bool {
108 lower_extension(path)
109 .as_deref()
110 .is_some_and(|ext| matches!(ext, "java" | "aj" | "jad" | "ajt"))
111}