Skip to content

Commit d65333e

Browse files
authored
Merge pull request #87 from kbarros/beta_fix
Fix `sandbox` call on 1.11-beta
2 parents 621a776 + b8f9be5 commit d65333e

File tree

6 files changed

+204
-3
lines changed

6 files changed

+204
-3
lines changed

.github/workflows/CI.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ jobs:
2020
- '1.7'
2121
- '1.8'
2222
- '1.9'
23+
- '1.10'
24+
- '^1.11.0-beta2'
2325
os:
2426
- ubuntu-latest
2527
- windows-latest
26-
- macOS-latest
28+
- macOS-12
2729
arch:
2830
- x64
2931
- x86
3032
exclude:
31-
- os: macOS-latest
33+
- os: macOS-12
3234
arch: x86
3335
steps:
3436
- uses: actions/checkout@v3

src/TestEnv.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ elseif VERSION < v"1.8-"
1414
include("julia-1.7/TestEnv.jl")
1515
elseif VERSION < v"1.9-"
1616
include("julia-1.8/TestEnv.jl")
17-
else
17+
elseif VERSION < v"1.11-"
1818
include("julia-1.9/TestEnv.jl")
19+
else
20+
include("julia-1.11/TestEnv.jl")
1921
end
2022

2123
end

src/julia-1.11/TestEnv.jl

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Pkg
2+
using Pkg: PackageSpec
3+
using Pkg.Types: Context, ensure_resolved, is_project_uuid, write_env, is_stdlib
4+
using Pkg.Types: Types, projectfile_path, manifestfile_path
5+
using Pkg.Operations: manifest_info, manifest_resolve!, project_deps_resolve!
6+
using Pkg.Operations: project_rel_path, project_resolve!
7+
using Pkg.Operations: sandbox, source_path, sandbox_preserve, abspath!
8+
using Pkg.Operations: gen_target_project, isfixed
9+
10+
11+
include("common.jl")
12+
include("activate_do.jl")
13+
include("activate_set.jl")

src/julia-1.11/activate_do.jl

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
TestEnv.activate(f, [pkg]; allow_reresolve=true)
3+
4+
Activate the test enviroment of `pkg` (defaults to current enviroment), and run `f()`,
5+
then deactivate the enviroment.
6+
This is not useful for many people: Julia is not really designed to have the enviroment
7+
being changed while you are executing code.
8+
However, this *is* useful for anyone doing something like making a alternative to
9+
`Pkg.test()`.
10+
Indeed this is basically extracted from what `Pkg.test()` does.
11+
"""
12+
function activate(f, pkg::AbstractString=current_pkg_name(); allow_reresolve=true)
13+
ctx, pkgspec = ctx_and_pkgspec(pkg)
14+
15+
test_project_override = maybe_gen_project_override!(ctx, pkgspec)
16+
path = pkgspec.path::String
17+
return sandbox(ctx, pkgspec, joinpath(path, "test"), test_project_override; allow_reresolve) do
18+
flush(stdout)
19+
f()
20+
end
21+
end

src/julia-1.11/activate_set.jl

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
# Originally from Pkg.Operations.sandbox
3+
4+
"""
5+
TestEnv.activate([pkg]; allow_reresolve=true)
6+
7+
Activate the test enviroment of `pkg` (defaults to current enviroment).
8+
"""
9+
function activate(pkg::AbstractString=current_pkg_name(); allow_reresolve=true)
10+
ctx, pkgspec = ctx_and_pkgspec(pkg)
11+
# This needs to be first as `gen_target_project` fixes `pkgspec.path` if it is nothing
12+
sandbox_project_override = maybe_gen_project_override!(ctx, pkgspec)
13+
14+
sandbox_path = joinpath(pkgspec.path::String, "test")
15+
sandbox_project = projectfile_path(sandbox_path)
16+
17+
tmp = mktempdir()
18+
tmp_project = projectfile_path(tmp)
19+
tmp_manifest = manifestfile_path(tmp)
20+
21+
# Copy env info over to temp env
22+
if sandbox_project_override !== nothing
23+
Types.write_project(sandbox_project_override, tmp_project)
24+
elseif isfile(sandbox_project)
25+
cp(sandbox_project, tmp_project)
26+
chmod(tmp_project, 0o600)
27+
end
28+
# create merged manifest
29+
# - copy over active subgraph
30+
# - abspath! to maintain location of all deved nodes
31+
working_manifest = abspath!(ctx.env, sandbox_preserve(ctx.env, pkgspec, tmp_project))
32+
33+
# - copy over fixed subgraphs from test subgraph
34+
# really only need to copy over "special" nodes
35+
sandbox_env = Types.EnvCache(projectfile_path(sandbox_path))
36+
sandbox_manifest = abspath!(sandbox_env, sandbox_env.manifest)
37+
for (name, uuid) in sandbox_env.project.deps
38+
entry = get(sandbox_manifest, uuid, nothing)
39+
if entry !== nothing && isfixed(entry)
40+
subgraph = Pkg.Operations.prune_manifest(sandbox_manifest, [uuid])
41+
for (uuid, entry) in subgraph
42+
if haskey(working_manifest, uuid)
43+
Pkg.Operations.pkgerror("can not merge projects")
44+
end
45+
working_manifest[uuid] = entry
46+
end
47+
end
48+
end
49+
50+
Types.write_manifest(working_manifest, tmp_manifest)
51+
52+
Base.ACTIVE_PROJECT[] = tmp_project
53+
54+
temp_ctx = Context()
55+
temp_ctx.env.project.deps[pkgspec.name] = pkgspec.uuid
56+
57+
try
58+
Pkg.resolve(temp_ctx; io=devnull)
59+
@debug "Using _parent_ dep graph"
60+
catch err# TODO
61+
allow_reresolve || rethrow()
62+
@debug err
63+
@warn "Could not use exact versions of packages in manifest, re-resolving"
64+
temp_ctx.env.manifest.deps = Dict(
65+
uuid => entry for
66+
(uuid, entry) in temp_ctx.env.manifest.deps if isfixed(entry)
67+
)
68+
Pkg.resolve(temp_ctx; io=devnull)
69+
@debug "Using _clean_ dep graph"
70+
end
71+
72+
write_env(temp_ctx.env; update_undo=false)
73+
74+
return Base.active_project()
75+
end

src/julia-1.11/common.jl

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
struct TestEnvError <: Exception
2+
msg::AbstractString
3+
end
4+
5+
function Base.showerror(io::IO, ex::TestEnvError, bt; backtrace=true)
6+
printstyled(io, ex.msg, color=Base.error_color())
7+
end
8+
9+
function current_pkg_name()
10+
ctx = Context()
11+
ctx.env.pkg === nothing && throw(TestEnvError("trying to activate test environment of an unnamed project"))
12+
return ctx.env.pkg.name
13+
end
14+
15+
"""
16+
ctx, pkgspec = ctx_and_pkgspec(pkg::AbstractString)
17+
18+
For a given package name `pkg`, instantiate a `Context` for it, and return that `Context`,
19+
and it's `PackageSpec`.
20+
"""
21+
function ctx_and_pkgspec(pkg::AbstractString)
22+
pkgspec = deepcopy(PackageSpec(pkg))
23+
ctx = Context()
24+
isinstalled!(ctx, pkgspec) || throw(TestEnvError("$pkg not installed 👻"))
25+
Pkg.instantiate(ctx)
26+
return ctx, pkgspec
27+
end
28+
29+
"""
30+
isinstalled!(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
31+
32+
Checks if the package is installed by using `ensure_resolved` from `Pkg/src/Types.jl`.
33+
This function fails if the package is not installed, but here we wrap it in a
34+
try-catch as we may want to test another package after the one that isn't installed.
35+
"""
36+
function isinstalled!(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
37+
project_resolve!(ctx.env, [pkgspec])
38+
project_deps_resolve!(ctx.env, [pkgspec])
39+
manifest_resolve!(ctx.env.manifest, [pkgspec])
40+
41+
try
42+
ensure_resolved(ctx, ctx.env.manifest, [pkgspec])
43+
catch err
44+
err isa MethodError && rethrow()
45+
return false
46+
end
47+
return true
48+
end
49+
50+
51+
function test_dir_has_project_file(ctx, pkgspec)
52+
test_dir = get_test_dir(ctx, pkgspec)
53+
test_dir === nothing && return false
54+
return isfile(joinpath(test_dir, "Project.toml"))
55+
end
56+
57+
"""
58+
get_test_dir(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
59+
60+
Gets the testfile path of the package. Code for each Julia version mirrors that found
61+
in `Pkg/src/Operations.jl`.
62+
"""
63+
function get_test_dir(ctx::Context, pkgspec::Pkg.Types.PackageSpec)
64+
if is_project_uuid(ctx.env, pkgspec.uuid)
65+
pkgspec.path = dirname(ctx.env.project_file)
66+
pkgspec.version = ctx.env.pkg.version
67+
else
68+
is_stdlib(pkgspec.uuid::Base.UUID) && return
69+
entry = manifest_info(ctx.env.manifest, pkgspec.uuid)
70+
pkgspec.version = entry.version
71+
pkgspec.tree_hash = entry.tree_hash
72+
pkgspec.repo = entry.repo
73+
pkgspec.path = entry.path
74+
pkgspec.pinned = entry.pinned
75+
pkgspec.path = project_rel_path(ctx.env, source_path(ctx.env.project_file, pkgspec)::String)
76+
end
77+
pkgfilepath = source_path(ctx.env.project_file, pkgspec)::String
78+
return joinpath(pkgfilepath, "test")
79+
end
80+
81+
82+
function maybe_gen_project_override!(ctx, pkgspec)
83+
if !test_dir_has_project_file(ctx, pkgspec)
84+
gen_target_project(ctx, pkgspec, pkgspec.path::String, "test")
85+
else
86+
nothing
87+
end
88+
end

0 commit comments

Comments
 (0)