Skip to content

Commit

Permalink
Add preference for version named manifest files (#43845) (#56600)
Browse files Browse the repository at this point in the history
  • Loading branch information
IanButterworth authored Nov 28, 2024
1 parent e6c7c92 commit 36d428a
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 6 deletions.
7 changes: 6 additions & 1 deletion base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,12 @@ end
## generic project & manifest API ##

const project_names = ("JuliaProject.toml", "Project.toml")
const manifest_names = ("JuliaManifest.toml", "Manifest.toml")
const manifest_names = (
"JuliaManifest-v$(VERSION.major).$(VERSION.minor).toml",
"Manifest-v$(VERSION.major).$(VERSION.minor).toml",
"JuliaManifest.toml",
"Manifest.toml",
)
const preferences_names = ("JuliaLocalPreferences.toml", "LocalPreferences.toml")

function locate_project_file(env::String)
Expand Down
4 changes: 2 additions & 2 deletions doc/src/manual/code-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Code inclusion is quite straightforward and simple: it evaluates the given sourc

A *package* is a source tree with a standard layout providing functionality that can be reused by other Julia projects. A package is loaded by `import X` or `using X` statements. These statements also make the module named `X`—which results from loading the package code—available within the module where the import statement occurs. The meaning of `X` in `import X` is context-dependent: which `X` package is loaded depends on what code the statement occurs in. Thus, handling of `import X` happens in two stages: first, it determines **what** package is defined to be `X` in this context; second, it determines **where** that particular `X` package is found.

These questions are answered by searching through the project environments listed in [`LOAD_PATH`](@ref) for project files (`Project.toml` or `JuliaProject.toml`), manifest files (`Manifest.toml` or `JuliaManifest.toml`), or folders of source files.
These questions are answered by searching through the project environments listed in [`LOAD_PATH`](@ref) for project files (`Project.toml` or `JuliaProject.toml`), manifest files (`Manifest.toml` or `JuliaManifest.toml`, or the same names suffixed by `-v{major}.{minor}.toml` for specific versions), or folders of source files.


## Federation of packages
Expand Down Expand Up @@ -63,7 +63,7 @@ Each kind of environment defines these three maps differently, as detailed in th

### Project environments

A project environment is determined by a directory containing a project file called `Project.toml`, and optionally a manifest file called `Manifest.toml`. These files may also be called `JuliaProject.toml` and `JuliaManifest.toml`, in which case `Project.toml` and `Manifest.toml` are ignored. This allows for coexistence with other tools that might consider files called `Project.toml` and `Manifest.toml` significant. For pure Julia projects, however, the names `Project.toml` and `Manifest.toml` are preferred.
A project environment is determined by a directory containing a project file called `Project.toml`, and optionally a manifest file called `Manifest.toml`. These files may also be called `JuliaProject.toml` and `JuliaManifest.toml`, in which case `Project.toml` and `Manifest.toml` are ignored. This allows for coexistence with other tools that might consider files called `Project.toml` and `Manifest.toml` significant. For pure Julia projects, however, the names `Project.toml` and `Manifest.toml` are preferred. However, from Julia v1.10.8 onwards, `(Julia)Manifest-v{major}.{minor}.toml` is recognized as a format to make a given julia version use a specific manifest file i.e. in the same folder, a `Manifest-v1.11.toml` would be used by v1.11 and `Manifest.toml` by any other julia version.

The roots, graph and paths maps of a project environment are defined as follows:

Expand Down
2 changes: 1 addition & 1 deletion stdlib/Artifacts/src/Artifacts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function parse_toml(path::String)
Base.parsed_toml(path)
end

# keep in sync with Base.project_names and Base.manifest_names
# keep in sync with Base.project_names
const artifact_names = ("JuliaArtifacts.toml", "Artifacts.toml")

const ARTIFACTS_DIR_OVERRIDE = Ref{Union{String,Nothing}}(nothing)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Artifacts/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,6 @@ end
@testset "`Artifacts.artifact_names` and friends" begin
n = length(Artifacts.artifact_names)
@test length(Base.project_names) == n
@test length(Base.manifest_names) == n
@test length(Base.manifest_names) == 2n # there are two manifest names per project name
@test length(Base.preferences_names) == n
end
31 changes: 30 additions & 1 deletion test/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -795,8 +795,10 @@ end
@testset "`Base.project_names` and friends" begin
# Some functions in Pkg assumes that these tuples have the same length
n = length(Base.project_names)
@test length(Base.manifest_names) == n
@test length(Base.preferences_names) == n

# there are two manifest names per project name
@test length(Base.manifest_names) == 2n
end

@testset "Manifest formats" begin
Expand Down Expand Up @@ -825,6 +827,33 @@ end
end
end

@testset "Manifest name preferential loading" begin
mktempdir() do tmp
proj = joinpath(tmp, "Project.toml")
touch(proj)
for man_name in (
"Manifest.toml",
"JuliaManifest.toml",
"Manifest-v$(VERSION.major).$(VERSION.minor).toml",
"JuliaManifest-v$(VERSION.major).$(VERSION.minor).toml"
)
touch(joinpath(tmp, man_name))
man = basename(Base.project_file_manifest_path(proj))
@test man == man_name
end
end
mktempdir() do tmp
# check that another version isn't preferred
proj = joinpath(tmp, "Project.toml")
touch(proj)
touch(joinpath(tmp, "Manifest-v1.5.toml"))
@test Base.project_file_manifest_path(proj) == nothing
touch(joinpath(tmp, "Manifest.toml"))
man = basename(Base.project_file_manifest_path(proj))
@test man == "Manifest.toml"
end
end

@testset "error message loading pkg bad module name" begin
mktempdir() do tmp
old_loadpath = copy(LOAD_PATH)
Expand Down

0 comments on commit 36d428a

Please sign in to comment.