17
17
//! should catch the majority of "broken link" cases.
18
18
19
19
use std:: cell:: { Cell , RefCell } ;
20
+ use std:: collections:: hash_map:: Entry ;
20
21
use std:: collections:: { HashMap , HashSet } ;
21
22
use std:: fs;
22
23
use std:: io:: ErrorKind ;
24
+ use std:: iter:: once;
23
25
use std:: path:: { Component , Path , PathBuf } ;
24
26
use std:: rc:: Rc ;
25
27
use std:: time:: Instant ;
@@ -114,13 +116,19 @@ macro_rules! t {
114
116
#[ derive( Parser ) ]
115
117
struct Cli {
116
118
docs : PathBuf ,
119
+ #[ clap( long) ]
120
+ link_targets_dir : Vec < PathBuf > ,
117
121
}
118
122
119
123
fn main ( ) {
120
124
let mut cli = Cli :: parse ( ) ;
121
125
cli. docs = cli. docs . canonicalize ( ) . unwrap ( ) ;
122
126
123
- let mut checker = Checker { root : cli. docs . clone ( ) , cache : HashMap :: new ( ) } ;
127
+ let mut checker = Checker {
128
+ root : cli. docs . clone ( ) ,
129
+ link_targets_dirs : cli. link_targets_dir ,
130
+ cache : HashMap :: new ( ) ,
131
+ } ;
124
132
let mut report = Report {
125
133
errors : 0 ,
126
134
start : Instant :: now ( ) ,
@@ -142,6 +150,7 @@ fn main() {
142
150
143
151
struct Checker {
144
152
root : PathBuf ,
153
+ link_targets_dirs : Vec < PathBuf > ,
145
154
cache : Cache ,
146
155
}
147
156
@@ -434,15 +443,22 @@ impl Checker {
434
443
let pretty_path =
435
444
file. strip_prefix ( & self . root ) . unwrap_or ( file) . to_str ( ) . unwrap ( ) . to_string ( ) ;
436
445
437
- let entry =
438
- self . cache . entry ( pretty_path. clone ( ) ) . or_insert_with ( || match fs:: metadata ( file) {
446
+ for base in once ( & self . root ) . chain ( self . link_targets_dirs . iter ( ) ) {
447
+ if let Entry :: Occupied ( e) = self . cache . entry ( pretty_path. clone ( ) )
448
+ && let FileEntry :: Missing = e. get ( )
449
+ {
450
+ break ;
451
+ }
452
+
453
+ let file = base. join ( & pretty_path) ;
454
+ entry. insert_entry ( match fs:: metadata ( & file) {
439
455
Ok ( metadata) if metadata. is_dir ( ) => FileEntry :: Dir ,
440
456
Ok ( _) => {
441
457
if file. extension ( ) . and_then ( |s| s. to_str ( ) ) != Some ( "html" ) {
442
458
FileEntry :: OtherFile
443
459
} else {
444
460
report. html_files += 1 ;
445
- load_html_file ( file, report)
461
+ load_html_file ( & file, report)
446
462
}
447
463
}
448
464
Err ( e) if e. kind ( ) == ErrorKind :: NotFound => FileEntry :: Missing ,
@@ -458,6 +474,9 @@ impl Checker {
458
474
panic ! ( "unexpected read error for {}: {}" , file. display( ) , e) ;
459
475
}
460
476
} ) ;
477
+ }
478
+
479
+ let entry = self . cache . get ( & pretty_path) . unwrap ( ) ;
461
480
( pretty_path, entry)
462
481
}
463
482
}
0 commit comments