Skip to content

Commit 41b5f4c

Browse files
author
José Valim
committed
Merge pull request #1122 from ericmj/mix-rebar
Handle rebar dependencies better
2 parents ac0ac7f + 406edcb commit 41b5f4c

File tree

13 files changed

+373
-63
lines changed

13 files changed

+373
-63
lines changed

lib/mix/lib/mix/deps.ex

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
defrecord Mix.Dep, [ scm: nil, app: nil, requirement: nil, status: nil, opts: nil,
2-
project: nil, deps: [] ] do
2+
deps: [], source: nil, manager: nil ] do
33
@moduledoc """
44
This is a record that keeps information about your project
55
dependencies. It keeps:
@@ -9,7 +9,9 @@ defrecord Mix.Dep, [ scm: nil, app: nil, requirement: nil, status: nil, opts: ni
99
* requirements - a binary or regexp with the deps requirement;
1010
* status - the current status of dependency, check `Mix.Deps.format_status/1` for more info;
1111
* opts - the options given by the developer
12-
* project - the Mix.Project for the dependency
12+
* source - any possible configuration associated with the manager field,
13+
rebar.config for rebar or the Mix.Project for Mix
14+
* manager - the project management, possible values: :rebar / :mix / nil
1315
"""
1416
end
1517

@@ -81,7 +83,7 @@ defmodule Mix.Deps do
8183
index = Mix.Dep.__index__(:app)
8284
Enum.each apps, fn(app) ->
8385
unless List.keyfind(deps, app, index) do
84-
Mix.shell.info message: "unknown dependency #{app} for env #{Mix.env}"
86+
Mix.shell.info "unknown dependency #{app} for env #{Mix.env}"
8587
end
8688
end
8789

@@ -93,7 +95,20 @@ defmodule Mix.Deps do
9395
changing the current working directory and loading the given
9496
project into the project stack.
9597
"""
96-
def in_dependency(Mix.Dep[app: app, opts: opts], post_config // [], fun) do
98+
def in_dependency(dep, post_config // [], fun)
99+
100+
def in_dependency(Mix.Dep[manager: :rebar, opts: opts], post_config, fun) do
101+
# Use post_config for rebar deps
102+
Mix.Project.post_config(post_config)
103+
Mix.Project.push(Mix.Rebar)
104+
try do
105+
File.cd!(opts[:dest], fn -> fun.(nil) end)
106+
after
107+
Mix.Project.pop
108+
end
109+
end
110+
111+
def in_dependency(Mix.Dep[app: app, opts: opts], post_config, fun) do
97112
env = opts[:env] || :prod
98113
old_env = Mix.env
99114

@@ -207,8 +222,8 @@ defmodule Mix.Deps do
207222
@doc """
208223
Returns all compile paths for the dependency.
209224
"""
210-
def compile_paths(Mix.Dep[app: app, opts: opts] = dep) do
211-
if mix?(dep) do
225+
def compile_paths(Mix.Dep[app: app, opts: opts, manager: manager]) do
226+
if manager == :mix do
212227
Mix.Project.in_project app, opts[:dest], fn _ ->
213228
Mix.Project.compile_paths
214229
end
@@ -220,31 +235,38 @@ defmodule Mix.Deps do
220235
@doc """
221236
Returns all load paths for the dependency.
222237
"""
223-
def load_paths(Mix.Dep[app: app, opts: opts] = dep) do
224-
if mix?(dep) do
225-
paths = Mix.Project.in_project app, opts[:dest], fn _ ->
226-
Mix.Project.load_paths
227-
end
228-
Enum.uniq paths
229-
else
230-
[ Path.join(opts[:dest], "ebin") ]
238+
def load_paths(Mix.Dep[manager: :mix, app: app, opts: opts]) do
239+
paths = Mix.Project.in_project app, opts[:dest], fn _ ->
240+
Mix.Project.load_paths
231241
end
242+
Enum.uniq paths
243+
end
244+
245+
def load_paths(Mix.Dep[manager: :rebar, opts: opts, source: source]) do
246+
# Add root dir and all sub dirs with ebin/ directory
247+
[ opts[:dest] | (source[:sub_dirs] || []) ]
248+
|> Enum.map(Path.wildcard(&1))
249+
|> List.concat
250+
|> Enum.map(fn path -> Path.join([opts[:dest], path, "ebin"]) end)
251+
|> Enum.filter(File.dir?(&1))
252+
end
253+
254+
def load_paths(Mix.Dep[manager: nil, opts: opts]) do
255+
[ Path.join(opts[:dest], "ebin") ]
232256
end
233257

234258
@doc """
235259
Returns true if dependency is a mix project.
236260
"""
237-
def mix?(dep) do
238-
dep.project != nil
261+
def mix?(Mix.Dep[manager: manager]) do
262+
manager == :mix
239263
end
240264

241265
@doc """
242266
Returns true if dependency is a rebar project.
243267
"""
244-
def rebar?(dep) do
245-
Enum.any? ["rebar.config", "rebar.config.script"], fn file ->
246-
File.regular? Path.join(dep.opts[:dest], file)
247-
end
268+
def rebar?(Mix.Dep[manager: manager]) do
269+
manager == :rebar
248270
end
249271

250272
@doc """

lib/mix/lib/mix/deps/converger.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ defmodule Mix.Deps.Converger do
2020
def all(rest, callback) do
2121
config = [ deps_path: Path.expand(Mix.project[:deps_path]),
2222
root_lockfile: Path.expand(Mix.project[:lockfile]) ]
23-
{ main, rest } = Mix.Deps.Retriever.all(rest, config,callback)
23+
{ main, rest } = Mix.Deps.Retriever.all(rest, config, callback)
2424
{ all(Enum.reverse(main), [], [], main), rest }
2525
end
2626

lib/mix/lib/mix/deps/retriever.ex

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ defmodule Mix.Deps.Retriever do
1414
provides a dependency in the wrong format.
1515
"""
1616
def all(post_config // []) do
17-
{ deps, _ } = all(nil, post_config, fn(dep, acc) -> { dep, acc } end)
17+
{ deps, _ } = all(nil, children(post_config), post_config, fn(dep, acc) -> { dep, acc } end)
1818
deps
1919
end
2020

@@ -24,22 +24,36 @@ defmodule Mix.Deps.Retriever do
2424
in case some processing is done.
2525
"""
2626
def all(rest, post_config // [], callback) do
27-
Enum.map_reduce children, rest, fn (dep, rest) ->
27+
all(rest, children(post_config), post_config, callback)
28+
end
29+
30+
defp all(rest, childs, post_config, callback) do
31+
Enum.map_reduce childs, rest, fn (dep, rest) ->
2832
{ dep, rest } = callback.(dep, rest)
2933

30-
if Mix.Deps.available?(dep) and mixfile?(dep) do
31-
{ dep, rest } = Mix.Deps.in_dependency dep, post_config, fn project ->
32-
{ deps, rest } = all(rest, callback)
34+
cond do
35+
Mix.Deps.available?(dep) and mixfile?(dep) ->
36+
Mix.Deps.in_dependency(dep, post_config, fn project ->
37+
{ deps, rest } = all(rest, children(post_config), post_config, callback)
3338

34-
# We need to call with_mix_project once again
35-
# here in case the dependency was not available
36-
# the first time and the callback hook just
37-
# happened to fetch it.
38-
{ with_mix_project(dep, project).deps(deps), rest }
39-
end
40-
end
39+
# We need to call with_mix_project once again
40+
# here in case the dependency was not available
41+
# the first time and the callback hook just
42+
# happened to fetch it.
43+
{ with_mix_project(dep, project).deps(deps), rest }
44+
end)
45+
46+
Mix.Deps.available?(dep) and rebarconfig?(dep) ->
47+
dep = rebar_dep(dep)
4148

42-
{ dep, rest }
49+
Mix.Deps.in_dependency(dep, post_config, fn _ ->
50+
{ deps, rest } = all(rest, rebar_children("."), post_config, callback)
51+
{ dep.deps(deps), rest }
52+
end)
53+
54+
true ->
55+
{ dep, rest }
56+
end
4357
end
4458
end
4559

@@ -48,21 +62,10 @@ defmodule Mix.Deps.Retriever do
4862
as a `Mix.Dep` record. Unlike with `all` the `deps`
4963
field is not populated.
5064
"""
51-
def children() do
52-
deps = Mix.project[:deps] || []
53-
scms = Mix.SCM.available
54-
55-
Enum.map deps, fn dep ->
56-
dep = with_scm_and_status(dep, scms)
57-
58-
if Mix.Deps.available?(dep) and mixfile?(dep) do
59-
Mix.Deps.in_dependency dep, fn project ->
60-
with_mix_project(dep, project)
61-
end
62-
else
63-
dep
64-
end
65-
end
65+
def children(post_config // []) do
66+
Mix.Project.recur(post_config, fn _ ->
67+
(Mix.project[:deps] || []) |> setup_deps
68+
end) |> List.concat
6669
end
6770

6871
@doc """
@@ -74,16 +77,50 @@ defmodule Mix.Deps.Retriever do
7477

7578
## Helpers
7679

77-
defp with_mix_project(Mix.Dep[project: nil] = dep, project) do
80+
defp rebar_children(dir) do
81+
Mix.Rebar.recur(dir, fn config ->
82+
Mix.Rebar.deps(config) |> setup_deps
83+
end) |> List.concat
84+
end
85+
86+
defp setup_deps(deps) do
87+
scms = Mix.SCM.available
88+
89+
Enum.map deps, fn dep ->
90+
dep = with_scm_and_status(dep, scms)
91+
92+
cond do
93+
Mix.Deps.available?(dep) and mixfile?(dep) ->
94+
Mix.Deps.in_dependency(dep, fn project ->
95+
with_mix_project(dep, project)
96+
end)
97+
98+
Mix.Deps.available?(dep) and rebarconfig?(dep) ->
99+
rebar_dep(dep)
100+
101+
true ->
102+
dep
103+
end
104+
end
105+
end
106+
107+
defp with_mix_project(Mix.Dep[manager: nil] = dep, project) do
78108
if match?({ :noappfile, _ }, dep.status) and Mix.Project.umbrella? do
79109
dep = dep.update_opts(Keyword.put(&1, :app, false))
80110
.status({ :ok, nil })
81111
end
82-
dep.project(project)
112+
dep.manager(:mix).source(project)
83113
end
84114

85115
defp with_mix_project(dep, _project), do: dep
86116

117+
defp rebar_dep(Mix.Dep[manager: nil, opts: opts] = dep) do
118+
config = Mix.Rebar.load_config(opts[:dest])
119+
dep.manager(:rebar).source(config)
120+
end
121+
122+
defp rebar_dep(dep), do: dep
123+
87124
defp with_scm_and_status({ app, opts }, scms) when is_atom(app) and is_list(opts) do
88125
with_scm_and_status({ app, nil, opts }, scms)
89126
end
@@ -156,6 +193,12 @@ defmodule Mix.Deps.Retriever do
156193
defp vsn_match?(expected, actual) when is_regex(expected), do: actual =~ expected
157194

158195
defp mixfile?(dep) do
159-
File.regular?(Path.join dep.opts[:dest], "mix.exs")
196+
File.regular?(Path.join(dep.opts[:dest], "mix.exs"))
197+
end
198+
199+
defp rebarconfig?(dep) do
200+
Enum.any?(["rebar.config", "rebar.config.script"], fn file ->
201+
File.regular?(Path.join(dep.opts[:dest], file))
202+
end)
160203
end
161204
end

lib/mix/lib/mix/project.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ defmodule Mix.Project do
149149
use this function to transparently go through the project, regardless
150150
if it is an umbrella project or not.
151151
"""
152-
def recur(fun) do
152+
def recur(post_config // [], fun) do
153153
if apps_path = config[:apps_path] do
154154
paths = Path.wildcard(Path.join(apps_path, "*"))
155155
paths = Enum.filter(paths, File.dir?(&1))
@@ -163,11 +163,12 @@ defmodule Mix.Project do
163163
projects = topsort_projects(projects, Path.expand(apps_path))
164164

165165
results = Enum.map projects, fn { app, app_path } ->
166-
in_project(app, app_path, fun)
166+
in_project(app, app_path, post_config, fun)
167167
end
168168

169169
results
170170
else
171+
# Note that post_config isnt used for this case
171172
[fun.(get)]
172173
end
173174
end

0 commit comments

Comments
 (0)