Compare commits

...
14 Commits
Author SHA1 Message Date
José Valim e5374cf5d3 Release v1.2.5 2016-04-30 13:34:56 +02:00
José Valim 352a357460 Do not assume @impl is a list, closes #4519
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-30 13:29:32 +02:00
Michael Pope cc018f90bf Stringify truncated function data in Logger (#4562)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-30 13:27:46 +02:00
José Valim 9374fbeae6 Revert manifest changes for release (they are part of master) 2016-04-30 13:27:30 +02:00
José Valim 9a44775b68 Make prune part of the public API in the formatter
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-30 13:25:05 +02:00
José Valim 07c6356354 Ensure poorly formatted chardata is pruned in Logger watcher
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-30 13:24:40 +02:00
Aleksei Magusev 55b124a478 Fix String.replace_trailing/3 replacement bug 2016-04-25 18:33:32 +02:00
Aleksei Magusev 5249d1d2f0 Fix String.replace_leading/3 replacement bug 2016-04-25 18:33:22 +02:00
Aleksei Magusev 59c0752143 Fix String.replace_leading/3 bug when the rest of string equals match 2016-04-25 18:33:08 +02:00
José Valim 39160df6a6 Improve Access deprecation warning 2016-04-15 09:36:46 +02:00
José Valim 08d2aaaf53 Also purge modules on outdated manifest
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-13 17:17:39 +02:00
José Valim 715a38a6e5 Integrate non-fetchable (path) dependencies into compilers
This commit changes Elixir compilers so a path dependencies
no longer forces the "parent" project to recompile. This
means each compiler must know how to track dependencies but
it gives faster compilation times as a benefit.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-13 16:29:57 +02:00
José Valim 7cc1ab4c63 Migrate from previous manifest versions
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-13 13:27:40 +02:00
José Valim 3798dff0fc Only recompile empty files if they changed
Prior to this commit, an Elixir file that did not
generate any modules would always be regenerated
whenever mix compile was invoked.

This commit addresses this issue by keeping source
files on its own rows in the Elixir manifest.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-04-13 12:56:00 +02:00
14 changed files with 91 additions and 27 deletions
+9
View File
@@ -85,6 +85,15 @@ ask Mix to use Rebar 3 to compile it by passing the `manager: :rebar3` option.
Once configured, Mix will prompt you to install Rebar 3 if it is not yet
available.
## v1.2.5 (2016-04-30)
### 1. Bug fixes
* [Logger] Stringify truncated function data in Logger
* [Logger] Ensure poorly formatted char data can also be logged by using the replacement character "�" (diamond question mark)
* [Mix] Do not assume `@impl` is always a list
* [String] Fix bugs in `String.replace_*` functions where it would not include the accumulated value for certain replacements
## v1.2.4 (2016-04-01)
### 1. Enhancements
+1 -1
View File
@@ -1 +1 @@
1.2.4
1.2.5
+3 -2
View File
@@ -44,8 +44,9 @@ defmodule Access do
nil
Since Access is a behaviour, it can be implemented to key-value
data structures. Access requires the key comparison to be
implemented using the `===` operator.
data structures. The implementation should be added to the
module that defines the struct being access. Access requires the
key comparison to be implemented using the `===` operator.
## Field-based lookups
+1 -1
View File
@@ -537,7 +537,7 @@ defmodule Protocol do
if Atom.to_string(protocol) =~ "Elixir.Access" do
:elixir_errors.warn __ENV__.line, __ENV__.file,
"implementation of the Access protocol is deprecated. For customization of " <>
"the dict[key] syntax, please implement the Dict behaviour instead"
"the data[key] syntax, please implement the Access behaviour in your struct"
else
Protocol.assert_protocol!(protocol)
Protocol.__ensure_defimpl__(protocol, for, __ENV__)
+3 -3
View File
@@ -628,12 +628,12 @@ defmodule String do
replace_leading(string, match, replacement, prefix_size, suffix_size, "")
end
defp replace_leading(string, match, replacement, prefix_size, suffix_size, acc) when suffix_size > 0 do
defp replace_leading(string, match, replacement, prefix_size, suffix_size, acc) when suffix_size >= 0 do
case string do
<<prefix::size(prefix_size)-binary, suffix::size(suffix_size)-binary>> when prefix == match ->
replace_leading(suffix, match, replacement, prefix_size, suffix_size - prefix_size, acc <> replacement)
_ ->
string
acc <> string
end
end
@@ -671,7 +671,7 @@ defmodule String do
<<prefix::size(prefix_size)-binary, suffix::size(suffix_size)-binary>> when suffix == match ->
replace_trailing(prefix, match, replacement, prefix_size - suffix_size, suffix_size, acc <> replacement)
_ ->
string
string <> acc
end
end
+27 -8
View File
@@ -164,15 +164,34 @@ defmodule StringTest do
assert String.capitalize("fin") == "Fin"
end
test "replace_leading" do
assert String.replace_leading("aa abc ", "a", "b") == "bb abc "
assert String.replace_leading("__ abc ", "_", "b") == "bb abc "
assert String.replace_leading("aaaaaaaa ", "a", "b") == "bbbbbbbb "
assert String.replace_leading("aaaaaaaa ", "aaa", "b") == "bbaa "
assert String.replace_leading("aaaaaaaaa", "a", "b") == "bbbbbbbbb"
assert String.replace_leading("]]]]]]", "]", "[]") == "[][][][][][]"
assert String.replace_leading("]]]]]]]]", "]", "") == ""
assert String.replace_leading("]]]]]] ]", "]", "") == " ]"
assert String.replace_leading("猫猫 cat ", "猫", "й") == "йй cat "
assert String.replace_leading("test", "t", "T") == "Test"
assert String.replace_leading("t", "t", "T") == "T"
assert String.replace_leading("aaa", "b", "c") == "aaa"
end
test "replace_trailing" do
assert String.replace_trailing(" abc aa", "a", "") == " abc "
assert String.replace_trailing(" abc __", "_", "") == " abc "
assert String.replace_trailing(" aaaaaaaaa", "a", "") == " "
assert String.replace_trailing("aaaaaaaaaa", "a", "") == ""
assert String.replace_trailing("]]]]]]]]]]", "]", "") == ""
assert String.replace_trailing(" cat 猫猫", "猫", "") == " cat "
assert String.replace_trailing("test", "t", "") == "tes"
assert String.replace_trailing("t", "t", "") == ""
assert String.replace_trailing(" abc aa", "a", "b") == " abc bb"
assert String.replace_trailing(" abc __", "_", "b") == " abc bb"
assert String.replace_trailing(" aaaaaaaa", "a", "b") == " bbbbbbbb"
assert String.replace_trailing(" aaaaaaaa", "aaa", "b") == " aabb"
assert String.replace_trailing("aaaaaaaaa", "a", "b") == "bbbbbbbbb"
assert String.replace_trailing("]]]]]]", "]", "[]") == "[][][][][][]"
assert String.replace_trailing("]]]]]]]]", "]", "") == ""
assert String.replace_trailing("] ]]]]]]", "]", "") == "] "
assert String.replace_trailing(" cat 猫猫", "猫", "й") == " cat йй"
assert String.replace_trailing("test", "t", "T") == "tesT"
assert String.replace_trailing("t", "t", "T") == "T"
assert String.replace_trailing("aaa", "b", "c") == "aaa"
end
test "rstrip" do
+1 -1
View File
@@ -562,7 +562,7 @@ defmodule Logger do
end
defp truncate(data, n) when is_function(data, 0),
do: Logger.Utils.truncate(data.(), n)
do: truncate(data.(), n)
defp truncate(data, n) when is_list(data) or is_binary(data),
do: Logger.Utils.truncate(data, n)
defp truncate(data, n),
+7 -2
View File
@@ -74,11 +74,16 @@ defmodule Logger.Backends.Console do
enabled: Keyword.get(colors, :enabled, IO.ANSI.enabled?)}
end
defp log_event(level, msg, ts, md, %{colors: colors} = state) do
defp log_event(level, msg, ts, md, %{colors: colors, device: device} = state) do
output =
format_event(level, msg, ts, md, state)
|> color_event(level, colors)
IO.write(state.device, output)
try do
IO.write(device, output)
rescue
ArgumentError ->
IO.write(device, Logger.Formatter.prune(output))
end
end
defp format_event(level, msg, ts, md, %{format: format, metadata: keys}) do
+20
View File
@@ -44,6 +44,26 @@ defmodule Logger.Formatter do
@type pattern :: :date | :level | :levelpad | :message | :metadata | :node | :time
@valid_patterns [:time, :date, :message, :level, :node, :metadata, :levelpad]
@default_pattern "\n$time $metadata[$level] $levelpad$message\n"
@replacement "�"
@doc """
Prune non-valid UTF-8 codepoints.
Typically called after formatting when the data cannot be printed.
"""
@spec prune(IO.chardata) :: IO.chardata
def prune(binary) when is_binary(binary), do: prune_binary(binary, "")
def prune([h|t]) when h in 0..1114111, do: [h|prune(t)]
def prune([h|t]), do: [prune(h)|prune(t)]
def prune([]), do: []
def prune(_), do: @replacement
defp prune_binary(<<h::utf8, t::binary>>, acc),
do: prune_binary(t, <<acc::binary, h::utf8>>)
defp prune_binary(<<_, t::binary>>, acc),
do: prune_binary(t, <<acc::binary, @replacement>>)
defp prune_binary(<<>>, acc),
do: acc
@doc ~S"""
Compiles a format string into an array that the `format/5` can handle.
+3 -3
View File
@@ -10,9 +10,9 @@ defmodule Logger.Watcher do
"""
def start_link(m, f, a) do
import Supervisor.Spec
child = worker(__MODULE__, [],
[function: :watcher, restart: :transient])
options = [strategy: :simple_one_for_one, name: @name]
child = worker(__MODULE__, [], [function: :watcher, restart: :transient])
options = [strategy: :simple_one_for_one, name: @name,
max_restarts: 30, max_seconds: 3]
case Supervisor.start_link([child], options) do
{:ok, _} = ok ->
_ = for {mod, handler, args} <- apply(m, f, a) do
@@ -4,6 +4,14 @@ defmodule Logger.FormatterTest do
import Logger.Formatter
test "prune/1" do
assert prune(1) == "�"
assert prune(<<"hí", 233>>) == "hí�"
assert prune(["hi"|233]) == ["hi"|"�"]
assert prune([233|"hi"]) == [233|"hi"]
assert prune([[]|[]]) == [[]]
end
defmodule CompileMod do
def format(_level, _msg, _ts, _md) do
true
+3 -3
View File
@@ -80,16 +80,16 @@ defmodule Logger.UtilsTest do
{'~ts~ts~ts', ["abcdeabcde", "", ""]}
end
test "timestamp" do
test "timestamp/1" do
assert {{_, _, _}, {_, _, _, _}} = timestamp(true)
end
test "format_date" do
test "format_date/1" do
date = {2015, 1, 30}
assert format_date(date) == ["2015", ?-, [?0, "1"], ?-, "30"]
end
test "format_time" do
test "format_time/1" do
time = {12, 30, 10, 1}
assert format_time(time) == ["12", ?:, "30", ?:, "10", ?., [?0, ?0, "1"]]
+4 -2
View File
@@ -145,10 +145,12 @@ defmodule Mix.Compilers.Elixir do
end
defp detect_kind(module) do
impl = Module.get_attribute(module, :impl)
cond do
impl = Module.get_attribute(module, :impl) ->
is_list(impl) and impl[:protocol] ->
{:impl, impl[:protocol]}
Module.get_attribute(module, :protocol) ->
is_list(Module.get_attribute(module, :protocol)) ->
:protocol
true ->
:module
+1 -1
View File
@@ -1,6 +1,6 @@
{application, elixir,
[{description, "elixir"},
{vsn, "1.2.4"},
{vsn, "1.2.5"},
{modules, [
elixir
]},