hexpm / hex

Package manager for the Erlang ecosystem.
https://hex.pm
978 stars 187 forks source link

Incompatibility detected with unused optional dependencies #963

Closed maennchen closed 2 years ago

maennchen commented 2 years ago

Problem description

If two dependencies have incompatible optional dependencies and that optional dependency is not used, an error is raised when executing mix deps.get.

Example Error:

Resolving Hex dependencies...
#Incompatibility<#Term<your app>, cause: {:conflict, #Incompatibility<#Term<auth0_jwks >= 0.2.0>, cause: {:conflict, #Incompatibility<#Term<arc >= 0.7.0>, #Term<auth0_jwks >= 0.2.0>, cause: {:conflict, #Incompatibility<#Term<arc >= 0.7.0>, #Term<not poison ~> 2.2 or ~> 3.1 (optional)>, cause: :dependency>, #Incompatibility<#Term<auth0_jwks >= 0.2.0>, #Term<not poison ~> 4.0 (optional)>, cause: :dependency>}>, #Incompatibility<#Term<your app>, #Term<not arc ~> 0.11>, cause: :dependency>}>, #Incompatibility<#Term<your app>, #Term<not auth0_jwks ~> 0.3>, cause: :dependency>}>
Resolution completed in 0.024s
Because arc >= 0.7.0 depends on poison ~> 2.2 or ~> 3.1 and auth0_jwks >= 0.2.0 depends on poison ~> 4.0, arc >= 0.7.0 is incompatible with auth0_jwks >= 0.2.0.
And because your app depends on arc ~> 0.11, auth0_jwks >= 0.2.0 is forbidden.
So, because your app depends on auth0_jwks ~> 0.3, version solving failed.
** (Mix) Hex dependency resolution failed

Expected

No error

PS: When displaying the Incompatibility struct, it would help to format it on multiple lines. It's a bit hard to read right now being just one line.

Used Versions

Minimal Reproduction

defmodule HexProblem.MixProject do
  use Mix.Project

  def project do
    [
      deps: [
        {:arc, "~> 0.11"},
        {:auth0_jwks, "~> 0.3"},
      ]
    ]
  end
end
mgwidmann commented 2 years ago

Can confirm:

➜  options_tracker git:(main) mix deps.get
Resolving Hex dependencies...
#Incompatibility<#Term<your app>, cause: {:conflict, #Incompatibility<#Term<the lock>, cause: {:conflict, #Incompatibility<#Term<the lock>, #Term<not recaptcha 3.0.0 (optional)>, cause: :dependency>, #Incompatibility<#Term<recaptcha >= 3.0.0 and < 3.1.0>, #Term<the lock>, cause: {:conflict, #Incompatibility<#Term<recaptcha >= 3.0.0 and < 3.1.0>, #Term<not poison ~> 1.5.2 or ~> 2.2.0 or ~> 3.1.0 (optional)>, cause: :dependency>, #Incompatibility<#Term<the lock>, #Term<not poison 4.0.1 (optional)>, cause: :dependency>}>}>, #Incompatibility<#Term<your app>, #Term<not the lock>, cause: :dependency>}>
Resolution completed in 0.256s
Because recaptcha >= 3.0.0 and < 3.1.0 depends on poison ~> 1.5.2 or ~> 2.2.0 or ~> 3.1.0 and "the lock" specifies poison 4.0.1, recaptcha >= 3.0.0 and < 3.1.0 is incompatible with the lock.
And because "the lock" specifies recaptcha 3.0.0, no version of the lock is allowed.
So, because your app depends on the lock, version solving failed.
** (Mix) Hex dependency resolution failed
➜  options_tracker git:(main) git --no-pager log --date=short --pretty=format:"%h%x09%an%x09%ad%x09%s" -n3 mix.lock
aaf6f13 Matt Widmann    2022-10-21  Deployed to fly.io
7062c08 Matt Widmann    2022-10-20  Use latest branch for flames
8171734 Matt Widmann    2022-10-20  Upgrading phoenix and other elixir dependencies.%

https://github.com/mgwidmann/options_tracker

mgwidmann commented 2 years ago

Confirmed that doing mix hex.install 1.0.1 and then mix deps.get fixes the issue:

➜  options_tracker git:(main) mix hex.install 2.0.0
* creating /Users/matt/.kiex/mix/archives/elixir-1.14.1/hex-2.0.0
➜  options_tracker git:(main) mix deps.get
Resolving Hex dependencies...
#Incompatibility<#Term<your app>, cause: {:conflict, #Incompatibility<#Term<the lock>, cause: {:conflict, #Incompatibility<#Term<the lock>, #Term<not recaptcha 3.0.0 (optional)>, cause: :dependency>, #Incompatibility<#Term<recaptcha >= 3.0.0 and < 3.1.0>, #Term<the lock>, cause: {:conflict, #Incompatibility<#Term<recaptcha >= 3.0.0 and < 3.1.0>, #Term<not poison ~> 1.5.2 or ~> 2.2.0 or ~> 3.1.0 (optional)>, cause: :dependency>, #Incompatibility<#Term<the lock>, #Term<not poison 4.0.1 (optional)>, cause: :dependency>}>}>, #Incompatibility<#Term<your app>, #Term<not the lock>, cause: :dependency>}>
Resolution completed in 0.24s
Because recaptcha >= 3.0.0 and < 3.1.0 depends on poison ~> 1.5.2 or ~> 2.2.0 or ~> 3.1.0 and "the lock" specifies poison 4.0.1, recaptcha >= 3.0.0 and < 3.1.0 is incompatible with the lock.
And because "the lock" specifies recaptcha 3.0.0, no version of the lock is allowed.
So, because your app depends on the lock, version solving failed.
** (Mix) Hex dependency resolution failed
➜  options_tracker git:(main) mix hex.install 1.0.1
* creating /Users/matt/.kiex/mix/archives/elixir-1.14.1/hex-1.0.1
➜  options_tracker git:(main) mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
...
ericmj commented 2 years ago

The solver only makes sure optional dependencies aren't selected, it doesn't skip them during solving. It is something I am working on fixing but it will probably take some time until we have a fix in place.

In the mean time I would suggest using v1.0.1 or doing something like {:poison, ..., override: true, runtime: false} to select a version of the incompatible package but not include it in the release.

maennchen commented 2 years ago

@ericmj That's exactly what I did. In this case that works since Poison is also compatible at compile time.

Therefore this is not a pressing issue for me currently. But it should be solved anyways in the future :)

Thanks for having a look :heart: