JuliaLang / Pkg.jl

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

Feature request (with code!): Search for registered packages + display releases #3926

Open haakon-e opened 2 weeks ago

haakon-e commented 2 weeks ago

Pkg has seen amazing improvements in the past few versions, with indicators for packages that are upgradeable, hindered from being upgraded, and so on.

One feature I'm missing that I've found in other ecosystems is a "search" functionality with some basic information about the packages.

Personally, I'm most interested in learning about package versions and url, a small blurb/about-me could be useful too (see related discussions below for potential approaches)

I'm envisioning something along the lines of:


pkg> search Makie
Package 'Makie' is available from:
- "General" registry
    Most recent releases: 0.21.2, 0.21.1, 0.21.0, 0.20.10, 0.20.9
    Repository: https://github.com/MakieOrg/Makie.jl.git

[Potentially / easy to support too:] 
- "OtherInstalledRegistry" registry
    [...]

Below is a quickly hacked together code for obtaining version history for a given package in the General registry, mostly achieved by poking into Pkgs existing internals (e.g. Pkg.status(), Pkg.print_status(...), Pkg.Types.Context())

import Pkg: Pkg, API, Operations, Registry

function search(pkgname; min_version = v"0.0.0", max_version = nothing)
    registries = Registry.reachable_registries();  # can loop over this to print info from all installed registries
    reg_ind = findfirst(r -> r.name == "General", registries);
    reg = registries[reg_ind];
    pkguuids_in_registry = collect(keys(reg.pkgs));
    pkgnames_in_registry = [reg.pkgs[key].name for key in pkguuids_in_registry];

    pkgname_ind = findfirst(==(pkgname), pkgnames_in_registry);
    pkguuid = pkguuids_in_registry[pkgname_ind]

    reg_pkg = get(reg, pkguuid, nothing);  # Pkg.Registry.PkgEntry

    info = Registry.registry_info(reg_pkg);
    reg_compat_info = Registry.compat_info(info);
    versions = keys(reg_compat_info);
    versions = Base.filter(v -> !Registry.isyanked(info, v), collect(versions));
    versions_sorted = sort(versions, rev=true)

    # filter between min_version and max_version
    max_version = isnothing(max_version) ? maximum(versions_sorted; init=v"0") : max_version
    filter!(v -> min_version <= v <= max_version, versions_sorted) 

    version_list = versions_sorted[1:min(5, length(versions_sorted))]
    pkg_url = info.repo

    # Prints what is shown above
    println("Package '$pkgname' is available from:")
    println("- '$(reg.name)' registry")
    println("    Most recent releases: $(join(version_list, ", "))")
    println("    Repository: $pkg_url")
    nothing
end

Having written the code first, then discovered all the discussion about this already (as one does...), I realize more thinking may be needed to hone down a really great long-term interface. That said, I hope a variant of this suggestion can be a small, but practically achievable step, in this direction.


relevant issue(s): #3259, #2613, #1397 (with great discussion) Related to (but smaller(?) in scope than): discourse#98813 Tags/metadata aspect also described in: #1967, #1070 (includes similar code to the above) Similar goals, but web-based: https://juliapackages.com

KristofferC commented 2 weeks ago

While I understand it can be nice to do everything from Pkg itself I am not sure it is worth spending much effort on to this when you can just go to https://juliahub.com/ui/Packages/ or https://juliapackages.com/ etc and have a much better experience with graphs and tables etc than what Pkg can ever provide.