Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minimal hook into loading needed for Pkg3 (take 2) #20120

Merged
merged 5 commits into from Jan 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion base/REPLCompletions.jl
Expand Up @@ -494,7 +494,7 @@ function completions(string, pos)
s = string[startpos:pos]
if dotpos <= startpos
for dir in [Pkg.dir(); LOAD_PATH; pwd()]
isdir(dir) || continue
dir isa AbstractString && isdir(dir) || continue
for pname in readdir(dir)
if pname[1] != '.' && pname != "METADATA" &&
pname != "REQUIRE" && startswith(pname, s)
Expand Down
18 changes: 15 additions & 3 deletions base/initdefs.jl
Expand Up @@ -30,11 +30,23 @@ isinteractive() = (is_interactive::Bool)
"""
LOAD_PATH

An array of paths (as strings) where the `require` function looks for code.
An array of paths as strings or custom loader objects for the `require`
function and `using` and `import` statements to consider when loading
code. To create a custom loader type, define the type and then add
appropriate methods to the `Base.load_hook` function with the following
signature:

Base.load_hook(loader::Loader, name::String, found::Any)

The `loader` argument is the current value in `LOAD_PATH`, `name` is the
name of the module to load, and `found` is the path of any previously
found code to provide `name`. If no provider has been found earlier in
`LOAD_PATH` then the value of `found` will be `nothing`. Custom loader
functionality is experimental and may break or change in Julia 1.0.
"""
const LOAD_PATH = String[]

const LOAD_PATH = Any[]
const LOAD_CACHE_PATH = String[]

function init_load_path()
vers = "v$(VERSION.major).$(VERSION.minor)"
if haskey(ENV, "JULIA_LOAD_PATH")
Expand Down
31 changes: 19 additions & 12 deletions base/loading.jl
Expand Up @@ -80,19 +80,26 @@ else
end
end

function try_path(prefix::String, base::String, name::String)
path = joinpath(prefix, name)
function load_hook(prefix::String, name::String, ::Void)
name_jl = "$name.jl"
path = joinpath(prefix, name_jl)
isfile_casesensitive(path) && return abspath(path)
path = joinpath(prefix, base, "src", name)
path = joinpath(prefix, name_jl, "src", name_jl)
isfile_casesensitive(path) && return abspath(path)
path = joinpath(prefix, name, "src", name)
path = joinpath(prefix, name, "src", name_jl)
isfile_casesensitive(path) && return abspath(path)
return nothing
end
load_hook(prefix::String, name::String, path::String) = path
load_hook(prefix, name::String, ::Any) =
throw(ArgumentError("unrecognized custom loader in LOAD_PATH: $prefix"))

_str(x::AbstractString) = String(x)
_str(x) = x

# `wd` is a working directory to search. defaults to current working directory.
# if `wd === nothing`, no extra path is searched.
function find_in_path(name::String, wd)
function find_in_path(name::String, wd::Union{Void,String})
isabspath(name) && return name
base = name
if endswith(name,".jl")
Expand All @@ -103,15 +110,15 @@ function find_in_path(name::String, wd)
if wd !== nothing
isfile_casesensitive(joinpath(wd,name)) && return joinpath(wd,name)
end
p = try_path(Pkg.dir(), base, name)
p !== nothing && return p
for prefix in LOAD_PATH
p = try_path(prefix, base, name)
p !== nothing && return p
path = nothing
path = _str(load_hook(_str(Pkg.dir()), base, path))
for dir in LOAD_PATH
path = _str(load_hook(_str(dir), base, path))
end
return nothing
return path
end
find_in_path(name::AbstractString, wd = pwd()) = find_in_path(String(name), wd)
find_in_path(name::AbstractString, wd::AbstractString = pwd()) =
find_in_path(String(name), String(wd))

function find_in_node_path(name::String, srcpath, node::Int=1)
if myid() == node
Expand Down
4 changes: 3 additions & 1 deletion base/pkg/entry.jl
Expand Up @@ -600,9 +600,11 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
# are serialized to errfile for later retrieval into errs[pkg]
errfile = tempname()
close(open(errfile, "w")) # create empty file
# TODO: serialize the same way the load cache does, not with strings
LOAD_PATH = filter(x -> x isa AbstractString, Base.LOAD_PATH)
code = """
empty!(Base.LOAD_PATH)
append!(Base.LOAD_PATH, $(repr(Base.LOAD_PATH)))
append!(Base.LOAD_PATH, $(repr(LOAD_PATH)))
empty!(Base.LOAD_CACHE_PATH)
append!(Base.LOAD_CACHE_PATH, $(repr(Base.LOAD_CACHE_PATH)))
empty!(Base.DL_LOAD_PATH)
Expand Down
135 changes: 0 additions & 135 deletions base/require.jl

This file was deleted.

28 changes: 25 additions & 3 deletions test/loading.jl
Expand Up @@ -40,7 +40,29 @@ mktempdir() do dir
end
end

let paddedname = "Ztest_sourcepath.jl"
filename = SubString(paddedname, 2, length(paddedname))
@test Base.find_in_path(filename) == abspath(paddedname[2:end])
SAVED_LOAD_PATH = copy(LOAD_PATH)
empty!(LOAD_PATH)
dir = abspath(@__DIR__)
push!(LOAD_PATH, dir)

@test Base.find_in_path("test_sourcepath") == joinpath(dir, "test_sourcepath.jl")
@test Base.find_in_path(GenericString("test_sourcepath")) == joinpath(dir, "test_sourcepath.jl")
LOAD_PATH[end] = GenericString(LOAD_PATH[end])
@test Base.find_in_path("test_sourcepath") == joinpath(dir, "test_sourcepath.jl")

immutable CustomLoader
path::String
end
push!(LOAD_PATH, CustomLoader("abc"))
let name = randstring(20)
@test_throws ArgumentError Base.find_in_path(name, nothing)
Base.load_hook(prefix::CustomLoader, name::String, found) = joinpath(prefix.path, name)
@test Base.find_in_path(name, nothing) == joinpath("abc", name)
end
@test Base.find_in_path("test_sourcepath", nothing) == joinpath("abc", "test_sourcepath")
Base.load_hook(prefix::CustomLoader, name::String, found::String) = found
@test Base.find_in_path("test_sourcepath", nothing) == joinpath(dir, "test_sourcepath.jl")

empty!(LOAD_PATH)
append!(LOAD_PATH, SAVED_LOAD_PATH)
@test LOAD_PATH == SAVED_LOAD_PATH