Skip to content

Commit adb3ab7

Browse files
committed
Add Sys.which and Sys.isexecutable
1 parent c5527e9 commit adb3ab7

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ Currently, the `@compat` macro supports the following syntaxes:
301301

302302
* `squeeze` with `dims` as keyword argument ([#26660]).
303303

304+
* `Compat.Sys.which` and `Compat.Sys.isexecutable` ([#26559]).
305+
304306
* `Compat.qr` takes `pivot` as a `Val` _instance_ and keyword argument `full` ([#22475], [#24279]).
305307

306308
* `Compat.rmul!` provides a subset of the functionality of `LinearAlgebra.rmul!` for
@@ -637,6 +639,7 @@ includes this fix. Find the minimum version from there.
637639
[#26369]: https://github.com/JuliaLang/julia/issues/26369
638640
[#26436]: https://github.com/JuliaLang/julia/issues/26436
639641
[#26442]: https://github.com/JuliaLang/julia/issues/26442
642+
[#26559]: https://github.com/JuliaLang/julia/issues/26559
640643
[#26660]: https://github.com/JuliaLang/julia/issues/26660
641644
[#26670]: https://github.com/JuliaLang/julia/issues/26670
642645
[#27077]: https://github.com/JuliaLang/julia/issues/27077

src/Compat.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,45 @@ module Sys
492492
import Base.Sys: isapple, isbsd, islinux, isunix, iswindows
493493
end
494494

495+
@static if VERSION < v"0.7.0-DEV.5171"
496+
function isexecutable(path::AbstractString)
497+
if iswindows()
498+
isfile(path)
499+
else
500+
ccall(:access, Cint, (Ptr{UInt8}, Cint), path, 0x01) == 0
501+
end
502+
end
503+
504+
function which(program::AbstractString)
505+
progs = String[]
506+
base = basename(program)
507+
if iswindows()
508+
isempty(last(splitext(base))) || push!(progs, base)
509+
for p = [".exe", ".com"]
510+
push!(progs, base * p)
511+
end
512+
else
513+
push!(progs, base)
514+
end
515+
dirs = String[]
516+
dir = dirname(program)
517+
if isempty(dir)
518+
pathsep = iswindows() ? ';' : ':'
519+
append!(dirs, map(abspath, split(get(ENV, "PATH", ""), pathsep)))
520+
iswindows() && pushfirst!(dirs, pwd())
521+
else
522+
push!(dirs, abspath(dir))
523+
end
524+
for d in dirs, p in progs
525+
path = joinpath(d, p)
526+
isexecutable(path) && return realpath(path)
527+
end
528+
error("$program not found")
529+
end
530+
else
531+
import Base.Sys: which, isexecutable
532+
end
533+
495534
# https://github.com/JuliaLang/julia/pull/25102
496535
# NOTE: This needs to be in an __init__ because JULIA_HOME is not
497536
# defined when building system images.

test/runtests.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,4 +1757,14 @@ end
17571757
@test isletter('β')
17581758
@test !isletter('3')
17591759

1760+
# 0.7.0-DEV.5171
1761+
let sep = Compat.Sys.iswindows() ? ';' : ':'
1762+
withenv("PATH" => string(Compat.Sys.BINDIR, sep, get(ENV, "PATH", ""))) do
1763+
jl = joinpath(Compat.Sys.BINDIR, "julia") * (Compat.Sys.iswindows() ? ".exe" : "")
1764+
@test Compat.Sys.which("julia") == realpath(jl)
1765+
@test Compat.Sys.isexecutable(jl)
1766+
@test_throws ErrorException Compat.Sys.which("reallyseriouslynotathingyoushouldhave")
1767+
end
1768+
end
1769+
17601770
nothing

0 commit comments

Comments
 (0)