1
1
use std:: io;
2
2
use std:: path:: { Path , PathBuf } ;
3
3
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.
5
45
pub fn copy_dir_all ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) {
6
46
fn copy_dir_all_inner ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) -> io:: Result < ( ) > {
7
47
let dst = dst. as_ref ( ) ;
@@ -14,31 +54,7 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
14
54
if ty. is_dir ( ) {
15
55
copy_dir_all_inner ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
16
56
} 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 ( ) ) ) ?;
42
58
} else {
43
59
std:: fs:: copy ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
44
60
}
0 commit comments