Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0397a46bb7 | ||
|
|
b87e58e7e3 | ||
|
|
6cb09a77e6 | ||
|
|
12edab720c | ||
|
|
74f9a34015 | ||
|
|
49af97a800 | ||
|
|
b806ee8559 | ||
|
|
7d09c2b857 | ||
|
|
f38646781b | ||
|
|
b5777de582 | ||
|
|
67f77ec1cd | ||
|
|
8a91f648a8 | ||
|
|
7f61b0ff05 | ||
|
|
c830fde31e | ||
|
|
019e6b85e6 | ||
|
|
097fe87eb7 | ||
|
|
6ec1e7f7b4 |
@@ -109,6 +109,26 @@ You can now also install archives from Hex in this way. Since they are fetched a
|
||||
|
||||
It is also possible to install escripts and archives by providing a Git/GitHub repo. See `mix help escript.install` and `mix help archive.install` for more details.
|
||||
|
||||
## v1.4.1 (2017-01-26)
|
||||
|
||||
### 1. Bug fixes
|
||||
|
||||
#### Elixir
|
||||
|
||||
* [Kernel] Remove warning when making private functions overridable
|
||||
* [Path] Ensure `Path.join/1` returns strings for lists of one element
|
||||
* [Regex] Ensure `Regex.escape/1` also escapes `-`
|
||||
|
||||
#### IEx
|
||||
|
||||
* [IEx] Disable ANSI detection for powershell to avoid false positives
|
||||
|
||||
#### Mix
|
||||
|
||||
* [Mix.Make] Run `make clean` for `erlang.mk`
|
||||
* [Mix.Rebar] Support all of rebar3 dependency package declaration
|
||||
* [Mix.Rebar] Only pass overrides from parent to child in Rebar dep
|
||||
|
||||
## v1.4.0 (2017-01-05)
|
||||
|
||||
### 1. Enhancements
|
||||
@@ -119,6 +139,7 @@ It is also possible to install escripts and archives by providing a Git/GitHub r
|
||||
* [Calendar] Support `NaiveDateTime.add/3` and `NaiveDateTime.diff/3` for adding seconds (up to microseconds) as well as the difference between two NaiveDateTimes in seconds (up to microseconds)
|
||||
* [Calendar] Add `Date.leap_year?/1` and `Date.day_of_week/1`
|
||||
* [Calendar] Ensure `Date`, `Time` and `NaiveDateTime` APIs work with any struct that provides the same set of fields as their respective struct. For example, a `NaiveDateTime` can be given to `Date` since it contains a superset of the fields in the `Date` struct
|
||||
* [Calendar] Add `Time.utc_now/0` and `NaiveDateTime.utc_now/0`
|
||||
* [Enum] Add `Enum.map_every/2` that invokes the given function with every nth item
|
||||
* [Enum] Add `min/2`, `max/2`, `min_max/2`, `min_by/3`, `max_by/3`, and `min_max_by/3` that allow a function specifying the default value when the enumerable is empty
|
||||
* [Enum] Introduce `Enum.zip/1` to zip multiple entries at once
|
||||
|
||||
@@ -100,27 +100,6 @@ for /d %%d in ("%originPath%..\lib\*.") do (
|
||||
)
|
||||
setlocal disabledelayedexpansion
|
||||
|
||||
rem ******* detect ANSI terminal support ********************
|
||||
timeout 0 2>nul >nul || goto run
|
||||
where /Q powershell || goto run
|
||||
|
||||
set ASSERT_ANSI= ^
|
||||
$err = 1; ^
|
||||
$Kernel32 = Add-Type -Name 'Kernel32' -PassThru -MemberDefinition ' ^
|
||||
[DllImport(\"Kernel32.dll\", SetLastError = true)] ^
|
||||
public static extern IntPtr GetStdHandle(int nStdHandle); ^
|
||||
[DllImport(\"Kernel32.dll\", SetLastError = true)] ^
|
||||
public static extern bool GetConsoleMode(IntPtr hWnd, ref UInt32 lpMode); ^
|
||||
'; ^
|
||||
$StdoutHandle = $Kernel32::GetStdHandle(-11); ^
|
||||
$ConsoleMode = New-Object -TypeName UInt32; ^
|
||||
$null = $Kernel32::GetConsoleMode($StdoutHandle, [ref]$ConsoleMode); ^
|
||||
if ($ConsoleMode -band 0x4) { $err = 0 } ^
|
||||
exit $err
|
||||
|
||||
powershell -NoProfile -NonInteractive -Command %ASSERT_ANSI% || goto run
|
||||
set parsErlang=%parsErlang% -elixir ansi_enabled true
|
||||
|
||||
:run
|
||||
if not %runMode% == "iex" (
|
||||
set beforeExtra=-noshell -s elixir start_cli %beforeExtra%
|
||||
|
||||
@@ -51,17 +51,17 @@ defmodule Calendar do
|
||||
@type std_offset :: integer
|
||||
|
||||
@typedoc "Any map/struct that contains the date fields"
|
||||
@type date :: %{calendar: calendar, year: year, month: month, day: day}
|
||||
@type date :: %{optional(any) => any, calendar: calendar, year: year, month: month, day: day}
|
||||
|
||||
@typedoc "Any map/struct that contains the time fields"
|
||||
@type time :: %{hour: hour, minute: minute, second: second, microsecond: microsecond}
|
||||
@type time :: %{optional(any) => any, hour: hour, minute: minute, second: second, microsecond: microsecond}
|
||||
|
||||
@typedoc "Any map/struct that contains the naive_datetime fields"
|
||||
@type naive_date_time :: %{calendar: calendar, year: year, month: month, day: day,
|
||||
@type naive_date_time :: %{optional(any) => any, calendar: calendar, year: year, month: month, day: day,
|
||||
hour: hour, minute: minute, second: second, microsecond: microsecond}
|
||||
|
||||
@typedoc "Any map/struct that contains the datetime fields"
|
||||
@type date_time :: %{calendar: calendar, year: year, month: month, day: day,
|
||||
@type date_time :: %{optional(any) => any, calendar: calendar, year: year, month: month, day: day,
|
||||
hour: hour, minute: minute, second: second, microsecond: microsecond,
|
||||
time_zone: time_zone, zone_abbr: zone_abbr, utc_offset: utc_offset, std_offset: std_offset}
|
||||
|
||||
|
||||
@@ -808,13 +808,6 @@ defmodule Module do
|
||||
"cannot make private macro #{name}/#{arity} overridable, overriding " <>
|
||||
"private macros is not supported"
|
||||
clause ->
|
||||
{{_def, kind, _line, _file, _check, _location, _defaults}, _clauses} = clause
|
||||
|
||||
# TODO: Remove on v2.0
|
||||
if kind == :defp do
|
||||
IO.warn "making private functions (#{name}/#{arity} in this case) overridable is deprecated"
|
||||
end
|
||||
|
||||
neighbours =
|
||||
if :elixir_compiler.get_opt(:internal) do
|
||||
[]
|
||||
|
||||
@@ -428,10 +428,10 @@ defmodule Path do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Joins a list of strings.
|
||||
Joins a list of paths.
|
||||
|
||||
This function should be used to convert a list of strings to a path.
|
||||
Note that any trailing slash is removed on join.
|
||||
This function should be used to convert a list of paths to a path.
|
||||
Note that any trailing slash is removed when joining.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -445,11 +445,11 @@ defmodule Path do
|
||||
"/foo/bar"
|
||||
|
||||
"""
|
||||
@spec join([t]) :: binary
|
||||
@spec join(nonempty_list(t)) :: binary
|
||||
def join([name1, name2 | rest]), do:
|
||||
join([join(name1, name2) | rest])
|
||||
def join([name]), do:
|
||||
name
|
||||
IO.chardata_to_string(name)
|
||||
|
||||
@doc """
|
||||
Joins two paths.
|
||||
|
||||
@@ -629,7 +629,7 @@ defmodule Regex do
|
||||
[get_index(string, h) | get_indexes(string, t, arity - 1)]
|
||||
end
|
||||
|
||||
{:ok, pattern} = :re.compile(~S"[.^$*+?()\[\]{}\\\|\s#]", [:unicode])
|
||||
{:ok, pattern} = :re.compile(~S"[.^$*+?()\[\]{}\\\|\s#-]", [:unicode])
|
||||
@escape_pattern pattern
|
||||
|
||||
@doc ~S"""
|
||||
|
||||
+12
-12
@@ -56,28 +56,27 @@ defmodule Task do
|
||||
|
||||
## Supervised tasks
|
||||
|
||||
It is also possible to spawn a task under a supervisor
|
||||
with `start_link/1` and `start_link/3`:
|
||||
|
||||
Task.start_link(fn -> IO.puts "ok" end)
|
||||
|
||||
Such tasks can be mounted in your supervision tree as:
|
||||
It is also possible to spawn a task under a supervisor:
|
||||
|
||||
import Supervisor.Spec
|
||||
|
||||
children = [
|
||||
#
|
||||
worker(Task, [fn -> IO.puts "ok" end])
|
||||
]
|
||||
|
||||
Internally the supervisor will invoke `Task.start_link/1`.
|
||||
|
||||
Since these tasks are supervised and not directly linked to
|
||||
the caller, they cannot be awaited on. Note `start_link/1`,
|
||||
unlike `async/1`, returns `{:ok, pid}` (which is
|
||||
the result expected by supervision trees).
|
||||
|
||||
By default, most supervision strategies will try to restart
|
||||
a worker after it exits regardless of the reason. If you design the
|
||||
task to terminate normally (as in the example with `IO.puts/2` above),
|
||||
consider passing `restart: :transient` in the options to `Supervisor.Spec.worker/3`.
|
||||
a worker after it exits regardless of the reason. If you design
|
||||
the task to terminate normally (as in the example with `IO.puts/2`
|
||||
above), consider passing `restart: :transient` in the options
|
||||
to `Supervisor.Spec.worker/3`.
|
||||
|
||||
## Dynamically supervised tasks
|
||||
|
||||
@@ -286,7 +285,7 @@ defmodule Task do
|
||||
Returns a stream that runs the given `module`, `function` and `args`
|
||||
concurrently on each item in `enumerable`.
|
||||
|
||||
Each item will be appended to the given `args` and processed by its
|
||||
Each item will be prepended to the given `args` and processed by its
|
||||
own task. The tasks will be linked to an intermediate process that is
|
||||
then linked to the current process. This means a failure in a task
|
||||
terminates the current process and a failure in the current process
|
||||
@@ -297,7 +296,7 @@ defmodule Task do
|
||||
are emitted in the same order as the original `enumerable`.
|
||||
|
||||
The level of concurrency can be controlled via the `:max_concurrency`
|
||||
option and defaults to `System.schedulers_online/1`. The timeout
|
||||
option and defaults to `System.schedulers_online/0`. The timeout
|
||||
can also be given as option and defaults to 5000 and it defaults to
|
||||
the maximum amount of time to wait without a task reply.
|
||||
|
||||
@@ -309,9 +308,10 @@ defmodule Task do
|
||||
## Options
|
||||
|
||||
* `:max_concurrency` - sets the maximum number of tasks to run
|
||||
at the same time. Defaults to `System.schedulers_online/1`.
|
||||
at the same time. Defaults to `System.schedulers_online/0`.
|
||||
* `:timeout` - the maximum amount of time to wait without
|
||||
receiving a task reply (across all running tasks).
|
||||
Defaults to `5000`.
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ defmodule Task.Supervisor do
|
||||
are emitted in the same order as the original `enumerable`.
|
||||
|
||||
The level of concurrency can be controlled via the `:max_concurrency`
|
||||
option and defaults to `System.schedulers_online/1`. The timeout
|
||||
option and defaults to `System.schedulers_online/0`. The timeout
|
||||
can also be given as option and defaults to 5000 and it defaults to
|
||||
the maximum amount of time to wait without a task reply.
|
||||
|
||||
@@ -133,9 +133,10 @@ defmodule Task.Supervisor do
|
||||
## Options
|
||||
|
||||
* `:max_concurrency` - sets the maximum number of tasks to run
|
||||
at the same time. Defaults to `System.schedulers_online/1`.
|
||||
at the same time. Defaults to `System.schedulers_online/0`.
|
||||
* `:timeout` - the maximum amount of time to wait without
|
||||
receiving a task reply (across all running tasks).
|
||||
Defaults to `5000`.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ check_module_availability(Line, File, Module) ->
|
||||
end.
|
||||
|
||||
warn_unused_attributes(File, Data, PersistedAttrs) ->
|
||||
ReservedAttrs = [after_compile, before_compile, moduledoc, on_definition | PersistedAttrs],
|
||||
ReservedAttrs = [after_compile, before_compile, moduledoc, on_definition, impl | PersistedAttrs],
|
||||
Keys = ets:select(Data, [{{'$1', '_', '_', '$2'}, [{is_atom, '$1'}, {is_integer, '$2'}], [['$1', '$2']]}]),
|
||||
[elixir_errors:form_warn([{line, Line}], File, ?MODULE, {unused_attribute, Key}) ||
|
||||
[Key, Line] <- Keys, not lists:member(Key, ReservedAttrs)].
|
||||
|
||||
@@ -264,16 +264,16 @@ defmodule ExceptionTest do
|
||||
end
|
||||
|
||||
test "format_exit with call with exception" do
|
||||
Process.flag(:trap_exit, true)
|
||||
# Fake reason to prevent error_logger printing to stdout
|
||||
fsm_reason = {%ArgumentError{}, [{:not_a_real_module, :function, 0, []}]}
|
||||
reason = try do
|
||||
:gen_fsm.sync_send_event(spawn(fn() ->
|
||||
Process.sleep(200)
|
||||
exit(fsm_reason)
|
||||
end), :hello)
|
||||
catch
|
||||
:exit, reason -> reason
|
||||
end
|
||||
exit_reason = {%ArgumentError{}, [{:not_a_real_module, :function, 0, []}]}
|
||||
exit_fun = fn() -> receive do: (_ -> exit(exit_reason)) end
|
||||
reason =
|
||||
try do
|
||||
:gen_fsm.sync_send_event(spawn_link(exit_fun), :hello)
|
||||
catch
|
||||
:exit, reason -> reason
|
||||
end
|
||||
|
||||
formatted = Exception.format_exit(reason)
|
||||
assert formatted =~ ~r"exited in: :gen_fsm\.sync_send_event\(#PID<\d+\.\d+\.\d+>, :hello\)"
|
||||
@@ -283,14 +283,16 @@ defmodule ExceptionTest do
|
||||
end
|
||||
|
||||
test "format_exit with nested calls" do
|
||||
Process.flag(:trap_exit, true)
|
||||
# Fake reason to prevent error_logger printing to stdout
|
||||
event_fun = fn() ->
|
||||
Process.sleep(200)
|
||||
exit(:normal)
|
||||
end
|
||||
server_pid = spawn(fn()-> :gen_event.call(spawn(event_fun), :handler, :hello) end)
|
||||
exit_fun = fn() -> receive do: (_ -> exit(:normal)) end
|
||||
outer_pid =
|
||||
spawn_link(fn()->
|
||||
Process.flag(:trap_exit, true)
|
||||
:gen_event.call(spawn_link(exit_fun), :handler, :hello)
|
||||
end)
|
||||
reason = try do
|
||||
:gen_server.call(server_pid, :hi)
|
||||
:gen_server.call(outer_pid, :hi)
|
||||
catch
|
||||
:exit, reason -> reason
|
||||
end
|
||||
@@ -302,15 +304,17 @@ defmodule ExceptionTest do
|
||||
end
|
||||
|
||||
test "format_exit with nested calls and exception" do
|
||||
Process.flag(:trap_exit, true)
|
||||
# Fake reason to prevent error_logger printing to stdout
|
||||
event_reason = {%ArgumentError{}, [{:not_a_real_module, :function, 0, []}]}
|
||||
event_fun = fn() ->
|
||||
Process.sleep(200)
|
||||
exit(event_reason)
|
||||
end
|
||||
server_pid = spawn(fn()-> :gen_event.call(spawn(event_fun), :handler, :hello) end)
|
||||
exit_reason = {%ArgumentError{}, [{:not_a_real_module, :function, 0, []}]}
|
||||
exit_fun = fn() -> receive do: (_ -> exit(exit_reason)) end
|
||||
outer_pid =
|
||||
spawn_link(fn()->
|
||||
Process.flag(:trap_exit, true)
|
||||
:gen_event.call(spawn_link(exit_fun), :handler, :hello)
|
||||
end)
|
||||
reason = try do
|
||||
:gen_server.call(server_pid, :hi)
|
||||
:gen_server.call(outer_pid, :hi)
|
||||
catch
|
||||
:exit, reason -> reason
|
||||
end
|
||||
|
||||
@@ -211,6 +211,8 @@ defmodule PathTest do
|
||||
assert Path.join(['/foo/', "/bar/"]) == "/foo/bar"
|
||||
assert Path.join(["/", ""]) == "/"
|
||||
assert Path.join(["/", "", "bar"]) == "/bar"
|
||||
assert Path.join(['foo', [?b, "a", ?r]]) == "foo/bar"
|
||||
assert Path.join([[?f, 'o', "o"]]) == "foo"
|
||||
end
|
||||
|
||||
test "join two" do
|
||||
|
||||
@@ -247,6 +247,7 @@ defmodule RegexTest do
|
||||
assert matches_escaped?("# lol")
|
||||
|
||||
assert matches_escaped?("\\A.^$*+?()[{\\| \t\n\x20\\z #hello\u202F\u205F")
|
||||
assert Regex.match? Regex.compile!("[" <> Regex.escape("!-#") <> "]"), "-"
|
||||
|
||||
assert Regex.escape("{}") == "\\{\\}"
|
||||
assert Regex.escape("[]") == "\\[\\]"
|
||||
|
||||
@@ -264,11 +264,13 @@ defmodule Mix.Dep.Loader do
|
||||
{dep, deps}
|
||||
end
|
||||
|
||||
defp rebar_dep(%Mix.Dep{app: app, opts: opts} = dep, children, manager) do
|
||||
config = File.cd!(opts[:dest], fn ->
|
||||
Mix.Rebar.load_config(".")
|
||||
end)
|
||||
extra = Mix.Rebar.merge_config(dep.extra, config)
|
||||
defp rebar_dep(%Mix.Dep{app: app, opts: opts, extra: overrides} = dep, children, manager) do
|
||||
config =
|
||||
File.cd!(opts[:dest], fn -> Mix.Rebar.load_config(".") end)
|
||||
|
||||
config =
|
||||
Mix.Rebar.apply_overrides(app, config, overrides)
|
||||
|
||||
deps =
|
||||
if children do
|
||||
from = Path.join(opts[:dest], "rebar.config")
|
||||
@@ -277,9 +279,10 @@ defmodule Mix.Dep.Loader do
|
||||
# files in the dependency
|
||||
Enum.map(children, &to_dep(&1, from, manager))
|
||||
else
|
||||
rebar_children(app, config, extra, manager)
|
||||
rebar_children(config, manager, opts[:dest])
|
||||
end
|
||||
{%{dep | extra: extra}, deps}
|
||||
|
||||
{%{dep | extra: config}, deps}
|
||||
end
|
||||
|
||||
defp make_dep(dep) do
|
||||
@@ -301,17 +304,18 @@ defmodule Mix.Dep.Loader do
|
||||
|> elem(0)
|
||||
end
|
||||
|
||||
defp rebar_children(app, root_config, extra, manager) do
|
||||
from = Path.absname("rebar.config")
|
||||
defp rebar_children(root_config, manager, dest) do
|
||||
from = Path.absname(Path.join(dest, "rebar.config"))
|
||||
Mix.Rebar.recur(root_config, fn config ->
|
||||
app
|
||||
|> Mix.Rebar.deps(config, overrides(manager, extra))
|
||||
|> Enum.map(fn dep -> %{to_dep(dep, from, manager) | extra: extra} end)
|
||||
overrides = overrides(manager, config)
|
||||
config
|
||||
|> Mix.Rebar.deps()
|
||||
|> Enum.map(fn dep -> %{to_dep(dep, from, manager) | extra: overrides} end)
|
||||
end) |> Enum.concat
|
||||
end
|
||||
|
||||
defp overrides(:rebar3, extra), do: extra[:overrides] || []
|
||||
defp overrides(_, _extra), do: []
|
||||
defp overrides(:rebar3, config), do: config[:overrides] || []
|
||||
defp overrides(_, _config), do: []
|
||||
|
||||
defp validate_app(%Mix.Dep{opts: opts, requirement: req, app: app} = dep) do
|
||||
opts_app = opts[:app]
|
||||
|
||||
+59
-146
@@ -61,108 +61,6 @@ defmodule Mix.Rebar do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Merges a rebar3 parent config with a child config.
|
||||
"""
|
||||
# From https://github.com/rebar/rebar3/blob/b1da2ec0674df89599564252734bd4d794436425/src/rebar_opts.erl#L103
|
||||
def merge_config(old, new) do
|
||||
Keyword.merge(old, new, fn
|
||||
:deps, old, _new -> old
|
||||
{:deps, _}, _old, new -> new
|
||||
:plugins, _old, new -> new
|
||||
{:plugins, _}, _old, new -> new
|
||||
:profiles, old, new -> merge_config(old, new)
|
||||
:mib_first_files, value, value -> value
|
||||
:mib_first_files, old, new -> old ++ new
|
||||
:relx, old, new -> tuple_merge(new, old)
|
||||
_key, old, new when is_list(new) ->
|
||||
case :io_lib.printable_list(new) do
|
||||
true when new == [] ->
|
||||
if :io_lib.printable_list(old), do: new, else: old
|
||||
true ->
|
||||
new
|
||||
false ->
|
||||
tuple_merge(old, new)
|
||||
end
|
||||
_key, _old, new -> new
|
||||
end)
|
||||
end
|
||||
|
||||
# From https://github.com/rebar/rebar3/blob/b1da2ec0674df89599564252734bd4d794436425/src/rebar_utils.erl#L282
|
||||
defp tuple_merge(old, new),
|
||||
do: do_tuple_merge(tuple_sort(old), tuple_sort(new))
|
||||
|
||||
defp do_tuple_merge(old, []),
|
||||
do: old
|
||||
defp do_tuple_merge(olds, [new | news]),
|
||||
do: do_tuple_umerge_dedup(umerge(:new, olds, [], news, new), [])
|
||||
|
||||
defp umerge(_, [], [], acc, current),
|
||||
do: [current | acc]
|
||||
defp umerge(:new, [], news, acc, current),
|
||||
do: Enum.reverse(news, [current | acc])
|
||||
defp umerge(:old, olds, [], acc, current),
|
||||
do: Enum.reverse(olds, [current | acc])
|
||||
defp umerge(:new, [old | olds], news, acc, current) do
|
||||
{dir, merged, new_current} = compare({:new, current}, {:old, old})
|
||||
umerge(dir, olds, news, [merged | acc], new_current)
|
||||
end
|
||||
defp umerge(:old, olds, [new | news], acc, current) do
|
||||
{dir, merged, new_current} = compare({:new, new}, {:old, current})
|
||||
umerge(dir, olds, news, [merged | acc], new_current)
|
||||
end
|
||||
|
||||
defp compare({priority, a}, {secondary, b}) when is_tuple(a) and is_tuple(b) do
|
||||
ka = elem(a, 0)
|
||||
kb = elem(b, 0)
|
||||
cond do
|
||||
ka == kb -> {secondary, a, b}
|
||||
ka < kb -> {secondary, a, b}
|
||||
ka > kb -> {priority, b, a}
|
||||
end
|
||||
end
|
||||
defp compare({priority, a}, {secondary, b}) when not is_tuple(a) and not is_tuple(b) do
|
||||
cond do
|
||||
a == b -> {secondary, a, b}
|
||||
a < b -> {secondary, a, b}
|
||||
a > b -> {priority, b, a}
|
||||
end
|
||||
end
|
||||
defp compare({priority, a}, {secondary, b}) when is_tuple(a) and not is_tuple(b) do
|
||||
ka = elem(a, 0)
|
||||
cond do
|
||||
ka == b -> {secondary, a, b}
|
||||
ka < b -> {secondary, a, b}
|
||||
ka > b -> {priority, b, a}
|
||||
end
|
||||
end
|
||||
defp compare({priority, a}, {secondary, b}) when not is_tuple(a) and is_tuple(b) do
|
||||
kb = elem(b, 0)
|
||||
cond do
|
||||
a == kb -> {secondary, a, b}
|
||||
a < kb -> {secondary, a, b}
|
||||
a > kb -> {priority, b, a}
|
||||
end
|
||||
end
|
||||
|
||||
defp do_tuple_umerge_dedup([], acc), do: acc
|
||||
defp do_tuple_umerge_dedup([h | t], acc) do
|
||||
if h in t do
|
||||
do_tuple_umerge_dedup(t, acc)
|
||||
else
|
||||
do_tuple_umerge_dedup(t, [h | acc])
|
||||
end
|
||||
end
|
||||
|
||||
defp tuple_sort(list) do
|
||||
Enum.sort(list, fn
|
||||
a, b when is_tuple(a) and is_tuple(b) -> elem(a, 0) <= elem(b, 0)
|
||||
a, b when is_tuple(a) -> elem(a, 0) <= b
|
||||
a, b when is_tuple(b) -> a <= elem(b, 0)
|
||||
a, b -> a <= b
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Serializes a Rebar config to a term file.
|
||||
"""
|
||||
@@ -178,7 +76,7 @@ defmodule Mix.Rebar do
|
||||
def dependency_config(config) do
|
||||
Enum.map(config, fn
|
||||
{:erl_opts, opts} ->
|
||||
{:erl_opts, Enum.reject(opts, &(&1 == :warnings_as_errors))}
|
||||
{:erl_opts, List.delete(opts, :warnings_as_errors)}
|
||||
other ->
|
||||
other
|
||||
end)
|
||||
@@ -187,10 +85,9 @@ defmodule Mix.Rebar do
|
||||
@doc """
|
||||
Parses the dependencies in given `rebar.config` to Mix's dependency format.
|
||||
"""
|
||||
def deps(app, config, overrides) do
|
||||
def deps(config) do
|
||||
# We don't have to handle rebar3 profiles because dependencies
|
||||
# are always in the default profile which cannot be customized
|
||||
config = apply_overrides(app, config, overrides)
|
||||
if deps = config[:deps] do
|
||||
Enum.map(deps, &parse_dep/1)
|
||||
else
|
||||
@@ -201,23 +98,23 @@ defmodule Mix.Rebar do
|
||||
@doc """
|
||||
Runs `fun` for the given config and for each `sub_dirs` in the
|
||||
given Rebar config.
|
||||
"""
|
||||
def recur(config, fun) when is_binary(config) do
|
||||
recur(load_config(config), fun)
|
||||
end
|
||||
|
||||
`sub_dirs` is only supported in Rebar 2. In Rebar 3, the equivalent
|
||||
to umbrella apps cannot be used as dependencies, so we don't need
|
||||
to worry about such cases in Mix.
|
||||
"""
|
||||
def recur(config, fun) do
|
||||
subs =
|
||||
(config[:sub_dirs] || [])
|
||||
|> Enum.map(&Path.wildcard(&1))
|
||||
|> Enum.concat
|
||||
|> Enum.flat_map(&Path.wildcard(&1))
|
||||
|> Enum.filter(&File.dir?(&1))
|
||||
|> Enum.map(&recur(&1, fun))
|
||||
|> Enum.concat
|
||||
|> Enum.flat_map(&recur(load_config(&1), fun))
|
||||
|
||||
[fun.(config) | subs]
|
||||
end
|
||||
|
||||
# Translate a rebar dependency declaration to a mix declaration
|
||||
# From http://www.rebar3.org/docs/dependencies#section-declaring-dependencies
|
||||
defp parse_dep(app) when is_atom(app) do
|
||||
{app, ">= 0.0.0"}
|
||||
end
|
||||
@@ -226,10 +123,6 @@ defmodule Mix.Rebar do
|
||||
{app, List.to_string(req)}
|
||||
end
|
||||
|
||||
defp parse_dep({app, req, {:pkg, package}}) when is_list(req) do
|
||||
{app, List.to_string(req), hex: package}
|
||||
end
|
||||
|
||||
defp parse_dep({app, source}) when is_tuple(source) do
|
||||
parse_dep({app, nil, source, []})
|
||||
end
|
||||
@@ -239,25 +132,33 @@ defmodule Mix.Rebar do
|
||||
end
|
||||
|
||||
defp parse_dep({app, req, source, opts}) do
|
||||
[scm, url | source] = Tuple.to_list(source)
|
||||
|
||||
ref =
|
||||
case source do
|
||||
["" | _] -> [branch: "HEAD"]
|
||||
[{:branch, branch} | _] -> [branch: to_string(branch)]
|
||||
[{:tag, tag} | _] -> [tag: to_string(tag)]
|
||||
[{:ref, ref} | _] -> [ref: to_string(ref)]
|
||||
[ref | _] -> [ref: to_string(ref)]
|
||||
_ -> []
|
||||
end
|
||||
source = parse_source(source)
|
||||
|
||||
compile =
|
||||
if :proplists.get_value(:raw, opts, false),
|
||||
do: [compile: false],
|
||||
else: []
|
||||
|
||||
mix_opts = [{scm, to_string(url)}] ++ ref ++ compile
|
||||
{app, compile_req(req), mix_opts}
|
||||
{app, compile_req(req), source ++ compile}
|
||||
end
|
||||
|
||||
defp parse_source({:pkg, pkg}) do
|
||||
[hex: pkg]
|
||||
end
|
||||
defp parse_source(source) do
|
||||
[scm, url | source] = Tuple.to_list(source)
|
||||
|
||||
ref =
|
||||
case source do
|
||||
["" | _] -> [branch: "HEAD"]
|
||||
[{:branch, branch} | _] -> [branch: to_string(branch)]
|
||||
[{:tag, tag} | _] -> [tag: to_string(tag)]
|
||||
[{:ref, ref} | _] -> [ref: to_string(ref)]
|
||||
[ref | _] -> [ref: to_string(ref)]
|
||||
_ -> []
|
||||
end
|
||||
|
||||
[{scm, to_string(url)}] ++ ref
|
||||
end
|
||||
|
||||
defp compile_req(nil) do
|
||||
@@ -265,11 +166,18 @@ defmodule Mix.Rebar do
|
||||
end
|
||||
|
||||
defp compile_req(req) do
|
||||
case Regex.compile(List.to_string(req)) do
|
||||
{:ok, re} ->
|
||||
re
|
||||
{:error, reason} ->
|
||||
Mix.raise "Unable to compile version regex: #{inspect req}, #{reason}"
|
||||
req = List.to_string(req)
|
||||
|
||||
case Version.parse_requirement(req) do
|
||||
{:ok, _} ->
|
||||
req
|
||||
:error ->
|
||||
case Regex.compile(req) do
|
||||
{:ok, re} ->
|
||||
re
|
||||
{:error, reason} ->
|
||||
Mix.raise "Unable to compile version regex: #{inspect req}, #{reason}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -312,9 +220,11 @@ defmodule Mix.Rebar do
|
||||
end
|
||||
end
|
||||
|
||||
defp apply_overrides(app, config, overrides) do
|
||||
@doc """
|
||||
Applies the given overrides for app config.
|
||||
"""
|
||||
def apply_overrides(app, config, overrides) do
|
||||
# Inefficient. We want the order we get here though.
|
||||
|
||||
config =
|
||||
Enum.reduce(overrides, config, fn
|
||||
{:override, overrides}, config ->
|
||||
@@ -327,7 +237,7 @@ defmodule Mix.Rebar do
|
||||
|
||||
config =
|
||||
Enum.reduce(overrides, config, fn
|
||||
{:override, oapp, overrides}, config when oapp == app ->
|
||||
{:override, ^app, overrides}, config ->
|
||||
Enum.reduce(overrides, config, fn {key, value}, config ->
|
||||
Keyword.put(config, key, value)
|
||||
end)
|
||||
@@ -335,14 +245,17 @@ defmodule Mix.Rebar do
|
||||
config
|
||||
end)
|
||||
|
||||
Enum.reduce(overrides, config, fn
|
||||
{:add, oapp, overrides}, config when oapp == app ->
|
||||
Enum.reduce(overrides, config, fn {key, value}, config ->
|
||||
old_value = Keyword.get(config, key, [])
|
||||
Keyword.put(config, key, value ++ old_value)
|
||||
config =
|
||||
Enum.reduce(overrides, config, fn
|
||||
{:add, ^app, overrides}, config ->
|
||||
Enum.reduce(overrides, config, fn {key, value}, config ->
|
||||
old_value = Keyword.get(config, key, [])
|
||||
Keyword.put(config, key, value ++ old_value)
|
||||
end)
|
||||
_, config ->
|
||||
config
|
||||
end)
|
||||
_, config ->
|
||||
config
|
||||
end)
|
||||
|
||||
Keyword.update(config, :overrides, overrides, &(overrides ++ &1))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -191,19 +191,29 @@ defmodule Mix.Tasks.Deps.Compile do
|
||||
Mix.raise "\"#{manager}\" installation failed"
|
||||
end
|
||||
|
||||
defp do_make(%{opts: opts} = dep, config) do
|
||||
os_type = :os.type
|
||||
defp do_make(dep, config) do
|
||||
command = make_command(dep)
|
||||
do_command(dep, config, command, true, [{"IS_DEP", "1"}])
|
||||
end
|
||||
|
||||
defp make_command(dep) do
|
||||
makefile_win? = makefile_win?(dep)
|
||||
|
||||
command =
|
||||
cond do
|
||||
match?({:win32, _}, os_type) and File.regular?(Path.join(opts[:dest], "Makefile.win")) ->
|
||||
case :os.type do
|
||||
{:win32, _} when makefile_win? ->
|
||||
"nmake /F Makefile.win"
|
||||
match?({:unix, type} when type in [:freebsd, :openbsd], os_type) ->
|
||||
{:unix, type} when type in [:freebsd, :openbsd] ->
|
||||
"gmake"
|
||||
true ->
|
||||
_ ->
|
||||
"make"
|
||||
end
|
||||
do_command(dep, config, command, true, [{"IS_DEP", "1"}])
|
||||
|
||||
if erlang_mk?(dep) do
|
||||
"#{command} clean && #{command}"
|
||||
else
|
||||
command
|
||||
end
|
||||
end
|
||||
|
||||
defp do_compile(%Mix.Dep{opts: opts} = dep, config) do
|
||||
@@ -248,4 +258,12 @@ defmodule Mix.Tasks.Deps.Compile do
|
||||
req
|
||||
end
|
||||
end
|
||||
|
||||
defp erlang_mk?(%Mix.Dep{opts: opts}) do
|
||||
File.regular?(Path.join(opts[:dest], "erlang.mk"))
|
||||
end
|
||||
|
||||
defp makefile_win?(%Mix.Dep{opts: opts}) do
|
||||
File.regular?(Path.join(opts[:dest], "Makefile.win"))
|
||||
end
|
||||
end
|
||||
|
||||
+213
-194
@@ -33,212 +33,231 @@ defmodule Mix.RebarTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "load Rebar config" do
|
||||
path = MixTest.Case.fixture_path("rebar_dep")
|
||||
config = Mix.Rebar.load_config(path)
|
||||
assert config[:sub_dirs] == ['apps/*']
|
||||
assert config[:SCRIPT] == 'rebar.config.script'
|
||||
end
|
||||
|
||||
test "execute rebar.config.script on dependency directory" do
|
||||
path = MixTest.Case.fixture_path("rebar_dep_script")
|
||||
config = Mix.Rebar.load_config(path)
|
||||
assert config[:dir] == {:ok, String.to_charlist(path)}
|
||||
end
|
||||
|
||||
test "parse Rebar dependencies" do
|
||||
config = [deps: [{:git_rebar, '~> 1.0'}]]
|
||||
assert [{:git_rebar, "~> 1.0"}] ==
|
||||
Mix.Rebar.deps(:foo, config, [])
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 1.0', {:pkg, :rebar_fork}}]]
|
||||
assert [{:git_rebar, "~> 1.0", hex: :rebar_fork}] ==
|
||||
Mix.Rebar.deps(:foo, config, [])
|
||||
|
||||
config = [deps: [{:git_rebar, '0.1..*', {:git, '../../test/fixtures/git_rebar', :master}}]]
|
||||
assert [{:git_rebar, ~r"0.1..*", [git: "../../test/fixtures/git_rebar", ref: "master"]}] ==
|
||||
Mix.Rebar.deps(:foo, config, [])
|
||||
|
||||
config = [deps: [{:git_rebar, {:git, '../../test/fixtures/git_rebar', :master}}]]
|
||||
assert [{:git_rebar, ">= 0.0.0", [git: "../../test/fixtures/git_rebar", ref: "master"]}] ==
|
||||
Mix.Rebar.deps(:foo, config, [])
|
||||
|
||||
config = [deps: [{:git_rebar, '0.1..*', {:git, '../../test/fixtures/git_rebar'}, [:raw]}]]
|
||||
assert [{:git_rebar, ~r"0.1..*", [git: "../../test/fixtures/git_rebar", compile: false]}] ==
|
||||
Mix.Rebar.deps(:foo, config, [])
|
||||
|
||||
config = [deps: [{:git_rebar, '', {:git, '../../test/fixtures/git_rebar', {:ref, '64691eb'}}}]]
|
||||
assert [{:git_rebar, ~r"", [git: "../../test/fixtures/git_rebar", ref: "64691eb"]}] ==
|
||||
Mix.Rebar.deps(:foo, config, [])
|
||||
|
||||
config = [deps: {:git_rebar, '~> 2.0'}]
|
||||
overrides = [{:override, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert [{:git_rebar, "~> 1.0"}] ==
|
||||
Mix.Rebar.deps(:foo, config, overrides)
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 2.0'}]]
|
||||
overrides = [{:override, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert [{:git_rebar, "~> 1.0"}] ==
|
||||
Mix.Rebar.deps(:foo, config, overrides)
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 2.0'}]]
|
||||
overrides = [{:override, :bar, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert [{:git_rebar, "~> 2.0"}] ==
|
||||
Mix.Rebar.deps(:foo, config, overrides)
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 2.0'}]]
|
||||
overrides = [{:override, :foo, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert [{:git_rebar, "~> 1.0"}] ==
|
||||
Mix.Rebar.deps(:foo, config, overrides)
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 1.0'}]]
|
||||
overrides = [{:add, :foo, [deps: [{:git_rebar2, '~> 2.0'}]]}]
|
||||
assert [{:git_rebar2, "~> 2.0"}, {:git_rebar, "~> 1.0"}] ==
|
||||
Mix.Rebar.deps(:foo, config, overrides)
|
||||
|
||||
end
|
||||
|
||||
test "convert rebar config to dependency config" do
|
||||
config = Mix.Rebar.load_config(fixture_path("rebar_dep"))
|
||||
dep_config = Mix.Rebar.dependency_config(config)
|
||||
|
||||
assert config[:erl_opts] == [:warnings_as_errors]
|
||||
assert dep_config[:erl_opts] == []
|
||||
end
|
||||
|
||||
test "parse Rebar dependencies from rebar.config" do
|
||||
Mix.Project.push(RebarAsDep)
|
||||
|
||||
deps = Mix.Dep.loaded([])
|
||||
assert Enum.find(deps, &(&1.app == :rebar_dep))
|
||||
|
||||
assert Enum.find(deps, fn %Mix.Dep{app: app, opts: opts} ->
|
||||
if app == :git_rebar do
|
||||
assert Enum.find(opts, &match?({:git, _}, &1))
|
||||
assert Enum.find(opts, &match?({:ref, "master"}, &1))
|
||||
true
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "inherit Rebar manager" do
|
||||
Mix.Project.push(Rebar3AsDep)
|
||||
|
||||
deps = Mix.Dep.loaded([])
|
||||
assert Enum.all?(deps, &(&1.manager == :rebar3))
|
||||
end
|
||||
|
||||
test "Rebar overrides" do
|
||||
Mix.Project.push(RebarOverrideAsDep)
|
||||
|
||||
in_tmp "Rebar overrides", fn ->
|
||||
Mix.Tasks.Deps.Get.run []
|
||||
assert Mix.Dep.loaded([]) |> Enum.map(& &1.app) ==
|
||||
[:git_repo, :git_rebar, :rebar_override]
|
||||
describe "load_config/1" do
|
||||
test "loads rebar.config" do
|
||||
path = MixTest.Case.fixture_path("rebar_dep")
|
||||
config = Mix.Rebar.load_config(path)
|
||||
assert config[:sub_dirs] == ['apps/*']
|
||||
assert config[:SCRIPT] == 'rebar.config.script'
|
||||
end
|
||||
|
||||
test "loads rebar.config.script on dependency directory" do
|
||||
path = MixTest.Case.fixture_path("rebar_dep_script")
|
||||
config = Mix.Rebar.load_config(path)
|
||||
assert config[:dir] == {:ok, String.to_charlist(path)}
|
||||
end
|
||||
after
|
||||
purge [GitRepo.Mixfile]
|
||||
end
|
||||
|
||||
test "recurs over sub dirs" do
|
||||
path = MixTest.Case.fixture_path("rebar_dep")
|
||||
describe "deps/1" do
|
||||
test "parses Rebar dependencies" do
|
||||
config = [deps: [{:git_rebar, '~> 1.0'}]]
|
||||
assert [{:git_rebar, "~> 1.0"}] ==
|
||||
Mix.Rebar.deps(config)
|
||||
|
||||
File.cd! path, fn ->
|
||||
config = Mix.Rebar.load_config(path)
|
||||
config = [deps: [{:git_rebar, '~> 1.0', {:pkg, :rebar_fork}}]]
|
||||
assert [{:git_rebar, "~> 1.0", hex: :rebar_fork}] ==
|
||||
Mix.Rebar.deps(config)
|
||||
|
||||
Mix.Rebar.recur(config, fn config ->
|
||||
if config[:sub_dirs] == ['from_apps_another'] do
|
||||
Process.put(:inside_apps_another, true)
|
||||
config = [deps: [{:git_rebar, {:pkg, :rebar_fork}}]]
|
||||
assert [{:git_rebar, ">= 0.0.0", hex: :rebar_fork}] ==
|
||||
Mix.Rebar.deps(config)
|
||||
|
||||
config = [deps: [{:git_rebar, '0.1..*', {:git, '../../test/fixtures/git_rebar', :master}}]]
|
||||
assert [{:git_rebar, ~r"0.1..*", [git: "../../test/fixtures/git_rebar", ref: "master"]}] ==
|
||||
Mix.Rebar.deps(config)
|
||||
|
||||
config = [deps: [{:git_rebar, {:git, '../../test/fixtures/git_rebar', :master}}]]
|
||||
assert [{:git_rebar, ">= 0.0.0", [git: "../../test/fixtures/git_rebar", ref: "master"]}] ==
|
||||
Mix.Rebar.deps(config)
|
||||
|
||||
config = [deps: [{:git_rebar, '0.1..*', {:git, '../../test/fixtures/git_rebar'}, [:raw]}]]
|
||||
assert [{:git_rebar, ~r"0.1..*", [git: "../../test/fixtures/git_rebar", compile: false]}] ==
|
||||
Mix.Rebar.deps(config)
|
||||
|
||||
config = [deps: [{:git_rebar, '', {:git, '../../test/fixtures/git_rebar', {:ref, '64691eb'}}}]]
|
||||
assert [{:git_rebar, ~r"", [git: "../../test/fixtures/git_rebar", ref: "64691eb"]}] ==
|
||||
Mix.Rebar.deps(config)
|
||||
end
|
||||
end
|
||||
|
||||
describe "apply_overrides/3" do
|
||||
test "applies overrides" do
|
||||
config = [deps: {:git_rebar, '~> 2.0'}]
|
||||
overrides = [{:override, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert Mix.Rebar.apply_overrides(:foo, config, overrides) ==
|
||||
[deps: [{:git_rebar, '~> 1.0'}], overrides: overrides]
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 2.0'}]]
|
||||
overrides = [{:override, :bar, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert Mix.Rebar.apply_overrides(:foo, config, overrides) ==
|
||||
[deps: [{:git_rebar, '~> 2.0'}], overrides: overrides]
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 2.0'}]]
|
||||
overrides = [{:override, :foo, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert Mix.Rebar.apply_overrides(:foo, config, overrides) ==
|
||||
[deps: [{:git_rebar, '~> 1.0'}], overrides: overrides]
|
||||
|
||||
config = [deps: [{:git_rebar, '~> 1.0'}]]
|
||||
overrides = [{:add, :foo, [deps: [{:git_rebar2, '~> 2.0'}]]}]
|
||||
assert Mix.Rebar.apply_overrides(:foo, config, overrides) ==
|
||||
[deps: [{:git_rebar2, '~> 2.0'}, {:git_rebar, '~> 1.0'}], overrides: overrides]
|
||||
end
|
||||
|
||||
test "concatenates overrides" do
|
||||
config = [deps: {:git_rebar, '~> 2.0'}, overrides: [{:add, :bar, []}]]
|
||||
overrides = [{:override, [deps: [{:git_rebar, '~> 1.0'}]]}]
|
||||
assert Mix.Rebar.apply_overrides(:foo, config, overrides) ==
|
||||
[deps: [{:git_rebar, '~> 1.0'}], overrides: overrides ++ [{:add, :bar, []}]]
|
||||
end
|
||||
end
|
||||
|
||||
describe "dependency_config/1" do
|
||||
test "converts Rebar config to dependency config" do
|
||||
config = Mix.Rebar.load_config(fixture_path("rebar_dep"))
|
||||
dep_config = Mix.Rebar.dependency_config(config)
|
||||
|
||||
assert config[:erl_opts] == [:warnings_as_errors]
|
||||
assert dep_config[:erl_opts] == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "recur/1" do
|
||||
test "recurs over sub dirs" do
|
||||
path = MixTest.Case.fixture_path("rebar_dep")
|
||||
|
||||
File.cd! path, fn ->
|
||||
config = Mix.Rebar.load_config(path)
|
||||
|
||||
Mix.Rebar.recur(config, fn config ->
|
||||
if config[:sub_dirs] == ['from_apps_another'] do
|
||||
Process.put(:inside_apps_another, true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
unless Process.get(:inside_apps_another) do
|
||||
flunk "Expected inside_apps_another to return true"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "integration with Mix" do
|
||||
test "inherits Rebar manager" do
|
||||
Mix.Project.push(Rebar3AsDep)
|
||||
deps = Mix.Dep.loaded([])
|
||||
assert Enum.all?(deps, &(&1.manager == :rebar3))
|
||||
end
|
||||
|
||||
|
||||
test "parses Rebar dependencies from rebar.config" do
|
||||
Mix.Project.push(RebarAsDep)
|
||||
|
||||
deps = Mix.Dep.loaded([])
|
||||
assert Enum.find(deps, &(&1.app == :rebar_dep))
|
||||
|
||||
assert Enum.find(deps, fn %Mix.Dep{app: app, opts: opts} ->
|
||||
if app == :git_rebar do
|
||||
assert Enum.find(opts, &match?({:git, _}, &1))
|
||||
assert Enum.find(opts, &match?({:ref, "master"}, &1))
|
||||
true
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
unless Process.get(:inside_apps_another) do
|
||||
flunk "Expected inside_apps_another to return true"
|
||||
end
|
||||
end
|
||||
test "handles Rebar overrides" do
|
||||
Mix.Project.push(RebarOverrideAsDep)
|
||||
|
||||
test "get and compile dependencies for Rebar" do
|
||||
Mix.Project.push(RebarAsDep)
|
||||
|
||||
in_tmp "get and compile dependencies for Rebar", fn ->
|
||||
Mix.Tasks.Deps.Get.run []
|
||||
assert_received {:mix_shell, :info, ["* Getting git_rebar" <> _]}
|
||||
|
||||
Mix.Tasks.Deps.Compile.run []
|
||||
assert_received {:mix_shell, :run, ["===> Compiling git_rebar\n"]}
|
||||
assert_received {:mix_shell, :run, ["===> Compiling rebar_dep\n"]}
|
||||
assert :git_rebar.any_function == :ok
|
||||
assert :rebar_dep.any_function == :ok
|
||||
|
||||
load_paths = Mix.Dep.loaded([])
|
||||
|> Enum.map(&Mix.Dep.load_paths(&1))
|
||||
|> Enum.concat
|
||||
|
||||
assert File.exists?("_build/dev/lib/rebar_dep/ebin/rebar_dep.beam")
|
||||
assert File.exists?("_build/dev/lib/git_rebar/ebin/git_rebar.beam")
|
||||
|
||||
# Assert we have no .compile.lock as a .compile.lock
|
||||
# means we check for the Elixir version on every command.
|
||||
refute File.exists?("_build/dev/lib/rebar_dep/.compile.lock")
|
||||
refute File.exists?("_build/dev/lib/git_rebar/.compile.lock")
|
||||
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "git_rebar/ebin"))
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "rebar_dep/ebin"))
|
||||
end
|
||||
end
|
||||
|
||||
test "get and compile dependencies for rebar3" do
|
||||
Mix.Project.push(Rebar3AsDep)
|
||||
|
||||
in_tmp "get and compile dependencies for rebar3", fn ->
|
||||
Mix.Tasks.Deps.Get.run []
|
||||
assert_received {:mix_shell, :info, ["* Getting git_rebar " <> _]}
|
||||
|
||||
Mix.Tasks.Deps.Compile.run []
|
||||
assert_received {:mix_shell, :run, ["===> Compiling git_rebar\n"]}
|
||||
assert_received {:mix_shell, :run, ["===> Compiling rebar_dep\n"]}
|
||||
assert :git_rebar.any_function == :ok
|
||||
assert :rebar_dep.any_function == :ok
|
||||
|
||||
load_paths = Mix.Dep.loaded([])
|
||||
|> Enum.map(&Mix.Dep.load_paths(&1))
|
||||
|> Enum.concat
|
||||
|
||||
assert File.exists?("_build/dev/lib/rebar_dep/ebin/rebar_dep.beam")
|
||||
assert File.exists?("_build/dev/lib/git_rebar/ebin/git_rebar.beam")
|
||||
|
||||
# Assert we have no .compile.lock as a .compile.lock
|
||||
# means we check for the Elixir version on every command.
|
||||
refute File.exists?("_build/dev/lib/rebar_dep/.compile.lock")
|
||||
refute File.exists?("_build/dev/lib/git_rebar/.compile.lock")
|
||||
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "git_rebar/ebin"))
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "rebar_dep/ebin"))
|
||||
end
|
||||
end
|
||||
|
||||
test "get and compile dependencies for Rebar with Mix" do
|
||||
Mix.Project.push(RebarAsDep)
|
||||
|
||||
in_tmp "get and compile dependencies for Rebar with Mix", fn ->
|
||||
File.write! MixTest.Case.tmp_path("rebar_dep/mix.exs"), """
|
||||
defmodule RebarDep.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[app: :rebar_dep,
|
||||
version: "0.0.1"]
|
||||
end
|
||||
in_tmp "Rebar overrides", fn ->
|
||||
Mix.Tasks.Deps.Get.run []
|
||||
assert Mix.Dep.loaded([]) |> Enum.map(& &1.app) ==
|
||||
[:git_repo, :git_rebar, :rebar_override]
|
||||
end
|
||||
"""
|
||||
after
|
||||
purge [GitRepo.Mixfile]
|
||||
end
|
||||
|
||||
Mix.Tasks.Deps.Compile.run []
|
||||
assert_received {:mix_shell, :info, ["==> rebar_dep"]}
|
||||
assert_received {:mix_shell, :info, ["Generated rebar_dep app"]}
|
||||
assert File.regular?("_build/dev/lib/rebar_dep/ebin/rebar_dep.app")
|
||||
test "gets and compiles dependencies for Rebar" do
|
||||
Mix.Project.push(RebarAsDep)
|
||||
|
||||
in_tmp "get and compile dependencies for Rebar", fn ->
|
||||
Mix.Tasks.Deps.Get.run []
|
||||
assert_received {:mix_shell, :info, ["* Getting git_rebar" <> _]}
|
||||
|
||||
Mix.Tasks.Deps.Compile.run []
|
||||
assert_received {:mix_shell, :run, ["===> Compiling git_rebar\n"]}
|
||||
assert_received {:mix_shell, :run, ["===> Compiling rebar_dep\n"]}
|
||||
assert :git_rebar.any_function == :ok
|
||||
assert :rebar_dep.any_function == :ok
|
||||
|
||||
load_paths = Mix.Dep.loaded([])
|
||||
|> Enum.map(&Mix.Dep.load_paths(&1))
|
||||
|> Enum.concat
|
||||
|
||||
assert File.exists?("_build/dev/lib/rebar_dep/ebin/rebar_dep.beam")
|
||||
assert File.exists?("_build/dev/lib/git_rebar/ebin/git_rebar.beam")
|
||||
|
||||
# Assert we have no .compile.lock as a .compile.lock
|
||||
# means we check for the Elixir version on every command.
|
||||
refute File.exists?("_build/dev/lib/rebar_dep/.compile.lock")
|
||||
refute File.exists?("_build/dev/lib/git_rebar/.compile.lock")
|
||||
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "git_rebar/ebin"))
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "rebar_dep/ebin"))
|
||||
end
|
||||
end
|
||||
|
||||
test "gets and compiles dependencies for rebar3" do
|
||||
Mix.Project.push(Rebar3AsDep)
|
||||
|
||||
in_tmp "get and compile dependencies for rebar3", fn ->
|
||||
Mix.Tasks.Deps.Get.run []
|
||||
assert_received {:mix_shell, :info, ["* Getting git_rebar " <> _]}
|
||||
|
||||
Mix.Tasks.Deps.Compile.run []
|
||||
assert_received {:mix_shell, :run, ["===> Compiling git_rebar\n"]}
|
||||
assert_received {:mix_shell, :run, ["===> Compiling rebar_dep\n"]}
|
||||
assert :git_rebar.any_function == :ok
|
||||
assert :rebar_dep.any_function == :ok
|
||||
|
||||
load_paths = Mix.Dep.loaded([])
|
||||
|> Enum.map(&Mix.Dep.load_paths(&1))
|
||||
|> Enum.concat
|
||||
|
||||
assert File.exists?("_build/dev/lib/rebar_dep/ebin/rebar_dep.beam")
|
||||
assert File.exists?("_build/dev/lib/git_rebar/ebin/git_rebar.beam")
|
||||
|
||||
# Assert we have no .compile.lock as a .compile.lock
|
||||
# means we check for the Elixir version on every command.
|
||||
refute File.exists?("_build/dev/lib/rebar_dep/.compile.lock")
|
||||
refute File.exists?("_build/dev/lib/git_rebar/.compile.lock")
|
||||
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "git_rebar/ebin"))
|
||||
assert Enum.any?(load_paths, &String.ends_with?(&1, "rebar_dep/ebin"))
|
||||
end
|
||||
end
|
||||
|
||||
test "gets and compiles dependencies for Rebar with Mix" do
|
||||
Mix.Project.push(RebarAsDep)
|
||||
|
||||
in_tmp "get and compile dependencies for Rebar with Mix", fn ->
|
||||
File.write! MixTest.Case.tmp_path("rebar_dep/mix.exs"), """
|
||||
defmodule RebarDep.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[app: :rebar_dep,
|
||||
version: "0.0.1"]
|
||||
end
|
||||
end
|
||||
"""
|
||||
|
||||
Mix.Tasks.Deps.Compile.run []
|
||||
assert_received {:mix_shell, :info, ["==> rebar_dep"]}
|
||||
assert_received {:mix_shell, :info, ["Generated rebar_dep app"]}
|
||||
assert File.regular?("_build/dev/lib/rebar_dep/ebin/rebar_dep.app")
|
||||
end
|
||||
after
|
||||
File.rm MixTest.Case.tmp_path("rebar_dep/mix.exs")
|
||||
end
|
||||
after
|
||||
File.rm MixTest.Case.tmp_path("rebar_dep/mix.exs")
|
||||
end
|
||||
end
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{application, elixir,
|
||||
[{description, "elixir"},
|
||||
{vsn, "1.4.0"},
|
||||
{vsn, "1.4.1"},
|
||||
{modules, [
|
||||
elixir
|
||||
]},
|
||||
|
||||
Reference in New Issue
Block a user