@@ -171,14 +171,16 @@ fn copy_volume_files_nocache(
171
171
container : & str ,
172
172
src : & Path ,
173
173
dst : & Path ,
174
+ copy_symlinks : bool ,
174
175
msg_info : MessageInfo ,
175
176
) -> Result < ExitStatus > {
176
177
// avoid any cached directories when copying
177
178
// see https://bford.info/cachedir/
178
179
// SAFETY: safe, single-threaded execution.
179
180
let tempdir = unsafe { temp:: TempDir :: new ( ) ? } ;
180
181
let temppath = tempdir. path ( ) ;
181
- copy_dir ( src, temppath, 0 , |e, _| is_cachedir ( e) ) ?;
182
+ let had_symlinks = copy_dir ( src, temppath, copy_symlinks, 0 , |e, _| is_cachedir ( e) ) ?;
183
+ warn_symlinks ( had_symlinks, msg_info) ?;
182
184
copy_volume_files ( engine, container, temppath, dst, msg_info)
183
185
}
184
186
@@ -234,10 +236,18 @@ pub fn copy_volume_container_cargo(
234
236
}
235
237
236
238
// recursively copy a directory into another
237
- fn copy_dir < Skip > ( src : & Path , dst : & Path , depth : u32 , skip : Skip ) -> Result < ( ) >
239
+ fn copy_dir < Skip > (
240
+ src : & Path ,
241
+ dst : & Path ,
242
+ copy_symlinks : bool ,
243
+ depth : u32 ,
244
+ skip : Skip ,
245
+ ) -> Result < bool >
238
246
where
239
247
Skip : Copy + Fn ( & fs:: DirEntry , u32 ) -> bool ,
240
248
{
249
+ let mut had_symlinks = false ;
250
+
241
251
for entry in fs:: read_dir ( src) ? {
242
252
let file = entry?;
243
253
if skip ( & file, depth) {
@@ -248,13 +258,47 @@ where
248
258
let dst_path = dst. join ( file. file_name ( ) ) ;
249
259
if file. file_type ( ) ?. is_file ( ) {
250
260
fs:: copy ( & src_path, & dst_path) ?;
251
- } else {
261
+ } else if file . file_type ( ) ? . is_dir ( ) {
252
262
fs:: create_dir ( & dst_path) . ok ( ) ;
253
- copy_dir ( & src_path, & dst_path, depth + 1 , skip) ?;
263
+ had_symlinks = copy_dir ( & src_path, & dst_path, copy_symlinks, depth + 1 , skip) ?;
264
+ } else if copy_symlinks {
265
+ had_symlinks = true ;
266
+ let link_dst = fs:: read_link ( src_path) ?;
267
+
268
+ #[ cfg( target_family = "unix" ) ]
269
+ {
270
+ std:: os:: unix:: fs:: symlink ( link_dst, dst_path) ?;
271
+ }
272
+
273
+ #[ cfg( target_family = "windows" ) ]
274
+ {
275
+ let link_dst_absolute = if link_dst. is_absolute ( ) {
276
+ link_dst
277
+ } else {
278
+ // we cannot fail even if the linked to path does not exist.
279
+ src. join ( link_dst)
280
+ } ;
281
+ if link_dst_absolute. is_dir ( ) {
282
+ std:: os:: windows:: fs:: symlink_dir ( link_dst, dst_path) ?;
283
+ } else {
284
+ // symlink_file handles everything that isn't a directory
285
+ std:: os:: windows:: fs:: symlink_file ( link_dst, dst_path) ?;
286
+ }
287
+ }
288
+ } else {
289
+ had_symlinks = true ;
254
290
}
255
291
}
256
292
257
- Ok ( ( ) )
293
+ Ok ( had_symlinks)
294
+ }
295
+
296
+ fn warn_symlinks ( had_symlinks : bool , msg_info : MessageInfo ) -> Result < ( ) > {
297
+ if had_symlinks {
298
+ shell:: warn ( "copied directory contained symlinks. if the volume the link points to was not mounted, the remote build may fail" , msg_info)
299
+ } else {
300
+ Ok ( ( ) )
301
+ }
258
302
}
259
303
260
304
// copy over files needed for all targets in the toolchain that should never change
@@ -284,20 +328,25 @@ fn copy_volume_container_rust_base(
284
328
let tempdir = unsafe { temp:: TempDir :: new ( ) ? } ;
285
329
let temppath = tempdir. path ( ) ;
286
330
fs:: create_dir_all ( & temppath. join ( & rustlib) ) ?;
287
- copy_dir ( & sysroot. join ( "lib" ) , & temppath. join ( "lib" ) , 0 , |e, d| {
288
- d == 0 && e. file_name ( ) == "rustlib"
289
- } ) ?;
331
+ let mut had_symlinks = copy_dir (
332
+ & sysroot. join ( "lib" ) ,
333
+ & temppath. join ( "lib" ) ,
334
+ true ,
335
+ 0 ,
336
+ |e, d| d == 0 && e. file_name ( ) == "rustlib" ,
337
+ ) ?;
290
338
291
339
// next, copy the src/etc directories inside rustlib
292
- copy_dir (
340
+ had_symlinks |= copy_dir (
293
341
& sysroot. join ( & rustlib) ,
294
342
& temppath. join ( & rustlib) ,
343
+ true ,
295
344
0 ,
296
345
|e, d| d == 0 && !( e. file_name ( ) == "src" || e. file_name ( ) == "etc" ) ,
297
346
) ?;
298
347
copy_volume_files ( engine, container, & temppath. join ( "lib" ) , & dst, msg_info) ?;
299
348
300
- Ok ( ( ) )
349
+ warn_symlinks ( had_symlinks , msg_info )
301
350
}
302
351
303
352
fn copy_volume_container_rust_manifest (
@@ -316,15 +365,16 @@ fn copy_volume_container_rust_manifest(
316
365
let tempdir = unsafe { temp:: TempDir :: new ( ) ? } ;
317
366
let temppath = tempdir. path ( ) ;
318
367
fs:: create_dir_all ( & temppath. join ( & rustlib) ) ?;
319
- copy_dir (
368
+ let had_symlinks = copy_dir (
320
369
& sysroot. join ( & rustlib) ,
321
370
& temppath. join ( & rustlib) ,
371
+ true ,
322
372
0 ,
323
373
|e, d| d != 0 || e. file_type ( ) . map ( |t| !t. is_file ( ) ) . unwrap_or ( true ) ,
324
374
) ?;
325
375
copy_volume_files ( engine, container, & temppath. join ( "lib" ) , & dst, msg_info) ?;
326
376
327
- Ok ( ( ) )
377
+ warn_symlinks ( had_symlinks , msg_info )
328
378
}
329
379
330
380
// copy over the toolchain for a specific triple
@@ -570,7 +620,7 @@ fn copy_volume_container_project(
570
620
if copy_cache {
571
621
copy_volume_files ( engine, container, src, dst, msg_info)
572
622
} else {
573
- copy_volume_files_nocache ( engine, container, src, dst, msg_info)
623
+ copy_volume_files_nocache ( engine, container, src, dst, true , msg_info)
574
624
}
575
625
} ;
576
626
match volume {
@@ -809,7 +859,7 @@ pub(crate) fn run(
809
859
if copy_cache {
810
860
copy_volume_files ( engine, & container, src, dst, msg_info)
811
861
} else {
812
- copy_volume_files_nocache ( engine, & container, src, dst, msg_info)
862
+ copy_volume_files_nocache ( engine, & container, src, dst, true , msg_info)
813
863
}
814
864
} ;
815
865
let mount_prefix_path = mount_prefix. as_ref ( ) ;
0 commit comments