@@ -823,6 +823,303 @@ mktempdir() do tmpdir
823
823
rm (b_tmpdir)
824
824
end
825
825
826
+ @testset " rename" begin
827
+ # some of the windows specific behavior may be fixed in new versions of julia
828
+ mktempdir () do dir
829
+ # see if can make symlinks
830
+ local can_symlink = try
831
+ symlink (" foo" , joinpath (dir, " link" ))
832
+ rm (joinpath (dir, " link" ))
833
+ true
834
+ catch
835
+ false
836
+ end
837
+ local f1 = joinpath (dir, " file1" )
838
+ local f2 = joinpath (dir, " file2" )
839
+ local d1 = joinpath (dir, " dir1" )
840
+ local d2 = joinpath (dir, " dir2" )
841
+ local subd1f1 = joinpath (d1, " file1" )
842
+ local subd1f2 = joinpath (d1, " file2" )
843
+ local subd2f1 = joinpath (d2, " file1" )
844
+ local subd2f2 = joinpath (d2, " file2" )
845
+ local h1 = joinpath (dir, " hlink1" )
846
+ local h2 = joinpath (dir, " hlink2" )
847
+ local s1 = joinpath (dir, " slink1" )
848
+ local s2 = joinpath (dir, " slink2" )
849
+ @testset " renaming to non existing newpath in same directory" begin
850
+ # file, make sure isexecutable is copied
851
+ for mode in (0o644 , 0o755 )
852
+ write (f1, b " data" )
853
+ chmod (f1, mode)
854
+ Base. rename (f1, f2)
855
+ @test ! isfile (f1)
856
+ @test isfile (f2)
857
+ @test read (f2) == b " data"
858
+ if mode == 0o644
859
+ @test ! isexecutable (f2)
860
+ else
861
+ @test isexecutable (f2)
862
+ end
863
+ rm (f2)
864
+ end
865
+ # empty directory
866
+ mkdir (d1)
867
+ Base. rename (d1, d2)
868
+ @test ! isdir (d1)
869
+ @test isdir (d2)
870
+ @test isempty (readdir (d2))
871
+ rm (d2)
872
+ # non empty directory
873
+ mkdir (d1)
874
+ write (subd1f1, b " data" )
875
+ chmod (subd1f1, 0o644 )
876
+ write (subd1f2, b " exe" )
877
+ chmod (subd1f2, 0o755 )
878
+ Base. rename (d1, d2)
879
+ @test ! isdir (d1)
880
+ @test isdir (d2)
881
+ @test read (subd2f1) == b " data"
882
+ @test read (subd2f2) == b " exe"
883
+ @test ! isexecutable (subd2f1)
884
+ @test isexecutable (subd2f2)
885
+ rm (d2; recursive= true )
886
+ # hardlink
887
+ write (f1, b " data" )
888
+ hardlink (f1, h1)
889
+ Base. rename (h1, h2)
890
+ @test isfile (f1)
891
+ @test ! isfile (h1)
892
+ @test isfile (h2)
893
+ @test read (h2) == b " data"
894
+ write (h2, b " data2" )
895
+ @test read (f1) == b " data2"
896
+ rm (h2)
897
+ rm (f1)
898
+ # symlink
899
+ if can_symlink
900
+ symlink (" foo" , s1)
901
+ Base. rename (s1, s2)
902
+ @test ! islink (s1)
903
+ @test islink (s2)
904
+ @test readlink (s2) == " foo"
905
+ rm (s2)
906
+ end
907
+ end
908
+ @test isempty (readdir (dir)) # make sure everything got cleaned up
909
+
910
+ # Get the error code from failed rename, or nothing if it worked
911
+ function rename_errorcodes (oldpath, newpath)
912
+ try
913
+ Base. rename (oldpath, newpath)
914
+ nothing
915
+ catch e
916
+ e. code
917
+ end
918
+ end
919
+ @testset " errors" begin
920
+ # invalid paths
921
+ @test_throws ArgumentError Base. rename (f1* " \0 " , " " )
922
+ @test Base. UV_ENOENT == rename_errorcodes (" " , " " )
923
+ write (f1, b " data" )
924
+ @test Base. UV_ENOENT == rename_errorcodes (f1, " " )
925
+ @test read (f1) == b " data"
926
+ @test Base. UV_ENOENT == rename_errorcodes (" " , f1)
927
+ @test read (f1) == b " data"
928
+ @test Base. UV_ENOENT == rename_errorcodes (f2, f1)
929
+ @test read (f1) == b " data"
930
+ @test Base. UV_ENOENT == rename_errorcodes (f1, subd1f1)
931
+ @test read (f1) == b " data"
932
+ rm (f1)
933
+ # attempt to make a directory a subdirectory of itself
934
+ mkdir (d1)
935
+ if Sys. iswindows ()
936
+ @test rename_errorcodes (d1, joinpath (d1, " subdir" )) ∈ (Base. UV_EINVAL, Base. UV_EBUSY)
937
+ else
938
+ @test Base. UV_EINVAL == rename_errorcodes (d1, joinpath (d1, " subdir" ))
939
+ end
940
+ rm (d1)
941
+ # rename to child of a file
942
+ mkdir (d1)
943
+ write (f2, " foo" )
944
+ if Sys. iswindows ()
945
+ @test Base. UV_EINVAL == rename_errorcodes (d1, joinpath (f2, " subdir" ))
946
+ else
947
+ @test Base. UV_ENOTDIR == rename_errorcodes (d1, joinpath (f2, " subdir" ))
948
+ end
949
+ # replace a file with a directory
950
+ if ! Sys. iswindows ()
951
+ @test Base. UV_ENOTDIR == rename_errorcodes (d1, f2)
952
+ else
953
+ # this should work on windows
954
+ Base. rename (d1, f2)
955
+ @test isdir (f2)
956
+ @test ! ispath (d1)
957
+ end
958
+ rm (f2; force= true )
959
+ rm (d1; force= true )
960
+ # symlink loop
961
+ if can_symlink
962
+ symlink (s1, s2)
963
+ symlink (s2, s1)
964
+ @test Base. UV_ELOOP == rename_errorcodes (joinpath (s1, " foo" ), f2)
965
+ write (f2, b " data" )
966
+ @test Base. UV_ELOOP == rename_errorcodes (f2, joinpath (s1, " foo" ))
967
+ rm (s1)
968
+ rm (s2)
969
+ rm (f2)
970
+ end
971
+ # newpath is a nonempty directory
972
+ mkdir (d1)
973
+ mkdir (d2)
974
+ write (subd2f1, b " data" )
975
+ write (f1, b " otherdata" )
976
+ if Sys. iswindows ()
977
+ @test Base. UV_EACCES == rename_errorcodes (f1, d1)
978
+ @test Base. UV_EACCES == rename_errorcodes (f1, d2)
979
+ @test Base. UV_EACCES == rename_errorcodes (d1, d2)
980
+ @test Base. UV_EACCES == rename_errorcodes (subd2f1, d2)
981
+ else
982
+ @test Base. UV_EISDIR == rename_errorcodes (f1, d1)
983
+ @test Base. UV_EISDIR == rename_errorcodes (f1, d2)
984
+ @test rename_errorcodes (d1, d2) ∈ (Base. UV_ENOTEMPTY, Base. UV_EEXIST)
985
+ @test rename_errorcodes (subd2f1, d2) ∈ (Base. UV_ENOTEMPTY, Base. UV_EEXIST, Base. UV_EISDIR)
986
+ end
987
+ rm (f1)
988
+ rm (d1)
989
+ rm (d2; recursive= true )
990
+ end
991
+ @test isempty (readdir (dir)) # make sure everything got cleaned up
992
+
993
+ @testset " replacing existing file" begin
994
+ write (f2, b " olddata" )
995
+ chmod (f2, 0o755 )
996
+ write (f1, b " newdata" )
997
+ chmod (f1, 0o644 )
998
+ @test isexecutable (f2)
999
+ @test ! isexecutable (f1)
1000
+ Base. rename (f1, f2)
1001
+ @test ! ispath (f1)
1002
+ @test read (f2) == b " newdata"
1003
+ @test ! isexecutable (f2)
1004
+ rm (f2)
1005
+ end
1006
+
1007
+ @testset " replacing file with itself" begin
1008
+ write (f1, b " data" )
1009
+ Base. rename (f1, f1)
1010
+ @test read (f1) == b " data"
1011
+ hardlink (f1, h1)
1012
+ Base. rename (f1, h1)
1013
+ if Sys. iswindows ()
1014
+ # On Windows f1 gets deleted
1015
+ @test ! ispath (f1)
1016
+ else
1017
+ @test read (f1) == b " data"
1018
+ end
1019
+ @test read (h1) == b " data"
1020
+ rm (h1)
1021
+ rm (f1; force= true )
1022
+ end
1023
+
1024
+ @testset " replacing existing file in different directories" begin
1025
+ mkdir (d1)
1026
+ mkdir (d2)
1027
+ write (subd2f2, b " olddata" )
1028
+ chmod (subd2f2, 0o755 )
1029
+ write (subd1f1, b " newdata" )
1030
+ chmod (subd1f1, 0o644 )
1031
+ @test isexecutable (subd2f2)
1032
+ @test ! isexecutable (subd1f1)
1033
+ Base. rename (subd1f1, subd2f2)
1034
+ @test ! ispath (subd1f1)
1035
+ @test read (subd2f2) == b " newdata"
1036
+ @test ! isexecutable (subd2f2)
1037
+ @test isdir (d1)
1038
+ @test isdir (d2)
1039
+ rm (d1; recursive= true )
1040
+ rm (d2; recursive= true )
1041
+ end
1042
+
1043
+ @testset " rename with open files" begin
1044
+ # both open
1045
+ write (f2, b " olddata" )
1046
+ write (f1, b " newdata" )
1047
+ open (f1) do handle1
1048
+ open (f2) do handle2
1049
+ if Sys. iswindows ()
1050
+ # currently this doesn't work on windows
1051
+ @test Base. UV_EBUSY == rename_errorcodes (f1, f2)
1052
+ else
1053
+ Base. rename (f1, f2)
1054
+ @test ! ispath (f1)
1055
+ @test read (f2) == b " newdata"
1056
+ end
1057
+ # rename doesn't break already opened files
1058
+ @test read (handle1) == b " newdata"
1059
+ @test read (handle2) == b " olddata"
1060
+ end
1061
+ end
1062
+ rm (f1; force= true )
1063
+ rm (f2; force= true )
1064
+
1065
+ # oldpath open
1066
+ write (f2, b " olddata" )
1067
+ write (f1, b " newdata" )
1068
+ open (f1) do handle1
1069
+ if Sys. iswindows ()
1070
+ # currently this doesn't work on windows
1071
+ @test Base. UV_EBUSY == rename_errorcodes (f1, f2)
1072
+ else
1073
+ Base. rename (f1, f2)
1074
+ @test ! ispath (f1)
1075
+ @test read (f2) == b " newdata"
1076
+ end
1077
+ # rename doesn't break already opened files
1078
+ @test read (handle1) == b " newdata"
1079
+ end
1080
+ rm (f1; force= true )
1081
+ rm (f2; force= true )
1082
+
1083
+ # newpath open
1084
+ write (f2, b " olddata" )
1085
+ write (f1, b " newdata" )
1086
+ open (f2) do handle2
1087
+ if Sys. iswindows ()
1088
+ # currently this doesn't work on windows
1089
+ @test Base. UV_EACCES == rename_errorcodes (f1, f2)
1090
+ else
1091
+ Base. rename (f1, f2)
1092
+ @test ! ispath (f1)
1093
+ @test read (f2) == b " newdata"
1094
+ end
1095
+ # rename doesn't break already opened files
1096
+ @test read (handle2) == b " olddata"
1097
+ end
1098
+ rm (f1; force= true )
1099
+ rm (f2; force= true )
1100
+ end
1101
+
1102
+ @testset " replacing empty directory with directory" begin
1103
+ mkdir (d1)
1104
+ mkdir (d2)
1105
+ write (subd1f1, b " data" )
1106
+ if Sys. iswindows ()
1107
+ # currently this doesn't work on windows
1108
+ @test Base. UV_EACCES == rename_errorcodes (d1, d2)
1109
+ rm (d1; recursive= true )
1110
+ rm (d2)
1111
+ else
1112
+ Base. rename (d1, d2)
1113
+ @test isdir (d2)
1114
+ @test read (subd2f1) == b " data"
1115
+ @test ! ispath (d1)
1116
+ rm (d2; recursive= true )
1117
+ end
1118
+ end
1119
+ @test isempty (readdir (dir)) # make sure everything got cleaned up
1120
+ end
1121
+ end
1122
+
826
1123
# issue #10506 #10434
827
1124
# # Tests for directories and links to directories
828
1125
if ! Sys. iswindows () || Sys. windows_version () >= Sys. WINDOWS_VISTA_VER
@@ -1472,7 +1769,7 @@ rm(dir)
1472
1769
1473
1770
1474
1771
# #################
1475
- # Return values of mkpath, mkdir, cp, mv and touch
1772
+ # Return values of mkpath, mkdir, cp, mv, rename and touch
1476
1773
# ###################
1477
1774
mktempdir () do dir
1478
1775
name1 = joinpath (dir, " apples" )
@@ -1489,6 +1786,9 @@ mktempdir() do dir
1489
1786
@test cp (name2, name1) == name1
1490
1787
@test isfile (name1)
1491
1788
@test isfile (name2)
1789
+ @test Base. rename (name1, name2) == name2
1790
+ @test ! ispath (name1)
1791
+ @test isfile (name2)
1492
1792
namedir = joinpath (dir, " chalk" )
1493
1793
namepath = joinpath (dir, " chalk" , " cheese" , " fresh" )
1494
1794
@test ! ispath (namedir)
0 commit comments