Skip to content
This repository has been archived by the owner on Aug 16, 2023. It is now read-only.

Commit

Permalink
Add withenv(), remove activate() and deactivate()
Browse files Browse the repository at this point in the history
  • Loading branch information
staticfloat committed Sep 20, 2018
1 parent e6cfe4c commit 799dc4d
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 90 deletions.
1 change: 0 additions & 1 deletion src/BinaryProvider.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ function __init__()

# Initialize our global_prefix
global_prefix = Prefix(joinpath(dirname(@__FILE__), "../", "global_prefix"))
activate(global_prefix)

# Find the right download/compression engines for this platform
probe_platform_engines!()
Expand Down
94 changes: 23 additions & 71 deletions src/Prefix.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## This file contains functionality related to the actual layout of the files
# on disk. Things like the name of where downloads are stored, and what
# environment variables must be updated to, etc...
import Base: convert, joinpath, show
import Base: convert, joinpath, show, withenv
using SHA

export Prefix, bindir, libdir, includedir, logdir, activate, deactivate,
Expand Down Expand Up @@ -92,33 +92,35 @@ joinpath(s::AbstractString, prefix::Prefix, args...) = joinpath(s, prefix.path,
convert(::Type{AbstractString}, prefix::Prefix) = prefix.path
show(io::IO, prefix::Prefix) = show(io, "Prefix($(prefix.path))")

"""
split_PATH(PATH::AbstractString = ENV["PATH"])

Splits a string such as the `PATH` environment variable into a list of strings
according to the path separation rules for the current platform.
"""
function split_PATH(PATH::AbstractString = ENV["PATH"])
@static if Sys.iswindows()
return split(PATH, ";")
else
return split(PATH, ":")
end
end
withenv(f::Function, prefixes::Vector{Prefix})
Wrapper function designed to help executables find dynamic libraries and child
binaries by wrapping PATH and (DY)LD_LIBRARY_PATH.
"""
join_PATH(PATH::Vector{AbstractString})
function withenv(f::Function, prefixes::Vector{Prefix})
# Join `dirs` to ENV[key], removing duplicates and nonexistent directories
# as we go, normalizing directory names, splitting and joining by `sep`.
function joinenv(key, dirs, sep)
value = [dirs..., split(get(ENV, key, ""), sep)...]
return join([abspath(d) for d in value if isdir(d)], sep)
end
# We're going to build up PATH and {DY,}LD_LIBRARY_PATH such that binaries
# that use things from the given prefixes can function properly.
sep = Sys.iswindows() ? ";" : ":"
mapping = ["PATH" => joinenv("PATH", bindir.(prefixes), sep)]

Given a list of strings, return a joined string suitable for the `PATH`
environment variable appropriate for the current platform.
"""
function join_PATH(paths::Vector{S}) where S<:AbstractString
@static if Sys.iswindows()
return join(paths, ";")
else
return join(paths, ":")
# {DY,}LD_LIBRARY_PATH only makes sense on non-windows
if !Sys.iswindows()
envname = Sys.isapple() ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH"
push!(mapping, envname => joinenv(envname, libdir.(prefixes), ":"))
end

# Use withenv to apply the calculated environment mappings to f.
return withenv(f, mapping...)
end
withenv(f::Function, prefix::Prefix) = withenv(f, [prefix])

"""
bindir(prefix::Prefix)
Expand Down Expand Up @@ -161,56 +163,6 @@ function logdir(prefix::Prefix)
return joinpath(prefix, "logs")
end

"""
activate(prefix::Prefix)
Prepends paths to environment variables so that binaries and libraries are
available to Julia.
"""
function activate(prefix::Prefix)
# Add to PATH
paths = split_PATH()
if !(bindir(prefix) in paths)
prepend!(paths, [bindir(prefix)])
end
ENV["PATH"] = join_PATH(paths)

# Add to DL_LOAD_PATH
if !(libdir(prefix) in Libdl.DL_LOAD_PATH)
prepend!(Libdl.DL_LOAD_PATH, [libdir(prefix)])
end
return nothing
end

"""
activate(func::Function, prefix::Prefix)
Prepends paths to environment variables so that binaries and libraries are
available to Julia, calls the user function `func`, then `deactivate()`'s
the `prefix`` again.
"""
function activate(func::Function, prefix::Prefix)
activate(prefix)
func()
deactivate(prefix)
end

"""
deactivate(prefix::Prefix)
Removes paths added to environment variables by `activate()`
"""
function deactivate(prefix::Prefix)
# Remove from PATH
paths = split_PATH()
filter!(p -> p != bindir(prefix), paths)
ENV["PATH"] = join_PATH(paths)

# Remove from DL_LOAD_PATH
filter!(p -> p != libdir(prefix), Libdl.DL_LOAD_PATH)
return nothing
end

"""
extract_platform_key(path::AbstractString)
Expand Down
32 changes: 14 additions & 18 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -343,25 +343,21 @@ end
end
chmod(ppt_path, 0o775)

# Test that activation adds certain paths to our environment variables
activate(prefix)

# PATH[1] should be "<prefix>/bin" now
@test BinaryProvider.split_PATH()[1] == bindir(prefix)
@test Libdl.DL_LOAD_PATH[1] == libdir(prefix)

# Test we can run the script we dropped within this prefix. Once again,
# something about Windows | busybox | Julia won't pick this up even though
# the path clearly points to the file. :(
@static if !Sys.iswindows()
@test success(sh(`$(ppt_path)`))
@test success(sh(`prefix_path_test.sh`))
# Test that our `withenv()` stuff works. :D
withenv(prefix) do
@test startswith(ENV["PATH"], bindir(prefix))

if !Sys.iswindows()
envname = Sys.isapple() ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH"
@test startswith(ENV[envname], libdir(prefix))

# Test we can run the script we dropped within this prefix.
# Once again, something about Windows | busybox | Julia won't
# pick this up even though the path clearly points to the file.
@test success(sh(`$(ppt_path)`))
@test success(sh(`prefix_path_test.sh`))
end
end

# Now deactivate and make sure that all traces are gone
deactivate(prefix)
@test BinaryProvider.split_PATH()[1] != bindir(prefix)
@test Libdl.DL_LOAD_PATH[1] != libdir(prefix)

# Test that we can control libdir() via platform arguments
@test libdir(prefix, Linux(:x86_64)) == joinpath(prefix, "lib")
Expand Down

0 comments on commit 799dc4d

Please sign in to comment.