Browse Source

Merge pull request #489 from kovyl2404/windows-ct-fix

Make test on windows green.
pull/554/head
Tristan Sloughter 9 years ago
parent
commit
5012e06e68
11 changed files with 141 additions and 53 deletions
  1. +3
    -3
      src/rebar_agent.erl
  2. +5
    -1
      src/rebar_dir.erl
  3. +69
    -21
      src/rebar_file_utils.erl
  4. +1
    -1
      src/rebar_git_resource.erl
  5. +16
    -13
      src/rebar_prv_common_test.erl
  6. +9
    -1
      src/rebar_prv_dialyzer.erl
  7. +9
    -5
      src/rebar_utils.erl
  8. +5
    -3
      test/rebar_compile_SUITE.erl
  9. +1
    -1
      test/rebar_hooks_SUITE.erl
  10. +8
    -2
      test/rebar_test_utils.erl
  11. +15
    -2
      test/rebar_utils_SUITE.erl

+ 3
- 3
src/rebar_agent.erl View File

@ -20,7 +20,7 @@ do(Namespace, Command) when is_atom(Namespace), is_atom(Command) ->
gen_server:call(?MODULE, {cmd, Namespace, Command}, infinity).
init(State) ->
{ok, Cwd} = file:get_cwd(),
Cwd = rebar_dir:get_cwd(),
{ok, #state{state=State, cwd=Cwd}}.
handle_call({cmd, Command}, _From, State=#state{state=RState, cwd=Cwd}) ->
@ -48,8 +48,8 @@ terminate(_Reason, _State) ->
run(Namespace, Command, RState, Cwd) ->
try
case file:get_cwd() of
{ok, Cwd} ->
case rebar_dir:get_cwd() of
Cwd ->
Args = [atom_to_list(Namespace), atom_to_list(Command)],
CmdState0 = refresh_state(RState, Cwd),
CmdState1 = rebar_state:set(CmdState0, task, atom_to_list(Command)),

+ 5
- 1
src/rebar_dir.erl View File

@ -100,7 +100,11 @@ local_cache_dir(Dir) ->
get_cwd() ->
{ok, Dir} = file:get_cwd(),
Dir.
%% On windows cwd may return capital letter for drive,
%% for example C:/foobar. But as said in http://www.erlang.org/doc/man/filename.html#join-1
%% filename:join/1,2 anyway will convert drive-letter to lowercase, so we have to "internalize"
%% cwd as soon as it possible.
filename:join([Dir]).
template_globals(State) ->
filename:join([global_config_dir(State), "templates", "globals"]).

+ 69
- 21
src/rebar_file_utils.erl View File

@ -36,10 +36,14 @@
write_file_if_contents_differ/2,
system_tmpdir/0,
system_tmpdir/1,
reset_dir/1]).
reset_dir/1,
touch/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
-include_lib("kernel/include/file.hrl").
%% ===================================================================
%% Public API
@ -71,9 +75,40 @@ symlink_or_copy(Source, Target) ->
{error, eexist} ->
ok;
{error, _} ->
cp_r([Source], Target)
case os:type() of
{win32, _} ->
S = unicode:characters_to_list(Source),
T = unicode:characters_to_list(Target),
case filelib:is_dir(S) of
true ->
win32_symlink(S, T);
false ->
cp_r([S], T)
end;
_ ->
case filelib:is_dir(Target) of
true ->
ok;
false ->
cp_r([Source], Target)
end
end
end.
win32_symlink(Source, Target) ->
Res = rebar_utils:sh(
?FMT("cmd /c mklink /j \"~s\" \"~s\"",
[filename:nativename(Target), filename:nativename(Source)]),
[{use_stdout, false}, return_on_error]),
case win32_ok(Res) of
true -> ok;
false ->
{error, lists:flatten(
io_lib:format("Failed to symlink ~s to ~s~n",
[Source, Target]))}
end.
%% @doc Remove files and directories.
%% Target is a single filename, directoryname or wildcard expression.
-spec rm_rf(string()) -> 'ok'.
@ -120,21 +155,24 @@ mv(Source, Dest) ->
[{use_stdout, false}, abort_on_error]),
ok;
{win32, _} ->
{ok, R} = rebar_utils:sh(
?FMT("move /y \"~s\" \"~s\" 1> nul",
Res = rebar_utils:sh(
?FMT("robocopy /move /s \"~s\" \"~s\" 1> nul",
[filename:nativename(Source),
filename:nativename(Dest)]),
[{use_stdout, false}, return_on_error]),
case R of
[] ->
ok;
_ ->
case win32_ok(Res) of
true -> ok;
false ->
{error, lists:flatten(
io_lib:format("Failed to move ~s to ~s~n",
[Source, Dest]))}
end
end.
win32_ok({ok, _}) -> true;
win32_ok({error, {Rc, _}}) when Rc<9; Rc=:=16 -> true;
win32_ok(_) -> false.
delete_each([]) ->
ok;
delete_each([File | Rest]) ->
@ -186,6 +224,17 @@ reset_dir(Path) ->
%% recreate the directory
filelib:ensure_dir(filename:join([Path, "dummy.beam"])).
%% Linux touch but using erlang functions to work in bot *nix os and
%% windows
-spec touch(Path) -> ok | {error, Reason} when
Path :: file:name(),
Reason :: file:posix().
touch(Path) ->
{ok, A} = file:read_file_info(Path),
ok = file:write_file_info(Path, A#file_info{mtime = calendar:local_time(),
atime = calendar:local_time()}).
%% ===================================================================
%% Internal functions
%% ===================================================================
@ -198,28 +247,27 @@ delete_each_dir_win32([Dir | Rest]) ->
delete_each_dir_win32(Rest).
xcopy_win32(Source,Dest)->
{ok, R} = rebar_utils:sh(
?FMT("xcopy \"~s\" \"~s\" /q /y /e 2> nul",
%% "xcopy \"~s\" \"~s\" /q /y /e 2> nul", Chanegd to robocopy to
%% handle long names. May have issues with older windows.
Res = rebar_utils:sh(
?FMT("robocopy \"~s\" \"~s\" /e /is /purge 2> nul",
[filename:nativename(Source), filename:nativename(Dest)]),
[{use_stdout, false}, return_on_error]),
case length(R) > 0 of
%% when xcopy fails, stdout is empty and and error message is printed
%% to stderr (which is redirected to nul)
true -> ok;
false ->
{error, lists:flatten(
io_lib:format("Failed to xcopy from ~s to ~s~n",
[Source, Dest]))}
case win32_ok(Res) of
true -> ok;
false ->
{error, lists:flatten(
io_lib:format("Failed to copy ~s to ~s~n",
[Source, Dest]))}
end.
cp_r_win32({true, SourceDir}, {true, DestDir}) ->
%% from directory to directory
SourceBase = filename:basename(SourceDir),
ok = case file:make_dir(filename:join(DestDir, SourceBase)) of
ok = case file:make_dir(DestDir) of
{error, eexist} -> ok;
Other -> Other
end,
ok = xcopy_win32(SourceDir, filename:join(DestDir, SourceBase));
ok = xcopy_win32(SourceDir, DestDir);
cp_r_win32({false, Source} = S,{true, DestDir}) ->
%% from file to directory
cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))});

+ 1
- 1
src/rebar_git_resource.erl View File

@ -109,7 +109,7 @@ download(Dir, {git, Url, Rev}, _State) ->
rebar_utils:sh(?FMT("git checkout -q ~s", [Rev]), [{cd, Dir}]).
make_vsn(Dir) ->
{ok, Cwd} = file:get_cwd(),
Cwd = rebar_dir:get_cwd(),
try
ok = file:set_cwd(Dir),
{Vsn, RawRef, RawCount} = collect_default_refcount(),

+ 16
- 13
src/rebar_prv_common_test.erl View File

@ -347,23 +347,26 @@ reduce_path([_|Acc], [".."|Rest]) -> reduce_path(Acc, Rest);
reduce_path([], [".."|Rest]) -> reduce_path([], Rest);
reduce_path(Acc, [Component|Rest]) -> reduce_path([Component|Acc], Rest).
remove_links(Path) ->
case ec_file:is_dir(Path) of
false -> ok;
true -> remove_links1(Path)
end.
remove_links1(Path) ->
remove_links(Path) ->
IsDir = ec_file:is_dir(Path),
case ec_file:is_symlink(Path) of
true ->
file:delete(Path);
false ->
lists:foreach(fun(ChildPath) ->
remove_links(ChildPath)
end, sub_dirs(Path))
true when IsDir ->
delete_dir_link(Path);
false when IsDir ->
lists:foreach(fun(ChildPath) ->
remove_links(ChildPath)
end, dir_entries(Path));
_ -> file:delete(Path)
end.
sub_dirs(Path) ->
delete_dir_link(Path) ->
case os:type() of
{unix, _} -> file:delete(Path);
{win32, _} -> file:del_dir(Path)
end.
dir_entries(Path) ->
{ok, SubDirs} = file:list_dir(Path),
[filename:join(Path, SubDir) || SubDir <- SubDirs].

+ 9
- 1
src/rebar_prv_dialyzer.erl View File

@ -72,6 +72,7 @@ short_desc() ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
maybe_fix_env(),
?INFO("Dialyzer starting, this may take a while...", []),
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
Plt = get_plt(State),
@ -91,6 +92,13 @@ do(State) ->
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default))
end.
%% This is used to workaround dialyzer quirk discussed here
%% https://github.com/rebar/rebar3/pull/489#issuecomment-107953541
%% Dialyzer gets default plt location wrong way by peeking HOME environment
%% variable which usually is not defined on Windows.
maybe_fix_env() ->
os:putenv("DIALYZER_PLT", filename:join(rebar_dir:home_dir(), ".dialyzer_plt")).
-spec format_error(any()) -> iolist().
format_error({error_processing_apps, Error}) ->
io_lib:format("Error in dialyzing apps: ~s", [Error]);
@ -380,7 +388,7 @@ run_dialyzer(State, Opts, Output) ->
{check_plt, false} |
Opts],
?DEBUG("Running dialyzer with options: ~p~n", [Opts2]),
_ = dialyzer:run(Opts2),
dialyzer:run(Opts2),
{0, State}
end.

+ 9
- 5
src/rebar_utils.erl View File

@ -154,7 +154,7 @@ sh(Command0, Options0) ->
Command = lists:flatten(patch_on_windows(Command0, proplists:get_value(env, Options, []))),
PortSettings = proplists:get_all_values(port_settings, Options) ++
[exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide],
[exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide, eof],
?DEBUG("Port Cmd: ~s\nPort Opts: ~p\n", [Command, PortSettings]),
Port = open_port({spawn, Command}, PortSettings),
@ -435,10 +435,14 @@ sh_loop(Port, Fun, Acc) ->
sh_loop(Port, Fun, Fun(Line ++ "\n", Acc));
{Port, {data, {noeol, Line}}} ->
sh_loop(Port, Fun, Fun(Line, Acc));
{Port, {exit_status, 0}} ->
{ok, lists:flatten(lists:reverse(Acc))};
{Port, {exit_status, Rc}} ->
{error, {Rc, lists:flatten(lists:reverse(Acc))}}
{Port, eof} ->
Data = lists:flatten(lists:reverse(Acc)),
receive
{Port, {exit_status, 0}} ->
{ok, Data};
{Port, {exit_status, Rc}} ->
{error, {Rc, Data}}
end
end.
beam_to_mod(Dir, Filename) ->

+ 5
- 3
test/rebar_compile_SUITE.erl View File

@ -163,9 +163,10 @@ recompile_when_hrl_changes(Config) ->
ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- Files, filename:extension(F) == ".beam"],
timer:sleep(1000),
os:cmd("touch " ++ HeaderFile),
rebar_file_utils:touch(HeaderFile),
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
@ -274,9 +275,9 @@ delete_beam_if_source_deleted(Config) ->
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
SrcDir = filename:join([AppDir, "_build", "default", "lib", Name, "src"]),
_SrcDir = filename:join([AppDir, "_build", "default", "lib", Name, "src"]),
?assert(filelib:is_regular(filename:join(EbinDir, "not_a_real_src_" ++ Name ++ ".beam"))),
file:delete(filename:join(SrcDir, "not_a_real_src_" ++ Name ++ ".erl")),
file:delete(filename:join([AppDir, "src", "not_a_real_src_" ++ Name ++ ".erl"])),
rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, [{app, Name}]}),
@ -307,6 +308,7 @@ deps_in_path(Config) ->
?assertEqual([], [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, DepName)]]),
%% Hope not to find pkg name in there
?assertEqual([], [Path || Path <- code:get_path(),
{match, _} <- [re:run(Path, PkgName)]]),
%% Build things

+ 1
- 1
test/rebar_hooks_SUITE.erl View File

@ -114,7 +114,7 @@ run_hooks_for_plugins(Config) ->
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
PluginName = rebar_test_utils:create_random_name("plugin1_"),
mock_git_resource:mock([{config, [{pre_hooks, [{compile, "touch randomfile"}]}]}]),
mock_git_resource:mock([{config, [{pre_hooks, [{compile, "echo whatsup > randomfile"}]}]}]),
RConfFile = rebar_test_utils:create_config(AppDir,
[{plugins, [

+ 8
- 2
test/rebar_test_utils.erl View File

@ -105,16 +105,22 @@ create_config(AppDir, Contents) ->
%% @doc Util to create a random variation of a given name.
create_random_name(Name) ->
random:seed(os:timestamp()),
random_seed(),
Name ++ erlang:integer_to_list(random:uniform(1000000)).
%% @doc Util to create a random variation of a given version.
create_random_vsn() ->
random:seed(os:timestamp()),
random_seed(),
lists:flatten([erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100))]).
random_seed() ->
<<A:32, B:32, C:32>> = crypto:rand_bytes(12),
random:seed({A,B,C}).
expand_deps(_, []) -> [];
expand_deps(git, [{Name, Deps} | Rest]) ->
Dep = {Name, ".*", {git, "https://example.org/user/"++Name++".git", "master"}},

+ 15
- 2
test/rebar_utils_SUITE.erl View File

@ -21,7 +21,8 @@
task_with_flag_with_trailing_comma/1,
task_with_flag_with_commas/1,
task_with_multiple_flags/1,
special_task_do/1]).
special_task_do/1,
sh_does_not_miss_messages/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@ -29,7 +30,8 @@
all() ->
[{group, args_to_tasks}].
[{group, args_to_tasks},
sh_does_not_miss_messages].
groups() ->
[{args_to_tasks, [], [empty_arglist,
@ -118,3 +120,14 @@ special_task_do(_Config) ->
"do",
"bar,",
"baz"]).
sh_does_not_miss_messages(_Config) ->
Source = "~nmain(_) ->~n io:format(\"donotmissme\").~n",
file:write_file("do_not_miss_messages", io_lib:format(Source,[])),
{ok, "donotmissme"} = rebar_utils:sh("escript do_not_miss_messages", []),
AnyMessageRemained =
receive
What -> What
after 100 ->
false
end,
AnyMessageRemained = false.

Loading…
Cancel
Save