diff --git a/base/path.jl b/base/path.jl index 156f1b0999f12..4e602dde4f98d 100644 --- a/base/path.jl +++ b/base/path.jl @@ -495,6 +495,9 @@ contractuser(path::AbstractString) Return a relative filepath to `path` either from the current directory or from an optional start directory. This is a path computation: the filesystem is not accessed to confirm the existence or nature of `path` or `startpath`. + +On Windows, case sensitivity is applied to every part of the path except drive letters. If +`path` and `startpath` refer to different drives, the absolute path of `path` is returned. """ function relpath(path::String, startpath::String = ".") isempty(path) && throw(ArgumentError("`path` must be specified")) @@ -502,8 +505,13 @@ function relpath(path::String, startpath::String = ".") curdir = "." pardir = ".." path == startpath && return curdir - path_arr = split(abspath(path), path_separator_re) - start_arr = split(abspath(startpath), path_separator_re) + path_drive, path_without_drive = splitdrive(path) + startpath_drive, startpath_without_drive = splitdrive(startpath) + path_arr = split(abspath(path_without_drive), path_separator_re) + start_arr = split(abspath(startpath_without_drive), path_separator_re) + if Sys.iswindows() + lowercase(path_drive) != lowercase(startpath_drive) && return abspath(path) + end i = 0 while i < min(length(path_arr), length(start_arr)) i += 1 diff --git a/test/path.jl b/test/path.jl index e09a46ef9370e..bbd9159c59295 100644 --- a/test/path.jl +++ b/test/path.jl @@ -262,6 +262,12 @@ res = relpath(filep, startp) idx += 1 @test res == relpath_expected_results[idx] + if Sys.iswindows() + @test relpath("e:$filep", "e:$startp") == relpath_expected_results[idx] + @test relpath("e:$filep", "E:$startp") == relpath_expected_results[idx] + @test relpath("E:$filep", "e:$startp") == relpath_expected_results[idx] + @test relpath("E:$filep", "E:$startp") == relpath_expected_results[idx] + end end end # Additional cases @@ -271,6 +277,20 @@ test_relpath() end + if Sys.iswindows() + @testset "issue #23646" begin + @test lowercase(relpath("E:\\a\\b", "C:\\c")) == "e:\\a\\b" + @test lowercase(relpath("E:\\a\\b", "c:\\c")) == "e:\\a\\b" + @test lowercase(relpath("e:\\a\\b", "C:\\c")) == "e:\\a\\b" + @test lowercase(relpath("e:\\a\\b", "c:\\c")) == "e:\\a\\b" + + @test relpath("C:\\a\\b", "c:\\a\\b") == "." + @test relpath("c:\\a\\b", "C:\\a\\b") == "." + @test lowercase(relpath("C:\\a\\b", "c:\\c\\d")) == "..\\..\\a\\b" + @test lowercase(relpath("c:\\a\\b", "C:\\c\\d")) == "..\\..\\a\\b" + end + end + @testset "type stability" begin @test isa(joinpath(S("a"), S("b")), String) @test isa(joinpath(S(abspath("a")), S("b")), String)