From 5a692a1a68671849af049ca13851da81446d8748 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Mon, 8 Jan 2018 17:18:32 +0800 Subject: [PATCH 1/5] Starts to replace 'prefix' with Key Mapping in configuration. 1. Fixes README. 1. Upgrades plugins. 1. Fixes test. --- CHANGELOG.md | 10 ++-- README.md | 66 +++++++++++++------------ mix.exs | 4 +- mix.lock | 8 +-- test/rat_error_test.exs | 106 +++++++++++++++++++++++++++++----------- 5 files changed, 126 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 855505f..250d0d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,14 @@ ## TODO + 1. Removes 'prefix' configuration and adds Key Mapping. + 1. Integrates with Circle CI. + 1. Releases `0.0.2`. + ## Schedule ### Release `0.0.1` - * Exports function `rat_error` (after calling `use RatError`). - * Exports `rat_error` configuration (see `config/*.exs` for detail). - * Implements module `RatError.Formatter` and `RatError.Structure`. +1. Exports function `rat_error` (after calling `use RatError`). +1. Exports `rat_error` configuration (see `config/*.exs` for detail). +1. Implements module `RatError.Formatter` and `RatError.Structure`. diff --git a/README.md b/README.md index dc468d2..fa50805 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Provides helper functions for error handling: ```elixir def deps do [ - {:rat_error, "~> 0.0.1"} + {:rat_error, "~> 0.0.2"} ] end ``` @@ -19,9 +19,14 @@ end ```elixir config :rat_error, RatError.Structure, - # Node Name, the default value is 'error'. + # Node Name # - # If node is 'err', the structure is, + # The node is removed if key `node` is not existing or value is nil. Error + # fields are exposed outside, and the below configuration `keys` must be set + # to distinguish with other caller's keys. + node: :err, + + # So the structure should be, # # %{ # err: @@ -34,47 +39,46 @@ config :rat_error, RatError.Structure, # module: Elixir.MyApp.Registration.UserController # } # } - # - # If node is nil or an empty string, the node is removed. The fields are - # exposed outside, and the below configuration 'prefix' could be set to - # distinguish with other caller's keys. - node: :error, - # Field Prefix, the default value is nil (NO prefix). - # - # If node is nil and prefix is 'err_', the structure is, - # - # %{ - # err_code: :invalid_argument, - # err_file: "/home/dummy/my_app/web/user_controller.ex", - # err_function: {:authenticate, 1}, - # err_line: 123, - # err_message: "wrong token!", - # err_module: Elixir.MyApp.Registration.UserController - # } + # Support Key Mapping # - prefix: nil, - - # Support Keys + # This Map must be set with the original fields (as Map keys). Map keys are + # original fields (see the below description for detail). Map values are + # custom field names (for formatting, they could be the same atoms as keys). + # The field is ignored if key is not existing or value is nil. keys: - [ + %{ # Error code defined by caller, e.g. an atom :no_entry, an integer 9 or a # string "unexpected". - :code, + code: :err_code, # Error file path. - :file, + file: :file, # Error function name. - :function, + function: :function, # Error file line. - :line, + line: :line, # Error message of string passed in by caller. - :message, + message: :err_msg, # Error module. - :module - ] + module: :module + } + + # So the structure should be, + # + # %{ + # err: + # %{ + # err_code: :invalid_argument, + # err_msg: "wrong token!", + # file: "/home/dummy/my_app/web/user_controller.ex", + # function: {:authenticate, 1}, + # line: 123, + # module: Elixir.MyApp.Registration.UserController + # } + # } ``` diff --git a/mix.exs b/mix.exs index 3745e2e..6bbbf1f 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule RatError.Mixfile do def project do [ app: :rat_error, - version: "0.0.1", + version: "0.0.2", elixir: "~> 1.5", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, @@ -24,7 +24,7 @@ defmodule RatError.Mixfile do defp deps do [ - {:credo, "~> 0.5", only: [:dev, :test]}, + {:credo, "~> 0.8", only: [:dev, :test], runtime: false}, {:ex_doc, ">= 0.0.0", only: :dev} ] end diff --git a/mix.lock b/mix.lock index 23a1be9..7263468 100644 --- a/mix.lock +++ b/mix.lock @@ -1,4 +1,4 @@ -%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []}, - "credo": {:hex, :credo, "0.8.6", "335f723772d35da499b5ebfdaf6b426bfb73590b6fcbc8908d476b75f8cbca3f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, - "earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.16.4", "4bf6b82d4f0a643b500366ed7134896e8cccdbab4d1a7a35524951b25b1ec9f0", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}} +%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, + "credo": {:hex, :credo, "0.8.10", "261862bb7363247762e1063713bb85df2bbd84af8d8610d1272cd9c1943bba63", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, + "earmark": {:hex, :earmark, "1.2.4", "99b637c62a4d65a20a9fb674b8cffb8baa771c04605a80c911c4418c69b75439", [:mix], [], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}} diff --git a/test/rat_error_test.exs b/test/rat_error_test.exs index 53863ae..a7d257a 100644 --- a/test/rat_error_test.exs +++ b/test/rat_error_test.exs @@ -3,47 +3,97 @@ defmodule RatErrorTest do use RatError doctest RatError - defp rat_error_fun(invalid_arg, opts \\ []) do - message = "Invalid argument '#{inspect(invalid_arg)}'!" + test "checks error with default configuration" do + expected_result = %{ + error: %{ + code: :invalid_argument, + file: "rat_error_test.exs", + function: {:rat_error_fun, 2}, + line: 9, + message: "Invalid argument 'user'!", + module: RatErrorTest + } + } - rat_error(:invalid_argument, message, opts) + opts = %{ + node: :error, + + keys: %{ + code: :code, + file: :file, + function: :function, + line: :line, + message: :message, + module: :module + } + } + + result = rat_error_fun("user", opts) + + # retrieves the last component of the path. + file = Path.basename(result.error.file) + error = %{result.error | file: file} + + result = %{result | error: error} + + assert result == expected_result end - test "checks error with default configuration" do - expected_result = - %{ - error: - %{ - code: :invalid_argument, - file: "rat_error_test.exs", - function: {:rat_error_fun, 2}, - line: 9, - message: "Invalid argument 'nil'!", - module: RatErrorTest - } + test "checks error with null node" do + expected_result = %{ + code: :invalid_argument, + file: "rat_error_test.exs", + function: {:rat_error_fun, 2}, + line: 9, + message: "Invalid argument 'user'!", + module: RatErrorTest + } + + opts = %{ + # Removes key 'node'. + + keys: %{ + code: :code, + file: :file, + function: :function, + line: :line, + message: :message, + module: :module } + } - real_result = rat_error_fun(nil) + result = rat_error_fun("user", opts) # retrieves the last component of the path. - file = Path.basename(real_result.error.file) - error = %{real_result.error | file: file} + file = Path.basename(result.error.file) + error = %{result.error | file: file} - real_result = %{real_result | error: error} + result = %{result | error: error} - assert expected_result == real_result + assert result == expected_result end - test "checks error with custom configuration" do - expected_result = - %{ - err_code: :invalid_argument, - err_message: "Invalid argument 'nil'!" + test "checks error with null node and custom keys" do + expected_result = %{ + err_code: :invalid_argument, + err_msg: "Invalid argument 'user'!" + } + + opts = %{ + keys: %{ + code: :err_code, + message: :err_msg } + } - real_result = - rat_error_fun(nil, node: nil, prefix: :err_, keys: [:code, :message]) + result = rat_error_fun("user", opts) - assert expected_result == real_result + assert result == expected_result + end + + defp rat_error_fun(invalid_arg, opts \\ []) do + message = "Invalid argument '#{inspect(invalid_arg)}'!" + + rat_error(:invalid_argument, message, opts) end end From 1f1e11148de3fd2c8993879c8b235bf10ffb8608 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Thu, 11 Jan 2018 14:23:36 +0800 Subject: [PATCH 2/5] Removes 'prefix' configuration and adds Key Mapping. --- CHANGELOG.md | 7 +-- config/dev.exs | 65 +++-------------------- config/prod.exs | 8 +-- config/test.exs | 20 ++++--- lib/rat_error.ex | 6 +-- lib/rat_error/formatter.ex | 23 ++++---- lib/rat_error/structure.ex | 106 ++++++++++++++++++------------------- test/rat_error_test.exs | 86 ++++++++++++++---------------- 8 files changed, 137 insertions(+), 184 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 250d0d6..ef813ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,13 @@ ## TODO - 1. Removes 'prefix' configuration and adds Key Mapping. - 1. Integrates with Circle CI. - 1. Releases `0.0.2`. +1. Integrates with Circle CI. +1. Releases `0.0.2`. ## Schedule +1. Removes 'prefix' configuration and adds Key Mapping. + ### Release `0.0.1` 1. Exports function `rat_error` (after calling `use RatError`). diff --git a/config/dev.exs b/config/dev.exs index 801a86f..65078e8 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -1,61 +1,12 @@ use Mix.Config config :rat_error, RatError.Structure, - # Node Name, the default value is 'error'. - # - # If node is 'err', the structure is, - # - # %{ - # err: - # %{ - # code: :invalid_argument, - # file: "/home/dummy/my_app/web/user_controller.ex", - # function: {:authenticate, 1}, - # line: 123, - # message: "wrong token!", - # module: Elixir.MyApp.Registration.UserController - # } - # } - # - # If node is nil or an empty string, the node is removed. The fields are - # exposed outside, and the below configuration 'prefix' could be set to - # distinguish with other caller's keys. node: :error, - - # Field Prefix, the default value is nil (NO prefix). - # - # If node is nil and prefix is 'err_', the structure is, - # - # %{ - # err_code: :invalid_argument, - # err_file: "/home/dummy/my_app/web/user_controller.ex", - # err_function: {:authenticate, 1}, - # err_line: 123, - # err_message: "wrong token!", - # err_module: Elixir.MyApp.Registration.UserController - # } - # - prefix: nil, - - # Support Keys - keys: - [ - # Error code defined by caller, e.g. an atom :no_entry, an integer 9 or a - # string "unexpected". - :code, - - # Error file path. - :file, - - # Error function name. - :function, - - # Error file line. - :line, - - # Error message of string passed in by caller. - :message, - - # Error module. - :module - ] + keys: %{ + code: :code, + file: :file, + function: :function, + line: :line, + message: :message, + module: :module + } diff --git a/config/prod.exs b/config/prod.exs index 50fdabb..a57ab13 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -1,6 +1,8 @@ use Mix.Config config :rat_error, RatError.Structure, - node: :error, - prefix: nil, - keys: :code + node: :error, + keys: %{ + code: :code, + message: :message + } diff --git a/config/test.exs b/config/test.exs index 3428160..65078e8 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,14 +1,12 @@ use Mix.Config config :rat_error, RatError.Structure, - node: :error, - prefix: nil, - keys: - [ - :code, - :file, - :function, - :line, - :message, - :module - ] + node: :error, + keys: %{ + code: :code, + file: :file, + function: :function, + line: :line, + message: :message, + module: :module + } diff --git a/lib/rat_error.ex b/lib/rat_error.ex index d893e09..1b7e7ca 100644 --- a/lib/rat_error.ex +++ b/lib/rat_error.ex @@ -33,15 +33,15 @@ defmodule RatError do Parameter 'opts' merges with the configuration in 'config/test.exs'. - iex> opts = [keys: [:code, :message]] + iex> opts = [keys: %{code: :code, message: :message}] iex> rat_error(:wrong_password, "Wrong password!", opts) %{error: %{code: :wrong_password, message: "Wrong password!"}} """ defmacro rat_error(error_code \\ nil, error_message \\ "", opts \\ []) do - quote(bind_quoted: [error_code: error_code, + quote(bind_quoted: [error_code: error_code, error_message: error_message, - opts: opts], + opts: opts], location: :keep) do structure = Structure.update(@structure, opts) diff --git a/lib/rat_error/formatter.ex b/lib/rat_error/formatter.ex index 3d1a2be..6ac4bce 100644 --- a/lib/rat_error/formatter.ex +++ b/lib/rat_error/formatter.ex @@ -21,12 +21,14 @@ defmodule RatError.Formatter do ## Examples - iex> structure = %Structure{node: :err, keys: [:code, :message]} + iex> support_keys = %{code: :code, message: :message} + iex> structure = %Structure{node: :err, keys: support_keys} iex> message = "Bad response!" iex> Formatter.format(structure, __ENV__, :bad_response, message) %{err: %{code: :bad_response, message: "Bad response!"}} - iex> structure = %Structure{keys: [:code, :message]} + iex> support_keys = %{code: :code, message: :message} + iex> structure = %Structure{keys: support_keys} iex> message = "Out of memory!" iex> Formatter.format(structure, __ENV__, :no_memory, message) %{code: :no_memory, message: "Out of memory!"} @@ -50,17 +52,16 @@ defmodule RatError.Formatter do end end + defp add_field(nil, _value, params), do: params + defp add_field(key, value, params), do: Map.put(params, key, value) + defp format_code(params, structure, value), do: format_entry(params, structure, :code, value) defp format_entry(params, structure, key, value) when is_atom(key) do - if structure.keys |> List.wrap |> Enum.member?(key) do - new_key = String.to_atom(to_string(structure.prefix) <> to_string(key)) - - Map.put(params, new_key, value) - else - params - end + structure.keys + |> get_field_name(key) + |> add_field(value, params) end defp format_env_values(params, structure, env) do @@ -70,4 +71,8 @@ defmodule RatError.Formatter do defp format_message(params, structure, value), do: format_entry(params, structure, :message, value) + + defp get_field_name(nil, _key), do: nil + defp get_field_name(support_keys, key) when is_map(support_keys), + do: support_keys[key] end diff --git a/lib/rat_error/structure.ex b/lib/rat_error/structure.ex index 0b04b9a..9d1f5fe 100644 --- a/lib/rat_error/structure.ex +++ b/lib/rat_error/structure.ex @@ -5,9 +5,11 @@ defmodule RatError.Structure do This struct could be created from the specified options as below, [ - node: :error, - prefix: nil, - keys: [:code, :message] + node: :error, + keys: %{ + code: :code, + message: :message + } ] References the 'RatError.Structure' configuration in 'config/*.exs' for @@ -17,9 +19,9 @@ defmodule RatError.Structure do alias __MODULE__ require Logger - defstruct [:node, :prefix, :keys] + defstruct [:node, :keys] - @support_keys [ + @support_fields [ # Error code defined by caller, e.g. an atom :no_entry, an integer 9 or a # string "unexpected". :code, @@ -50,20 +52,17 @@ defmodule RatError.Structure do References 'config/test.exs' for the test configuration. iex> Structure.create_from_default_config - %RatError.Structure - { - node: :error, - prefix: nil, - keys: - [ - :code, - :file, - :function, - :line, - :message, - :module - ] + %RatError.Structure{ + node: :error, + keys: %{ + code: :code, + file: :file, + function: :function, + line: :line, + message: :message, + module: :module } + } """ def create_from_default_config do @@ -77,35 +76,37 @@ defmodule RatError.Structure do ## Examples - iex> Structure.create(node: :err, keys: [:code, :message]) - %RatError.Structure - { - node: :err, - prefix: nil, - keys: [:code, :message] + iex> support_keys = %{code: :code, message: :message} + iex> Structure.create(node: :err, keys: support_keys) + %RatError.Structure{ + node: :err, + keys: %{ + code: :code, + message: :message } - - iex> Structure.create(prefix: :err, keys: [:code, :message]) - %RatError.Structure - { - node: nil, - prefix: :err, - keys: [:code, :message] + } + + iex> support_keys = %{code: :code, message: :message} + iex> Structure.create(keys: support_keys) + %RatError.Structure{ + node: nil, + keys: %{ + code: :code, + message: :message } + } - iex> Structure.create(keys: :code) - %RatError.Structure - { - node: nil, - prefix: nil, - keys: [:code] - } + iex> Structure.create(keys: %{code: :code}) + %RatError.Structure{ + node: nil, + keys: %{code: :code} + } """ def create(opts) when is_list(opts) do keys = filter_keys(opts[:keys]) - %Structure{node: opts[:node], prefix: opts[:prefix], keys: keys} + %Structure{node: opts[:node], keys: keys} end @doc """ @@ -113,19 +114,17 @@ defmodule RatError.Structure do ## Examples - iex> structure = %Structure{node: :error, keys: [:code]} - iex> Structure.update(structure, node: :err, prefix: :err, keys: :message) - %RatError.Structure - { - node: :err, - prefix: :err, - keys: [:message] - } + iex> structure = %Structure{node: :error, keys: %{code: :code}} + iex> Structure.update(structure, node: :err, keys: %{message: :message}) + %RatError.Structure{ + node: :err, + keys: %{message: :message} + } """ def update(%Structure{} = structure, opts) when is_list(opts) do params = - Enum.reduce([:node, :prefix, :keys], %{}, + Enum.reduce([:node, :keys], %{}, fn(k, acc) -> case Keyword.fetch(opts, k) do {:ok, v} -> Map.put(acc, k, v) @@ -143,14 +142,15 @@ defmodule RatError.Structure do Map.merge(structure, params) end - defp filter_keys(keys) do - keys = List.wrap(keys) - filtered_keys = keys -- (keys -- @support_keys) + defp filter_keys(nil), do: nil + defp filter_keys(keys) when is_map(keys) do + fields = Map.keys(keys) + filtered_fields = fields -- (fields -- @support_fields) - if is_nil(List.first(filtered_keys)) do + if is_nil(List.first(filtered_fields)) do Logger.warn("there is no support keys - '#{inspect(keys)}'!") end - filtered_keys + Map.take(keys, filtered_fields) end end diff --git a/test/rat_error_test.exs b/test/rat_error_test.exs index a7d257a..6e7286c 100644 --- a/test/rat_error_test.exs +++ b/test/rat_error_test.exs @@ -3,97 +3,93 @@ defmodule RatErrorTest do use RatError doctest RatError + # Leaves this private function for the const 'line' value. + defp rat_error_fun(invalid_value, opts) do + message = "Invalid argument '#{invalid_value}'!" + + rat_error(:invalid_argument, message, opts) + end + test "checks error with default configuration" do expected_result = %{ error: %{ - code: :invalid_argument, - file: "rat_error_test.exs", + code: :invalid_argument, + file: "rat_error_test.exs", function: {:rat_error_fun, 2}, - line: 9, - message: "Invalid argument 'user'!", - module: RatErrorTest + line: 10, + message: "Invalid argument 'user'!", + module: RatErrorTest } } - opts = %{ + opts = [ node: :error, - keys: %{ - code: :code, - file: :file, + code: :code, + file: :file, function: :function, - line: :line, - message: :message, - module: :module + line: :line, + message: :message, + module: :module } - } + ] result = rat_error_fun("user", opts) # retrieves the last component of the path. file = Path.basename(result.error.file) - error = %{result.error | file: file} + error = %{result.error | file: file} result = %{result | error: error} - assert result == expected_result end test "checks error with null node" do expected_result = %{ - code: :invalid_argument, - file: "rat_error_test.exs", + code: :invalid_argument, + file: "rat_error_test.exs", function: {:rat_error_fun, 2}, - line: 9, - message: "Invalid argument 'user'!", - module: RatErrorTest + line: 10, + message: "Invalid argument 'user'!", + module: RatErrorTest } - opts = %{ - # Removes key 'node'. - + opts = [ + node: nil, keys: %{ - code: :code, - file: :file, + code: :code, + file: :file, function: :function, - line: :line, - message: :message, - module: :module + line: :line, + message: :message, + module: :module } - } + ] result = rat_error_fun("user", opts) # retrieves the last component of the path. - file = Path.basename(result.error.file) - error = %{result.error | file: file} - - result = %{result | error: error} + file = Path.basename(result.file) + result = %{result | file: file} assert result == expected_result end test "checks error with null node and custom keys" do expected_result = %{ err_code: :invalid_argument, - err_msg: "Invalid argument 'user'!" + err_msg: "Invalid argument 'user'!" } - opts = %{ + opts = [ + node: nil, keys: %{ - code: :err_code, - message: :err_msg + code: :err_code, + message: :err_msg } - } + ] result = rat_error_fun("user", opts) - assert result == expected_result end - - defp rat_error_fun(invalid_arg, opts \\ []) do - message = "Invalid argument '#{inspect(invalid_arg)}'!" - - rat_error(:invalid_argument, message, opts) - end end From dad70eed7a818344b8ac291d4e66c34617f583c3 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Mon, 15 Jan 2018 16:09:26 +0800 Subject: [PATCH 3/5] Integrates with Travis CI. --- .travis.xml | 10 ++++++++++ CHANGELOG.md | 2 +- README.md | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .travis.xml diff --git a/.travis.xml b/.travis.xml new file mode 100644 index 0000000..00f9e7c --- /dev/null +++ b/.travis.xml @@ -0,0 +1,10 @@ +language: elixir +elixir: + - 1.5.3 +otp_release: + - 19.3 + - 20.2 +dist: trusty +notifications: + recipients: + - asongala@163.com diff --git a/CHANGELOG.md b/CHANGELOG.md index ef813ab..7984425 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,12 @@ ## TODO -1. Integrates with Circle CI. 1. Releases `0.0.2`. ## Schedule 1. Removes 'prefix' configuration and adds Key Mapping. +1. Integrates with Travis CI. ### Release `0.0.1` diff --git a/README.md b/README.md index fa50805..35c9f7f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Rat Error +[![Build Status](https://travis-ci.org/silathdiir/rat_error.svg?branch=master)](https://travis-ci.org/silathdiir/rat_error) + Provides helper functions for error handling: * detailed error description. From a721c2f6f598bfcacb44ab0879b106aac15b4ad1 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Mon, 15 Jan 2018 16:16:24 +0800 Subject: [PATCH 4/5] Updates CHANGELOG. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7984425..140cf9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,10 @@ ## TODO -1. Releases `0.0.2`. - ## Schedule +### Release `0.0.2` + 1. Removes 'prefix' configuration and adds Key Mapping. 1. Integrates with Travis CI. From 83bb10bbce98b92bae0fd0d77f69525924f63b8c Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Mon, 15 Jan 2018 16:18:53 +0800 Subject: [PATCH 5/5] Fixes the wrong filename of Travis CI configuration. --- .travis.xml => .travis.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .travis.xml => .travis.yml (100%) diff --git a/.travis.xml b/.travis.yml similarity index 100% rename from .travis.xml rename to .travis.yml