@@ -4,6 +4,7 @@ use ignore::gitignore::Gitignore;
44use mdbook:: errors:: Result ;
55use mdbook:: utils;
66use mdbook:: MDBook ;
7+ use pathdiff:: diff_paths;
78use std:: path:: { Path , PathBuf } ;
89use std:: sync:: mpsc:: channel;
910use std:: thread:: sleep;
@@ -86,12 +87,21 @@ fn find_gitignore(book_root: &Path) -> Option<PathBuf> {
8687 . find ( |p| p. exists ( ) )
8788}
8889
90+ // Note: The usage of `canonicalize` may encounter occasional failures on the Windows platform, presenting a potential risk.
91+ // For more details, refer to [Pull Request #2229](https://github.com/rust-lang/mdBook/pull/2229#discussion_r1408665981).
8992fn filter_ignored_files ( ignore : Gitignore , paths : & [ PathBuf ] ) -> Vec < PathBuf > {
93+ let ignore_root = ignore
94+ . path ( )
95+ . canonicalize ( )
96+ . expect ( "ignore root canonicalize error" ) ;
97+
9098 paths
9199 . iter ( )
92100 . filter ( |path| {
101+ let relative_path =
102+ diff_paths ( & path, & ignore_root) . expect ( "One of the paths should be an absolute" ) ;
93103 !ignore
94- . matched_path_or_any_parents ( path , path . is_dir ( ) )
104+ . matched_path_or_any_parents ( & relative_path , relative_path . is_dir ( ) )
95105 . is_ignore ( )
96106 } )
97107 . map ( |path| path. to_path_buf ( ) )
@@ -176,3 +186,44 @@ where
176186 }
177187 }
178188}
189+
190+ #[ cfg( test) ]
191+ mod tests {
192+ use super :: * ;
193+ use ignore:: gitignore:: GitignoreBuilder ;
194+ use std:: env;
195+
196+ #[ test]
197+ fn test_filter_ignored_files ( ) {
198+ let current_dir = env:: current_dir ( ) . unwrap ( ) ;
199+
200+ let ignore = GitignoreBuilder :: new ( & current_dir)
201+ . add_line ( None , "*.html" )
202+ . unwrap ( )
203+ . build ( )
204+ . unwrap ( ) ;
205+ let should_remain = current_dir. join ( "record.text" ) ;
206+ let should_filter = current_dir. join ( "index.html" ) ;
207+
208+ let remain = filter_ignored_files ( ignore, & [ should_remain. clone ( ) , should_filter] ) ;
209+ assert_eq ! ( remain, vec![ should_remain] )
210+ }
211+
212+ #[ test]
213+ fn filter_ignored_files_should_handle_parent_dir ( ) {
214+ let current_dir = env:: current_dir ( ) . unwrap ( ) ;
215+
216+ let ignore = GitignoreBuilder :: new ( & current_dir)
217+ . add_line ( None , "*.html" )
218+ . unwrap ( )
219+ . build ( )
220+ . unwrap ( ) ;
221+
222+ let parent_dir = current_dir. join ( ".." ) ;
223+ let should_remain = parent_dir. join ( "record.text" ) ;
224+ let should_filter = parent_dir. join ( "index.html" ) ;
225+
226+ let remain = filter_ignored_files ( ignore, & [ should_remain. clone ( ) , should_filter] ) ;
227+ assert_eq ! ( remain, vec![ should_remain] )
228+ }
229+ }
0 commit comments