@@ -298,11 +298,41 @@ end
298298
299299# Used by Pkg but not used in loading itself
300300function find_package (arg)
301- pkg = identify_package (arg)
302- pkg === nothing && return nothing
303- return locate_package (pkg)
301+ pkgenv = identify_package_env (arg)
302+ pkgenv === nothing && return nothing
303+ pkg, env = pkgenv
304+ return locate_package (pkg, env)
304305end
305306
307+ """
308+ Base.identify_package_env(name::String)::Union{Tuple{PkgId, String}, Nothing}
309+ Base.identify_package_env(where::Union{Module,PkgId}, name::String)::Union{Tuple{PkgId, String} Nothing}
310+
311+ Same as [`Base.identify_package`](@ref) except that the path to the environment where the package is identified
312+ is also returned.
313+ """
314+ identify_package_env (where :: Module , name:: String ) = identify_package_env (PkgId (where ), name)
315+ function identify_package_env (where :: PkgId , name:: String )
316+ where . name === name && return where , nothing
317+ where . uuid === nothing && return identify_package_env (name) # ignore `where`
318+ for env in load_path ()
319+ pkgid = manifest_deps_get (env, where , name)
320+ pkgid === nothing && continue # not found--keep looking
321+ pkgid. uuid === nothing || return pkgid, env # found in explicit environment--use it
322+ return nothing # found in implicit environment--return "not found"
323+ end
324+ return nothing
325+ end
326+ function identify_package_env (name:: String )
327+ for env in load_path ()
328+ uuid = project_deps_get (env, name)
329+ uuid === nothing || return uuid, env # found--return it
330+ end
331+ return nothing
332+ end
333+
334+ _nothing_or_first (x) = x === nothing ? nothing : first (x)
335+
306336"""
307337 Base.identify_package(name::String)::Union{PkgId, Nothing}
308338 Base.identify_package(where::Union{Module,PkgId}, name::String)::Union{PkgId, Nothing}
@@ -329,25 +359,10 @@ julia> Base.identify_package(LinearAlgebra, "Pkg") # Pkg is not a dependency of
329359
330360````
331361"""
332- identify_package (where :: Module , name:: String ) = identify_package (PkgId (where ), name)
333- function identify_package (where :: PkgId , name:: String ):: Union{Nothing,PkgId}
334- where . name === name && return where
335- where . uuid === nothing && return identify_package (name) # ignore `where`
336- for env in load_path ()
337- pkgid = manifest_deps_get (env, where , name)
338- pkgid === nothing && continue # not found--keep looking
339- pkgid. uuid === nothing || return pkgid # found in explicit environment--use it
340- return nothing # found in implicit environment--return "not found"
341- end
342- return nothing
343- end
344- function identify_package (name:: String ):: Union{Nothing,PkgId}
345- for env in load_path ()
346- uuid = project_deps_get (env, name)
347- uuid === nothing || return uuid # found--return it
348- end
349- return nothing
350- end
362+ identify_package (where :: Module , name:: String ) = _nothing_or_first (identify_package_env (where , name))
363+ identify_package (where :: PkgId , name:: String ) = _nothing_or_first (identify_package_env (where , name))
364+ identify_package (name:: String ) = _nothing_or_first (identify_package_env (name))
365+
351366
352367"""
353368 Base.locate_package(pkg::PkgId)::Union{String, Nothing}
@@ -363,7 +378,7 @@ julia> Base.locate_package(pkg)
363378"/path/to/julia/stdlib/v$(VERSION . major) .$(VERSION . minor) /Pkg/src/Pkg.jl"
364379```
365380"""
366- function locate_package (pkg:: PkgId ):: Union{Nothing,String}
381+ function locate_package (pkg:: PkgId , stopenv :: Union{String, Nothing} = nothing ):: Union{Nothing,String}
367382 if pkg. uuid === nothing
368383 for env in load_path ()
369384 # look for the toplevel pkg `pkg.name` in this entry
@@ -377,16 +392,20 @@ function locate_package(pkg::PkgId)::Union{Nothing,String}
377392 return implicit_manifest_uuid_path (env, pkg)
378393 end
379394 end
395+ stopenv == env && return nothing
380396 end
381397 else
382398 for env in load_path ()
383399 path = manifest_uuid_path (env, pkg)
400+ # missing is used as a sentinel to stop looking further down in envs
401+ path === missing && return nothing
384402 path === nothing || return entry_path (path, pkg. name)
403+ stopenv == env && break
385404 end
386405 # Allow loading of stdlibs if the name/uuid are given
387406 # e.g. if they have been explicitly added to the project/manifest
388407 path = manifest_uuid_path (Sys. STDLIB, pkg)
389- path === nothing || return entry_path (path, pkg. name)
408+ path isa String && return entry_path (path, pkg. name)
390409 end
391410 return nothing
392411end
@@ -539,7 +558,7 @@ function manifest_deps_get(env::String, where::PkgId, name::String)::Union{Nothi
539558 return nothing
540559end
541560
542- function manifest_uuid_path (env:: String , pkg:: PkgId ):: Union{Nothing,String}
561+ function manifest_uuid_path (env:: String , pkg:: PkgId ):: Union{Nothing,String,Missing }
543562 project_file = env_project_file (env)
544563 if project_file isa String
545564 proj = project_file_name_uuid (project_file, pkg. name)
@@ -730,7 +749,7 @@ function explicit_manifest_deps_get(project_file::String, where::UUID, name::Str
730749end
731750
732751# find `uuid` stanza, return the corresponding path
733- function explicit_manifest_uuid_path (project_file:: String , pkg:: PkgId ):: Union{Nothing,String}
752+ function explicit_manifest_uuid_path (project_file:: String , pkg:: PkgId ):: Union{Nothing,String,Missing }
734753 manifest_file = project_file_manifest_path (project_file)
735754 manifest_file === nothing && return nothing # no manifest, skip env
736755
@@ -765,7 +784,8 @@ function explicit_manifest_entry_path(manifest_file::String, pkg::PkgId, entry::
765784 ispath (path) && return abspath (path)
766785 end
767786 end
768- return nothing
787+ # no depot contains the package, return missing to stop looking
788+ return missing
769789end
770790
771791# # implicit project & manifest API ##
@@ -1204,9 +1224,9 @@ function require(into::Module, mod::Symbol)
12041224 @lock require_lock begin
12051225 LOADING_CACHE[] = LoadingCache ()
12061226 try
1207- uuidkey = identify_package (into, String (mod))
1208- # Core.println("require($(PkgId(into)), $mod) -> $uuidkey")
1209- if uuidkey === nothing
1227+ uuidkey_env = identify_package_env (into, String (mod))
1228+ # Core.println("require($(PkgId(into)), $mod) -> $uuidkey from env \"$env\" ")
1229+ if uuidkey_env === nothing
12101230 where = PkgId (into)
12111231 if where . uuid === nothing
12121232 hint, dots = begin
@@ -1234,10 +1254,11 @@ function require(into::Module, mod::Symbol)
12341254 - Otherwise you may need to report an issue with $(where . name) """ ))
12351255 end
12361256 end
1257+ uuidkey, env = uuidkey_env
12371258 if _track_dependencies[]
12381259 push! (_require_dependencies, (into, binpack (uuidkey), 0.0 ))
12391260 end
1240- return _require_prelocked (uuidkey)
1261+ return _require_prelocked (uuidkey, env )
12411262 finally
12421263 LOADING_CACHE[] = nothing
12431264 end
@@ -1254,10 +1275,10 @@ const pkgorigins = Dict{PkgId,PkgOrigin}()
12541275
12551276require (uuidkey:: PkgId ) = @lock require_lock _require_prelocked (uuidkey)
12561277
1257- function _require_prelocked (uuidkey:: PkgId )
1278+ function _require_prelocked (uuidkey:: PkgId , env = nothing )
12581279 assert_havelock (require_lock)
12591280 if ! root_module_exists (uuidkey)
1260- newm = _require (uuidkey)
1281+ newm = _require (uuidkey, env )
12611282 if newm === nothing
12621283 error (" package `$(uuidkey. name) ` did not define the expected \
12631284 module `$(uuidkey. name) `, check for typos in package module name" )
@@ -1349,7 +1370,7 @@ function set_pkgorigin_version_path(pkg::PkgId, path::Union{String,Nothing})
13491370end
13501371
13511372# Returns `nothing` or the new(ish) module
1352- function _require (pkg:: PkgId )
1373+ function _require (pkg:: PkgId , env = nothing )
13531374 assert_havelock (require_lock)
13541375 # handle recursive calls to require
13551376 loading = get (package_locks, pkg, false )
@@ -1364,7 +1385,7 @@ function _require(pkg::PkgId)
13641385 try
13651386 toplevel_load[] = false
13661387 # perform the search operation to select the module file require intends to load
1367- path = locate_package (pkg)
1388+ path = locate_package (pkg, env )
13681389 if path === nothing
13691390 throw (ArgumentError ("""
13701391 Package $pkg is required but does not seem to be installed:
0 commit comments