diff --git a/base/loading.jl b/base/loading.jl index 24d13074a7106..0aea2c3a22849 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -479,13 +479,8 @@ end # find project file root or deps `name => uuid` mapping # - `false` means: did not find `name` -# - `true` means: found `name` without UUID +# - `true` means: found `name` without UUID (can't happen in explicit projects) # - `uuid` means: found `name` with `uuid` in project file -# -# `true` can only be returned in the case that `name` is the project's name -# and the project file does not have a top-level `uuid` mapping -# it is not currently supported to have a name in `deps` mapped to anything -# besides a UUID, so otherwise the answer is `false` or a UUID value function explicit_project_deps_get(project_file::String, name::String)::Union{Bool,UUID} open(project_file) do io @@ -507,10 +502,10 @@ function explicit_project_deps_get(project_file::String, name::String)::Union{Bo m.captures[1] == name && return UUID(m.captures[2]) end elseif occursin(re_section, line) - state = :deps + state = occursin(re_section_deps, line) ? :deps : :other end end - return false + return root_name == name && root_uuid end end diff --git a/stdlib/Pkg3/src/precompile.jl b/stdlib/Pkg3/src/precompile.jl index 73fe07d11e893..e20ee5d367ea2 100644 --- a/stdlib/Pkg3/src/precompile.jl +++ b/stdlib/Pkg3/src/precompile.jl @@ -781,7 +781,6 @@ precompile(Tuple{typeof(REPL.LineEdit.fixup_keymaps!), Base.Dict{Char, Any}, Int precompile(Tuple{typeof(REPL.LineEdit.region_active), REPL.LineEdit.PromptState}) precompile(Tuple{typeof(REPL.LineEdit.setup_prefix_keymap), REPL.REPLHistoryProvider, REPL.LineEdit.Prompt}) precompile(Tuple{typeof(REPL.LineEdit.setup_search_keymap), REPL.REPLHistoryProvider}) -precompile(Tuple{getfield(Pkg3.Types, Symbol("##printpkgstyle#56")), Bool, typeof(Pkg3.Types.printpkgstyle), Base.TTY, Symbol, String}) precompile(Tuple{typeof(REPL.LineEdit.complete_line), Pkg3.REPLMode.PkgCompletionProvider, REPL.LineEdit.PromptState}) diff --git a/test/loading.jl b/test/loading.jl index 83b01834ad419..549f7a2a0fc57 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -79,11 +79,69 @@ mktempdir() do dir end end +## unit tests of project parsing ## + import Base: SHA1, PkgId, load_path, identify_package, locate_package, version_slug, dummy_uuid import UUIDs: UUID, uuid4, uuid_version import Random: shuffle, randstring using Test +function subset(v::Vector{T}, m::Int) where T + T[v[j] for j = 1:length(v) if ((m >>> (j - 1)) & 1) == 1] +end + +function perm(p::Vector, i::Int) + for j = length(p):-1:1 + i, k = divrem(i, j) + p[j], p[k+1] = p[k+1], p[j] + end + return p +end + +@testset "explicit_project_deps_get" begin + project_file = "$(tempname()).toml" + touch(project_file) # dummy_uuid calls realpath + proj_uuid = dummy_uuid(project_file) + root_uuid = UUID("43306aae-ef21-43f3-9517-81724f2885ac") + this_uuid = UUID("b36283d3-af40-4a18-9ee0-d12ee9c142ac") + lines = split(""" + name = "Root" + uuid = "$root_uuid" + [deps] + This = "$this_uuid" + """, '\n') + N = length(lines) + for m = 0:2^N-1 + # for every subset of lines + s = subset(lines, m) + for i = 1:factorial(count_ones(m)) + # for every permutation of that subset + p = perm(s, i) + open(project_file, write=true) do io + for line in p + println(io, line) + end + end + # look at lines and their order + n = findfirst(line -> startswith(line, "name"), p) + u = findfirst(line -> startswith(line, "uuid"), p) + d = findfirst(line -> line == "[deps]", p) + t = findfirst(line -> startswith(line, "This"), p) + # look up various packages by name + root = Base.explicit_project_deps_get(project_file, "Root") + this = Base.explicit_project_deps_get(project_file, "This") + that = Base.explicit_project_deps_get(project_file, "That") + # test that the correct answers are given + @test root == (coalesce(n, N+1) ≥ coalesce(d, N+1) ? false : + coalesce(u, N+1) < coalesce(d, N+1) ? root_uuid : proj_uuid) + @test this == (coalesce(d, N+1) < coalesce(t, N+1) ≤ N ? this_uuid : false) + @test that == false + end + end +end + +## functional testing of package identification, location & loading ## + saved_load_path = copy(LOAD_PATH) saved_depot_path = copy(DEPOT_PATH) push!(empty!(LOAD_PATH), "project") @@ -415,14 +473,14 @@ function test_find( end end -@testset "identify_package with one env in load path" begin +@testset "find_package with one env in load path" begin for (env, (_, _, roots, graph, paths)) in envs push!(empty!(LOAD_PATH), env) test_find(roots, graph, paths) end end -@testset "identify_package with two envs in load path" begin +@testset "find_package with two envs in load path" begin for x = false:true, (env1, (_, _, roots1, graph1, paths1)) in (x ? envs : rand(envs, 10)), (env2, (_, _, roots2, graph2, paths2)) in (x ? rand(envs, 10) : envs) @@ -434,7 +492,7 @@ end end end -@testset "identify_package with three envs in load path" begin +@testset "find_package with three envs in load path" begin for (env1, (_, _, roots1, graph1, paths1)) in rand(envs, 10), (env2, (_, _, roots2, graph2, paths2)) in rand(envs, 10), (env3, (_, _, roots3, graph3, paths3)) in rand(envs, 10)