JuliaLang / Pkg.jl

Pkg - Package manager for the Julia programming language
https://pkgdocs.julialang.org
Other
620 stars 260 forks source link

Can the function `Resolve.sanity_check` be moved to be a test utility? #2164

Open KristofferC opened 3 years ago

KristofferC commented 3 years ago

It is only called from the tests, could it be moved there? If not, when it is supposed to be used in Pkg? cc @carlobaldassi

carlobaldassi commented 3 years ago

Indeed, it's only used for testing that the repository information does not have any inconsistencies. It used to be ran by pull-requests against METADATA in Pkg2 times, I'm not sure whether it's used in the general registry now. But I suppose it could still be useful for registries in general?

KristofferC commented 3 years ago

Could you give a description of what it does and how you are supposed to use it? You load all of the registry and run it and it finds inconsistencies?

carlobaldassi commented 3 years ago

Basically yes. You build a Graph object from the dependency data, and pass it to sanity_check. It then simplifies the graph keeping only the packages that are compatible with the current julia version, and it also groups together versions that are indistinguishable from the point of view of the resolver (they have the same dependencies and they always appear together in all the requirements). Then it simulates the installation of each version of each package one by one, as if it was the only requirement. If it finds that a version of a package cannot be installed (the resolution process fails), then it assumes that there is an inconsistency. It returns the list of un-installable (package,version). It's pretty heavy, obviously.

KristofferC commented 3 years ago

I'll try run it on the current registry to see what the status is.

KristofferC commented 3 years ago

For posterity, here is some code that runs it on the registry using https://github.com/JuliaLang/Pkg.jl/pull/2163

using Pkg
using Pkg.Types
using Pkg: RegistryHandling, Resolve
reg = Context().env.registries[1]

all_versions = VersionsDict()
all_compat   = CompatDict()
uuid_to_name = Dict{UUID, String}()
reqs = Resolve.Requires()
fixed = Dict{UUID, Resolve.Fixed}()

for (uuid, pkg) in reg
    pkg_info = RegistryHandling.registry_info(pkg)
    uuid_to_name[pkg.uuid] = pkg.name
    all_versions[pkg.uuid] = keys(pkg_info.version_info)
    all_compat[pkg.uuid] = RegistryHandling.uncompressed_data(pkg_info)
end

# Add stdlibs
for (uuid, name) in Pkg.Types.stdlibs()
    path = Pkg.Types.stdlib_path(stdlibs()[uuid])
    proj_file = Pkg.Operations.projectfile_path(path; strict=true)
    proj = Pkg.Operations.read_package(proj_file)
    all_compat_u_vr = Dict{UUID, VersionSpec}()
    for (_, other_uuid) in proj.deps
        all_compat_u_vr[other_uuid] = VersionSpec()
    end
    v = something(proj.version, VERSION)
    all_compat[uuid] = Dict(VERSION => all_compat_u_vr)
    all_versions[uuid] = Set((VERSION,))
    uuid_to_name[uuid] = name
end

g = Resolve.Graph(all_versions, all_compat, uuid_to_name, reqs, fixed, false, VERSION)

Resolve.sanity_check(g)
KristofferC commented 3 years ago
julia> include("/home/kristofferc/julia/reg_sanity.jl")
found 418 problematic versions
10633.818614 seconds (29.62 G allocations: 1.728 TiB, 13.15% gc time, 0.00% compilation time)
418-element Vector{Tuple{String, VersionNumber}}:
 ("AmplNLReader [77dd3d4c]", v"0.1.0")
 ("ApplicationBuilder [f9309374]", v"0.2.1")
 ("ApplicationBuilder [f9309374]", v"0.3.1")
 ("ApproxFun [28f2ccd6]", v"0.9.0")
 ("ApproxFun [28f2ccd6]", v"0.10.1")
 ("ApproxFun [28f2ccd6]", v"0.10.2")
 ("ApproxFun [28f2ccd6]", v"0.10.3")
 ("ApproxFun [28f2ccd6]", v"0.10.4")
...

Here is a full list: https://gist.github.com/KristofferC/79566b8588bc7049c9e058bc8a08579d

And indeed:

(@v1.6) pkg> add ApproxFun@0.9.0
   Resolving package versions...
ERROR: Unsatisfiable requirements detected for package BlockArrays [8e7c35d0]:
 BlockArrays [8e7c35d0] log:
 ├─possible versions are: 0.4.1-0.12.13 or uninstalled
 ├─restricted by compatibility requirements with ApproxFun [28f2ccd6] to versions: 0.4.1
 │ └─ApproxFun [28f2ccd6] log:
 │   ├─possible versions are: 0.9.0-0.12.2 or uninstalled
 │   └─restricted to versions 0.9.0 by an explicit requirement, leaving only versions 0.9.0
 └─restricted by compatibility requirements with BlockBandedMatrices [ffab5731] to versions: 0.5.0-0.7.0 — no versions left
   └─BlockBandedMatrices [ffab5731] log:
     ├─possible versions are: 0.2.0-0.9.5 or uninstalled
     └─restricted by compatibility requirements with ApproxFun [28f2ccd6] to versions: 0.2.0
       └─ApproxFun [28f2ccd6] log: see above

What should be done with these versions? Also, 3 hours is a bit long for CI probably :P