@@ -5,7 +5,7 @@ use std::{
55 collections:: HashMap ,
66 fs:: { self , File , OpenOptions } ,
77 io:: { BufReader , BufWriter } ,
8- path:: PathBuf ,
8+ path:: { Path , PathBuf } ,
99 sync:: Mutex ,
1010} ;
1111
@@ -22,9 +22,8 @@ pub(crate) fn build_project_file(path: PathBuf, use_cache: bool) -> ProjectFile
2222
2323 let project_file = build_project_file_without_cache ( & path) ;
2424
25- if let Ok ( mut cache) = PROJECT_FILE_CACHE . lock ( ) {
26- cache. insert ( path. clone ( ) , project_file. owner . clone ( ) . unwrap ( ) ) ;
27- }
25+ save_project_file_to_cache ( & path, & project_file) ;
26+
2827 project_file
2928}
3029
@@ -55,13 +54,19 @@ pub(crate) fn build_project_file_without_cache(path: &PathBuf) -> ProjectFile {
5554 ProjectFile { path : path. clone ( ) , owner }
5655}
5756
57+ #[ derive( Clone , serde:: Serialize , serde:: Deserialize ) ]
58+ struct CacheEntry {
59+ timestamp : u64 ,
60+ owner : Option < String > ,
61+ }
62+
5863lazy_static ! {
5964 static ref TEAM_REGEX : Regex = Regex :: new( r#"^(?:#|//) @team (.*)$"# ) . expect( "error compiling regular expression" ) ;
60- static ref PROJECT_FILE_CACHE : Box <Mutex <HashMap <PathBuf , String >>> =
65+ static ref PROJECT_FILE_CACHE : Box <Mutex <HashMap <PathBuf , CacheEntry >>> =
6166 Box :: new( Mutex :: new( load_cache( ) . unwrap_or_else( |_| HashMap :: with_capacity( 10000 ) ) ) ) ;
6267}
6368
64- fn load_cache ( ) -> Result < HashMap < PathBuf , String > , Error > {
69+ fn load_cache ( ) -> Result < HashMap < PathBuf , CacheEntry > , Error > {
6570 let cache_path = get_cache_path ( ) ;
6671 if !cache_path. exists ( ) {
6772 return Ok ( HashMap :: with_capacity ( 10000 ) ) ;
@@ -95,12 +100,39 @@ fn get_cache_path() -> PathBuf {
95100
96101fn get_project_file_from_cache ( path : & PathBuf ) -> Result < Option < ProjectFile > , Error > {
97102 if let Ok ( cache) = PROJECT_FILE_CACHE . lock ( ) {
98- if let Some ( cached_owner) = cache. get ( path) {
99- return Ok ( Some ( ProjectFile {
100- path : path. clone ( ) ,
101- owner : Some ( cached_owner. clone ( ) ) ,
102- } ) ) ;
103+ if let Some ( cached_entry) = cache. get ( path) {
104+ let timestamp = get_file_timestamp ( path) ?;
105+ if cached_entry. timestamp == timestamp {
106+ return Ok ( Some ( ProjectFile {
107+ path : path. clone ( ) ,
108+ owner : cached_entry. owner . clone ( ) ,
109+ } ) ) ;
110+ }
103111 }
104112 }
105113 Ok ( None )
106114}
115+
116+ fn save_project_file_to_cache ( path : & Path , project_file : & ProjectFile ) {
117+ if let Ok ( mut cache) = PROJECT_FILE_CACHE . lock ( ) {
118+ if let Ok ( timestamp) = get_file_timestamp ( path) {
119+ cache. insert (
120+ path. to_path_buf ( ) ,
121+ CacheEntry {
122+ timestamp,
123+ owner : project_file. owner . clone ( ) ,
124+ } ,
125+ ) ;
126+ }
127+ }
128+ }
129+
130+ fn get_file_timestamp ( path : & Path ) -> Result < u64 , Error > {
131+ let metadata = fs:: metadata ( path) . change_context ( Error :: Io ) ?;
132+ metadata
133+ . modified ( )
134+ . change_context ( Error :: Io ) ?
135+ . duration_since ( std:: time:: UNIX_EPOCH )
136+ . change_context ( Error :: Io )
137+ . map ( |duration| duration. as_secs ( ) )
138+ }
0 commit comments