Compare commits

...
17 Commits
Author SHA1 Message Date
José Valim 2b338092b6 Release v1.7.2 2018-08-05 09:01:26 +02:00
Scott Riley 557b779bd4 Move parentheses in System.cmd() docs (#8046) 2018-08-04 18:44:11 +02:00
José Valim ece40480f6 Update CHANGELOG 2018-08-04 16:12:28 +02:00
José Valim a77445c46b Revert "Fix errors with ref/4 IEx helper (#8016)"
This reverts commit b9d6f4f9c1.
2018-08-04 15:37:15 +02:00
José Valim 4d55fa6814 Accordingly mark top level optional dependencies from child deps (#8035)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-08-04 14:08:33 +02:00
Fernando Tapia Rico b9d6f4f9c1 Fix errors with ref/4 IEx helper (#8016)
* Fix errors with ref/4 IEx helper

In addition, include documentation for that function.

* Update helpers.ex

* Add IEx.Helpers.ref/* tests

* Use examples that do not return ArgumentError

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-08-04 14:07:37 +02:00
Fernando Tapia Rico b0cf76c74c Fix year in negative datetimes with offset (#8038) 2018-08-04 13:18:41 +02:00
José Valim 7841fbb8e0 Do not fail suite if there are no tests to run
This matters in umbrella apps where some apps may not
have Elixir tests.

Closes #8040

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-08-04 00:46:04 +02:00
José Valim f5773fed42 Take negative years into account in DateTime (#8033)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-08-03 11:39:30 +02:00
José Valim e2b8ab9a0d Unify alias doc handling
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-31 23:20:35 +02:00
Dave Lucia 1dc6d10f30 mix help when theres a task and alias (#8020)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-31 23:20:30 +02:00
José Valim e7138fb2c6 Avoid Mix.ProjectStack deadlock, closes #8024
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-31 21:29:45 +02:00
José Valim 04ecc05adc Remove warnings for docs in the same clause
Unfortunately this leads to false positives when trying
to override the docs of an overridable definition.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-28 21:33:46 +02:00
José Valim 8aab53b941 Release v1.7.1 2018-07-26 21:33:18 +02:00
Michał Muskała 07c276ab5c Fix issues with dialyzer infinite loop (#7993)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-26 21:30:35 +02:00
David Cuddeback 89e3a81adc Skip intermediate parts when creating NaiveDateTime 2018-07-26 11:37:43 +02:00
David Cuddeback 9752f1ce05 Optimize ISO-8601 parsing for UTC 2018-07-26 11:37:43 +02:00
17 changed files with 423 additions and 110 deletions
+24
View File
@@ -116,6 +116,30 @@ Percentage | Module
77.19% | Total
```
## v1.7.2 (2018-08-05)
### 1. Bug fixes
#### Elixir
* [DateTime] Take negative years into account in `DateTime.from_iso8601/1`
* [Kernel] Do not emit warnings for repeated docs over different clauses due to false positives
#### Mix
* [mix compile] Properly mark top-level dependencies as optional and as runtime. This fixes a bug where Mix attempted to start optional dependencies of a package when those optional dependencies were not available
* [mix compile] Avoid deadlock when a config has a timestamp later than current time
* [mix help] Show task and alias help when both are available
* [mix test] Do not fail suite if there are no test files
## v1.7.1 (2018-07-26)
### 1. Bug fixes
#### Elixir
* [Calendar] Work-around a Dialyzer bug that causes it to loop for a long time, potentially indefinitely
## v1.7.0 (2018-07-25)
### 1. Enhancements
+1 -1
View File
@@ -1 +1 @@
1.7.0
1.7.2
+19 -14
View File
@@ -263,24 +263,29 @@ defmodule Date do
@spec from_iso8601(String.t(), Calendar.calendar()) :: {:ok, t} | {:error, atom}
def from_iso8601(string, calendar \\ Calendar.ISO)
[match_date, guard_date, read_date] = Calendar.ISO.__match_date__()
def from_iso8601(unquote(match_date), calendar) when unquote(guard_date) do
{year, month, day} = unquote(read_date)
with {:ok, date} <- new(year, month, day, Calendar.ISO) do
convert(date, calendar)
end
end
def from_iso8601(<<?-, next, rest::binary>>, calendar) when next != ?- do
with {:ok, %{year: year} = date} <- from_iso8601(<<next>> <> rest, calendar) do
def from_iso8601(<<?-, rest::binary>>, calendar) do
with {:ok, %{year: year} = date} <- raw_from_iso8601(rest, calendar) do
{:ok, %{date | year: -year}}
end
end
def from_iso8601(<<_::binary>>, _calendar) do
{:error, :invalid_format}
def from_iso8601(<<rest::binary>>, calendar) do
raw_from_iso8601(rest, calendar)
end
[match_date, guard_date, read_date] = Calendar.ISO.__match_date__()
defp raw_from_iso8601(string, calendar) do
with unquote(match_date) <- string,
true <- unquote(guard_date) do
{year, month, day} = unquote(read_date)
with {:ok, date} <- new(year, month, day, Calendar.ISO) do
convert(date, calendar)
end
else
_ -> {:error, :invalid_format}
end
end
@doc """
+39 -3
View File
@@ -485,6 +485,14 @@ defmodule DateTime do
iex> datetime
#DateTime<2015-01-23 21:20:07.123Z>
iex> {:ok, datetime, 0} = DateTime.from_iso8601("-2015-01-23T23:50:07Z")
iex> datetime
#DateTime<-2015-01-23 23:50:07Z>
iex> {:ok, datetime, 9000} = DateTime.from_iso8601("-2015-01-23T23:50:07,123+02:30")
iex> datetime
#DateTime<-2015-01-23 21:20:07.123Z>
iex> DateTime.from_iso8601("2015-01-23P23:50:07")
{:error, :invalid_format}
iex> DateTime.from_iso8601("2015-01-23 23:50:07A")
@@ -505,18 +513,28 @@ defmodule DateTime do
@doc since: "1.4.0"
@spec from_iso8601(String.t(), Calendar.calendar()) ::
{:ok, t, Calendar.utc_offset()} | {:error, atom}
def from_iso8601(string, calendar \\ Calendar.ISO)
def from_iso8601(<<?-, rest::binary>>, calendar) do
raw_from_iso8601(rest, calendar, true)
end
def from_iso8601(<<rest::binary>>, calendar) do
raw_from_iso8601(rest, calendar, false)
end
@sep [?\s, ?T]
[match_date, guard_date, read_date] = Calendar.ISO.__match_date__()
[match_time, guard_time, read_time] = Calendar.ISO.__match_time__()
def from_iso8601(string, calendar \\ Calendar.ISO) when is_binary(string) do
with <<unquote(match_date), sep, unquote(match_time), rest::binary>>
when unquote(guard_date) and sep in @sep and unquote(guard_time) <- string,
defp raw_from_iso8601(string, calendar, is_negative_datetime) do
with <<unquote(match_date), sep, unquote(match_time), rest::binary>> <- string,
true <- unquote(guard_date) and sep in @sep and unquote(guard_time),
{microsecond, rest} <- Calendar.ISO.parse_microsecond(rest),
{offset, ""} <- Calendar.ISO.parse_offset(rest) do
{year, month, day} = unquote(read_date)
{hour, minute, second} = unquote(read_time)
year = if is_negative_datetime, do: -year, else: year
cond do
not calendar.valid_date?(year, month, day) ->
@@ -525,6 +543,24 @@ defmodule DateTime do
not calendar.valid_time?(hour, minute, second, microsecond) ->
{:error, :invalid_time}
offset == 0 ->
datetime = %DateTime{
calendar: calendar,
year: year,
month: month,
day: day,
hour: hour,
minute: minute,
second: second,
microsecond: microsecond,
std_offset: 0,
utc_offset: 0,
zone_abbr: "UTC",
time_zone: "Etc/UTC"
}
{:ok, datetime, 0}
is_nil(offset) ->
{:error, :missing_offset}
+38 -9
View File
@@ -171,10 +171,35 @@ defmodule NaiveDateTime do
Calendar.microsecond(),
Calendar.calendar()
) :: {:ok, t} | {:error, atom}
def new(year, month, day, hour, minute, second, microsecond \\ {0, 0}, calendar \\ Calendar.ISO) do
with {:ok, date} <- Date.new(year, month, day, calendar),
{:ok, time} <- Time.new(hour, minute, second, microsecond, calendar),
do: new(date, time)
def new(year, month, day, hour, minute, second, microsecond \\ {0, 0}, calendar \\ Calendar.ISO)
def new(year, month, day, hour, minute, second, microsecond, calendar)
when is_integer(microsecond) do
new(year, month, day, hour, minute, second, {microsecond, 6}, calendar)
end
def new(year, month, day, hour, minute, second, microsecond, calendar) do
cond do
not calendar.valid_date?(year, month, day) ->
{:error, :invalid_date}
not calendar.valid_time?(hour, minute, second, microsecond) ->
{:error, :invalid_time}
true ->
naive_datetime = %NaiveDateTime{
calendar: calendar,
year: year,
month: month,
day: day,
hour: hour,
minute: minute,
second: second,
microsecond: microsecond
}
{:ok, naive_datetime}
end
end
@doc """
@@ -470,19 +495,23 @@ defmodule NaiveDateTime do
@spec from_iso8601(String.t(), Calendar.calendar()) :: {:ok, t} | {:error, atom}
def from_iso8601(string, calendar \\ Calendar.ISO)
def from_iso8601(<<?-, next, rest::binary>>, calendar) when next != ?- do
with {:ok, %{year: year} = naive_datetime} <- from_iso8601(<<next>> <> rest, calendar) do
def from_iso8601(<<?-, rest::binary>>, calendar) do
with {:ok, %{year: year} = naive_datetime} <- raw_from_iso8601(rest, calendar) do
{:ok, %{naive_datetime | year: -year}}
end
end
def from_iso8601(<<rest::binary>>, calendar) do
raw_from_iso8601(rest, calendar)
end
@sep [?\s, ?T]
[match_date, guard_date, read_date] = Calendar.ISO.__match_date__()
[match_time, guard_time, read_time] = Calendar.ISO.__match_time__()
def from_iso8601(string, calendar) when is_binary(string) do
with <<unquote(match_date), sep, unquote(match_time), rest::binary>>
when unquote(guard_date) and sep in @sep and unquote(guard_time) <- string,
defp raw_from_iso8601(string, calendar) do
with <<unquote(match_date), sep, unquote(match_time), rest::binary>> <- string,
true <- unquote(guard_date) and sep in @sep and unquote(guard_time),
{microsec, rest} <- Calendar.ISO.parse_microsecond(rest),
{_offset, ""} <- Calendar.ISO.parse_offset(rest) do
{year, month, day} = unquote(read_date)
+9 -4
View File
@@ -217,14 +217,19 @@ defmodule Time do
@spec from_iso8601(String.t(), Calendar.calendar()) :: {:ok, t} | {:error, atom}
def from_iso8601(string, calendar \\ Calendar.ISO)
def from_iso8601(<<?T, h, rest::binary>>, calendar) when h in ?0..?9 do
from_iso8601(<<h, rest::binary>>, calendar)
def from_iso8601(<<?T, rest::binary>>, calendar) do
raw_from_iso8601(rest, calendar)
end
def from_iso8601(<<rest::binary>>, calendar) do
raw_from_iso8601(rest, calendar)
end
[match_time, guard_time, read_time] = Calendar.ISO.__match_time__()
def from_iso8601(string, calendar) do
with <<unquote(match_time), rest::binary>> when unquote(guard_time) <- string,
defp raw_from_iso8601(string, calendar) do
with <<unquote(match_time), rest::binary>> <- string,
true <- unquote(guard_time),
{microsec, rest} <- Calendar.ISO.parse_microsecond(rest),
{_offset, ""} <- Calendar.ISO.parse_offset(rest) do
{hour, min, sec} = unquote(read_time)
-10
View File
@@ -1331,16 +1331,6 @@ defmodule Module do
[{_, current_line, current_sign, current_doc, current_doc_meta}] ->
signature = merge_signatures(current_sign, signature, 1)
if is_binary(doc) and is_binary(current_doc) and not is_nil(body) do
message =
"redefining @doc attribute previously set at line #{current_line}. " <>
"If you want to redefine a previously specified doc, " <>
"use a definition without a body after the original documentation"
:elixir_errors.warn(line, env.file, message)
end
doc = if is_nil(doc), do: current_doc, else: doc
doc = if is_nil(doc) && impl, do: false, else: doc
doc_meta = Map.merge(current_doc_meta, doc_meta)
+2 -2
View File
@@ -564,10 +564,10 @@ defmodule System do
iex> System.cmd("echo", ["hello"])
{"hello\n", 0}
iex> System.cmd("echo", ["hello"]), env: [{"MIX_ENV", "test"}]
iex> System.cmd("echo", ["hello"], env: [{"MIX_ENV", "test"}])
{"hello\n", 0}
iex> System.cmd("echo", ["hello"]), into: IO.stream(:stdio, :line)
iex> System.cmd("echo", ["hello"], into: IO.stream(:stdio, :line))
hello
{%IO.Stream{}, 0}
+94 -4
View File
@@ -293,8 +293,7 @@ defmodule DateTimeTest do
end
test "from_iso8601/1 handles positive and negative offsets" do
assert DateTime.from_iso8601("2015-01-24T09:50:07-10:00")
|> elem(1) ==
assert DateTime.from_iso8601("2015-01-24T09:50:07-10:00") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 1,
@@ -309,8 +308,7 @@ defmodule DateTimeTest do
second: 7
}
assert DateTime.from_iso8601("2015-01-24T09:50:07+10:00")
|> elem(1) ==
assert DateTime.from_iso8601("2015-01-24T09:50:07+10:00") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 1,
@@ -324,6 +322,98 @@ defmodule DateTimeTest do
minute: 50,
second: 7
}
assert DateTime.from_iso8601("0000-01-01T01:22:07+10:30") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 12,
std_offset: 0,
time_zone: "Etc/UTC",
utc_offset: 0,
year: -1,
zone_abbr: "UTC",
day: 31,
hour: 14,
minute: 52,
second: 7
}
end
test "from_iso8601/1 handles negative dates" do
assert DateTime.from_iso8601("-2015-01-24T09:50:07-10:00") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 1,
std_offset: 0,
time_zone: "Etc/UTC",
utc_offset: 0,
year: -2015,
zone_abbr: "UTC",
day: 24,
hour: 19,
minute: 50,
second: 7
}
assert DateTime.from_iso8601("-2015-01-24T09:50:07+10:00") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 1,
std_offset: 0,
time_zone: "Etc/UTC",
utc_offset: 0,
year: -2015,
zone_abbr: "UTC",
day: 23,
hour: 23,
minute: 50,
second: 7
}
assert DateTime.from_iso8601("-0001-01-01T01:22:07+10:30") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 12,
std_offset: 0,
time_zone: "Etc/UTC",
utc_offset: 0,
year: -2,
zone_abbr: "UTC",
day: 31,
hour: 14,
minute: 52,
second: 7
}
assert DateTime.from_iso8601("-0001-01-01T01:22:07-10:30") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 1,
std_offset: 0,
time_zone: "Etc/UTC",
utc_offset: 0,
year: -1,
zone_abbr: "UTC",
day: 1,
hour: 11,
minute: 52,
second: 7
}
assert DateTime.from_iso8601("-0001-12-31T23:22:07-10:30") |> elem(1) ==
%DateTime{
microsecond: {0, 0},
month: 1,
std_offset: 0,
time_zone: "Etc/UTC",
utc_offset: 0,
year: 0,
zone_abbr: "UTC",
day: 1,
hour: 9,
minute: 52,
second: 7
}
end
test "from_unix/2" do
@@ -1109,34 +1109,6 @@ defmodule Kernel.WarningTest do
purge(Sample)
end
test "duplicated docs across multiple clauses" do
output =
capture_err(fn ->
Code.eval_string("""
defmodule Sample do
@doc "Something"
def foo(a)
@doc "Something"
def foo(1), do: :ok
@doc "Something"
def foo(2), do: :ok
@doc "Something"
def foo(a)
end
""")
end)
assert output =~ "redefining @doc attribute previously set at line 2"
assert output =~ "nofile:5"
assert output =~ "nofile:8"
refute output =~ "nofile:11"
after
purge(Sample)
end
test "reserved doc metadata keys" do
output =
capture_err(fn ->
+27 -3
View File
@@ -117,6 +117,11 @@ defmodule Mix.Dep do
end
end
# optional and runtime only matter at the top level.
# Any non-top level dependency that is optional and
# is still available means it has been fulfilled.
@child_keep_opts [:optional, :runtime]
defp load_and_cache(_config, top, top, env) do
converge(env: env)
end
@@ -124,11 +129,30 @@ defmodule Mix.Dep do
defp load_and_cache(config, _top, bottom, _env) do
{_, deps} = Mix.ProjectStack.read_cache({:cached_deps, bottom})
app = Keyword.fetch!(config, :app)
top_level = for dep <- deps, dep.app == app, child <- dep.deps, do: child.app
seen = populate_seen(MapSet.new(), [app])
children = get_deps(deps, tl(Enum.uniq(get_children(deps, seen, [app]))))
Enum.map(children, &%{&1 | top_level: &1.app in top_level})
top_level =
for dep <- deps,
dep.app == app,
child <- dep.deps,
do: {child.app, Keyword.take(child.opts, @child_keep_opts)},
into: %{}
Enum.map(children, fn %{app: app} = dep ->
case top_level do
%{^app => child_opts} ->
opts =
dep.opts
|> Keyword.drop(@child_keep_opts)
|> Keyword.merge(child_opts)
%{dep | top_level: true, opts: opts}
%{} ->
%{dep | top_level: false}
end
end)
end
defp read_cached_deps(project, env) do
+18 -12
View File
@@ -99,19 +99,25 @@ defmodule Mix.ProjectStack do
@spec config_mtime() :: [integer]
def config_mtime() do
get_and_update(fn state ->
get_and_update_in(state.stack, fn
[%{config_mtime: nil, config_files: files} = h | t] ->
mtime = files |> Enum.map(&Mix.Utils.last_modified/1) |> Enum.max()
{mtime, [%{h | config_mtime: mtime} | t]}
[%{config_mtime: mtime} | _] = stack ->
{mtime, stack}
[] ->
{0, []}
mtime_or_files =
get(fn
%{stack: [%{config_mtime: nil, config_files: files} | _]} -> files
%{stack: [%{config_mtime: mtime} | _]} -> mtime
%{stack: []} -> 0
end)
end)
if is_list(mtime_or_files) do
mtime = mtime_or_files |> Enum.map(&Mix.Utils.last_modified/1) |> Enum.max()
cast(fn state ->
update_in(state.stack, fn [h | t] -> [%{h | config_mtime: mtime} | t] end)
end)
mtime
else
mtime = mtime_or_files
mtime
end
end
@spec config_apps() :: [atom]
+47 -19
View File
@@ -75,7 +75,6 @@ defmodule Mix.Tasks.Help do
aliases = Enum.filter(load_aliases(), fn {name, _} -> String.contains?(name, pattern) end)
{docs, max} = build_doc_list(modules, aliases)
display_doc_list(docs, max)
end
@@ -86,25 +85,39 @@ defmodule Mix.Tasks.Help do
def run([task]) do
loadpaths!()
{doc, location} = verbose_doc(task)
opts = Application.get_env(:mix, :colors)
if ansi_docs?(opts) do
opts = [width: width()] ++ opts
IO.ANSI.Docs.print_heading("mix #{task}", opts)
IO.ANSI.Docs.print(doc, opts)
else
IO.puts("# mix #{task}\n")
IO.puts(doc)
end
opts =
if ansi_docs?(opts) do
[width: width()] ++ opts
else
opts
end
IO.puts("Location: #{location}")
for doc <- verbose_doc(task) do
print_doc(task, doc, opts)
end
end
def run(_) do
Mix.raise("Unexpected arguments, expected \"mix help\" or \"mix help TASK\"")
end
defp print_doc(task, {doc, location, note}, opts) do
if ansi_docs?(opts) do
opts = [width: width()] ++ opts
IO.ANSI.Docs.print_heading("mix #{task}", opts)
IO.ANSI.Docs.print(doc, opts)
IO.puts("Location: #{location}")
note && IO.puts("") && IO.ANSI.Docs.print(note, opts)
else
IO.puts("# mix #{task}\n")
IO.puts(doc)
IO.puts("\nLocation: #{location}")
note && IO.puts([?\n, note, ?\n, ?\n])
end
end
# Loadpaths without checks because tasks may be defined in deps.
defp loadpaths! do
args = ["--no-elixir-version-check", "--no-deps-check", "--no-archives-check"]
@@ -194,14 +207,29 @@ defmodule Mix.Tasks.Help do
defp verbose_doc(task) do
aliases = load_aliases()
if Map.has_key?(aliases, task) do
task_name = aliases[task]
doc = "Alias for " <> inspect(task_name)
{doc, "mix.exs"}
else
module = Mix.Task.get!(task)
doc = Mix.Task.moduledoc(module) || "There is no documentation for this task"
{doc, where_is_file(module)}
has_alias? = Map.has_key?(aliases, task)
has_task? = Mix.Task.get(task)
cond do
has_alias? and has_task? ->
note = "There is also a task named \"#{task}\". The documentation is shown next."
[alias_doc(aliases[task], note), task_doc(task)]
has_alias? ->
[alias_doc(aliases[task], nil)]
true ->
[task_doc(task)]
end
end
defp alias_doc(task_name, note) do
{"Alias for " <> inspect(task_name), "mix.exs", note}
end
defp task_doc(task) do
module = Mix.Task.get!(task)
doc = Mix.Task.moduledoc(module) || "There is no documentation for this task"
{doc, where_is_file(module), nil}
end
end
+1 -1
View File
@@ -407,7 +407,7 @@ defmodule Mix.Tasks.Test do
Mix.shell().info("No stale tests")
files == [] ->
raise_or_error_at_exit("There are no tests to run", opts)
Mix.shell().info("There are no tests to run")
true ->
message = "Paths given to `mix test` did not match any directory/file: "
+71
View File
@@ -509,6 +509,77 @@ defmodule Mix.DepTest do
end)
end
test "nested deps with optional matching" do
Process.put(:custom_deps_git_repo_opts, optional: true)
# deps_repo brings git_repo but it is optional
deps = [
{:deps_repo, "0.1.0", path: "custom/deps_repo"},
{:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo")}
]
with_deps(deps, fn ->
in_fixture("deps_status", fn ->
File.mkdir_p!("custom/deps_repo/lib")
File.write!("custom/deps_repo/lib/a.ex", """
# Check that the child dependency is top_level and optional
[%Mix.Dep{app: :git_repo, top_level: true, opts: opts}] = Mix.Dep.cached()
true = Keyword.fetch!(opts, :optional)
""")
Mix.Tasks.Deps.Get.run([])
Mix.Tasks.Deps.Compile.run([])
end)
end)
end
test "nested deps with runtime override on parent" do
Process.put(:custom_deps_git_repo_opts, runtime: false)
deps = [
{:deps_repo, "0.1.0", path: "custom/deps_repo"},
{:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo")}
]
with_deps(deps, fn ->
in_fixture("deps_status", fn ->
File.mkdir_p!("custom/deps_repo/lib")
File.write!("custom/deps_repo/lib/a.ex", """
# Check that the child dependency is top_level and optional
[%Mix.Dep{app: :git_repo, top_level: true, opts: opts}] = Mix.Dep.cached()
false = Keyword.fetch!(opts, :runtime)
""")
Mix.Tasks.Deps.Get.run([])
Mix.Tasks.Deps.Compile.run([])
end)
end)
end
test "nested deps with runtime override on child" do
deps = [
{:deps_repo, "0.1.0", path: "custom/deps_repo"},
{:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo"), runtime: false}
]
with_deps(deps, fn ->
in_fixture("deps_status", fn ->
File.mkdir_p!("custom/deps_repo/lib")
File.write!("custom/deps_repo/lib/a.ex", """
# Check that the child dependency is top_level and optional
[%Mix.Dep{app: :git_repo, top_level: true, opts: opts}] = Mix.Dep.cached()
false = Keyword.has_key?(opts, :runtime)
""")
Mix.Tasks.Deps.Get.run([])
Mix.Tasks.Deps.Compile.run([])
end)
end)
end
test "nested deps with overrides" do
# deps_repo brings git_repo but it is overriden
deps = [
+27
View File
@@ -136,6 +136,33 @@ defmodule Mix.Tasks.HelpTest do
end)
end
defmodule ShadowedAliases do
def project do
[aliases: [compile: "compile"]]
end
end
test "help TASK && ALIAS", context do
Mix.Project.push(ShadowedAliases)
in_tmp(context.test, fn ->
output =
capture_io(fn ->
Mix.Tasks.Help.run(["compile"])
end)
assert output =~ "# mix compile\n\n"
assert output =~ "Alias for \"compile\"\n"
assert output =~ ~r/^Location: mix.exs/m
assert output =~
"\nThere is also a task named \"compile\". The documentation is shown next.\n"
assert output =~ "## Command line options"
assert output =~ ~r/^Location:/m
end)
end
test "help --search PATTERN", context do
in_tmp(context.test, fn ->
Mix.Tasks.Help.run(["--search", "deps"])
@@ -61,6 +61,12 @@ defmodule Mix.Tasks.LoadconfigTest do
Mix.Task.run("loadconfig", [config])
assert config in Mix.Project.config_files()
assert Mix.Project.config_mtime() > mtime
# Touching it should not have any deadlocks
File.touch!(config, {{2030, 1, 1}, {0, 0, 0}})
Mix.Task.run("loadconfig", [config])
assert config in Mix.Project.config_files()
assert Mix.Project.config_mtime() > mtime
end)
end