List an exact match first in package search (#1355)

This commit is contained in:
Jonatan Kłosko 2022-08-24 10:59:26 +02:00 committed by GitHub
parent 942e0ca113
commit 2c28d1a0ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 2 deletions

View file

@ -203,13 +203,17 @@ defmodule Livebook.Runtime.Dependencies do
def search_hex(search, opts) do
api_url = opts[:api_url] || "https://hex.pm/api"
params = %{"search" => "name:#{search}*", "sort" => "downloads"}
params = %{"search" => "name:#{search}*", "sort" => "recent_downloads"}
url = api_url <> "/packages?" <> URI.encode_query(params)
case Livebook.Utils.HTTP.request(:get, url) do
{:ok, status, _headers, body} ->
with 200 <- status, {:ok, packages} <- Jason.decode(body) do
packages = Enum.map(packages, &parse_package/1)
packages =
packages
|> Enum.map(&parse_package/1)
|> reorder_packages(search)
{:ok, packages}
else
_ -> {:error, "unexpected response"}
@ -231,4 +235,15 @@ defmodule Livebook.Runtime.Dependencies do
dependency: dependency
}
end
defp reorder_packages(packages, search) do
case Enum.find_index(packages, &(&1.name == search)) do
nil ->
packages
exact_idx ->
{package, packages} = List.pop_at(packages, exact_idx)
[package | packages]
end
end
end

View file

@ -265,6 +265,58 @@ defmodule Livebook.Runtime.DependenciesTest do
]}
end
test "lists a package matching exactly first", %{bypass: bypass} do
Bypass.expect_once(bypass, "GET", "/api/packages", fn conn ->
conn
|> Plug.Conn.put_resp_content_type("application/json")
|> Plug.Conn.resp(200, ~S"""
[
{
"configs": {
"erlang.mk": "dep_ecto_sql = hex 3.7.2",
"mix.exs": "{:ecto_sql, \"~> 3.7\"}",
"rebar.config": "{ecto_sql, \"3.7.2\"}"
},
"docs_html_url": "https://hexdocs.pm/ecto_sql/",
"html_url": "https://hex.pm/packages/ecto_sql",
"latest_stable_version": "3.7.2",
"latest_version": "3.7.2",
"meta": {
"description": "SQL-based adapters for Ecto and database migrations",
"licenses": ["Apache-2.0"],
"links": { "GitHub": "https://github.com/elixir-ecto/ecto_sql" }
},
"name": "ecto_sql",
"url": "https://hex.pm/api/packages/ecto_sql"
},
{
"configs": {
"erlang.mk": "dep_ecto = hex 3.7.2",
"mix.exs": "{:ecto, \"~> 3.7\"}",
"rebar.config": "{ecto, \"3.7.2\"}"
},
"docs_html_url": "https://hexdocs.pm/ecto/",
"html_url": "https://hex.pm/packages/ecto",
"latest_stable_version": "3.7.2",
"latest_version": "3.7.2",
"meta": {
"description": "A toolkit for data mapping and language integrated query for Elixir",
"licenses": ["Apache-2.0"],
"links": { "GitHub": "https://github.com/elixir-ecto/ecto" }
},
"name": "ecto",
"url": "https://hex.pm/api/packages/ecto"
}
]
""")
end)
api_url = api_url(bypass.port)
assert {:ok, [%{name: "ecto"}, %{name: "ecto_sql"}]} =
Dependencies.search_hex("ecto", api_url: api_url)
end
test "returns an error on unsuccessful API response", %{bypass: bypass} do
Bypass.expect_once(bypass, "GET", "/api/packages", fn conn ->
Plug.Conn.resp(conn, 500, "Error")