Skip to content

Commit f97a384

Browse files
author
José Valim
committed
Move dependencies callbacks back into Mix.Deps.Converger
The converger is the one that knows if a dependency exists or not and, as such, is the best one to know if a dependency callback should be invoked or not. This commit also normalizes some of the Retriever internal functions, for example, now we have mix_children and rebar_children. The goal is to extract those functions (and the ones in Mix.Deps) one by one into a Mix.DepsManager behaviour which will be implemented by Mix.DepsManager.Mix and Mix.DepsManager.Rebar, removing all the conditional calls existing in the code.
1 parent 7e856e1 commit f97a384

File tree

3 files changed

+55
-90
lines changed

3 files changed

+55
-90
lines changed

lib/mix/lib/mix/deps.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,12 @@ defmodule Mix.Deps do
243243
end
244244

245245
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] || []) ]
246+
subdirs = (source[:sub_dirs] || [])
248247
|> Enum.map(Path.wildcard(&1))
249248
|> List.concat
250249
|> Enum.map(fn path -> Path.join([opts[:dest], path, "ebin"]) end)
251-
|> Enum.filter(File.dir?(&1))
250+
251+
[Path.join(opts[:dest], "ebin")|subdirs] |> Enum.filter(File.dir?(&1))
252252
end
253253

254254
def load_paths(Mix.Dep[manager: nil, opts: opts]) do

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

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ 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)
24-
{ all(Enum.reverse(main), [], [], main), rest }
23+
main = Mix.Deps.Retriever.children(config)
24+
all(main, [], [], main, config, callback, rest)
2525
end
2626

2727
# We traverse the tree of dependencies in a breadth-
@@ -63,25 +63,22 @@ defmodule Mix.Deps.Converger do
6363
# Now, since `d` was specified in a parent project, no
6464
# exception is going to be raised since d is considered
6565
# to be the authorative source.
66-
defp all([dep|t], acc, upper_breadths, current_breadths) do
66+
defp all([dep|t], acc, upper_breadths, current_breadths, config, callback, rest) do
6767
cond do
6868
contains_dep?(upper_breadths, dep) ->
69-
all(t, acc, upper_breadths, current_breadths)
69+
all(t, acc, upper_breadths, current_breadths, config, callback, rest)
7070
match?({ diverged_acc, true }, diverged_dep?(acc, dep)) ->
71-
all(t, diverged_acc, upper_breadths, current_breadths)
71+
all(t, diverged_acc, upper_breadths, current_breadths, config, callback, rest)
7272
true ->
73-
deps = dep.deps
74-
if deps != [] do
75-
acc = all(t, [dep|acc], upper_breadths, current_breadths)
76-
all(deps, acc, current_breadths, deps ++ current_breadths)
77-
else
78-
all(t, [dep|acc], upper_breadths, current_breadths)
79-
end
73+
{ dep, rest } = callback.(dep, rest)
74+
deps = Mix.Deps.Retriever.children(dep, config)
75+
{ acc, rest } = all(t, [dep.deps(deps)|acc], upper_breadths, current_breadths, config, callback, rest)
76+
all(deps, acc, current_breadths, deps ++ current_breadths, config, callback, rest)
8077
end
8178
end
8279

83-
defp all([], acc, _upper, _current) do
84-
acc
80+
defp all([], acc, _upper, _current, _config, _callback, rest) do
81+
{ acc, rest }
8582
end
8683

8784
# Does the list contain the given dependency?

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

Lines changed: 41 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,114 +5,82 @@ defmodule Mix.Deps.Retriever do
55
@moduledoc false
66

77
@doc """
8-
Returns all dependencies for the current Mix.Project
8+
Gets all direct children for the current Mix.Project
99
as a `Mix.Dep` record.
10-
11-
## Exceptions
12-
13-
This function raises an exception in case the developer
14-
provides a dependency in the wrong format.
1510
"""
16-
def all(post_config // []) do
17-
{ deps, _ } = all(nil, children(post_config), post_config, fn(dep, acc) -> { dep, acc } end)
18-
deps
11+
def children(post_config // []) do
12+
mix_children(post_config)
1913
end
2014

2115
@doc """
22-
Like `all/0` but takes a callback that is invoked for
23-
each dependency and must return an updated depedency
24-
in case some processing is done.
16+
Gets all children for a given dependency.
2517
"""
26-
def all(rest, post_config // [], callback) do
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) ->
32-
{ dep, rest } = callback.(dep, rest)
33-
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)
38-
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)
48-
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
18+
def children(dep, config) do
19+
cond do
20+
Mix.Deps.available?(dep) and mixfile?(dep) ->
21+
Mix.Deps.in_dependency(dep, config, fn _ ->
22+
mix_children(config)
23+
end)
24+
25+
Mix.Deps.available?(dep) and rebarconfig?(dep) ->
26+
Mix.Deps.in_dependency(dep, config, fn _ ->
27+
rebar_children(".")
28+
end)
29+
30+
true ->
31+
[]
5732
end
5833
end
5934

60-
@doc """
61-
Gets all direct children for the current Mix.Project
62-
as a `Mix.Dep` record. Unlike with `all` the `deps`
63-
field is not populated.
64-
"""
65-
def children(post_config // []) do
66-
Mix.Project.recur(post_config, fn _ ->
67-
(Mix.project[:deps] || []) |> setup_deps
68-
end) |> List.concat
69-
end
70-
7135
@doc """
7236
Receives a dependency and update its status.
7337
"""
7438
def update(Mix.Dep[scm: scm, app: app, requirement: req, opts: opts]) do
75-
with_scm_and_status({ app, req, opts }, [scm])
39+
update({ app, req, opts }, [scm])
7640
end
7741

7842
## Helpers
7943

80-
defp rebar_children(dir) do
81-
Mix.Rebar.recur(dir, fn config ->
82-
Mix.Rebar.deps(config) |> setup_deps
44+
defp mix_children(config) do
45+
scms = Mix.SCM.available
46+
Mix.Project.recur(config, fn _ ->
47+
(Mix.project[:deps] || []) |> Enum.map(update(&1, scms))
8348
end) |> List.concat
8449
end
8550

86-
defp setup_deps(deps) do
51+
defp rebar_children(dir) do
8752
scms = Mix.SCM.available
53+
Mix.Rebar.recur(dir, fn config ->
54+
Mix.Rebar.deps(config) |> Enum.map(update(&1, scms))
55+
end) |> List.concat
56+
end
8857

89-
Enum.map deps, fn dep ->
90-
dep = with_scm_and_status(dep, scms)
58+
defp update(tuple, scms) do
59+
dep = with_scm_and_status(tuple, scms)
9160

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)
61+
cond do
62+
Mix.Deps.available?(dep) and mixfile?(dep) ->
63+
Mix.Deps.in_dependency(dep, fn project ->
64+
mix_dep(dep, project)
65+
end)
9766

98-
Mix.Deps.available?(dep) and rebarconfig?(dep) ->
99-
rebar_dep(dep)
67+
Mix.Deps.available?(dep) and rebarconfig?(dep) ->
68+
rebar_dep(dep)
10069

101-
true ->
102-
dep
103-
end
70+
true ->
71+
dep
10472
end
10573
end
10674

107-
defp with_mix_project(Mix.Dep[manager: nil] = dep, project) do
75+
defp mix_dep(Mix.Dep[manager: nil] = dep, project) do
10876
if match?({ :noappfile, _ }, dep.status) and Mix.Project.umbrella? do
10977
dep = dep.update_opts(Keyword.put(&1, :app, false))
11078
.status({ :ok, nil })
11179
end
11280
dep.manager(:mix).source(project)
11381
end
11482

115-
defp with_mix_project(dep, _project), do: dep
83+
defp mix_dep(dep, _project), do: dep
11684

11785
defp rebar_dep(Mix.Dep[manager: nil, opts: opts] = dep) do
11886
config = Mix.Rebar.load_config(opts[:dest])

0 commit comments

Comments
 (0)