diff --git a/lib/elixir/include/elixir.hrl b/lib/elixir/include/elixir.hrl index fd27ba5b2f..202e470d0e 100644 --- a/lib/elixir/include/elixir.hrl +++ b/lib/elixir/include/elixir.hrl @@ -6,7 +6,7 @@ -define(atom_concat(Atoms), list_to_atom(lists:concat(Atoms))). -define(elixir_macro(Macro), list_to_atom(lists:concat(['MACRO-',Macro]))). --define(line(Opts), elixir_tree_helpers:get_line(Opts)). +-define(line(Opts), elixir_utils:get_line(Opts)). -record(elixir_scope, { context=nil, %% can be assign, guards or nil diff --git a/lib/elixir/lib/exception.ex b/lib/elixir/lib/exception.ex index f8a9969b55..67768bdb88 100644 --- a/lib/elixir/lib/exception.ex +++ b/lib/elixir/lib/exception.ex @@ -166,8 +166,9 @@ defmodule Exception do @doc """ Receives a tuple representing a stacktrace entry and formats it. - The current working directory may be given as an argument, which - is used to prettify the stacktrace. + + The current working directory may be given as an argument, + otherwise one is automatically retrieved. """ def format_stacktrace_entry(entry, cwd // nil) @@ -208,9 +209,11 @@ defmodule Exception do :stacktrace -> Enum.drop(:erlang.get_stacktrace, 1) end + cwd = System.cwd + case trace do [] -> "\n" - s -> " " <> Enum.map_join(s, "\n ", format_stacktrace_entry(&1)) <> "\n" + s -> " " <> Enum.map_join(s, "\n ", &format_stacktrace_entry(&1, cwd)) <> "\n" end end @@ -274,10 +277,7 @@ defmodule Exception do def format_file_line(file, line, cwd) do if file do file = to_binary(file) - - if cwd do - file = Path.relative_to(file, cwd) - end + file = if cwd, do: Path.relative_to(file, cwd), else: Path.relative_to_cwd(file) if line && line != 0 do "#{file}:#{line}: " diff --git a/lib/elixir/lib/file.ex b/lib/elixir/lib/file.ex index 76615c96d5..e3023a4d70 100644 --- a/lib/elixir/lib/file.ex +++ b/lib/elixir/lib/file.ex @@ -476,7 +476,7 @@ defmodule File do # src may be a file or a directory, dest is definitely # a directory. Returns nil unless an error is found. defp do_cp_r(src, dest, callback, acc) when is_list(acc) do - case :elixir.file_type(src) do + case :elixir_utils.file_type(src) do { :ok, :regular } -> do_cp_file(src, dest, callback, acc) { :ok, :symlink } -> @@ -721,9 +721,9 @@ defmodule File do end defp safe_list_dir(path) do - case :elixir.file_type(path) do + case :elixir_utils.file_type(path) do { :ok, :symlink } -> - case :elixir.file_type(path, :read_file_info) do + case :elixir_utils.file_type(path, :read_file_info) do { :ok, :directory } -> { :ok, :directory } _ -> { :ok, :regular } end diff --git a/lib/elixir/lib/macro.ex b/lib/elixir/lib/macro.ex index d5d71ae3e4..9819f47ed2 100644 --- a/lib/elixir/lib/macro.ex +++ b/lib/elixir/lib/macro.ex @@ -253,7 +253,7 @@ defmodule Macro do # Splat when def to_string({ :when, _, args }) do - { left, right } = :elixir_tree_helpers.split_last(args) + { left, right } = :elixir_utils.split_last(args) "(" <> Enum.map_join(left, ", ", to_string(&1)) <> ") when " <> to_string(right) end @@ -268,7 +268,7 @@ defmodule Macro do # All other calls def to_string({ target, _, args }) when is_list(args) do - { list, last } = :elixir_tree_helpers.split_last(args) + { list, last } = :elixir_utils.split_last(args) case is_kw_blocks?(last) do true -> call_to_string_with_args(target, list) <> kw_blocks_to_string(last) false -> call_to_string_with_args(target, args) diff --git a/lib/elixir/lib/path.ex b/lib/elixir/lib/path.ex index e321a821a1..8610e64f54 100644 --- a/lib/elixir/lib/path.ex +++ b/lib/elixir/lib/path.ex @@ -236,6 +236,18 @@ defmodule Path do original end + @doc """ + Convenience to get the path relative to the current working + directory. If, for some reason, the current working directory + cannot be retrieved, returns the full path. + """ + def relative_to_cwd(path) do + case :file.get_cwd do + { :ok, base } -> relative_to(path, base) + _ -> path + end + end + @doc """ Returns the last component of the path or the path itself if it does not contain any directory separators. diff --git a/lib/elixir/src/elixir.erl b/lib/elixir/src/elixir.erl index 1285b6ede2..9f398ccf54 100644 --- a/lib/elixir/src/elixir.erl +++ b/lib/elixir/src/elixir.erl @@ -2,11 +2,10 @@ -behaviour(application). -export([main/1, start_cli/0, scope_for_eval/1, scope_for_eval/2, - eval/2, eval/3, eval/4, file_type/1, file_type/2, + eval/2, eval/3, eval/4, eval_quoted/2, eval_quoted/3, eval_quoted/4, eval_forms/3, translate_forms/3]). -include("elixir.hrl"). --include_lib("kernel/include/file.hrl"). %% Top level types -export_type([char_list/0, as_boolean/1]). @@ -44,17 +43,6 @@ start_cli() -> application:start(?MODULE), 'Elixir.Kernel.CLI':main(init:get_plain_arguments()). -%% Helpers - -file_type(File) -> - file_type(File, read_link_info). - -file_type(File, Op) -> - case file:Op(File) of - { ok, #file_info{type=Type} } -> { ok, Type }; - { error, _ } = Error -> Error - end. - %% EVAL HOOKS scope_for_eval(Opts) -> diff --git a/lib/elixir/src/elixir_clauses.erl b/lib/elixir/src/elixir_clauses.erl index 3bacdf7ed4..5e58c7fca8 100644 --- a/lib/elixir/src/elixir_clauses.erl +++ b/lib/elixir/src/elixir_clauses.erl @@ -83,7 +83,7 @@ extract_args(_) -> error. % Extract guards when multiple left side args are allowed. extract_splat_guards([{ 'when', _, [_,_|_] = Args }]) -> - { Left, Right } = elixir_tree_helpers:split_last(Args), + { Left, Right } = elixir_utils:split_last(Args), { Left, extract_or_clauses(Right, []) }; extract_splat_guards(Else) -> { Else, [] }. diff --git a/lib/elixir/src/elixir_compiler.erl b/lib/elixir/src/elixir_compiler.erl index a7733323e1..dc416cf8e8 100644 --- a/lib/elixir/src/elixir_compiler.erl +++ b/lib/elixir/src/elixir_compiler.erl @@ -166,12 +166,7 @@ module_form(Fun, Exprs, Line, File, Module, Vars) when end, { nil, Line }, Vars), Args = [{ var, Line, '_@MODULE'}, Cons], - - Relative = - case get_opt(internal) of - true -> File; - false -> 'Elixir.Path':relative_to(File, 'Elixir.System':'cwd!'()) - end, + Relative = elixir_utils:relative_to_cwd(File), [ { attribute, Line, file, { unicode:characters_to_list(File), 1 } }, @@ -181,7 +176,7 @@ module_form(Fun, Exprs, Line, File, Module, Vars) when { clause, Line, Args, [], Exprs } ] }, { function, Line, '__RELATIVE__', 0, [ - { clause, Line, [], [], [elixir_tree_helpers:elixir_to_erl(Relative)] } + { clause, Line, [], [], [elixir_utils:elixir_to_erl(Relative)] } ] } ]. diff --git a/lib/elixir/src/elixir_def.erl b/lib/elixir/src/elixir_def.erl index 96df923bee..3b0d6c5b89 100644 --- a/lib/elixir/src/elixir_def.erl +++ b/lib/elixir/src/elixir_def.erl @@ -338,9 +338,9 @@ check_valid_clause(Line, File, Name, Arity, Kind, Table, StoredLine, StoredFile) {Name,Arity} -> []; [] -> []; _ -> - FileRel = 'Elixir.Path':relative_to(StoredFile, 'Elixir.System':'cwd!'()), + Relative = elixir_utils:relative_to_cwd(StoredFile), elixir_errors:handle_file_warning(File, { Line, ?MODULE, - { override_function, { Kind, Name, Arity, StoredLine, FileRel } } }) + { override_function, { Kind, Name, Arity, StoredLine, Relative } } }) end. check_valid_defaults(_Line, _File, _Name, _Arity, _Kind, 0, _) -> []; diff --git a/lib/elixir/src/elixir_errors.erl b/lib/elixir/src/elixir_errors.erl index d659819195..b480ad398d 100644 --- a/lib/elixir/src/elixir_errors.erl +++ b/lib/elixir/src/elixir_errors.erl @@ -8,7 +8,7 @@ assert_no_match_scope/3, assert_no_guard_scope/3, assert_no_match_or_guard_scope/3, warn/1, handle_file_warning/2, handle_file_warning/3, handle_file_error/2, - deprecation/3, deprecation/4, file_format/3]). + deprecation/3, deprecation/4]). -include("elixir.hrl"). warn(Warning) -> @@ -209,10 +209,10 @@ raise(Line, File, Kind, Message) when is_integer(Line) -> erlang:raise(error, Exception, tl(Stacktrace)). file_format(0, File, Message) -> - io_lib:format("~ts: ~ts~n", [File, Message]); + io_lib:format("~ts: ~ts~n", [elixir_helpers:relative_to_cwd(File), Message]); file_format(Line, File, Message) -> - io_lib:format("~ts:~w: ~ts~n", [File, Line, Message]). + io_lib:format("~ts:~w: ~ts~n", [elixir_helpers:relative_to_cwd(File), Line, Message]). format_var(Var) -> list_to_atom(lists:takewhile(fun(X) -> X /= $@ end, atom_to_list(Var))). diff --git a/lib/elixir/src/elixir_literal.erl b/lib/elixir/src/elixir_literal.erl index 3874fb53dc..ffe54d04ea 100644 --- a/lib/elixir/src/elixir_literal.erl +++ b/lib/elixir/src/elixir_literal.erl @@ -45,7 +45,7 @@ translate({ '[]', Meta, Args } = Original, S) when is_list(Args) -> { Exprs, SE } = translate_args(lists:reverse(RExprs), S), { Tail, ST } = TailFun(SE), - { elixir_tree_helpers:list_to_cons(?line(Meta), Exprs, Tail), ST }; + { elixir_utils:list_to_cons(?line(Meta), Exprs, Tail), ST }; Else -> Else end; @@ -65,7 +65,7 @@ translate(Atom, S) when is_atom(Atom) -> { { atom, 0, Atom }, S }; translate(Bitstring, S) when is_bitstring(Bitstring) -> - { elixir_tree_helpers:elixir_to_erl(Bitstring), S }; + { elixir_utils:elixir_to_erl(Bitstring), S }; translate(Other, S) -> elixir_errors:compile_error(0, S#elixir_scope.file, "invalid quoted expression: ~ts", diff --git a/lib/elixir/src/elixir_macros.erl b/lib/elixir/src/elixir_macros.erl index ac0756f552..de98c3c356 100644 --- a/lib/elixir/src/elixir_macros.erl +++ b/lib/elixir/src/elixir_macros.erl @@ -33,11 +33,11 @@ translate({ Op, Meta, Exprs }, S) when is_list(Exprs), translate({ '!', Meta, [{ '!', _, [Expr] }] }, S) -> { TExpr, SE } = translate_each(Expr, S), - elixir_tree_helpers:convert_to_boolean(?line(Meta), TExpr, true, S#elixir_scope.context == guard, SE); + elixir_utils:convert_to_boolean(?line(Meta), TExpr, true, S#elixir_scope.context == guard, SE); translate({ '!', Meta, [Expr] }, S) -> { TExpr, SE } = translate_each(Expr, S), - elixir_tree_helpers:convert_to_boolean(?line(Meta), TExpr, false, S#elixir_scope.context == guard, SE); + elixir_utils:convert_to_boolean(?line(Meta), TExpr, false, S#elixir_scope.context == guard, SE); translate({ in, Meta, [Left, Right] }, #elixir_scope{extra_guards=nil} = S) -> { _, TExpr, TS } = translate_in(Meta, Left, Right, S), @@ -87,7 +87,7 @@ translate({'@', Meta, [{ Name, _, Args }]}, S) -> }, S); _ -> Contents = 'Elixir.Module':get_attribute(S#elixir_scope.module, Name), - { elixir_tree_helpers:elixir_to_erl(Contents), S } + { elixir_utils:elixir_to_erl(Contents), S } end; _ -> syntax_error(Meta, S#elixir_scope.file, "expected 0 or 1 argument for @~ts, got: ~p", [Name, length(Args)]) @@ -101,7 +101,7 @@ translate({'case', Meta, [Expr, KV]}, S) when is_list(KV) -> Clauses = elixir_clauses:get_pairs(Meta, do, KV, S), { TExpr, NS } = translate_each(Expr, S), - RClauses = case elixir_tree_helpers:returns_boolean(TExpr) of + RClauses = case elixir_utils:returns_boolean(TExpr) of true -> rewrite_case_clauses(Clauses); false -> Clauses end, @@ -142,7 +142,7 @@ translate({'receive', Meta, [KV] }, S) when is_list(KV) -> _ -> After = elixir_clauses:get_pairs(Meta, 'after', KV, S), { TClauses, SC } = elixir_clauses:match(Meta, Do ++ After, S), - { FClauses, TAfter } = elixir_tree_helpers:split_last(TClauses), + { FClauses, TAfter } = elixir_utils:split_last(TClauses), { _, _, [FExpr], _, FAfter } = TAfter, { { 'receive', ?line(Meta), FClauses, FExpr, FAfter }, SC } end; @@ -239,7 +239,7 @@ translate_in(Meta, Left, Right, S) -> Expr = { atom, Line, false }, { Cache, Expr }; { cons, _, _, _ } -> - [H|T] = elixir_tree_helpers:cons_to_list(TRight), + [H|T] = elixir_utils:cons_to_list(TRight), Expr = lists:foldr(fun(X, Acc) -> { op, Line, 'orelse', { op, Line, '==', Var, X }, Acc } end, { op, Line, '==', Var, H }, T), diff --git a/lib/elixir/src/elixir_module.erl b/lib/elixir/src/elixir_module.erl index 2c8e94d7c1..55902c8e6b 100644 --- a/lib/elixir/src/elixir_module.erl +++ b/lib/elixir/src/elixir_module.erl @@ -43,7 +43,7 @@ docs_table(Module) -> translate(Meta, Ref, Block, S) -> Line = ?line(Meta), - MetaBlock = elixir_tree_helpers:elixir_to_erl(Block), + MetaBlock = elixir_utils:elixir_to_erl(Block), { MetaS, Vars } = elixir_scope:serialize_with_vars(Line, S), Args = [{integer, Line, Line}, Ref, MetaBlock, Vars, MetaS], @@ -314,11 +314,11 @@ add_info_function(Line, File, Module, Export, Def, Defmacro, C) -> end. functions_clause(Def) -> - { clause, 0, [{ atom, 0, functions }], [], [elixir_tree_helpers:elixir_to_erl(Def)] }. + { clause, 0, [{ atom, 0, functions }], [], [elixir_utils:elixir_to_erl(Def)] }. macros_clause(Module, Def, Defmacro) -> All = handle_builtin_macros(Module, Def, Defmacro), - { clause, 0, [{ atom, 0, macros }], [], [elixir_tree_helpers:elixir_to_erl(All)] }. + { clause, 0, [{ atom, 0, macros }], [], [elixir_utils:elixir_to_erl(All)] }. handle_builtin_macros('Elixir.Kernel', Def, Defmacro) -> ordsets:subtract(ordsets:union(Defmacro, @@ -330,14 +330,14 @@ module_clause(Module) -> docs_clause(Module, true) -> Docs = ordsets:from_list(ets:tab2list(docs_table(Module))), - { clause, 0, [{ atom, 0, docs }], [], [elixir_tree_helpers:elixir_to_erl(Docs)] }; + { clause, 0, [{ atom, 0, docs }], [], [elixir_utils:elixir_to_erl(Docs)] }; docs_clause(_Module, _) -> { clause, 0, [{ atom, 0, docs }], [], [{ atom, 0, nil }] }. moduledoc_clause(Line, Module, true) -> Docs = 'Elixir.Module':get_attribute(Module, moduledoc), - { clause, 0, [{ atom, 0, moduledoc }], [], [elixir_tree_helpers:elixir_to_erl({ Line, Docs })] }; + { clause, 0, [{ atom, 0, moduledoc }], [], [elixir_utils:elixir_to_erl({ Line, Docs })] }; moduledoc_clause(_Line, _Module, _) -> { clause, 0, [{ atom, 0, moduledoc }], [], [{ atom, 0, nil }] }. diff --git a/lib/elixir/src/elixir_parser.yrl b/lib/elixir/src/elixir_parser.yrl index 4144275e82..404eb48f42 100644 --- a/lib/elixir/src/elixir_parser.yrl +++ b/lib/elixir/src/elixir_parser.yrl @@ -614,7 +614,7 @@ unwrap_splice([{ '__block__', [], [{ unquote_splicing, _, _ }] = Splice }]) -> unwrap_splice(Other) -> Other. unwrap_when(Args) -> - case elixir_tree_helpers:split_last(Args) of + case elixir_utils:split_last(Args) of { Start, { 'when', Meta, [_, _] = End } } -> [{ 'when', Meta, Start ++ End }]; { _, _ } -> diff --git a/lib/elixir/src/elixir_scope.erl b/lib/elixir/src/elixir_scope.erl index e92e0230e5..a615b11298 100644 --- a/lib/elixir/src/elixir_scope.erl +++ b/lib/elixir/src/elixir_scope.erl @@ -103,7 +103,7 @@ list_vars(Other, _) -> Other. % Provides a tuple with only the scope information we want to serialize. serialize(S) -> - elixir_tree_helpers:elixir_to_erl( + elixir_utils:elixir_to_erl( { S#elixir_scope.file, S#elixir_scope.functions, S#elixir_scope.requires, S#elixir_scope.macros, S#elixir_scope.aliases, S#elixir_scope.macro_functions, S#elixir_scope.macro_macros, S#elixir_scope.macro_aliases, diff --git a/lib/elixir/src/elixir_translator.erl b/lib/elixir/src/elixir_translator.erl index 679443c26b..ce5cbdb070 100644 --- a/lib/elixir/src/elixir_translator.erl +++ b/lib/elixir/src/elixir_translator.erl @@ -162,7 +162,7 @@ translate_each({ '__DIR__', _Meta, Atom }, S) when is_atom(Atom) -> translate_each({ '__ENV__', Meta, Atom }, S) when is_atom(Atom) -> Env = elixir_scope:to_ex_env({ ?line(Meta), S }), - { elixir_tree_helpers:elixir_to_erl(Env), S }; + { elixir_utils:elixir_to_erl(Env), S }; translate_each({ '__CALLER__', Meta, Atom }, S) when is_atom(Atom) -> { { var, ?line(Meta), '__CALLER__' }, S#elixir_scope{caller=true} }; @@ -184,7 +184,7 @@ translate_each({ '__aliases__', Meta, _ } = Alias, S) -> elixir_tracker:record_alias(Receiver, S#elixir_scope.module), { { atom, ?line(Meta), Receiver }, SA }; false -> - Args = [elixir_tree_helpers:list_to_cons(?line(Meta), TAliases)], + Args = [elixir_utils:list_to_cons(?line(Meta), TAliases)], { ?wrap_call(?line(Meta), elixir_aliases, concat, Args), SA } end end; @@ -686,7 +686,7 @@ assert_no_ambiguous_op(_Atom, _Meta, _Args, _S) -> ok. %% Comprehensions translate_comprehension(Meta, Kind, Args, S) -> - case elixir_tree_helpers:split_last(Args) of + case elixir_utils:split_last(Args) of { Cases, [{do,Expr}] } -> { TCases, SC } = lists:mapfoldl(fun(C, Acc) -> translate_comprehension_clause(Meta, C, Acc) end, S, Cases), { TExpr, SE } = translate_comprehension_do(Meta, Kind, Expr, SC), @@ -720,5 +720,5 @@ translate_comprehension_clause(_Meta, {inlist, Meta, [Left, Right]}, S) -> translate_comprehension_clause(Meta, X, S) -> Line = ?line(Meta), { TX, TS } = translate_each(X, S), - { BX, BS } = elixir_tree_helpers:convert_to_boolean(Line, TX, true, false, TS), + { BX, BS } = elixir_utils:convert_to_boolean(Line, TX, true, false, TS), { { match, Line, { var, Line, '_' }, BX }, BS }. diff --git a/lib/elixir/src/elixir_tree_helpers.erl b/lib/elixir/src/elixir_utils.erl similarity index 86% rename from lib/elixir/src/elixir_tree_helpers.erl rename to lib/elixir/src/elixir_utils.erl index d2b20c9dd7..f14001ca0f 100644 --- a/lib/elixir/src/elixir_tree_helpers.erl +++ b/lib/elixir/src/elixir_utils.erl @@ -1,11 +1,12 @@ %% Convenience functions used throughout elixir source code -%% to generate erlang abstract format for basic structures -%% as lists, condition clauses, etc. --module(elixir_tree_helpers). --export([elixir_to_erl/1, split_last/1, +%% for ast manipulation and querying. +-module(elixir_utils). +-export([elixir_to_erl/1, get_line/1, split_last/1, cons_to_list/1, list_to_cons/2, list_to_cons/3, - convert_to_boolean/5, returns_boolean/1, get_line/1]). + convert_to_boolean/5, returns_boolean/1, + file_type/1, file_type/2, relative_to_cwd/1]). -include("elixir.hrl"). +-include_lib("kernel/include/file.hrl"). get_line(Opts) -> case lists:keyfind(line, 1, Opts) of @@ -18,6 +19,23 @@ split_last(List) -> split_last(List, []). split_last([H], Acc) -> { lists:reverse(Acc), H }; split_last([H|T], Acc) -> split_last(T, [H|Acc]). +file_type(File) -> + file_type(File, read_link_info). + +file_type(File, Op) -> + case file:Op(File) of + { ok, #file_info{type=Type} } -> { ok, Type }; + { error, _ } = Error -> Error + end. + +relative_to_cwd(Path) -> + case elixir_compiler:get_opt(internal) of + true -> Path; + false -> 'Elixir.Path':relative_to_cwd(Path) + end. + +%% List conversion + cons_to_list({ nil, _ }) -> []; cons_to_list({ cons, _, Left, Right }) -> [Left|cons_to_list(Right)]. @@ -60,7 +78,7 @@ elixir_to_erl_cons_2([H|T], Acc) -> elixir_to_erl_cons_2([], Acc) -> Acc. -%% Others +%% Boolean checks returns_boolean({ op, _, Op, _ }) when Op == 'not' -> true; diff --git a/lib/elixir/test/elixir/path_test.exs b/lib/elixir/test/elixir/path_test.exs index 914b2090b3..9711b18999 100644 --- a/lib/elixir/test/elixir/path_test.exs +++ b/lib/elixir/test/elixir/path_test.exs @@ -79,6 +79,14 @@ defmodule PathTest do end end + test :relative_to_cwd do + assert Path.relative_to_cwd(__FILE__) == + Path.relative_to(__FILE__, System.cwd!) + + assert Path.relative_to_cwd(to_char_list(__FILE__)) == + Path.relative_to(to_char_list(__FILE__), to_char_list(System.cwd!)) + end + test :absname_with_binary do assert (Path.absname("/foo/bar") |> strip_drive_letter_if_windows) == "/foo/bar" assert (Path.absname("/foo/bar/") |> strip_drive_letter_if_windows) == "/foo/bar" @@ -249,7 +257,7 @@ defmodule PathTest do assert Path.split('foo') == ['foo'] assert Path.split('/foo/bar') == ['/', 'foo', 'bar'] end - + if is_win? do defp strip_drive_letter_if_windows([_d,?:|rest]), do: rest defp strip_drive_letter_if_windows(<<_d,?:,rest::binary>>), do: rest diff --git a/lib/ex_unit/lib/ex_unit/cli_formatter.ex b/lib/ex_unit/lib/ex_unit/cli_formatter.ex index 933f510dce..1d49d3ae72 100644 --- a/lib/ex_unit/lib/ex_unit/cli_formatter.ex +++ b/lib/ex_unit/lib/ex_unit/cli_formatter.ex @@ -7,7 +7,7 @@ defmodule ExUnit.CLIFormatter do @timeout 30_000 use GenServer.Behaviour - import ExUnit.Formatter, only: [format_time: 2, format_test_failure: 4, format_test_case_failure: 4] + import ExUnit.Formatter, only: [format_time: 2, format_test_failure: 3, format_test_case_failure: 3] defrecord Config, tests_counter: 0, invalid_counter: 0, test_failures: [], case_failures: [], trace: false, color: true @@ -140,8 +140,8 @@ defmodule ExUnit.CLIFormatter do defp print_suite(counter, num_invalids, test_failures, case_failures, run_us, load_us, config) do IO.write "\n\nFailures:\n\n" - num_fails = Enum.reduce Enum.reverse(test_failures), 0, print_test_failure(&1, &2, File.cwd!, config) - Enum.reduce Enum.reverse(case_failures), num_fails, print_test_case_failure(&1, &2, File.cwd!, config) + num_fails = Enum.reduce Enum.reverse(test_failures), 0, print_test_failure(&1, &2, config) + Enum.reduce Enum.reverse(case_failures), num_fails, print_test_case_failure(&1, &2, config) IO.puts format_time(run_us, load_us) message = "#{counter} tests, #{num_fails} failures" @@ -157,13 +157,13 @@ defmodule ExUnit.CLIFormatter do end end - defp print_test_failure(test, acc, cwd, config) do - IO.puts format_test_failure(test, acc + 1, cwd, formatter(&1, &2, config)) + defp print_test_failure(test, acc, config) do + IO.puts format_test_failure(test, acc + 1, formatter(&1, &2, config)) acc + 1 end - defp print_test_case_failure(test_case, acc, cwd, config) do - IO.puts format_test_case_failure(test_case, acc + 1, cwd, formatter(&1, &2, config)) + defp print_test_case_failure(test_case, acc, config) do + IO.puts format_test_case_failure(test_case, acc + 1, formatter(&1, &2, config)) acc + 1 end diff --git a/lib/ex_unit/lib/ex_unit/doc_test.ex b/lib/ex_unit/lib/ex_unit/doc_test.ex index 808ba72569..421b0a5546 100644 --- a/lib/ex_unit/lib/ex_unit/doc_test.ex +++ b/lib/ex_unit/lib/ex_unit/doc_test.ex @@ -169,7 +169,7 @@ defmodule ExUnit.DocTest do defp test_content(Test[exprs: exprs, line: line, fun_arity: fun_arity], module, do_import) do file = module.__info__(:compile)[:source] - location = [line: line, file: Path.relative_to(file, System.cwd!)] + location = [line: line, file: Path.relative_to_cwd(file)] stack = Macro.escape [{ module, :__MODULE__, 0, location }] exc_filter_fn = fn @@ -287,7 +287,7 @@ defmodule ExUnit.DocTest do end defp string_to_quoted(module, line, file, expr) do - location = [line: line, file: Path.relative_to(file, System.cwd!)] + location = [line: line, file: Path.relative_to_cwd(file)] stack = Macro.escape [{ module, :__MODULE__, 0, location }] try do Code.string_to_quoted!(expr, line: line, file: file) diff --git a/lib/ex_unit/lib/ex_unit/formatter.ex b/lib/ex_unit/lib/ex_unit/formatter.ex index d396afd39e..2d2c4fc46d 100644 --- a/lib/ex_unit/lib/ex_unit/formatter.ex +++ b/lib/ex_unit/lib/ex_unit/formatter.ex @@ -71,23 +71,23 @@ defmodule ExUnit.Formatter do @doc %B""" Receives a test and formats its failure. """ - def format_test_failure(ExUnit.Test[] = test, counter, cwd, color) do + def format_test_failure(ExUnit.Test[] = test, counter, color) do ExUnit.Test[case: test_case, name: test, failure: { kind, reason, stacktrace }] = test test_info("#{counter}) #{test} (#{inspect test_case})", color) <> format_kind_reason(kind, reason, color) <> - format_stacktrace(stacktrace, test_case, test, cwd, color) + format_stacktrace(stacktrace, test_case, test, color) end @doc """ Receives a test case and formats its failure. """ - def format_test_case_failure(ExUnit.TestCase[] = test_case, counter, cwd, color) do + def format_test_case_failure(ExUnit.TestCase[] = test_case, counter, color) do ExUnit.TestCase[name: test_case, failure: { kind, reason, stacktrace }] = test_case test_case_info("#{counter}) #{inspect test_case}: ", color) <> format_kind_reason(kind, reason, color) <> - format_stacktrace(stacktrace, test_case, nil, cwd, color) + format_stacktrace(stacktrace, test_case, nil, color) end defp format_kind_reason(:error, ExUnit.ExpectationError[] = record, color) do @@ -115,11 +115,12 @@ defmodule ExUnit.Formatter do error_info "** (#{kind}) #{inspect(reason)}", color end - defp format_stacktrace([{ test_case, test, _, [ file: file, line: line ] }|_], test_case, test, cwd, color) do - location_info("at #{Path.relative_to(file, cwd)}:#{line}", color) + defp format_stacktrace([{ test_case, test, _, [ file: file, line: line ] }|_], test_case, test, color) do + location_info("at #{Path.relative_to_cwd(file)}:#{line}", color) end - defp format_stacktrace(stacktrace, _case, _test, cwd, color) do + defp format_stacktrace(stacktrace, _case, _test, color) do + cwd = System.cwd location_info("stacktrace:", color) <> Enum.map_join(stacktrace, fn(s) -> stacktrace_info format_stacktrace_entry(s, cwd), color end) end diff --git a/lib/ex_unit/test/ex_unit/formatter_test.exs b/lib/ex_unit/test/ex_unit/formatter_test.exs index e564cd2e6e..bd3b1f79a2 100644 --- a/lib/ex_unit/test/ex_unit/formatter_test.exs +++ b/lib/ex_unit/test/ex_unit/formatter_test.exs @@ -20,7 +20,7 @@ defmodule ExUnit.FormatterTest do test "formats test errors" do test = test { :error, catch_error(raise "oops"), [] } - assert format_test_failure(test, 1, __DIR__, nil) =~ """ + assert format_test_failure(test, 1, nil) =~ """ 1) world (Hello) ** (RuntimeError) oops stacktrace: @@ -29,7 +29,7 @@ defmodule ExUnit.FormatterTest do test "formats test exits" do test = test { :exit, 1, [] } - assert format_test_failure(test, 1, __DIR__, nil) == """ + assert format_test_failure(test, 1, nil) == """ 1) world (Hello) ** (exit) 1 stacktrace: @@ -38,7 +38,7 @@ defmodule ExUnit.FormatterTest do test "formats test throws" do test = test { :throw, 1, [] } - assert format_test_failure(test, 1, __DIR__, nil) == """ + assert format_test_failure(test, 1, nil) == """ 1) world (Hello) ** (throw) 1 stacktrace: @@ -47,7 +47,7 @@ defmodule ExUnit.FormatterTest do test "formats test expectations" do test = test { :error, catch_expectation(assert 1 == 2), [] } - assert format_test_failure(test, 1, __DIR__, nil) =~ """ + assert format_test_failure(test, 1, nil) =~ """ 1) world (Hello) ** (ExUnit.ExpectationError) expected: 1 @@ -58,7 +58,7 @@ defmodule ExUnit.FormatterTest do test "formats test expectations with prelude" do test = test { :error, catch_expectation(assert ExUnit.FormatterTest.falsy), [] } - assert format_test_failure(test, 1, __DIR__, nil) =~ """ + assert format_test_failure(test, 1, nil) =~ """ 1) world (Hello) ** (ExUnit.ExpectationError) expected: ExUnit.FormatterTest.falsy() @@ -70,26 +70,26 @@ defmodule ExUnit.FormatterTest do test "formats stacktraces with test location" do test = test { :error, catch_error(raise "oops"), [{ Hello, :world, 1, [file: __FILE__, line: 1]}] } - assert format_test_failure(test, 1, __DIR__, nil) =~ """ + assert format_test_failure(test, 1, nil) =~ """ 1) world (Hello) ** (RuntimeError) oops - at formatter_test.exs:1 + at test/ex_unit/formatter_test.exs:1 """ end test "formats stacktraces without test location" do test = test { :error, catch_error(raise "oops"), [{ Oops, :wrong, 1, [file: __FILE__, line: 1]}] } - assert format_test_failure(test, 1, __DIR__, nil) =~ """ + assert format_test_failure(test, 1, nil) =~ """ 1) world (Hello) ** (RuntimeError) oops stacktrace: - formatter_test.exs:1: Oops.wrong/1 + test/ex_unit/formatter_test.exs:1: Oops.wrong/1 """ end test "formats test case errors" do test_case = test_case { :error, catch_error(raise "oops"), [] } - assert format_test_case_failure(test_case, 1, __DIR__, nil) =~ """ + assert format_test_case_failure(test_case, 1, nil) =~ """ 1) Hello: failure on setup_all/teardown_all callback, tests invalidated ** (RuntimeError) oops stacktrace: diff --git a/lib/iex/lib/iex/helpers.ex b/lib/iex/lib/iex/helpers.ex index fec0a70a50..b3a1945ce1 100644 --- a/lib/iex/lib/iex/helpers.ex +++ b/lib/iex/lib/iex/helpers.ex @@ -465,7 +465,7 @@ defmodule IEx.Helpers do # Compiles and loads an erlang source file, returns { module, binary } defp compile_erlang(source) do - source = Path.relative_to(source, File.cwd!) |> String.to_char_list! + source = Path.relative_to_cwd(source) |> String.to_char_list! case :compile.file(source, [:binary, :report]) do { :ok, module, binary } -> :code.purge(module) diff --git a/lib/mix/lib/mix/deps.ex b/lib/mix/lib/mix/deps.ex index 3343741660..fc54178f2d 100644 --- a/lib/mix/lib/mix/deps.ex +++ b/lib/mix/lib/mix/deps.ex @@ -184,10 +184,10 @@ defmodule Mix.Deps do do: "ok" def format_status(Mix.Dep[status: { :noappfile, path }]), - do: "could not find an app file at #{Mix.Utils.relative_to_cwd(path)}" + do: "could not find an app file at #{Path.relative_to_cwd(path)}" def format_status(Mix.Dep[status: { :invalidapp, path }]), - do: "the app file at #{Mix.Utils.relative_to_cwd(path)} is invalid" + do: "the app file at #{Path.relative_to_cwd(path)} is invalid" def format_status(Mix.Dep[status: { :invalidvsn, vsn }]), do: "the app file contains an invalid version: #{inspect vsn}" diff --git a/lib/mix/lib/mix/scm/path.ex b/lib/mix/lib/mix/scm/path.ex index a559bb896c..cf4a2d5af7 100644 --- a/lib/mix/lib/mix/scm/path.ex +++ b/lib/mix/lib/mix/scm/path.ex @@ -39,7 +39,7 @@ defmodule Mix.SCM.Path do end def checkout(opts) do - path = Mix.Utils.relative_to_cwd opts[:dest] + path = Path.relative_to_cwd opts[:dest] raise Mix.Error, message: "Cannot checkout path dependency, expected a dependency at #{path}" end @@ -48,7 +48,7 @@ defmodule Mix.SCM.Path do end def clean(opts) do - path = Mix.Utils.relative_to_cwd opts[:dest] + path = Path.relative_to_cwd opts[:dest] Mix.shell.info " #{path} is a path dependency, it was not cleaned" :noop end diff --git a/lib/mix/lib/mix/tasks/compile.elixir.ex b/lib/mix/lib/mix/tasks/compile.elixir.ex index 3dea01d617..d788fabaa4 100644 --- a/lib/mix/lib/mix/tasks/compile.elixir.ex +++ b/lib/mix/lib/mix/tasks/compile.elixir.ex @@ -33,7 +33,7 @@ defmodule Mix.Tasks.Compile.Elixir do { :ok, pid } = :gen_server.start_link(__MODULE__, entries, []) try do - do_files_to_path(pid, entries, stale, compile_path, File.cwd) + do_files_to_path(pid, entries, stale, compile_path, System.cwd) :gen_server.cast(pid, :merge) after :gen_server.call(pid, { :stop, manifest }) @@ -75,7 +75,8 @@ defmodule Mix.Tasks.Compile.Elixir do Module.DispatchTracker.imports(module) deps = deps |> :lists.usort |> Enum.map(atom_to_binary(&1)) - :gen_server.cast(pid, { :store, beam, bin, Mix.Utils.relative_to_cwd(source, cwd), deps, binary }) + relative = if cwd, do: Path.relative_to(source, cwd), else: source + :gen_server.cast(pid, { :store, beam, bin, relative, deps, binary }) end defp each_file(file) do diff --git a/lib/mix/lib/mix/utils.ex b/lib/mix/lib/mix/utils.ex index 371782f52d..10d9f18f2d 100644 --- a/lib/mix/lib/mix/utils.ex +++ b/lib/mix/lib/mix/utils.ex @@ -262,18 +262,6 @@ defmodule Mix.Utils do <<>> end - @doc """ - Returns the given path string relative to the current - working directory. In case the current working directory - cannot be retrieved, returns the path with no changes. - """ - def relative_to_cwd(path, cwd // File.cwd) do - case cwd do - { :ok, base } -> Path.relative_to(path, base) - _ -> path - end - end - @doc """ Takes a module and converts it to a command. The nesting argument can be given in order to remove the nesting of a diff --git a/lib/mix/test/mix/rebar_test.exs b/lib/mix/test/mix/rebar_test.exs index b3b0d77d30..7b67dd09c8 100644 --- a/lib/mix/test/mix/rebar_test.exs +++ b/lib/mix/test/mix/rebar_test.exs @@ -27,12 +27,6 @@ defmodule Mix.RebarTest do assert config[:dir] == {:ok, String.to_char_list!(path)} end - test "rebar sub_dirs" do - path = MixTest.Case.fixture_path("rebar_dep") - assert Mix.Rebar.recur(path, fn _ -> File.cwd end) - [path, Path.join([path, "apps", "rebar_sub_dep"])] - end - test "parse rebar dependencies" do Mix.Project.push(RebarAsDep)