diff --git a/README.md b/README.md index c21a75013..ef7a50645 100644 --- a/README.md +++ b/README.md @@ -297,6 +297,8 @@ Currently, the `@compat` macro supports the following syntaxes: * `Compat.qr` takes `pivot` as a `Val` _instance_ ([#22475]). +* `Compat.Sys.which` and `Compat.Sys.isexecutable` ([#26559], [#27298]). + * `Compat.rmul!` provides a subset of the functionality of `LinearAlgebra.rmul!` for use with Julia 0.6 ([#25701], [#25812]). @@ -636,8 +638,10 @@ includes this fix. Find the minimum version from there. [#26436]: https://github.com/JuliaLang/julia/issues/26436 [#26442]: https://github.com/JuliaLang/julia/issues/26442 [#26486]: https://github.com/JuliaLang/julia/issues/26486 +[#26559]: https://github.com/JuliaLang/julia/issues/26559 [#26660]: https://github.com/JuliaLang/julia/issues/26660 [#26670]: https://github.com/JuliaLang/julia/issues/26670 [#26850]: https://github.com/JuliaLang/julia/issues/26850 [#27077]: https://github.com/JuliaLang/julia/issues/27077 -[#27258]: https://github.com/JuliaLang/julia/issues/27258 \ No newline at end of file +[#27258]: https://github.com/JuliaLang/julia/issues/27258 +[#27298]: https://github.com/JuliaLang/julia/issues/27298 diff --git a/src/Compat.jl b/src/Compat.jl index b7c056d1e..e3d90ebcc 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -453,6 +453,54 @@ module Sys import Base.Sys: isapple, isbsd, islinux, isunix, iswindows end + @static if VERSION < v"0.7.0-DEV.5171" + function isexecutable(path::AbstractString) + if iswindows() + isfile(path) + else + ccall(:access, Cint, (Ptr{UInt8}, Cint), path, 0x01) == 0 + end + end + + function which(program::AbstractString) + progs = String[] + base = basename(program) + if iswindows() + isempty(last(splitext(base))) || push!(progs, base) + for p = [".exe", ".com"] + push!(progs, base * p) + end + else + push!(progs, base) + end + dirs = String[] + dir = dirname(program) + if isempty(dir) + pathsep = iswindows() ? ';' : ':' + append!(dirs, map(abspath, split(get(ENV, "PATH", ""), pathsep))) + iswindows() && pushfirst!(dirs, pwd()) + else + push!(dirs, abspath(dir)) + end + for d in dirs, p in progs + path = joinpath(d, p) + isexecutable(path) && return realpath(path) + end + nothing + end + elseif VERSION < v"0.7.0-alpha.6" + import Base.Sys: isexecutable + + which(program::AbstractString) = try + Base.Sys.which(program) + catch err + err isa ErrorException || rethrow(err) + nothing + end + else + import Base.Sys: which, isexecutable + end + # https://github.com/JuliaLang/julia/pull/25102 # NOTE: This needs to be in an __init__ because JULIA_HOME is not # defined when building system images. diff --git a/test/runtests.jl b/test/runtests.jl index 948a12ffb..aa1bee14b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1749,4 +1749,14 @@ end @test something(Some(2), 1) === 2 @test something(nothing, Some(1)) === 1 +# 0.7.0-DEV.5171 +let sep = Compat.Sys.iswindows() ? ';' : ':' + withenv("PATH" => string(Compat.Sys.BINDIR, sep, get(ENV, "PATH", ""))) do + jl = joinpath(Compat.Sys.BINDIR, "julia") * (Compat.Sys.iswindows() ? ".exe" : "") + @test Compat.Sys.which("julia") == realpath(jl) + @test Compat.Sys.isexecutable(jl) + @test Compat.Sys.which("reallyseriouslynotathingyoushouldhave") === nothing + end +end + nothing