Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix sandbox call on 1.11-beta #87

Merged
merged 8 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/TestEnv.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ elseif VERSION < v"1.8-"
include("julia-1.7/TestEnv.jl")
elseif VERSION < v"1.9-"
include("julia-1.8/TestEnv.jl")
else
elseif VERSION < v"1.11-"
include("julia-1.9/TestEnv.jl")
else
include("julia-1.11/TestEnv.jl")
end

end
13 changes: 13 additions & 0 deletions src/julia-1.11/TestEnv.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Pkg
using Pkg: PackageSpec
using Pkg.Types: Context, ensure_resolved, is_project_uuid, write_env, is_stdlib
using Pkg.Types: Types, projectfile_path, manifestfile_path
using Pkg.Operations: manifest_info, manifest_resolve!, project_deps_resolve!
using Pkg.Operations: project_rel_path, project_resolve!
using Pkg.Operations: sandbox, source_path, sandbox_preserve, abspath!
using Pkg.Operations: gen_target_project, isfixed


include("common.jl")
include("activate_do.jl")
include("activate_set.jl")
21 changes: 21 additions & 0 deletions src/julia-1.11/activate_do.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
TestEnv.activate(f, [pkg]; allow_reresolve=true)

Activate the test enviroment of `pkg` (defaults to current enviroment), and run `f()`,
then deactivate the enviroment.
This is not useful for many people: Julia is not really designed to have the enviroment
being changed while you are executing code.
However, this *is* useful for anyone doing something like making a alternative to
`Pkg.test()`.
Indeed this is basically extracted from what `Pkg.test()` does.
"""
function activate(f, pkg::AbstractString=current_pkg_name(); allow_reresolve=true)
ctx, pkgspec = ctx_and_pkgspec(pkg)

Check warning on line 13 in src/julia-1.11/activate_do.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_do.jl#L12-L13

Added lines #L12 - L13 were not covered by tests

test_project_override = maybe_gen_project_override!(ctx, pkgspec)
path = pkgspec.path::String
return sandbox(ctx, pkgspec, joinpath(path, "test"), test_project_override; allow_reresolve) do
flush(stdout)
f()

Check warning on line 19 in src/julia-1.11/activate_do.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_do.jl#L15-L19

Added lines #L15 - L19 were not covered by tests
end
end
75 changes: 75 additions & 0 deletions src/julia-1.11/activate_set.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

# Originally from Pkg.Operations.sandbox

"""
TestEnv.activate([pkg]; allow_reresolve=true)

Activate the test enviroment of `pkg` (defaults to current enviroment).
"""
function activate(pkg::AbstractString=current_pkg_name(); allow_reresolve=true)
ctx, pkgspec = ctx_and_pkgspec(pkg)

Check warning on line 10 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L9-L10

Added lines #L9 - L10 were not covered by tests
# This needs to be first as `gen_target_project` fixes `pkgspec.path` if it is nothing
sandbox_project_override = maybe_gen_project_override!(ctx, pkgspec)

Check warning on line 12 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L12

Added line #L12 was not covered by tests

sandbox_path = joinpath(pkgspec.path::String, "test")
sandbox_project = projectfile_path(sandbox_path)

Check warning on line 15 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L14-L15

Added lines #L14 - L15 were not covered by tests

tmp = mktempdir()
tmp_project = projectfile_path(tmp)
tmp_manifest = manifestfile_path(tmp)

Check warning on line 19 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L17-L19

Added lines #L17 - L19 were not covered by tests

# Copy env info over to temp env
if sandbox_project_override !== nothing
Types.write_project(sandbox_project_override, tmp_project)
elseif isfile(sandbox_project)
cp(sandbox_project, tmp_project)
chmod(tmp_project, 0o600)

Check warning on line 26 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L22-L26

Added lines #L22 - L26 were not covered by tests
end
# create merged manifest
# - copy over active subgraph
# - abspath! to maintain location of all deved nodes
working_manifest = abspath!(ctx.env, sandbox_preserve(ctx.env, pkgspec, tmp_project))

Check warning on line 31 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L31

Added line #L31 was not covered by tests

# - copy over fixed subgraphs from test subgraph
# really only need to copy over "special" nodes
sandbox_env = Types.EnvCache(projectfile_path(sandbox_path))
sandbox_manifest = abspath!(sandbox_env, sandbox_env.manifest)
for (name, uuid) in sandbox_env.project.deps
entry = get(sandbox_manifest, uuid, nothing)
if entry !== nothing && isfixed(entry)
subgraph = Pkg.Operations.prune_manifest(sandbox_manifest, [uuid])
for (uuid, entry) in subgraph
if haskey(working_manifest, uuid)
Pkg.Operations.pkgerror("can not merge projects")

Check warning on line 43 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L35-L43

Added lines #L35 - L43 were not covered by tests
end
working_manifest[uuid] = entry
end

Check warning on line 46 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L45-L46

Added lines #L45 - L46 were not covered by tests
end
end

Check warning on line 48 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L48

Added line #L48 was not covered by tests

Types.write_manifest(working_manifest, tmp_manifest)

Check warning on line 50 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L50

Added line #L50 was not covered by tests

Base.ACTIVE_PROJECT[] = tmp_project

Check warning on line 52 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L52

Added line #L52 was not covered by tests

temp_ctx = Context()
temp_ctx.env.project.deps[pkgspec.name] = pkgspec.uuid

Check warning on line 55 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L54-L55

Added lines #L54 - L55 were not covered by tests

try
Pkg.resolve(temp_ctx; io=devnull)
@debug "Using _parent_ dep graph"

Check warning on line 59 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L57-L59

Added lines #L57 - L59 were not covered by tests
catch err# TODO
allow_reresolve || rethrow()
@debug err
@warn "Could not use exact versions of packages in manifest, re-resolving"
temp_ctx.env.manifest.deps = Dict(

Check warning on line 64 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L61-L64

Added lines #L61 - L64 were not covered by tests
uuid => entry for
(uuid, entry) in temp_ctx.env.manifest.deps if isfixed(entry)
)
Pkg.resolve(temp_ctx; io=devnull)
@debug "Using _clean_ dep graph"

Check warning on line 69 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L68-L69

Added lines #L68 - L69 were not covered by tests
end

write_env(temp_ctx.env; update_undo=false)

Check warning on line 72 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L72

Added line #L72 was not covered by tests

return Base.active_project()

Check warning on line 74 in src/julia-1.11/activate_set.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/activate_set.jl#L74

Added line #L74 was not covered by tests
end
88 changes: 88 additions & 0 deletions src/julia-1.11/common.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
struct TestEnvError <: Exception
msg::AbstractString
end

function Base.showerror(io::IO, ex::TestEnvError, bt; backtrace=true)
printstyled(io, ex.msg, color=Base.error_color())

Check warning on line 6 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L5-L6

Added lines #L5 - L6 were not covered by tests
end

function current_pkg_name()
ctx = Context()
ctx.env.pkg === nothing && throw(TestEnvError("trying to activate test environment of an unnamed project"))
return ctx.env.pkg.name

Check warning on line 12 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L9-L12

Added lines #L9 - L12 were not covered by tests
end

"""
ctx, pkgspec = ctx_and_pkgspec(pkg::AbstractString)

For a given package name `pkg`, instantiate a `Context` for it, and return that `Context`,
and it's `PackageSpec`.
"""
function ctx_and_pkgspec(pkg::AbstractString)
pkgspec = deepcopy(PackageSpec(pkg))
ctx = Context()
isinstalled!(ctx, pkgspec) || throw(TestEnvError("$pkg not installed 👻"))
Pkg.instantiate(ctx)
return ctx, pkgspec

Check warning on line 26 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L21-L26

Added lines #L21 - L26 were not covered by tests
end

"""
isinstalled!(ctx::Context, pkgspec::Pkg.Types.PackageSpec)

Checks if the package is installed by using `ensure_resolved` from `Pkg/src/Types.jl`.
This function fails if the package is not installed, but here we wrap it in a
try-catch as we may want to test another package after the one that isn't installed.
"""
function isinstalled!(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
project_resolve!(ctx.env, [pkgspec])
project_deps_resolve!(ctx.env, [pkgspec])
manifest_resolve!(ctx.env.manifest, [pkgspec])

Check warning on line 39 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L36-L39

Added lines #L36 - L39 were not covered by tests

try
ensure_resolved(ctx, ctx.env.manifest, [pkgspec])

Check warning on line 42 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L41-L42

Added lines #L41 - L42 were not covered by tests
catch err
err isa MethodError && rethrow()
return false

Check warning on line 45 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L44-L45

Added lines #L44 - L45 were not covered by tests
end
return true

Check warning on line 47 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L47

Added line #L47 was not covered by tests
end


function test_dir_has_project_file(ctx, pkgspec)
test_dir = get_test_dir(ctx, pkgspec)
test_dir === nothing && return false
return isfile(joinpath(test_dir, "Project.toml"))

Check warning on line 54 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L51-L54

Added lines #L51 - L54 were not covered by tests
end

"""
get_test_dir(ctx::Context, pkgspec::Pkg.Types.PackageSpec)

Gets the testfile path of the package. Code for each Julia version mirrors that found
in `Pkg/src/Operations.jl`.
"""
function get_test_dir(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
if is_project_uuid(ctx.env, pkgspec.uuid)
pkgspec.path = dirname(ctx.env.project_file)
pkgspec.version = ctx.env.pkg.version

Check warning on line 66 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L63-L66

Added lines #L63 - L66 were not covered by tests
else
is_stdlib(pkgspec.uuid::Base.UUID) && return
entry = manifest_info(ctx.env.manifest, pkgspec.uuid)
pkgspec.version = entry.version
pkgspec.tree_hash = entry.tree_hash
pkgspec.repo = entry.repo
pkgspec.path = entry.path
pkgspec.pinned = entry.pinned
pkgspec.path = project_rel_path(ctx.env, source_path(ctx.env.project_file, pkgspec)::String)

Check warning on line 75 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L68-L75

Added lines #L68 - L75 were not covered by tests
end
pkgfilepath = source_path(ctx.env.project_file, pkgspec)::String
return joinpath(pkgfilepath, "test")

Check warning on line 78 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L77-L78

Added lines #L77 - L78 were not covered by tests
end


function maybe_gen_project_override!(ctx, pkgspec)
if !test_dir_has_project_file(ctx, pkgspec)
gen_target_project(ctx, pkgspec, pkgspec.path::String, "test")

Check warning on line 84 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L82-L84

Added lines #L82 - L84 were not covered by tests
else
nothing

Check warning on line 86 in src/julia-1.11/common.jl

View check run for this annotation

Codecov / codecov/patch

src/julia-1.11/common.jl#L86

Added line #L86 was not covered by tests
end
end
Loading