diff --git a/src/Operations.jl b/src/Operations.jl index 2801d79241449..469a5e7f09cf3 100644 --- a/src/Operations.jl +++ b/src/Operations.jl @@ -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 @@ -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 diff --git a/src/Pkg2/query.jl b/src/Pkg2/query.jl index 80ecf2e33b680..912972b8e058b 100644 --- a/src/Pkg2/query.jl +++ b/src/Pkg2/query.jl @@ -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) @@ -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.""" @@ -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)) @@ -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 @@ -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}) @@ -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 diff --git a/src/Pkg2/resolve.jl b/src/Pkg2/resolve.jl index b2b81528956d3..6e10eee3c4f48 100644 --- a/src/Pkg2/resolve.jl +++ b/src/Pkg2/resolve.jl @@ -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) @@ -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. """