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,23 @@ 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
+ let entry = self . cache . entry ( pretty_path. clone ( ) ) ;
448
+ if let Entry :: Occupied ( e) = & entry
449
+ && !matches ! ( e. get( ) , FileEntry :: Missing )
450
+ {
451
+ break ;
452
+ }
453
+
454
+ let file = base. join ( & pretty_path) ;
455
+ entry. insert_entry ( match fs:: metadata ( & file) {
439
456
Ok ( metadata) if metadata. is_dir ( ) => FileEntry :: Dir ,
440
457
Ok ( _) => {
441
458
if file. extension ( ) . and_then ( |s| s. to_str ( ) ) != Some ( "html" ) {
442
459
FileEntry :: OtherFile
443
460
} else {
444
461
report. html_files += 1 ;
445
- load_html_file ( file, report)
462
+ load_html_file ( & file, report)
446
463
}
447
464
}
448
465
Err ( e) if e. kind ( ) == ErrorKind :: NotFound => FileEntry :: Missing ,
@@ -458,6 +475,9 @@ impl Checker {
458
475
panic ! ( "unexpected read error for {}: {}" , file. display( ) , e) ;
459
476
}
460
477
} ) ;
478
+ }
479
+
480
+ let entry = self . cache . get ( & pretty_path) . unwrap ( ) ;
461
481
( pretty_path, entry)
462
482
}
463
483
}
0 commit comments