Skip to content

Commit db83f33

Browse files
committed
Fix exotic candidate resolution
1 parent 8a70aee commit db83f33

4 files changed

Lines changed: 74 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 0.7.1
4+
5+
### Fixed
6+
7+
- Skip package versions with blocked transitive exotic dependencies during dependency solving instead of aborting resolution before a safe version can be selected.
8+
39
## 0.7.0
410

511
### Breaking changes

lib/npm/resolver.ex

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,10 @@ defmodule NPM.Resolver do
256256

257257
defp parse_sorted_versions(packument) do
258258
packument.versions
259-
|> Map.keys()
260-
|> Enum.flat_map(fn v ->
259+
|> Enum.reject(fn {version_str, info} ->
260+
exotic_candidate?(packument.name, version_str, info)
261+
end)
262+
|> Enum.flat_map(fn {v, _info} ->
261263
case Version.parse(v) do
262264
{:ok, version} -> [version]
263265
:error -> []
@@ -266,6 +268,13 @@ defmodule NPM.Resolver do
266268
|> Enum.sort(Version)
267269
end
268270

271+
defp exotic_candidate?(package, version_str, info) do
272+
ExoticDeps.validate!(package, version_str, info)
273+
false
274+
rescue
275+
ExoticDeps.Error -> true
276+
end
277+
269278
defp deps_for_version(package, packument, version_str) do
270279
excluded = get_excluded()
271280

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule NPM.MixProject do
22
use Mix.Project
33

4-
@version "0.7.0"
4+
@version "0.7.1"
55
@source_url "https://github.com/elixir-volt/npm_ex"
66

77
def project do
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
defmodule NPM.ResolverExoticCandidateTest do
2+
use ExUnit.Case, async: false
3+
4+
@table :npm_resolver_cache
5+
6+
setup do
7+
NPM.Resolver.clear_cache()
8+
ensure_table!()
9+
10+
on_exit(fn -> NPM.Resolver.clear_cache() end)
11+
12+
:ok
13+
end
14+
15+
test "versions excludes candidates with blocked transitive exotic dependencies" do
16+
package = "__exotic_filter__"
17+
18+
:ets.insert(@table, {
19+
package,
20+
%{
21+
name: package,
22+
versions: %{
23+
"1.0.0" => version_info(%{"payload" => "file:./payload"}),
24+
"1.0.1" => version_info(%{})
25+
}
26+
}
27+
})
28+
29+
assert {:ok, versions} = NPM.Resolver.versions(nil, package)
30+
assert versions == [Version.parse!("1.0.1")]
31+
end
32+
33+
defp version_info(dependencies) do
34+
%{
35+
dependencies: dependencies,
36+
optional_dependencies: %{},
37+
peer_dependencies: %{},
38+
peer_dependencies_meta: %{},
39+
bin: %{},
40+
engines: %{},
41+
os: [],
42+
cpu: [],
43+
has_install_script: false,
44+
deprecated: nil,
45+
created_at: nil,
46+
published_at: nil,
47+
dist: %{tarball: "", integrity: "", file_count: nil, unpacked_size: nil}
48+
}
49+
end
50+
51+
defp ensure_table! do
52+
if :ets.whereis(@table) == :undefined do
53+
:ets.new(@table, [:named_table, :set, :public])
54+
end
55+
end
56+
end

0 commit comments

Comments
 (0)