Skip to content

Commit fc02458

Browse files
belamensomusmvtjnash
authored
Fix #31368: joinpath works on collections of paths (#38263)
* Fix #31368: joinpath works on collections of paths * Update base/path.jl Co-authored-by: Jameson Nash <vtjnash@gmail.com> * Apply suggestions from code review * Fixup Co-authored-by: Mustafa M <mus-m@outlook.com> Co-authored-by: Jameson Nash <vtjnash@gmail.com>
1 parent 15a44e9 commit fc02458

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

base/path.jl

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,19 @@ function splitpath(p::String)
254254
return out
255255
end
256256

257-
joinpath(path::AbstractString)::String = path
258-
259257
if Sys.iswindows()
260258

261-
function joinpath(path::AbstractString, paths::AbstractString...)::String
262-
result_drive, result_path = splitdrive(path)
259+
function joinpath(paths::Union{Tuple, AbstractVector})::String
260+
assertstring(x) = x isa AbstractString || throw(ArgumentError("path component is not a string: $(repr(x))"))
261+
262+
isempty(paths) && throw(ArgumentError("collection of path components must be non-empty"))
263+
assertstring(paths[1])
264+
result_drive, result_path = splitdrive(paths[1])
263265

264-
local p_drive, p_path
265-
for p in paths
266-
p_drive, p_path = splitdrive(p)
266+
p_path = ""
267+
for i in firstindex(paths)+1:lastindex(paths)
268+
assertstring(paths[i])
269+
p_drive, p_path = splitdrive(paths[i])
267270

268271
if startswith(p_path, ('\\', '/'))
269272
# second path is absolute
@@ -299,8 +302,15 @@ end
299302

300303
else
301304

302-
function joinpath(path::AbstractString, paths::AbstractString...)::String
303-
for p in paths
305+
function joinpath(paths::Union{Tuple, AbstractVector})::String
306+
assertstring(x) = x isa AbstractString || throw(ArgumentError("path component is not a string: $(repr(x))"))
307+
308+
isempty(paths) && throw(ArgumentError("collection of path components must be non-empty"))
309+
assertstring(paths[1])
310+
path = paths[1]
311+
for i in firstindex(paths)+1:lastindex(paths)
312+
p = paths[i]
313+
assertstring(p)
304314
if isabspath(p)
305315
path = p
306316
elseif isempty(path) || path[end] == '/'
@@ -314,8 +324,12 @@ end
314324

315325
end # os-test
316326

327+
joinpath(paths::AbstractString...)::String = joinpath(paths)
328+
317329
"""
318330
joinpath(parts::AbstractString...) -> String
331+
joinpath(parts::Vector{AbstractString}) -> String
332+
joinpath(parts::Tuple{AbstractString}) -> String
319333
320334
Join path components into a full path. If some argument is an absolute path or
321335
(on Windows) has a drive specification that doesn't match the drive computed for
@@ -331,6 +345,11 @@ letter casing, hence `joinpath("C:\\A","c:b") = "C:\\A\\b"`.
331345
julia> joinpath("/home/myuser", "example.jl")
332346
"/home/myuser/example.jl"
333347
```
348+
349+
```jldoctest
350+
julia> joinpath(["/home/myuser", "example.jl"])
351+
"/home/myuser/example.jl"
352+
```
334353
"""
335354
joinpath
336355

test/path.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@
5959
@test joinpath(S("foo"), S(homedir())) == homedir()
6060
@test joinpath(S(abspath("foo")), S(homedir())) == homedir()
6161

62+
for str in map(S, [sep, "a$(sep)b", "a$(sep)b$(sep)c", "a$(sep)b$(sep)c$(sep)d"])
63+
@test str == joinpath(splitpath(str))
64+
@test joinpath(splitpath(str)) == joinpath(splitpath(str)...)
65+
end
66+
6267
if Sys.iswindows()
6368
@test joinpath(S("foo"),S("bar:baz")) == "bar:baz"
6469
@test joinpath(S("C:"),S("foo"),S("D:"),S("bar")) == "D:bar"
@@ -75,6 +80,11 @@
7580
@test joinpath(S("\\\\server\\share"),S("a")) == "\\\\server\\share\\a"
7681
@test joinpath(S("\\\\server\\share\\"), S("a")) == "\\\\server\\share\\a"
7782

83+
for str in map(S, ["c:\\", "c:\\a", "c:\\a\\b", "c:\\a\\b\\c", "c:\\a\\b\\c\\d"])
84+
@test str == joinpath(splitpath(str))
85+
@test joinpath(splitpath(str)) == joinpath(splitpath(str)...)
86+
end
87+
7888
elseif Sys.isunix()
7989
@test joinpath(S("foo"),S("bar:baz")) == "foo$(sep)bar:baz"
8090
@test joinpath(S("C:"),S("foo"),S("D:"),S("bar")) == "C:$(sep)foo$(sep)D:$(sep)bar"

0 commit comments

Comments
 (0)