Skip to content

Commit

Permalink
Refactor: use VersionSpec as the canonical compat representation (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
00vareladavid authored Apr 2, 2021
1 parent 9cf608c commit f073140
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 22 deletions.
34 changes: 17 additions & 17 deletions src/Operations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ end
#######################################
# Dependency gathering and resolution #
#######################################
get_compat(proj::Project, name::String) = haskey(proj.compat, name) ? proj.compat[name].val : Types.VersionSpec()
get_compat_str(proj::Project, name::String) = haskey(proj.compat, name) ? proj.compat[name].str : nothing
function set_compat(proj::Project, name::String, compat::String)
proj.compat[name] = Types.Compat(Types.semver_spec(compat), compat)
end

function collect_project!(pkg::PackageSpec, path::String,
deps_map::Dict{UUID,Vector{PackageSpec}})
deps_map[pkg.uuid] = PackageSpec[]
Expand All @@ -179,15 +185,15 @@ function collect_project!(pkg::PackageSpec, path::String,
pkgerror("could not find project file for package $(err_rep(pkg)) at `$path`")
end
project = read_package(project_file)
julia_compat = get(project.compat, "julia", nothing)
julia_compat = get_compat(project, "julia")
#=
# TODO, this should either error or be quiet
if julia_compat !== nothing && !(VERSION in Types.semver_spec(julia_compat))
if julia_compat !== nothing && !(VERSION in julia_compat)
println(io, "julia version requirement for package $(err_rep(pkg)) not satisfied")
end
=#
for (name, uuid) in project.deps
vspec = Types.semver_spec(get(project.compat, name, ">= 0"))
vspec = get_compat(project, name)
push!(deps_map[pkg.uuid], PackageSpec(name, uuid, vspec))
end
if project.version !== nothing
Expand Down Expand Up @@ -264,10 +270,6 @@ function collect_fixed!(env::EnvCache, pkgs::Vector{PackageSpec}, names::Dict{UU
end


function project_compatibility(env::EnvCache, name::String)
return VersionSpec(Types.semver_spec(get(env.project.compat, name, ">= 0")))
end

# Resolve a set of versions given package version specs
# looks at uuid, version, repo/path,
# sets version to a VersionNumber
Expand All @@ -276,7 +278,7 @@ end
function resolve_versions!(env::EnvCache, registries::Vector{Registry.RegistryInstance}, pkgs::Vector{PackageSpec}, julia_version)
# compatibility
if julia_version !== nothing
v = intersect(julia_version, project_compatibility(env, "julia"))
v = intersect(julia_version, get_compat(env.project, "julia"))
if isempty(v)
@warn "julia version requirement for project not satisfied" _module=nothing _file=nothing
end
Expand All @@ -300,7 +302,7 @@ function resolve_versions!(env::EnvCache, registries::Vector{Registry.RegistryIn

# check compat
for pkg in pkgs
compat = project_compatibility(env, pkg.name)
compat = get_compat(env.project, pkg.name)
v = intersect(pkg.version, compat)
if isempty(v)
throw(Resolve.ResolverError(
Expand Down Expand Up @@ -1432,7 +1434,6 @@ function sandbox(fn::Function, ctx::Context, target::PackageSpec, target_path::S
with_temp_env(tmp) do
temp_ctx = Context()
temp_ctx.env.project.deps[target.name] = target.uuid

try
Pkg.resolve(temp_ctx; io=devnull)
@debug "Using _parent_ dep graph"
Expand Down Expand Up @@ -1526,9 +1527,9 @@ function gen_target_project(env::EnvCache, registries::Vector{Registry.RegistryI
end
# collect compat entries
for (name, uuid) in test_project.deps
compat = get(source_env.project.compat, name, nothing)
compat = get_compat_str(source_env.project, name)
compat === nothing && continue
test_project.compat[name] = compat
set_compat(test_project, name, compat)
end
return test_project
end
Expand Down Expand Up @@ -1842,11 +1843,11 @@ function check_force_latest_compatible_version(ctx::Types.Context,
end
return true
end
compat_entry_string = ctx.env.project.compat[name]
compat_entry = ctx.env.project.compat[name].val
latest_compatible_version = get_latest_compatible_version(
ctx,
uuid,
compat_entry_string,
compat_entry,
)
earliest_backwards_compatible_version = get_earliest_backwards_compatible_version(latest_compatible_version)
if allow_earlier_backwards_compatible_versions
Expand All @@ -1859,7 +1860,7 @@ function check_force_latest_compatible_version(ctx::Types.Context,
"Package is not at the latest compatible version",
name,
uuid,
compat_entry_string,
compat_entry,
active_version,
latest_compatible_version,
earliest_backwards_compatible_version,
Expand All @@ -1877,9 +1878,8 @@ end

function get_latest_compatible_version(ctx::Types.Context,
uuid::Base.UUID,
compat_entry_string::AbstractString)
compat_spec::VersionSpec)
all_registered_versions = get_all_registered_versions(ctx, uuid)
compat_spec = Pkg.Types.semver_spec(compat_entry_string)
compatible_versions = filter(in(compat_spec), all_registered_versions)
latest_compatible_version = maximum(compatible_versions)
return latest_compatible_version
Expand Down
7 changes: 6 additions & 1 deletion src/Types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ function find_project_file(env::Union{Nothing,String}=nothing)
return Pkg.safe_realpath(project_file)
end

Base.@kwdef mutable struct Compat
val::VersionSpec
str::String
end

Base.@kwdef mutable struct Project
other::Dict{String,Any} = Dict{String,Any}()
# Fields
Expand All @@ -206,7 +211,7 @@ Base.@kwdef mutable struct Project
deps::Dict{String,UUID} = Dict{String,UUID}()
extras::Dict{String,UUID} = Dict{String,UUID}()
targets::Dict{String,Vector{String}} = Dict{String,Vector{String}}()
compat::Dict{String,String} = Dict{String,String}()# TODO Dict{String, VersionSpec}
compat::Dict{String,Compat} = Dict{String,Compat}()
end
Base.:(==)(t1::Project, t2::Project) = all(x -> (getfield(t1, x) == getfield(t2, x))::Bool, fieldnames(Project))
Base.hash(x::Project, h::UInt) = foldr(hash, [getfield(t, x) for x in fieldnames(Project)], init=h)
Expand Down
16 changes: 12 additions & 4 deletions src/project.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,17 @@ end
read_project_targets(raw, project::Project) =
pkgerror("Expected `targets` section to be a key-value list")

read_project_compat(::Nothing, project::Project) = Dict{String,Any}()
read_project_compat(::Nothing, project::Project) = Dict{String,Compat}()
function read_project_compat(raw::Dict{String,Any}, project::Project)
compat = Dict{String,Compat}()
for (name, version) in raw
try VersionSpec(semver_spec(version))
try
compat[name] = Compat(semver_spec(version), version)
catch err
pkgerror("Could not parse compatibility version for dependency `$name`")
end
end
return raw
return compat
end
read_project_compat(raw, project::Project) =
pkgerror("Expected `compat` section to be a key-value list")
Expand Down Expand Up @@ -147,6 +149,12 @@ end
function destructure(project::Project)::Dict
raw = deepcopy(project.other)

# sanity check for consistency between compat value and string representation
for (name, compat) in project.compat
@assert compat.val == semver_spec(compat.str) "inconsistency between compat values and string representation"
end

# if a field is set to its default value, don't include it in the write
should_delete(x::Dict) = isempty(x)
should_delete(x) = x === nothing
entry!(key::String, src) = should_delete(src) ? delete!(raw, key) : (raw[key] = src)
Expand All @@ -157,7 +165,7 @@ function destructure(project::Project)::Dict
entry!("manifest", project.manifest)
entry!("deps", project.deps)
entry!("extras", project.extras)
entry!("compat", project.compat)
entry!("compat", Dict(name => x.str for (name, x) in project.compat))
entry!("targets", project.targets)
return raw
end
Expand Down

0 comments on commit f073140

Please sign in to comment.