diff --git a/docs/src/environments.md b/docs/src/environments.md index fd6fff9ab4..ff22867573 100644 --- a/docs/src/environments.md +++ b/docs/src/environments.md @@ -91,6 +91,8 @@ In short, `instantiate` is your friend to make sure an environment is ready to u ```bash $ julia --project=. myscript.jl ``` + For Julia 1.7 or later, `--project=@stdlib` activates stdlib environment. + For Julia 1.11 or later, `--project=@temp` activates temporary environment. ## Temporary environments @@ -115,6 +117,13 @@ between several incompatible packages. [7876af07] + Example v0.5.3 ``` +```julia-repl +(@v1.11) pkg> activate @temp # requires Julia 1.11 or later + Activating new project at `/tmp/jl_OzBmCP` + +(jl_OzBmCP) pkg> +``` + ## Shared environments A "shared" environment is simply an environment that exists in `~/.julia/environments`. The default `v1.9` environment is @@ -136,6 +145,24 @@ Shared environments can be activated with the `--shared` flag to `activate`: Shared environments have a `@` before their name in the Pkg REPL prompt. +Shared stdlib environment that exists in `Sys.STDLIB` can be activated as follows: +```julia-repl +(@v1.11) pkg> activate --shared stdlib + Activating project at `@stdlib/v1.11` + +(v1.11) pkg> +``` + +```julia-repl +(@v1.11) pkg> activate @stdlib + Activating project at `@stdlib/v1.11` + +(v1.11) pkg> +``` + +!!! note + For Julia 1.11 or later `temp` is an invalid name for a shared environment as `activate @temp` creates temporary environments. + ## Environment Precompilation diff --git a/src/API.jl b/src/API.jl index 950d3b002c..932d948deb 100644 --- a/src/API.jl +++ b/src/API.jl @@ -1968,6 +1968,8 @@ function _activate_dep(dep_name::AbstractString) end function activate(path::AbstractString; shared::Bool=false, temp::Bool=false, io::IO=stderr_f()) temp && pkgerror("Can not give `path` argument when creating a temporary environment") + shared && path == "temp" && pkgerror("""`temp` is an invalid name for a shared environment. + To create a temporary environment use `Pkg.activate(; temp = true)`""") if !shared # `pkg> activate path`/`Pkg.activate(path)` does the following # 1. if path exists, activate that @@ -1982,20 +1984,24 @@ function activate(path::AbstractString; shared::Bool=false, temp::Bool=false, io end end else - # initialize `fullpath` in case of empty `Pkg.depots()` - fullpath = "" - # loop over all depots to check if the shared environment already exists - for depot in Pkg.depots() - fullpath = joinpath(Pkg.envdir(depot), path) - isdir(fullpath) && break - end - # this disallows names such as "Foo/bar", ".", "..", etc - if basename(abspath(fullpath)) != path - pkgerror("not a valid name for a shared environment: $(path)") - end - # unless the shared environment already exists, place it in the first depots - if !isdir(fullpath) - fullpath = joinpath(Pkg.envdir(Pkg.depots1()), path) + if path == "stdlib" + fullpath = Sys.STDLIB + else + # initialize `fullpath` in case of empty `Pkg.depots()` + fullpath = "" + # loop over all depots to check if the shared environment already exists + for depot in Pkg.depots() + fullpath = joinpath(Pkg.envdir(depot), path) + isdir(fullpath) && break + end + # this disallows names such as "Foo/bar", ".", "..", etc + if basename(abspath(fullpath)) != path + pkgerror("not a valid name for a shared environment: $(path)") + end + # unless the shared environment already exists, place it in the first depots + if !isdir(fullpath) + fullpath = joinpath(Pkg.envdir(Pkg.depots1()), path) + end end end if !isnothing(Base.active_project()) diff --git a/src/REPLMode/argument_parsers.jl b/src/REPLMode/argument_parsers.jl index c0f284a4b0..13ee167037 100644 --- a/src/REPLMode/argument_parsers.jl +++ b/src/REPLMode/argument_parsers.jl @@ -218,6 +218,15 @@ function parse_activate(args::Vector{QString}, options) if x == "-" options[:prev] = true return [] + elseif x == "@temp" + options[:temp] = true + return [] + elseif x == "@stdlib" + return [Sys.STDLIB] + elseif x == "@." + return [Base.current_project()] + elseif x == "@" + return [Base.active_project()] elseif first(x) == '@' options[:shared] = true return [x[2:end]] diff --git a/test/api.jl b/test/api.jl index e85150e7fd..694293f488 100644 --- a/test/api.jl +++ b/test/api.jl @@ -38,6 +38,9 @@ using ..Utils cd(mkdir("tests")) Pkg.activate("Foo") # activate developed Foo from another directory @test Base.active_project() == joinpath(path, "modules", "Foo", "Project.toml") + @test_throws PkgError Pkg.activate("temp"; shared = true) # Disallow naming a shared env as `temp`. + Pkg.activate("stdlib"; shared = true) # activate `@stdlib/Project.toml` + @test Base.active_project() == joinpath(Sys.STDLIB, "Project.toml") Pkg.activate() # activate LOAD_PATH project @test Base.ACTIVE_PROJECT[] === nothing end end diff --git a/test/repl.jl b/test/repl.jl index 210f1dd871..eb42d3f2a7 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -227,6 +227,7 @@ temp_pkg_dir() do project_path @test_throws Pkg.Types.PkgError pkg"activate --shared ./Foo" @test_throws Pkg.Types.PkgError pkg"activate --shared Foo/Bar" @test_throws Pkg.Types.PkgError pkg"activate --shared ../Bar" + @test_throws Pkg.Types.PkgError pkg"activate --shared temp" # check that those didn't change the environment @test Base.active_project() == joinpath(path, "Project.toml") mkdir("Foo") @@ -239,6 +240,8 @@ temp_pkg_dir() do project_path pkg"activate ." #=@test_logs (:info, r"activating new environment at ")))=# pkg"activate --shared Foo" # activate shared Foo @test Base.active_project() == joinpath(Pkg.envdir(), "Foo", "Project.toml") + pkg"activate --shared stdlib" # activate shared STDLIB + @test Base.active_project() == joinpath(Sys.STDLIB, "Project.toml") pkg"activate ." rm("Foo"; force=true, recursive=true) pkg"activate Foo" # activate path from developed Foo @@ -265,6 +268,15 @@ temp_pkg_dir() do project_path pop!(Base.DEPOT_PATH) pkg"activate" # activate LOAD_PATH project @test Base.ACTIVE_PROJECT[] === nothing + pkg"activate @temp" # activate a temporary environment + @test dirname(Base.ACTIVE_PROJECT[]) == tempdir() + pkg"activate @stdlib" # activate the STDLIB environment + @test Base.ACTIVE_PROJECT[] == Sys.STDLIB + pkg"activate @." # activate current project + @test Base.ACTIVE_PROJECT[] == Base.current_project() + pkg"activate @" # activate active project + @test Base.ACTIVE_PROJECT[] === Base.active_project() + # expansion of ~ if !Sys.iswindows() pkg"activate ~/Foo_lzTkPF6N"