@@ -35,13 +35,13 @@ defmodule Mix.Deps do
35
35
36
36
Inside Mix, those dependencies are converted to a `Mix.Dep` record.
37
37
This module provides conveniences to work with those dependencies
38
- and the dependencies are usually in two specific states: fetched and
39
- unfetched .
38
+ and the dependencies are usually in two specific states: loaded and
39
+ unloaded .
40
40
41
- When a dependency is unfetched , it means Mix only parsed its specification
42
- and made no attempt to actually fetch the dependency or validate its
43
- status. When the dependency is fetched , it means Mix attempted to fetch
44
- and validate it, the status is set in the status field.
41
+ When a dependency is unloaded , it means Mix only parsed its specification
42
+ and made no attempt to actually load the dependency or validate its
43
+ status. When the dependency is loaded , it means Mix attempted to fetch,
44
+ load and validate it, the status is set in the status field.
45
45
46
46
## Mix options
47
47
@@ -80,7 +80,7 @@ defmodule Mix.Deps do
80
80
Returns all children dependencies for the current project,
81
81
as well as the defined apps in case of umbrella projects.
82
82
The children dependencies returned by this function were
83
- not fetched yet.
83
+ not loaded yet.
84
84
85
85
## Exceptions
86
86
@@ -90,28 +90,28 @@ defmodule Mix.Deps do
90
90
defdelegate children(), to: Mix.Deps.Retriever
91
91
92
92
@doc " ""
93
- Returns fetched dependencies recursively as a `Mix. Dep ` record.
93
+ Returns loaded dependencies recursively as a `Mix. Dep ` record.
94
94
95
95
## Exceptions
96
96
97
97
This function raises an exception if any of the dependencies
98
98
provided in the project are in the wrong format .
99
99
"" "
100
- def fetched do
100
+ def loaded do
101
101
{ deps, _ } = Mix.Deps.Converger.all(nil, fn(dep, acc) -> { dep, acc } end)
102
102
Mix.Deps.Converger.topsort(deps)
103
103
end
104
104
105
105
@doc " ""
106
- Receives a list of dependency names and returns fetched dependency
106
+ Receives a list of dependency names and returns loaded dependency
107
107
records . Logs a message if the dependency could not be found .
108
108
109
109
## Exceptions
110
110
111
111
This function raises an exception if any of the dependencies
112
112
provided in the project are in the wrong format .
113
113
"" "
114
- def fetched_by_name (given, all_deps // fetched ) do
114
+ def loaded_by_name (given, all_deps // loaded ) do
115
115
# Ensure all apps are atoms
116
116
apps = to_app_names(given)
117
117
@@ -130,7 +130,7 @@ defmodule Mix.Deps do
130
130
end
131
131
132
132
@ doc """
133
- Maps and reduces over all unfetched dependencies, one by one.
133
+ Maps and reduces over all unloaded dependencies, one by one.
134
134
135
135
This is useful in case you want to retrieve the dependency
136
136
tree for a project but process and change them along the way.
@@ -145,7 +145,7 @@ defmodule Mix.Deps do
145
145
This function raises an exception if any of the dependencies
146
146
provided in the project are in the wrong format.
147
147
"""
148
- def unfetched ( acc , callback ) do
148
+ def unloaded ( acc , callback ) do
149
149
{ deps , acc } = Mix.Deps.Converger . all ( acc , callback )
150
150
{ Mix.Deps.Converger . topsort ( deps ) , acc }
151
151
end
@@ -159,10 +159,10 @@ defmodule Mix.Deps do
159
159
This function raises an exception if any of the dependencies
160
160
provided in the project are in the wrong format.
161
161
"""
162
- def unfetched_by_name ( given, acc , callback ) do
162
+ def unloaded_by_name ( given, acc , callback ) do
163
163
names = to_app_names( given)
164
164
165
- unfetched ( acc, fn ( dep, acc) ->
165
+ unloaded ( acc, fn ( dep, acc) ->
166
166
if dep. app in names do
167
167
callback . ( dep , acc )
168
168
else
@@ -176,8 +176,7 @@ defmodule Mix.Deps do
176
176
changing the current working directory and loading the given
177
177
project onto the project stack.
178
178
179
- This function only works for mix dependencies.
180
- It is expected a fetched dependency as argument.
179
+ It is expected a loaded dependency as argument.
181
180
"""
182
181
def in_dependency( dep, post_config // [ ] , fun )
183
182
@@ -252,7 +251,7 @@ defmodule Mix.Deps do
252
251
do: "the dependency requires Elixir #{req} but you are running on v#{System. version } "
253
252
254
253
defp dep_status(Mix.Dep[app: app, requirement: req, opts: opts, from: from]) do
255
- info = { app, req, Dict.drop(opts, [:dest, :lock, :env, :drop ]) }
254
+ info = { app, req, Dict.drop(opts, [:dest, :lock, :env, :build ]) }
256
255
" \n > In #{Path.relative_to_cwd(from)}:\n #{inspect info}\n"
257
256
end
258
257
@@ -270,22 +269,26 @@ defmodule Mix.Deps do
270
269
:outdated ->
271
270
dep . status :lockoutdated
272
271
:ok ->
273
- dep
272
+ if vsn = old_elixir_lock ( dep ) do
273
+ dep . status ( { :elixirlock , vsn } )
274
+ else
275
+ dep
276
+ end
274
277
end
275
278
else
276
279
dep
277
280
end
278
281
end
279
282
280
283
@ doc """
281
- Check if a dependency is ok.
284
+ Checks if a dependency is ok.
282
285
"""
283
286
def ok? ( Mix.Dep [ status : { :ok , _ } ] ) , do: true
284
287
def ok? ( Mix.Dep [ ]) , do: false
285
288
286
289
@ doc """
287
- Check if a dependency is available. Available dependencies
288
- are the ones that can be compiled, loaded, etc .
290
+ Checks if a dependency is available. Available dependencies
291
+ are the ones that can be loaded.
289
292
"""
290
293
def available? ( Mix.Dep [ status : { :overriden , _ } ] ) , do: false
291
294
def available? ( Mix.Dep [ status : { :diverged , _ } ] ) , do: false
@@ -295,13 +298,23 @@ defmodule Mix.Deps do
295
298
def available? ( Mix.Dep [ ]) , do: true
296
299
297
300
@ doc """
298
- Check if a dependency can be updated.
301
+ Checks if a dependency can be compiled.
302
+
303
+ All available dependencies can be compiled except for
304
+ umbrella applications.
305
+ """
306
+ def compilable? ( Mix.Dep [ manager : manager , extra: extra ] = dep ) do
307
+ available? ( dep ) and ( manager != :mix or ! extra [ :umbrella? ] )
308
+ end
309
+
310
+ @doc """
311
+ Checks if a dependency can be updated.
299
312
"" "
300
313
def updatable?(Mix.Dep[status: { :elixirreq, _ }]), do: true
301
314
def updatable?(dep), do: available?(dep)
302
315
303
316
@doc " ""
304
- Check if a dependency is out of date, also considering its
317
+ Checks if a dependency is out of date , also considering its
305
318
lock status . Therefore , be sure to call `check_lock ` before
306
319
invoking this function .
307
320
@@ -328,44 +341,36 @@ defmodule Mix.Deps do
328
341
end
329
342
330
343
@doc """
331
- Returns all compile paths for the dependency.
332
- Expects a fetched dependency .
344
+ Returns all load paths for the given dependency. Automatically
345
+ derived from source paths .
333
346
"" "
334
- def compile_path(Mix.Dep[app: app, opts: opts, manager: manager]) do
335
- if manager == :mix do
336
- Mix.Project.in_project app, opts[:dest], fn _ ->
337
- Mix.Project.compile_path
338
- end
339
- else
340
- Path.join(opts[:dest], " ebin ")
347
+ def load_paths(Mix.Dep[opts: opts] = dep) do
348
+ build_path = Path.dirname(opts[:build])
349
+ Enum.map source_paths(dep), fn path ->
350
+ Path.join [build_path, Path.basename(path), " ebin "]
341
351
end
342
352
end
343
353
344
354
@doc " ""
345
- Returns all load paths for the dependency.
346
- Expects a fetched dependency.
347
- """
348
- def load_paths(Mix.Dep[manager: :mix, app: app, opts: opts]) do
349
- Mix.Project.in_project(app, opts[:dest], fn _ ->
350
- Mix.Project.load_paths
351
- end) |> Enum.uniq
352
- end
355
+ Returns all source paths .
353
356
354
- def load_paths(Mix.Dep[manager: :rebar, opts: opts, extra: extra]) do
357
+ Source paths are the directories that contains ebin files for a given
358
+ dependency . All managers, except rebar , have only one source path .
359
+ "" "
360
+ def source_paths(Mix.Dep[manager: :rebar, opts: opts, extra: extra]) do
355
361
# Add root dir and all sub dirs with ebin/ directory
356
362
sub_dirs = Enum.map(extra[:sub_dirs] || [], fn path ->
357
363
Path.join(opts[:dest], path)
358
364
end)
359
365
360
- [ opts[:dest] | sub_dirs ]
361
- |> Enum.map(&Path.wildcard(&1))
362
- |> Enum.concat
363
- |> Enum.map(&Path.join(&1, "ebin "))
364
- |> Enum.filter(&File.dir?(&1))
366
+ [opts[:dest] | sub_dirs]
367
+ |> Enum.map(&Path.wildcard(&1))
368
+ |> Enum.concat
369
+ |> Enum.filter(fn p -> p |> Path.join(" ebin ") |> File.dir? end)
365
370
end
366
371
367
- def load_paths (Mix.Dep[manager: manager, opts: opts]) when manager in [:make] do
368
- [ Path.join( opts[:dest], " ebin ") ]
372
+ def source_paths (Mix.Dep[opts: opts]) do
373
+ [opts[:dest]]
369
374
end
370
375
371
376
@doc " ""
@@ -394,7 +399,7 @@ defmodule Mix.Deps do
394
399
@doc false
395
400
# Called by deps.get and deps.update
396
401
def finalize(all_deps, apps, lock, opts) do
397
- deps = fetched_by_name (apps, all_deps)
402
+ deps = loaded_by_name (apps, all_deps)
398
403
399
404
# Do not attempt to compile dependencies that are not available.
400
405
# mix deps.check at the end will emit proper status in case they failed.
@@ -404,22 +409,24 @@ defmodule Mix.Deps do
404
409
# deps if all dependencies are available. This is because if a
405
410
# dependency is missing, it could be a children of the parent
406
411
# (aka a sibling) which would make parent compilation fail.
412
+ #
413
+ # If there is any other dependency that is not ok, we include
414
+ # it for compilation too, this is our best to try to solve the
415
+ # maximum we can at each deps.get and deps.update.
407
416
if Enum.all?(all_deps, &available?/1) do
408
- deps = with_depending(deps, all_deps)
417
+ deps = with_depending(deps, all_deps) ++
418
+ Enum.filter(all_deps, fn dep -> not ok?(dep) end)
409
419
end
410
420
411
- apps = Enum.map(deps, &(&1.app))
421
+ apps = Enum.map(deps, &(&1.app)) |> Enum.uniq
412
422
Mix.Deps.Lock.write(lock)
413
423
414
424
unless opts[:no_compile] do
415
- # TODO: This is a temporary workaround to the fact
416
- # we do not loadpaths for deps.get and deps.update tasks
417
- # in the CLI.
418
- Mix.Task.run(" deps. loadpaths ", [" --no - deps -check "])
419
- Mix.Task.reenable(" deps. loadpaths ")
420
-
421
- args = if opts[:quiet], do: [" --quiet "|apps], else: apps
422
- Mix.Task.run(" deps. compile ", args)
425
+ if apps != [] do
426
+ args = if opts[:quiet], do: [" --quiet "|apps], else: apps
427
+ Mix.Task.run(" deps . compile ", args)
428
+ end
429
+
423
430
unless opts[:no_deps_check] do
424
431
Mix.Task.run(" deps. check ", [])
425
432
end
@@ -449,4 +456,11 @@ defmodule Mix.Deps do
449
456
if is_binary(app), do: binary_to_atom(app), else: app
450
457
end
451
458
end
459
+
460
+ defp old_elixir_lock(Mix.Dep[opts: opts]) do
461
+ old_vsn = Mix.Deps.Lock.elixir_vsn(opts[:build])
462
+ if old_vsn && old_vsn != System.version do
463
+ old_vsn
464
+ end
465
+ end
452
466
end
0 commit comments