@@ -689,8 +689,10 @@ fn rename(
689
689
to : & Path ,
690
690
opts : & Options ,
691
691
multi_progress : Option < & MultiProgress > ,
692
- hardlink_tracker : Option < & mut HardlinkTracker > ,
693
- hardlink_scanner : Option < & HardlinkGroupScanner > ,
692
+ #[ cfg( unix) ] hardlink_tracker : Option < & mut HardlinkTracker > ,
693
+ #[ cfg( unix) ] hardlink_scanner : Option < & HardlinkGroupScanner > ,
694
+ #[ cfg( not( unix) ) ] _hardlink_tracker : Option < ( ) > ,
695
+ #[ cfg( not( unix) ) ] _hardlink_scanner : Option < ( ) > ,
694
696
) -> io:: Result < ( ) > {
695
697
let mut backup_path = None ;
696
698
@@ -770,7 +772,14 @@ fn rename(
770
772
}
771
773
}
772
774
773
- rename_with_fallback ( from, to, multi_progress, hardlink_tracker, hardlink_scanner) ?;
775
+ #[ cfg( unix) ]
776
+ {
777
+ rename_with_fallback ( from, to, multi_progress, hardlink_tracker, hardlink_scanner) ?;
778
+ }
779
+ #[ cfg( not( unix) ) ]
780
+ {
781
+ rename_with_fallback ( from, to, multi_progress, None , None ) ?;
782
+ }
774
783
775
784
if opts. verbose {
776
785
let message = match backup_path {
@@ -817,8 +826,10 @@ fn rename_with_fallback(
817
826
from : & Path ,
818
827
to : & Path ,
819
828
multi_progress : Option < & MultiProgress > ,
820
- hardlink_tracker : Option < & mut HardlinkTracker > ,
821
- hardlink_scanner : Option < & HardlinkGroupScanner > ,
829
+ #[ cfg( unix) ] hardlink_tracker : Option < & mut HardlinkTracker > ,
830
+ #[ cfg( unix) ] hardlink_scanner : Option < & HardlinkGroupScanner > ,
831
+ #[ cfg( not( unix) ) ] _hardlink_tracker : Option < ( ) > ,
832
+ #[ cfg( not( unix) ) ] _hardlink_scanner : Option < ( ) > ,
822
833
) -> io:: Result < ( ) > {
823
834
fs:: rename ( from, to) . or_else ( |err| {
824
835
#[ cfg( windows) ]
@@ -841,21 +852,35 @@ fn rename_with_fallback(
841
852
if file_type. is_symlink ( ) {
842
853
rename_symlink_fallback ( from, to)
843
854
} else if file_type. is_dir ( ) {
844
- with_optional_hardlink_context (
845
- hardlink_tracker,
846
- hardlink_scanner,
847
- |tracker, scanner| {
848
- rename_dir_fallback_with_hardlinks ( from, to, multi_progress, tracker, scanner)
849
- } ,
850
- )
855
+ #[ cfg( unix) ]
856
+ {
857
+ with_optional_hardlink_context (
858
+ hardlink_tracker,
859
+ hardlink_scanner,
860
+ |tracker, scanner| {
861
+ rename_dir_fallback ( from, to, multi_progress, Some ( tracker) , Some ( scanner) )
862
+ } ,
863
+ )
864
+ }
865
+ #[ cfg( not( unix) ) ]
866
+ {
867
+ rename_dir_fallback ( from, to, multi_progress)
868
+ }
851
869
} else if is_fifo ( file_type) {
852
870
rename_fifo_fallback ( from, to)
853
871
} else {
854
- with_optional_hardlink_context (
855
- hardlink_tracker,
856
- hardlink_scanner,
857
- |tracker, scanner| rename_file_fallback ( from, to, tracker, scanner) ,
858
- )
872
+ #[ cfg( unix) ]
873
+ {
874
+ with_optional_hardlink_context (
875
+ hardlink_tracker,
876
+ hardlink_scanner,
877
+ |tracker, scanner| rename_file_fallback ( from, to, Some ( tracker) , Some ( scanner) ) ,
878
+ )
879
+ }
880
+ #[ cfg( not( unix) ) ]
881
+ {
882
+ rename_file_fallback ( from, to)
883
+ }
859
884
}
860
885
} )
861
886
}
@@ -909,12 +934,12 @@ fn rename_symlink_fallback(from: &Path, to: &Path) -> io::Result<()> {
909
934
) )
910
935
}
911
936
912
- fn rename_dir_fallback_with_hardlinks (
937
+ fn rename_dir_fallback (
913
938
from : & Path ,
914
939
to : & Path ,
915
940
multi_progress : Option < & MultiProgress > ,
916
- hardlink_tracker : & mut HardlinkTracker ,
917
- hardlink_scanner : & HardlinkGroupScanner ,
941
+ # [ cfg ( unix ) ] hardlink_tracker : Option < & mut HardlinkTracker > ,
942
+ # [ cfg ( unix ) ] hardlink_scanner : Option < & HardlinkGroupScanner > ,
918
943
) -> io:: Result < ( ) > {
919
944
// We remove the destination directory if it exists to match the
920
945
// behavior of `fs::rename`. As far as I can tell, `fs_extra`'s
@@ -943,11 +968,13 @@ fn rename_dir_fallback_with_hardlinks(
943
968
#[ cfg( all( unix, not( any( target_os = "macos" , target_os = "redox" ) ) ) ) ]
944
969
let xattrs = fsxattr:: retrieve_xattrs ( from) . unwrap_or_else ( |_| HashMap :: new ( ) ) ;
945
970
946
- // Use custom directory copying that preserves hardlinks
947
- let result = copy_dir_with_hardlinks (
971
+ // Use directory copying (with or without hardlink support)
972
+ let result = copy_dir_contents (
948
973
from,
949
974
to,
975
+ #[ cfg( unix) ]
950
976
hardlink_tracker,
977
+ #[ cfg( unix) ]
951
978
hardlink_scanner,
952
979
progress_bar. as_ref ( ) ,
953
980
) ;
@@ -963,29 +990,37 @@ fn rename_dir_fallback_with_hardlinks(
963
990
Ok ( ( ) )
964
991
}
965
992
966
- /// Copy directory recursively while preserving hardlinks
967
- fn copy_dir_with_hardlinks (
993
+ /// Copy directory recursively, optionally preserving hardlinks
994
+ fn copy_dir_contents (
968
995
from : & Path ,
969
996
to : & Path ,
970
- hardlink_tracker : & mut HardlinkTracker ,
971
- hardlink_scanner : & HardlinkGroupScanner ,
997
+ # [ cfg ( unix ) ] hardlink_tracker : Option < & mut HardlinkTracker > ,
998
+ # [ cfg ( unix ) ] hardlink_scanner : Option < & HardlinkGroupScanner > ,
972
999
progress_bar : Option < & ProgressBar > ,
973
1000
) -> io:: Result < ( ) > {
974
1001
// Create the destination directory
975
1002
fs:: create_dir_all ( to) ?;
976
1003
977
1004
// Recursively copy contents
978
- copy_dir_contents_with_hardlinks ( from, to, hardlink_tracker, hardlink_scanner, progress_bar) ?;
1005
+ #[ cfg( unix) ]
1006
+ {
1007
+ if let ( Some ( tracker) , Some ( scanner) ) = ( hardlink_tracker, hardlink_scanner) {
1008
+ copy_dir_contents_recursive ( from, to, tracker, scanner, progress_bar) ?;
1009
+ }
1010
+ }
1011
+ #[ cfg( not( unix) ) ]
1012
+ {
1013
+ copy_dir_contents_recursive ( from, to, progress_bar) ?;
1014
+ }
979
1015
980
1016
Ok ( ( ) )
981
1017
}
982
1018
983
- /// Recursively copy directory contents while preserving hardlinks
984
- fn copy_dir_contents_with_hardlinks (
1019
+ fn copy_dir_contents_recursive (
985
1020
from_dir : & Path ,
986
1021
to_dir : & Path ,
987
- hardlink_tracker : & mut HardlinkTracker ,
988
- hardlink_scanner : & HardlinkGroupScanner ,
1022
+ # [ cfg ( unix ) ] hardlink_tracker : & mut HardlinkTracker ,
1023
+ # [ cfg ( unix ) ] hardlink_scanner : & HardlinkGroupScanner ,
989
1024
progress_bar : Option < & ProgressBar > ,
990
1025
) -> io:: Result < ( ) > {
991
1026
let entries = fs:: read_dir ( from_dir) ?;
@@ -1003,16 +1038,30 @@ fn copy_dir_contents_with_hardlinks(
1003
1038
if from_path. is_dir ( ) {
1004
1039
// Recursively copy subdirectory
1005
1040
fs:: create_dir_all ( & to_path) ?;
1006
- copy_dir_contents_with_hardlinks (
1041
+ copy_dir_contents_recursive (
1007
1042
& from_path,
1008
1043
& to_path,
1044
+ #[ cfg( unix) ]
1009
1045
hardlink_tracker,
1046
+ #[ cfg( unix) ]
1010
1047
hardlink_scanner,
1011
1048
progress_bar,
1012
1049
) ?;
1013
1050
} else {
1014
- // Copy file, preserving hardlinks
1015
- copy_file_with_hardlinks ( & from_path, & to_path, hardlink_tracker, hardlink_scanner) ?;
1051
+ // Copy file with or without hardlink support based on platform
1052
+ #[ cfg( unix) ]
1053
+ {
1054
+ copy_file_with_hardlinks_helper (
1055
+ & from_path,
1056
+ & to_path,
1057
+ hardlink_tracker,
1058
+ hardlink_scanner,
1059
+ ) ?;
1060
+ }
1061
+ #[ cfg( not( unix) ) ]
1062
+ {
1063
+ fs:: copy ( & from_path, & to_path) ?;
1064
+ }
1016
1065
}
1017
1066
1018
1067
if let Some ( pb) = progress_bar {
@@ -1025,8 +1074,8 @@ fn copy_dir_contents_with_hardlinks(
1025
1074
Ok ( ( ) )
1026
1075
}
1027
1076
1028
- /// Copy a single file, creating hardlinks if it's part of a hardlink group
1029
- fn copy_file_with_hardlinks (
1077
+ # [ cfg ( unix ) ]
1078
+ fn copy_file_with_hardlinks_helper (
1030
1079
from : & Path ,
1031
1080
to : & Path ,
1032
1081
hardlink_tracker : & mut HardlinkTracker ,
@@ -1035,23 +1084,20 @@ fn copy_file_with_hardlinks(
1035
1084
// Check if this file should be a hardlink to an already-copied file
1036
1085
use crate :: hardlink:: HardlinkOptions ;
1037
1086
let hardlink_options = HardlinkOptions :: default ( ) ;
1038
- #[ cfg( unix) ]
1087
+ // Create a hardlink instead of copying
1088
+ if let Some ( existing_target) =
1089
+ hardlink_tracker. check_hardlink ( from, to, hardlink_scanner, & hardlink_options) ?
1039
1090
{
1040
- // Create a hardlink instead of copying
1041
- if let Some ( existing_target) =
1042
- hardlink_tracker. check_hardlink ( from, to, hardlink_scanner, & hardlink_options) ?
1043
- {
1044
- fs:: hard_link ( & existing_target, to) ?;
1045
- return Ok ( ( ) ) ;
1046
- }
1091
+ fs:: hard_link ( & existing_target, to) ?;
1092
+ return Ok ( ( ) ) ;
1047
1093
}
1048
1094
1049
1095
// Regular file copy
1050
1096
#[ cfg( all( unix, not( any( target_os = "macos" , target_os = "redox" ) ) ) ) ]
1051
1097
{
1052
1098
fs:: copy ( from, to) . and_then ( |_| fsxattr:: copy_xattrs ( & from, & to) ) ?;
1053
1099
}
1054
- #[ cfg( any( target_os = "macos" , target_os = "redox" , not ( unix ) ) ) ]
1100
+ #[ cfg( any( target_os = "macos" , target_os = "redox" ) ) ]
1055
1101
{
1056
1102
fs:: copy ( from, to) ?;
1057
1103
}
@@ -1062,8 +1108,8 @@ fn copy_file_with_hardlinks(
1062
1108
fn rename_file_fallback (
1063
1109
from : & Path ,
1064
1110
to : & Path ,
1065
- hardlink_tracker : & mut HardlinkTracker ,
1066
- hardlink_scanner : & HardlinkGroupScanner ,
1111
+ # [ cfg ( unix ) ] hardlink_tracker : Option < & mut HardlinkTracker > ,
1112
+ # [ cfg ( unix ) ] hardlink_scanner : Option < & HardlinkGroupScanner > ,
1067
1113
) -> io:: Result < ( ) > {
1068
1114
// Remove existing target file if it exists
1069
1115
if to. is_symlink ( ) {
@@ -1084,17 +1130,19 @@ fn rename_file_fallback(
1084
1130
}
1085
1131
1086
1132
// Check if this file is part of a hardlink group and if so, create a hardlink instead of copying
1087
- use crate :: hardlink:: HardlinkOptions ;
1088
- let hardlink_options = HardlinkOptions :: default ( ) ;
1089
- if let Some ( existing_target) =
1090
- hardlink_tracker. check_hardlink ( from, to, hardlink_scanner, & hardlink_options) ?
1133
+ #[ cfg( unix) ]
1091
1134
{
1092
- // Create a hardlink to the first moved file instead of copying
1093
- #[ cfg( unix) ]
1094
- {
1095
- fs:: hard_link ( & existing_target, to) ?;
1096
- fs:: remove_file ( from) ?;
1097
- return Ok ( ( ) ) ;
1135
+ if let ( Some ( tracker) , Some ( scanner) ) = ( hardlink_tracker, hardlink_scanner) {
1136
+ use crate :: hardlink:: HardlinkOptions ;
1137
+ let hardlink_options = HardlinkOptions :: default ( ) ;
1138
+ if let Some ( existing_target) =
1139
+ tracker. check_hardlink ( from, to, scanner, & hardlink_options) ?
1140
+ {
1141
+ // Create a hardlink to the first moved file instead of copying
1142
+ fs:: hard_link ( & existing_target, to) ?;
1143
+ fs:: remove_file ( from) ?;
1144
+ return Ok ( ( ) ) ;
1145
+ }
1098
1146
}
1099
1147
}
1100
1148
0 commit comments