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 ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) -> io:: Result < ( ) > {
15+ // Traverse symlink once to find path of target entity.
16+ let target_path = std:: fs:: read_link ( src) ?;
17+
18+ let new_symlink_path = dst. as_ref ( ) ;
19+ #[ cfg( windows) ]
20+ {
21+ use std:: os:: windows:: fs:: FileTypeExt ;
22+ if ty. is_symlink_dir ( ) {
23+ std:: os:: windows:: fs:: symlink_dir ( & target_path, new_symlink_path) ?;
24+ } else {
25+ // Target may be a file or another symlink, in any case we can use
26+ // `symlink_file` here.
27+ std:: os:: windows:: fs:: symlink_file ( & target_path, new_symlink_path) ?;
28+ }
29+ }
30+ #[ cfg( unix) ]
31+ {
32+ std:: os:: unix:: fs:: symlink ( target_path, new_symlink_path) ?;
33+ }
34+ #[ cfg( not( any( windows, unix) ) ) ]
35+ {
36+ // Technically there's also wasi, but I have no clue about wasi symlink
37+ // semantics and which wasi targets / environment support symlinks.
38+ unimplemented ! ( "unsupported target" ) ;
39+ }
40+ Ok ( ( ) )
41+ }
42+
43+ /// Copy a directory into another. This will not traverse symlinks; instead, it will create new
44+ /// symlinks pointing at target paths that symlinks in the original directory points to.
545pub fn copy_dir_all ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) {
646 fn copy_dir_all_inner ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) -> io:: Result < ( ) > {
747 let dst = dst. as_ref ( ) ;
@@ -14,31 +54,7 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
1454 if ty. is_dir ( ) {
1555 copy_dir_all_inner ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
1656 } 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- }
57+ copy_symlink_raw ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
4258 } else {
4359 std:: fs:: copy ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
4460 }
0 commit comments