diff --git a/src/API.jl b/src/API.jl index 834fbdcef5..e8a071cea8 100644 --- a/src/API.jl +++ b/src/API.jl @@ -1302,8 +1302,11 @@ function status(ctx::Context, pkgs::Vector{PackageSpec}; diff::Bool=false, mode= end -function activate(;temp=false, shared=false, prev=false, io::IO=stderr_f()) +function activate(;temp=false, shared=false, prev=false, target::Union{Symbol,Nothing}=nothing, io::IO=stderr_f()) shared && pkgerror("Must give a name for a shared environment") + if target !== nothing + return activate(Base.active_project(); target, io) + end temp && return activate(mktempdir(); io=io) if prev if isempty(PREV_ENV_PATH[]) @@ -1333,12 +1336,12 @@ function _activate_dep(dep_name::AbstractString) uuid = get(ctx.env.project.deps, dep_name, nothing) if uuid !== nothing entry = manifest_info(ctx.env.manifest, uuid) - if entry.path !== nothing + if entry !== nothing && entry.path !== nothing return joinpath(dirname(ctx.env.manifest_file), entry.path::String) end end end -function activate(path::AbstractString; shared::Bool=false, temp::Bool=false, io::IO=stderr_f()) +function activate(path::AbstractString; shared::Bool=false, temp::Bool=false, target::Union{Symbol,Nothing}=nothing, io::IO=stderr_f()) temp && pkgerror("Can not give `path` argument when creating a temporary environment") if !shared # `pkg> activate path`/`Pkg.activate(path)` does the following @@ -1370,6 +1373,14 @@ function activate(path::AbstractString; shared::Bool=false, temp::Bool=false, io fullpath = joinpath(Pkg.envdir(Pkg.depots1()), path) end end + if target !== nothing + printpkgstyle(io, :Creating, "temporary project based on the target `$target` in $(pathrepr(fullpath))", color = Base.info_color()) + target_project = Operations.gen_target_project(Context(), nothing, fullpath, "test") + temp_project_dir = mktempdir() + temp_projectfile = joinpath(temp_project_dir, "Project.toml") + Types.write_project(target_project, temp_projectfile) + fullpath = temp_projectfile + end if !isnothing(Base.active_project()) PREV_ENV_PATH[] = Base.active_project() end diff --git a/src/Operations.jl b/src/Operations.jl index 3fb44792ed..c76acc32bb 100644 --- a/src/Operations.jl +++ b/src/Operations.jl @@ -2219,11 +2219,15 @@ function parse_REQUIRE(require_path::String) end # "targets" based test deps -> "test/Project.toml" based deps -function gen_target_project(ctx::Context, pkg::PackageSpec, source_path::String, target::String) +function gen_target_project(ctx::Context, pkg::Union{PackageSpec,Nothing}, source_path::String, target::String) env = ctx.env registries = ctx.registries test_project = Types.Project() if projectfile_path(source_path; strict=true) === nothing + if pkg === nothing + # don't support REQUIRE if pkg isn't provided + pkgerror("No project file found in $(source_path)") + end # no project file, assuming this is an old REQUIRE package test_project.deps = copy(env.manifest[pkg.uuid].deps) if target == "test" diff --git a/src/REPLMode/argument_parsers.jl b/src/REPLMode/argument_parsers.jl index 5d909e91ba..e0db38124d 100644 --- a/src/REPLMode/argument_parsers.jl +++ b/src/REPLMode/argument_parsers.jl @@ -218,6 +218,7 @@ end # function parse_activate(args::Vector{QString}, options) isempty(args) && return [] # nothing to do + args = filter(a -> !in(a.raw, ("--test", "--build")), args) if length(args) == 1 x = first(args) if x.isquoted diff --git a/src/REPLMode/command_declarations.jl b/src/REPLMode/command_declarations.jl index a9d9cc3304..b838ae44bd 100644 --- a/src/REPLMode/command_declarations.jl +++ b/src/REPLMode/command_declarations.jl @@ -308,11 +308,13 @@ packages have changed causing the current Manifest to be out of sync. ], PSA[:name => "activate", :api => API.activate, - :arg_count => 0 => 1, + :arg_count => 0 => 2, :arg_parser => parse_activate, :option_spec => [ PSA[:name => "shared", :api => :shared => true], PSA[:name => "temp", :api => :temp => true], + PSA[:name => "test", :api => :target => :test], + PSA[:name => "build", :api => :target => :build], ], :completions => :complete_activate, :description => "set the primary environment the package manager manipulates", @@ -321,6 +323,8 @@ PSA[:name => "activate", activate [--shared] path activate --temp activate - (activates the previously active environment) + activate --test (activates the test target within the current environment) + activate --build (activates the build target within the current environment) Activate the environment at the given `path`, or use the first project found in `LOAD_PATH` (ignoring `"@"`) if no `path` is specified. diff --git a/src/Types.jl b/src/Types.jl index 5f72f49c96..162d47ecd8 100644 --- a/src/Types.jl +++ b/src/Types.jl @@ -172,6 +172,7 @@ end function projectfile_path(env_path::String; strict=false) for name in Base.project_names + basename(env_path) == name && isfile(env_path) && return env_path maybe_file = joinpath(env_path, name) isfile(maybe_file) && return maybe_file end