Skip to content

Commit 5c1ae1c

Browse files
committed
Rebar3 dependency support
1 parent a60d79a commit 5c1ae1c

File tree

15 files changed

+429
-130
lines changed

15 files changed

+429
-130
lines changed

lib/mix/lib/mix/dep.ex

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ defmodule Mix.Dep do
2323
* `top_level` - true if dependency was defined in the top-level project
2424
2525
* `manager` - the project management, possible values:
26-
`:rebar` | `:mix` | `:make` | `nil`
26+
`:rebar` | `:rebar3` | `:mix` | `:make` | `nil`
2727
2828
* `from` - path to the file where the dependency was defined
2929
@@ -57,7 +57,7 @@ defmodule Mix.Dep do
5757
status: atom,
5858
opts: Keyword.t,
5959
top_level: boolean,
60-
manager: :rebar | :mix | :make | nil,
60+
manager: :rebar | :rebar3 | :mix | :make | nil,
6161
from: String.t,
6262
extra: term}
6363

@@ -343,7 +343,7 @@ defmodule Mix.Dep do
343343
Returns `true` if dependency is a rebar project.
344344
"""
345345
def rebar?(%Mix.Dep{manager: manager}) do
346-
manager == :rebar
346+
manager in [:rebar, :rebar3]
347347
end
348348

349349
@doc """

lib/mix/lib/mix/dep/converger.ex

+10-12
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ defmodule Mix.Dep.Converger do
6565
# iteration.
6666
{deps, rest, lock} =
6767
all(main, only, [], current, callback, acc, lock, fn dep ->
68-
if (converger = Mix.RemoteConverger.get) &&
69-
converger.remote?(dep) do
68+
if (converger = Mix.RemoteConverger.get) && converger.remote?(dep) do
7069
{:loaded, dep}
7170
else
7271
{:unloaded, dep, nil}
@@ -79,21 +78,21 @@ defmodule Mix.Dep.Converger do
7978

8079
# Run remote converger if one is available and rerun Mix's
8180
# converger with the new information
82-
if converger = Mix.RemoteConverger.get do
81+
if remote = Mix.RemoteConverger.get do
8382
# If there is a lock, it means we are doing a get/update
8483
# and we need to hit the remote converger which do external
8584
# requests and what not. In case of deps.check, deps and so
8685
# on, there is no lock, so we won't hit this branch.
8786
if lock do
88-
lock = converger.converge(deps, lock)
87+
lock = remote.converge(deps, lock)
8988
end
9089

9190
deps = deps
92-
|> Enum.reject(&converger.remote?(&1))
91+
|> Enum.reject(&remote.remote?(&1))
9392
|> Enum.into(%{}, &{&1.app, &1})
9493

9594
# In case there is no lock, we will read the current lock
96-
# which is potentially stale. So converger.deps/2 needs to
95+
# which is potentially stale. So remote.deps/2 needs to
9796
# always check if the data it finds in the lock is actually
9897
# valid.
9998
lock_for_converger = lock || Mix.Dep.Lock.read
@@ -103,7 +102,7 @@ defmodule Mix.Dep.Converger do
103102
cached = deps[dep.app] ->
104103
{:loaded, cached}
105104
true ->
106-
{:unloaded, dep, converger.deps(dep, lock_for_converger)}
105+
{:unloaded, dep, remote.deps(dep, lock_for_converger)}
107106
end
108107
end)
109108
else
@@ -258,13 +257,12 @@ defmodule Mix.Dep.Converger do
258257
end
259258

260259
defp converge?(%Mix.Dep{scm: scm1, opts: opts1}, %Mix.Dep{scm: scm2, opts: opts2}) do
261-
scm1 == scm2 and mix_equal?(opts1, opts2) and scm1.equal?(opts1, opts2)
260+
scm1 == scm2 and opts_equal?(opts1, opts2) and scm1.equal?(opts1, opts2)
262261
end
263262

264-
defp mix_equal?(opts1, opts2) do
265-
Keyword.fetch(opts1, :app) == Keyword.fetch(opts2, :app) and
266-
Keyword.fetch(opts1, :env) == Keyword.fetch(opts2, :env) and
267-
Keyword.fetch(opts1, :compile) == Keyword.fetch(opts2, :compile)
263+
defp opts_equal?(opts1, opts2) do
264+
keys = ~w(app env compile manager)a
265+
Enum.all?(keys, &(Keyword.fetch(opts1, &1) == Keyword.fetch(opts2, &1)))
268266
end
269267

270268
defp reject_non_fullfilled_optional(children, upper_breadths) do

lib/mix/lib/mix/dep/loader.ex

+54-35
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
defmodule Mix.Dep.Loader do
55
@moduledoc false
66

7+
import Mix.Dep, only: [ok?: 1, mix?: 1, rebar?: 1, make?: 1]
8+
79
@doc """
810
Gets all direct children of the current `Mix.Project`
911
as a `Mix.Dep` struct. Umbrella project dependencies
@@ -37,25 +39,27 @@ defmodule Mix.Dep.Loader do
3739
Loads the given dependency information, including its
3840
latest status and children.
3941
"""
40-
def load(dep, children) do
41-
%Mix.Dep{manager: manager, scm: scm, opts: opts} = dep
42-
dep = %{dep | status: scm_status(scm, opts)}
43-
dest = opts[:dest]
42+
def load(%Mix.Dep{manager: manager, scm: scm, opts: opts} = dep, children) do
43+
manager = opts[:manager] ||
44+
scm_manager(scm, opts) ||
45+
select_manager(manager, opts[:dest])
46+
47+
dep = %{dep | manager: manager, status: scm_status(scm, opts)}
4448

4549
{dep, children} =
4650
cond do
47-
not ok?(dep.status) ->
51+
not ok?(dep) ->
4852
{dep, []}
4953

50-
mix?(dest) ->
54+
mix?(dep) ->
5155
mix_dep(dep, children)
5256

5357
# If not an explicit rebar or Mix dependency
5458
# but came from rebar, assume to be a rebar dep.
55-
rebar?(dest) or manager == :rebar ->
56-
rebar_dep(dep, children)
59+
rebar?(dep) ->
60+
rebar_dep(dep, children, manager)
5761

58-
make?(dest) ->
62+
make?(dep) ->
5963
make_dep(dep)
6064

6165
true ->
@@ -155,11 +159,18 @@ defmodule Mix.Dep.Loader do
155159
end
156160

157161
defp get_scm(app, opts) do
158-
Enum.find_value Mix.SCM.available, {nil, opts}, fn(scm) ->
162+
Enum.find_value Mix.SCM.available, {nil, opts}, fn scm ->
159163
(new = scm.accepts_options(app, opts)) && {scm, new}
160164
end
161165
end
162166

167+
@managers ~w(mix rebar rebar3 make)a
168+
169+
defp scm_manager(scm, opts) do
170+
managers = scm.managers(opts)
171+
Enum.find(@managers, &(&1 in managers))
172+
end
173+
163174
defp scm_status(scm, opts) do
164175
if scm.checked_out?(opts) do
165176
{:ok, nil}
@@ -168,19 +179,21 @@ defmodule Mix.Dep.Loader do
168179
end
169180
end
170181

171-
defp ok?({:ok, _}), do: true
172-
defp ok?(_), do: false
173-
174-
defp mix?(dest) do
175-
any_of?(dest, ["mix.exs"])
176-
end
177-
178-
defp rebar?(dest) do
179-
any_of?(dest, ["rebar", "rebar.config", "rebar.config.script"])
182+
defp select_manager(nil, dest) do
183+
cond do
184+
any_of?(dest, ["mix.exs"]) ->
185+
:mix
186+
any_of?(dest, ["rebar", "rebar.config", "rebar.config.script"]) ->
187+
:rebar
188+
any_of?(dest, ["Makefile", "Makefile.win"]) ->
189+
:make
190+
true ->
191+
nil
192+
end
180193
end
181194

182-
defp make?(dest) do
183-
any_of?(dest, ["Makefile", "Makefile.win"])
195+
defp select_manager(manager, _dest) do
196+
manager
184197
end
185198

186199
defp any_of?(dest, files) do
@@ -227,7 +240,7 @@ defmodule Mix.Dep.Loader do
227240
end
228241

229242
deps = mix_children(env: opts[:env] || :prod) ++ Mix.Dep.Umbrella.unloaded
230-
{%{dep | manager: :mix, opts: opts}, deps}
243+
{%{dep | opts: opts}, deps}
231244
end)
232245
end
233246

@@ -238,25 +251,28 @@ defmodule Mix.Dep.Loader do
238251
defp mix_dep(%Mix.Dep{opts: opts} = dep, children) do
239252
from = Path.join(opts[:dest], "mix.exs")
240253
deps = Enum.map(children, &to_dep(&1, from))
241-
{%{dep | manager: :mix}, deps}
254+
{dep, deps}
242255
end
243256

244-
defp rebar_dep(%Mix.Dep{} = dep, children) do
257+
defp rebar_dep(%Mix.Dep{app: app} = dep, children, manager) do
245258
Mix.Dep.in_dependency(dep, fn _ ->
246-
rebar = Mix.Rebar.load_config(".")
247-
extra = Keyword.take(rebar, [:sub_dirs])
248-
deps = if children do
259+
config = Mix.Rebar.load_config(".")
260+
extra = Mix.Rebar.merge_config(dep.extra, config)
261+
deps = if children do
249262
from = Path.absname("rebar.config")
250-
Enum.map(children, &to_dep(&1, from, :rebar))
263+
# Pass the manager because deps of a rebar project need
264+
# to default to rebar if we cannot chose a manager from
265+
# files in the dependency
266+
Enum.map(children, &to_dep(&1, from, manager))
251267
else
252-
rebar_children(rebar)
268+
rebar_children(app, config, extra, manager)
253269
end
254-
{%{dep | manager: :rebar, extra: extra}, deps}
270+
{%{dep | extra: extra}, deps}
255271
end)
256272
end
257273

258274
defp make_dep(dep) do
259-
{%{dep | manager: :make}, []}
275+
{dep, []}
260276
end
261277

262278
defp validate_only!(only) do
@@ -274,18 +290,21 @@ defmodule Mix.Dep.Loader do
274290
|> elem(0)
275291
end
276292

277-
defp rebar_children(root_config) do
293+
defp rebar_children(app, root_config, extra, manager) do
278294
from = Path.absname("rebar.config")
279295
Mix.Rebar.recur(root_config, fn config ->
280-
Mix.Rebar.deps(config) |> Enum.map(&to_dep(&1, from, :rebar))
296+
deps = Mix.Rebar.deps(app, config, extra[:overrides] || [])
297+
Enum.map(deps, fn dep ->
298+
%{to_dep(dep, from, manager) | extra: extra}
299+
end)
281300
end) |> Enum.concat
282301
end
283302

284-
defp validate_app(%Mix.Dep{opts: opts, requirement: req, app: app, status: status} = dep) do
303+
defp validate_app(%Mix.Dep{opts: opts, requirement: req, app: app} = dep) do
285304
opts_app = opts[:app]
286305

287306
cond do
288-
not ok?(status) ->
307+
not ok?(dep) ->
289308
dep
290309
recently_fetched?(dep) ->
291310
%{dep | status: :compile}

0 commit comments

Comments
 (0)