@@ -13,6 +13,7 @@ use rustc_middle::ty::TyCtxt;
13
13
use rustc_session:: Session ;
14
14
use rustc_span:: source_map:: FileName ;
15
15
16
+ use std:: cell:: RefCell ;
16
17
use std:: ffi:: OsStr ;
17
18
use std:: fs;
18
19
use std:: path:: { Component , Path , PathBuf } ;
@@ -72,12 +73,22 @@ impl LocalSourcesCollector<'_, '_> {
72
73
return ;
73
74
}
74
75
75
- let mut href = String :: new ( ) ;
76
- clean_path ( self . src_root , & p, false , |component| {
77
- href. push_str ( & component. to_string_lossy ( ) ) ;
78
- href. push ( '/' ) ;
79
- } ) ;
76
+ let href = RefCell :: new ( PathBuf :: new ( ) ) ;
77
+ clean_path (
78
+ & self . src_root ,
79
+ & p,
80
+ |component| {
81
+ href. borrow_mut ( ) . push ( component) ;
82
+ } ,
83
+ || {
84
+ href. borrow_mut ( ) . pop ( ) ;
85
+ } ,
86
+ ) ;
80
87
88
+ let mut href = href. into_inner ( ) . to_string_lossy ( ) . to_string ( ) ;
89
+ if let Some ( c) = href. as_bytes ( ) . last ( ) && * c != b'/' {
90
+ href. push ( '/' ) ;
91
+ }
81
92
let mut src_fname = p. file_name ( ) . expect ( "source has no filename" ) . to_os_string ( ) ;
82
93
src_fname. push ( ".html" ) ;
83
94
href. push_str ( & src_fname. to_string_lossy ( ) ) ;
@@ -180,13 +191,28 @@ impl SourceCollector<'_, '_> {
180
191
181
192
let shared = Rc :: clone ( & self . cx . shared ) ;
182
193
// Create the intermediate directories
183
- let mut cur = self . dst . clone ( ) ;
184
- let mut root_path = String :: from ( "../../" ) ;
185
- clean_path ( & shared. src_root , & p, false , |component| {
186
- cur. push ( component) ;
187
- root_path. push_str ( "../" ) ;
188
- } ) ;
194
+ let cur = RefCell :: new ( PathBuf :: new ( ) ) ;
195
+ let root_path = RefCell :: new ( PathBuf :: new ( ) ) ;
196
+
197
+ clean_path (
198
+ & shared. src_root ,
199
+ & p,
200
+ |component| {
201
+ cur. borrow_mut ( ) . push ( component) ;
202
+ root_path. borrow_mut ( ) . push ( ".." ) ;
203
+ } ,
204
+ || {
205
+ cur. borrow_mut ( ) . pop ( ) ;
206
+ root_path. borrow_mut ( ) . pop ( ) ;
207
+ } ,
208
+ ) ;
189
209
210
+ let root_path = PathBuf :: from ( "../../" ) . join ( root_path. into_inner ( ) ) ;
211
+ let mut root_path = root_path. to_string_lossy ( ) ;
212
+ if let Some ( c) = root_path. as_bytes ( ) . last ( ) && * c != b'/' {
213
+ root_path += "/" ;
214
+ }
215
+ let mut cur = self . dst . join ( cur. into_inner ( ) ) ;
190
216
shared. ensure_dir ( & cur) ?;
191
217
192
218
let src_fname = p. file_name ( ) . expect ( "source has no filename" ) . to_os_string ( ) ;
@@ -232,24 +258,26 @@ impl SourceCollector<'_, '_> {
232
258
/// Takes a path to a source file and cleans the path to it. This canonicalizes
233
259
/// things like ".." to components which preserve the "top down" hierarchy of a
234
260
/// static HTML tree. Each component in the cleaned path will be passed as an
235
- /// argument to `f`. The very last component of the path (ie the file name) will
236
- /// be passed to `f` if `keep_filename` is true, and ignored otherwise.
237
- pub ( crate ) fn clean_path < F > ( src_root : & Path , p : & Path , keep_filename : bool , mut f : F )
261
+ /// argument to `f`. The very last component of the path (ie the file name) is ignored.
262
+ /// If a `..` is encountered, the `parent` closure will be called to allow the callee to
263
+ /// handle it.
264
+ pub ( crate ) fn clean_path < F , P > ( src_root : & Path , p : & Path , mut f : F , mut parent : P )
238
265
where
239
266
F : FnMut ( & OsStr ) ,
267
+ P : FnMut ( ) ,
240
268
{
241
269
// make it relative, if possible
242
270
let p = p. strip_prefix ( src_root) . unwrap_or ( p) ;
243
271
244
272
let mut iter = p. components ( ) . peekable ( ) ;
245
273
246
274
while let Some ( c) = iter. next ( ) {
247
- if !keep_filename && iter. peek ( ) . is_none ( ) {
275
+ if iter. peek ( ) . is_none ( ) {
248
276
break ;
249
277
}
250
278
251
279
match c {
252
- Component :: ParentDir => f ( "up" . as_ref ( ) ) ,
280
+ Component :: ParentDir => parent ( ) ,
253
281
Component :: Normal ( c) => f ( c) ,
254
282
_ => continue ,
255
283
}
0 commit comments