Optional Mix deps being fetched with rebar3 plugins?

I have a rebar3 project that I am adding some Elixir deps. I want to keep the deps minimal, and that includes not fetching optional deps. It seems that the libraries that I have tried to use, rebar3_hex, and rebar3_elixir namely, fetch deps that are listed as optional in a project’s mix.exs file. An example is Jason: the decimal dep is fetched. It doesn’t seem as though rebar3 supports optional deps, and it doesn’t look like the mix.lock file contains the relevant metadata to declare that a top level dep is optional. I think the plugins fetch deps by parsing the mix.lock file and constructing a rebar.lock file. Is there any rebar3 plugin or convention that I could be missing that could support this functionality?

The rebar_mix plugin work by using the list of dependencies from the hex metadata.

My guess is rebar3 would need to be updated to ignore deps marked as optional.

This was never done because it currently, and may always, mean nothing to Erlang projects because unlike Mix the deps list and the .app file are completely separate. I could see that changing since we already have a .app.src it would be possible to add a feature of parsing the applications list and if the app is {app, optional} drop it or change it to just app depending on if the app is included in the final dependencies of the project.

Anyway… got off topic there, tldr: rebar3 needs to learn to ignore dependencies marked as optional in the hex metadata.

2 Likes

Would an optional field need to be added here: https://github.com/erlang/rebar3/blob/master/src/rebar_app_info.erl#L79
then checked in maybe_fetch here: https://github.com/erlang/rebar3/blob/master/src/rebar_prv_install_deps.erl#L330 ?
Optional would be set to false if the dep is a top-level dep in the current list?

Looks like hex returns the metadata with the Fetch a Release endpoint according to their docs:

...
              "dependencies": {
                "cowboy": {
                  "requirement": "~> 1.0",
                  "optional": true,
                  "app": "cowboy"
                }
              }

Is the package info fetched from hex used anywhere? All I see if a check for errors and printing in rebar_prv_packages.erl from the result of this call https://github.com/erlang/rebar3/blob/f23e5a423347c0b04d8513410132a875f3767340/src/rebar_packages.erl#L33

The optional information is in the registry so rebar3 has the information before fetching the package.

1 Like

I think it might be acceptable to just change https://github.com/erlang/rebar3/blob/master/src/rebar_packages.erl#L232-L235 to:

parse_deps(Deps) ->
    [{maps:get(app, D, Name), {pkg, Name, Constraint, undefined}}
     || D=#{package := Name,
            requirement := Constraint.
            optional := false} <- Deps].