@@ -333,62 +333,56 @@ Same as [`Base.identify_package`](@ref) except that the path to the environment
333333is also returned, except when the identity is not identified.
334334"""
335335identify_package_env (where :: Module , name:: String ) = identify_package_env (PkgId (where ), name)
336- function identify_package_env (where :: PkgId , name:: String )
337- assert_havelock (require_lock)
338- cache = LOADING_CACHE[]
339- if cache != = nothing
340- pkg_env = get (cache. identified_where, (where , name), missing )
341- pkg_env === missing || return pkg_env
342- end
343- pkg_env = nothing
344- if where . name === name
345- return (where , nothing )
346- elseif where . uuid === nothing
347- pkg_env = identify_package_env (name) # ignore `where`
348- else
349- for env in load_path ()
350- pkgid = manifest_deps_get (env, where , name)
351- # If we didn't find `where` at all, keep looking through the environment stack
352- pkgid === nothing && continue
353- if pkgid. uuid != = nothing
354- pkg_env = pkgid, env
355- end
356- # If we don't have pkgid.uuid, still break here - this is a sentinel that indicates
357- # that we've found `where` but it did not have the required dependency. We terminate the search.
358- break
336+ function identify_package_env (where :: Union{PkgId, Nothing} , name:: String )
337+ # Special cases
338+ if where != = nothing
339+ if where . name === name
340+ # Project tries to load itself
341+ return (where , nothing )
342+ elseif where . uuid === nothing
343+ # Project without Project.toml - treat as toplevel load
344+ where = nothing
359345 end
360- if pkg_env === nothing && is_stdlib (where )
361- # if not found it could be that manifests are from a different julia version/commit
362- # where stdlib dependencies have changed, so look up deps based on the stdlib Project.toml
363- # as a fallback
364- pkg_env = identify_stdlib_project_dep (where , name)
365- end
366- end
367- if cache != = nothing
368- cache. identified_where[(where , name)] = pkg_env
369346 end
370- return pkg_env
371- end
372- function identify_package_env (name:: String )
347+
348+ # Check if we have a cached answer for this
373349 assert_havelock (require_lock)
374350 cache = LOADING_CACHE[]
351+ cache_key = where === nothing ? name : (where , name)
375352 if cache != = nothing
376- pkg_env = get (cache. identified, name, missing )
353+ env_cache = where === nothing ? cache. identified : cache. identified_where
354+ pkg_env = get (env_cache, cache_key, missing )
377355 pkg_env === missing || return pkg_env
378356 end
357+
358+ # Main part: Search through all environments in the load path to see if we have
359+ # a matching entry.
379360 pkg_env = nothing
380361 for env in load_path ()
381- pkg = project_deps_get (env, name)
382- if pkg != = nothing
383- pkg_env = pkg, env # found--return it
384- break
362+ pkgid = environment_deps_get (env, where , name)
363+ # If we didn't find `where` at all, keep looking through the environment stack
364+ pkgid === nothing && continue
365+ if pkgid. uuid != = nothing || where === nothing
366+ pkg_env = pkgid, env
385367 end
368+ # If we don't have pkgid.uuid, still break here - this is a sentinel that indicates
369+ # that we've found `where` but it did not have the required dependency. We terminate the search.
370+ break
386371 end
372+ if pkg_env === nothing && where != = nothing && is_stdlib (where )
373+ # if not found it could be that manifests are from a different julia version/commit
374+ # where stdlib dependencies have changed, so look up deps based on the stdlib Project.toml
375+ # as a fallback
376+ pkg_env = identify_stdlib_project_dep (where , name)
377+ end
378+
379+ # Cache the result
387380 if cache != = nothing
388- cache . identified[name ] = pkg_env
381+ env_cache[cache_key ] = pkg_env
389382 end
390383 return pkg_env
391384end
385+ identify_package_env (name:: String ) = identify_package_env (nothing , name)
392386
393387function identify_stdlib_project_dep (stdlib:: PkgId , depname:: String )
394388 @debug """
@@ -447,19 +441,18 @@ function locate_package_env(pkg::PkgId, stopenv::Union{String, Nothing}=nothing)
447441 path = nothing
448442 env′ = nothing
449443 if pkg. uuid === nothing
444+ # The project we're looking for does not have a Project.toml (n.b. - present
445+ # `Project.toml` without UUID gets a path-based dummy UUID). It must have
446+ # come from an implicit manifest environment, so go through those only.
450447 for env in load_path ()
451- # look for the toplevel pkg `pkg.name` in this entry
452- found = project_deps_get (env, pkg. name)
453- if found != = nothing
448+ project_file = env_project_file (env)
449+ (project_file isa Bool && project_file) || continue
450+ found = implicit_manifest_pkgid (env, pkg. name)
451+ if found != = nothing && found. uuid === nothing
454452 @assert found. name == pkg. name
455- if found. uuid === nothing
456- # pkg.name is present in this directory or project file,
457- # return the path the entry point for the code, if it could be found
458- # otherwise, signal failure
459- path = implicit_manifest_uuid_path (env, pkg)
460- env′ = env
461- @goto done
462- end
453+ path = implicit_manifest_uuid_path (env, pkg)
454+ env′ = env
455+ @goto done
463456 end
464457 if ! (loading_extension || precompiling_extension)
465458 stopenv == env && @goto done
@@ -715,27 +708,18 @@ function base_project(project_file)
715708 end
716709end
717710
718- function project_deps_get (env:: String , name:: String ):: Union{Nothing,PkgId}
719- project_file = env_project_file (env)
720- if project_file isa String
721- pkg_uuid = explicit_project_deps_get (project_file, name)
722- pkg_uuid === nothing || return PkgId (pkg_uuid, name)
723- elseif project_file
724- return implicit_project_deps_get (env, name)
725- end
726- return nothing
727- end
728-
729711function package_get_here (project_file, name:: String )
730712 # if `where` matches the project, use [deps] section as manifest, and stop searching
731713 pkg_uuid = explicit_project_deps_get (project_file, name)
732714 pkg_uuid === nothing && return PkgId (name)
733715 return PkgId (pkg_uuid, name)
734716end
735717
736- function package_get (project_file, where :: PkgId , name:: String )
737- proj = project_file_name_uuid (project_file, where . name)
738- proj != where && return nothing
718+ function package_get (project_file, where :: Union{Nothing, PkgId} , name:: String )
719+ if where != = nothing
720+ proj = project_file_name_uuid (project_file, where . name)
721+ proj != where && return nothing
722+ end
739723 return package_get_here (project_file, name)
740724end
741725
@@ -766,23 +750,51 @@ function package_extension_get(project_file, where::PkgId, name::String)
766750 return nothing
767751end
768752
769- function manifest_deps_get (env:: String , where :: PkgId , name:: String ):: Union{Nothing,PkgId}
770- @assert where . uuid != = nothing
753+ function environment_deps_get (env:: String , where :: Union{Nothing, PkgId} , name:: String ):: Union{Nothing,PkgId}
754+ @assert where === nothing || where . uuid != = nothing
771755 project_file = env_project_file (env)
772756 implicit_manifest = ! (project_file isa String)
773757 if implicit_manifest
774758 project_file || return nothing
759+ if where === nothing
760+ # Toplevel load with a directory (implicit manifest) - all we look for is the
761+ # existence of the package name in the directory.
762+ pkg = implicit_manifest_pkgid (env, name)
763+ return pkg
764+ end
775765 project_file = implicit_manifest_project (env, where )
776766 project_file === nothing && return nothing
777767 end
778768
779- # 1. Are we loading into the top-level project itself? dependencies come from [deps]
780- # N.B.: Here "top-level" includes package loaded from an implicit manifest, which
781- # uses the same code path.
769+ # Are we
770+ # a) loading into a top-level project itself
771+ # b) loading into a non-top-level project that was part of an implicit
772+ # manifest environment (and for which we found the project file above)
773+ # c) performing a top-level load (where === nothing) - i.e. we're looking
774+ # at an environment's project file.
775+ #
776+ # If so, we may load either:
777+ # I: the project itself (if name matches where)
778+ # II: a dependency from [deps] section of the project file
779+ #
780+ # N.B.: Here "top-level" includes package loaded from an implicit manifest, which
781+ # uses the same code path. Otherwise this is the active project.
782782 pkg = package_get (project_file, where , name)
783- pkg === nothing || return pkg
783+ if pkg != = nothing
784+ if where === nothing && pkg. uuid === nothing
785+ # This is a top-level load - even though we didn't find the dependency
786+ # here, we still want to keep looking through the top-level environment stack.
787+ return nothing
788+ end
789+ return pkg
790+ end
784791
785- # 2. Are we an extension of the top-level project? dependencies come from [weakdeps] and [deps]
792+ @assert where != = nothing
793+
794+ # Are we an extension of a project from cases a), b) above
795+ # If so, in addition to I, II above, we get:
796+ # III: A dependency from [weakdeps] section of the project file as long
797+ # as it is an extension trigger for `where` in the `extensions` section.
786798 pkg = package_extension_get (project_file, where , name)
787799 pkg === nothing || return pkg
788800
@@ -1159,10 +1171,7 @@ function explicit_manifest_entry_path(manifest_file::String, pkg::PkgId, entry::
11591171end
11601172
11611173# # implicit project & manifest API ##
1162-
1163- # look for an entry point for `name` from a top-level package (no environment)
1164- # otherwise return `nothing` to indicate the caller should keep searching
1165- function implicit_project_deps_get (dir:: String , name:: String ):: Union{Nothing,PkgId}
1174+ function implicit_manifest_pkgid (dir:: String , name:: String ):: Union{Nothing,PkgId}
11661175 path, project_file = entry_point_and_project_file (dir, name)
11671176 if project_file === nothing
11681177 path === nothing && return nothing
@@ -1173,7 +1182,7 @@ function implicit_project_deps_get(dir::String, name::String)::Union{Nothing,Pkg
11731182 return proj
11741183end
11751184
1176- function implicit_manifest_project (dir, pkg:: PkgId ):: Union{Nothing, String}
1185+ function implicit_manifest_project (dir:: String , pkg:: PkgId ):: Union{Nothing, String}
11771186 @assert pkg. uuid != = nothing
11781187 project_file = entry_point_and_project_file (dir, pkg. name)[2 ]
11791188 if project_file === nothing
0 commit comments