11use std:: io;
22use std:: path:: { Path , PathBuf } ;
33
4- /// Copy a directory into another.
4+ /// Given a symlink at `src`, read its target, then create a new symlink at `dst` also pointing to
5+ /// target.
6+ pub fn copy_symlink ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) {
7+ let src = src. as_ref ( ) ;
8+ let dst = dst. as_ref ( ) ;
9+ if let Err ( e) = copy_symlink_raw ( src, dst) {
10+ panic ! ( "failed to copy symlink from `{}` to `{}`: {e}" , src. display( ) , dst. display( ) , ) ;
11+ }
12+ }
13+
14+ fn copy_symlink_raw ( ty : FileType , src : impl AsRef < Path > , dst : impl AsRef < Path > ) -> io:: Result < ( ) > {
15+ #![ allow( unused_variables) ]
16+
17+ // Traverse symlink once to find path of target entity.
18+ let target_path = std:: fs:: read_link ( src) ?;
19+
20+ let new_symlink_path = dst. as_ref ( ) ;
21+ #[ cfg( windows) ]
22+ {
23+ use std:: os:: windows:: fs:: FileTypeExt ;
24+ if ty. is_symlink_dir ( ) {
25+ std:: os:: windows:: fs:: symlink_dir ( & target_path, new_symlink_path) ?;
26+ } else {
27+ // Target may be a file or another symlink, in any case we can use
28+ // `symlink_file` here.
29+ std:: os:: windows:: fs:: symlink_file ( & target_path, new_symlink_path) ?;
30+ }
31+ }
32+ #[ cfg( unix) ]
33+ {
34+ std:: os:: unix:: fs:: symlink ( target_path, new_symlink_path) ?;
35+ }
36+ #[ cfg( not( any( windows, unix) ) ) ]
37+ {
38+ // Technically there's also wasi, but I have no clue about wasi symlink
39+ // semantics and which wasi targets / environment support symlinks.
40+ unimplemented ! ( "unsupported target" ) ;
41+ }
42+ Ok ( ( ) )
43+ }
44+
45+ /// Copy a directory into another. This will not traverse symlinks; instead, it will create new
46+ /// symlinks pointing at target paths that symlinks in the original directory points to.
547pub fn copy_dir_all ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) {
648 fn copy_dir_all_inner ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) -> io:: Result < ( ) > {
749 let dst = dst. as_ref ( ) ;
@@ -14,31 +56,7 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
1456 if ty. is_dir ( ) {
1557 copy_dir_all_inner ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
1658 } else if ty. is_symlink ( ) {
17- // Traverse symlink once to find path of target entity.
18- let target_path = std:: fs:: read_link ( entry. path ( ) ) ?;
19-
20- let new_symlink_path = dst. join ( entry. file_name ( ) ) ;
21- #[ cfg( windows) ]
22- {
23- use std:: os:: windows:: fs:: FileTypeExt ;
24- if ty. is_symlink_dir ( ) {
25- std:: os:: windows:: fs:: symlink_dir ( & target_path, new_symlink_path) ?;
26- } else {
27- // Target may be a file or another symlink, in any case we can use
28- // `symlink_file` here.
29- std:: os:: windows:: fs:: symlink_file ( & target_path, new_symlink_path) ?;
30- }
31- }
32- #[ cfg( unix) ]
33- {
34- std:: os:: unix:: fs:: symlink ( target_path, new_symlink_path) ?;
35- }
36- #[ cfg( not( any( windows, unix) ) ) ]
37- {
38- // Technically there's also wasi, but I have no clue about wasi symlink
39- // semantics and which wasi targets / environment support symlinks.
40- unimplemented ! ( "unsupported target" ) ;
41- }
59+ copy_symlink_raw ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
4260 } else {
4361 std:: fs:: copy ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
4462 }
0 commit comments