1- use crate :: { Base , ErrorKind , Uri } ;
2- use log:: info;
1+ use crate :: { Base , ErrorKind , Result } ;
2+ use log:: { info, warn } ;
33use std:: collections:: HashMap ;
44use std:: ffi:: OsString ;
55use std:: path:: Path ;
66use std:: sync:: Mutex ;
77use std:: { path:: PathBuf , sync:: Arc } ;
88use walkdir:: WalkDir ;
99
10+ /// Indexes a given directory mapping filenames to their corresponding path.
11+ ///
12+ /// The `WikilinkChecker` Recursively checks all subdirectories of the given
13+ /// base directory mapping any found files to the path where they can be found.
14+ /// Symlinks are ignored to prevent it from infinite loops.
1015#[ derive( Clone , Debug , Default ) ]
11- // Indexes a given directory for filenames and the corresponding path
1216pub ( crate ) struct WikilinkChecker {
1317 filenames : Arc < Mutex < HashMap < OsString , PathBuf > > > ,
1418 basedir : Option < Base > ,
@@ -18,58 +22,73 @@ impl WikilinkChecker {
1822 pub ( crate ) fn new ( base : Option < Base > ) -> Self {
1923 Self {
2024 basedir : base,
21- ..default :: Default ( )
25+ ..Default :: default ( )
2226 }
2327 }
2428
25- pub ( crate ) fn index_files ( & self ) {
26- //Skip the indexing step in case the filenames are already populated
29+ /// Populates the index of the `WikilinkChecker` unless it is already populated.
30+ ///
31+ /// Recursively walks the base directory mapping each filename to an absolute filepath.
32+ /// Errors if no base directory is given or if it is recognized as remote
33+ pub ( crate ) fn setup_wikilinks_index ( & self ) -> Result < ( ) > {
34+ // Skip the indexing step in case the filenames are already populated
2735 if !self . filenames . lock ( ) . unwrap ( ) . is_empty ( ) {
28- return ;
36+ return Ok ( ( ) ) ;
2937 }
3038 match self . basedir {
3139 None => {
32- info ! ( "File indexing for Wikilinks aborted as no base directory is specified" ) ;
40+ warn ! ( "File indexing for Wikilinks aborted as no base directory is specified" ) ;
41+ Ok ( ( ) )
3342 }
34- Some ( ref basetype ) => match basetype {
35- Base :: Local ( localbasename ) => {
36- //Start file indexing only if the Base is valid and local
43+ Some ( ref base_type ) => match base_type {
44+ Base :: Local ( local_base_name ) => {
45+ // Start file indexing only if the Base is valid and local
3746 info ! (
3847 "Starting file indexing for wikilinks in {}" ,
39- localbasename . display( )
48+ local_base_name . display( )
4049 ) ;
4150
42- let mut filenameslock = self . filenames . lock ( ) . unwrap ( ) ;
43- for entry in WalkDir :: new :: < PathBuf > ( localbasename. into ( ) )
44- //actively ignore symlinks
51+ let mut lock = self
52+ . filenames
53+ . lock ( )
54+ . map_err ( |_| ErrorKind :: MutexPoisoned ) ?;
55+ for entry in WalkDir :: new :: < PathBuf > ( local_base_name. into ( ) )
56+ // actively ignore symlinks
4557 . follow_links ( false )
4658 . into_iter ( )
4759 . filter_map ( std:: result:: Result :: ok)
4860 {
4961 if let Some ( filename) = entry. path ( ) . file_name ( ) {
50- filenameslock
51- . insert ( filename. to_ascii_lowercase ( ) , entry. path ( ) . to_path_buf ( ) ) ;
62+ lock. insert ( filename. to_ascii_lowercase ( ) , entry. path ( ) . to_path_buf ( ) ) ;
5263 }
5364 }
65+ Ok ( ( ) )
5466 }
67+
5568 // A remote base is of no use for the wikilink checker, silently skip over it
56- Base :: Remote ( _remotebasename) => { }
69+ Base :: Remote ( remote_base_name) => {
70+ warn ! ( "Error using remote base url for checking wililinks: {remote_base_name}" ) ;
71+ Ok ( ( ) )
72+ }
5773 } ,
5874 }
5975 }
60-
61- pub ( crate ) fn check ( & self , path : & Path , uri : & Uri ) -> Result < PathBuf , ErrorKind > {
76+ /// Checks the index for a filename. Returning the absolute path if the name is found,
77+ /// otherwise returning None
78+ pub ( crate ) fn contains_path ( & self , path : & Path ) -> Option < PathBuf > {
6279 match path. file_name ( ) {
63- None => Err ( ErrorKind :: InvalidFilePath ( uri . clone ( ) ) ) ,
80+ None => None ,
6481 Some ( filename) => {
65- let filenamelock = self . filenames . lock ( ) . unwrap ( ) ;
66- if filenamelock. contains_key ( & filename. to_ascii_lowercase ( ) ) {
67- Ok ( filenamelock
68- . get ( & filename. to_ascii_lowercase ( ) )
69- . expect ( "Could not retrieve inserted Path for discovered Wikilink-Path" ) )
82+ let filename_lock = self . filenames . lock ( ) . unwrap ( ) ;
83+ if filename_lock. contains_key ( & filename. to_ascii_lowercase ( ) ) {
84+ Some (
85+ filename_lock. get ( & filename. to_ascii_lowercase ( ) ) . expect (
86+ "Could not retrieve inserted Path for discovered Wikilink-Path" ,
87+ ) ,
88+ )
7089 . cloned ( )
7190 } else {
72- Err ( ErrorKind :: InvalidFilePath ( uri . clone ( ) ) )
91+ None
7392 }
7493 }
7594 }
0 commit comments