Skip to content

Commit

Permalink
show name of pkg on resolution failure
Browse files Browse the repository at this point in the history
  • Loading branch information
KristofferC committed Nov 19, 2017
1 parent 266ab1a commit 682cef5
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 18 deletions.
12 changes: 10 additions & 2 deletions src/Operations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ function resolve_versions!(env::EnvCache, pkgs::Vector{PackageSpec})::Dict{UUID,
info("Resolving package versions")
# anything not mentioned is fixed
uuids = UUID[pkg.uuid for pkg in pkgs]
uuid_to_name = Dict{String, String}()
for (name::String, uuid::UUID) in env.project["deps"]
uuid_to_name[string(uuid)] = name
uuid in uuids && continue
info = manifest_info(env, uuid)
haskey(info, "version") || continue
Expand All @@ -162,8 +164,14 @@ function resolve_versions!(env::EnvCache, pkgs::Vector{PackageSpec})::Dict{UUID,
# construct data structures for resolver and call it
reqs = Dict{String,Pkg2.Types.VersionSet}(string(pkg.uuid) => pkg.version for pkg in pkgs)
deps = convert(Dict{String,Dict{VersionNumber,Pkg2.Types.Available}}, deps_graph(env, pkgs))
deps = Pkg2.Query.prune_dependencies(reqs, deps)
vers = convert(Dict{UUID,VersionNumber}, Pkg2.Resolve.resolve(reqs, deps))
for dep_uuid in keys(deps)
info = manifest_info(env, UUID(dep_uuid))
if info != nothing
uuid_to_name[info["uuid"]] = info["name"]
end
end
deps = Pkg2.Query.prune_dependencies(reqs, deps, uuid_to_name)
vers = convert(Dict{UUID,VersionNumber}, Pkg2.Resolve.resolve(reqs, deps, uuid_to_name))
find_registered!(env, collect(keys(vers)))
# update vector of package versions
for pkg in pkgs
Expand Down
32 changes: 19 additions & 13 deletions src/Pkg2/query.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ using ..Types
# The propagation is tracked so that in case a contradiction is detected the error
# message allows to determine the cause.
# This is a pre-pruning step, so it also creates some structures which are later used by pruning
function filter_versions(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}}, bktrc::ResolveBacktrace)
function filter_versions(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}},
bktrc::ResolveBacktrace, uuid_to_name::Dict{String, String})
allowed = Dict{String,Dict{VersionNumber,Bool}}()
staged = copy(reqs)
while !isempty(staged)
Expand All @@ -34,7 +35,9 @@ function filter_versions(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Av
end
@assert !isempty(allowedp)
if !any(values(allowedp))
err_msg = "Unsatisfiable requirements detected for package $p:\n"
name = haskey(uuid_to_name, p) ? uuid_to_name[p] : "UNKNOWN"
uuid_short = p[1:8]
err_msg = "Unsatisfiable requirements detected for package $name [$uuid_short]:\n"
err_msg *= string(bktrc[p])
err_msg *= """The intersection of the requirements is $(bktrc[p].versionreq).
None of the available versions can satisfy this requirement."""
Expand Down Expand Up @@ -74,7 +77,9 @@ function filter_versions(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Av
bktrcp = get!(bktrc, rp) do; ResolveBacktraceItem(); end
push!(bktrcp, p=>bktrc[p], srvs)
if isa(bktrcp.versionreq, VersionSet) && isempty(bktrcp.versionreq)
err_msg = "Unsatisfiable requirements detected for package $rp:\n"
name = haskey(uuid_to_name, rp) ? uuid_to_name[rp] : "UNKNOWN"
uuid_short = rp[1:8]
err_msg = "Unsatisfiable requirements detected for package $name [$uuid_short]:\n"
err_msg *= string(bktrcp)
err_msg *= "The intersection of the requirements is empty."
throw(PkgError(err_msg))
Expand Down Expand Up @@ -105,8 +110,8 @@ end
# dependency relation, they are both required or both not required)
# 2) They have the same dependencies
# Preliminarily calls filter_versions.
function prune_versions(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}}, bktrc::ResolveBacktrace)
filtered_deps, allowed = filter_versions(reqs, deps, bktrc)
function prune_versions(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}}, bktrc::ResolveBacktrace, uuid_to_name::Dict{String, String})
filtered_deps, allowed = filter_versions(reqs, deps, bktrc, uuid_to_name)

# To each version in each package, we associate a BitVector.
# It is going to hold a pattern such that all versions with
Expand Down Expand Up @@ -250,10 +255,10 @@ function prune_versions(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Ava

return new_deps, eq_classes
end
prune_versions(deps::Dict{String,Dict{VersionNumber,Available}}) =
prune_versions(Dict{String,VersionSet}(), deps, ResolveBacktrace())
prune_versions(deps::Dict{String,Dict{VersionNumber,Available}}, bktrc::ResolveBacktrace) =
prune_versions(Dict{String,VersionSet}(), deps, bktrc)
prune_versions(env, deps::Dict{String,Dict{VersionNumber,Available}}) =
prune_versions(env, Dict{String,VersionSet}(), deps, ResolveBacktrace())
prune_versions(env, deps::Dict{String,Dict{VersionNumber,Available}}, bktrc::ResolveBacktrace) =
prune_versions(env, Dict{String,VersionSet}(), deps, bktrc)

# Build a graph restricted to a subset of the packages
function subdeps(deps::Dict{String,Dict{VersionNumber,Available}}, pkgs::Set{String})
Expand Down Expand Up @@ -286,17 +291,18 @@ function dependencies_subset(deps::Dict{String,Dict{VersionNumber,Available}}, p
return subdeps(deps, allpkgs)
end

function prune_dependencies(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}})
function prune_dependencies(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}}, uuid_to_name::Dict{String, String})
bktrc = ResolveBacktrace()
for (p,vs) in reqs
bktrc[p] = ResolveBacktraceItem(:required, vs)
end
return prune_dependencies(reqs, deps, bktrc)
return prune_dependencies(reqs, deps, bktrc, uuid_to_name)
end

function prune_dependencies(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}}, bktrc::ResolveBacktrace)
function prune_dependencies(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}},
bktrc::ResolveBacktrace, uuid_to_name::Dict{String, String})
deps = dependencies_subset(deps, Set{String}(keys(reqs)))
deps, _ = prune_versions(reqs, deps, bktrc)
deps, _ = prune_versions(reqs, deps, bktrc, uuid_to_name)

return deps
end
Expand Down
8 changes: 5 additions & 3 deletions src/Pkg2/resolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import ..PkgError
export resolve, sanity_check

# Use the max-sum algorithm to resolve packages dependencies
function resolve(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}})
function resolve(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}}, uuid_to_name::Dict{String,String})
# init interface structures
interface = Interface(reqs, deps)

Expand All @@ -28,13 +28,15 @@ function resolve(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available}
catch err
isa(err, UnsatError) || rethrow(err)
p = interface.pkgs[err.info]
name = haskey(uuid_to_name, p) ? uuid_to_name[p] : "UNKNOWN"
uuid_short = p[1:8]
# TODO: build tools to analyze the problem, and suggest to use them here.
msg =
"""
resolve is unable to satisfy package requirements.
The problem was detected when trying to find a feasible version
for package $p.
However, this only means that package $p is involved in an
for package $name [$uuid_short].
However, this only means that package $name [$uuid_short] is involved in an
unsatisfiable or difficult dependency relation, and the root of
the problem may be elsewhere.
"""
Expand Down

0 comments on commit 682cef5

Please sign in to comment.