From 9c544217ba73bbccfdb664baf2cb7738ffc91777 Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Sat, 9 May 2015 12:49:49 -0700 Subject: delete all symlinks when copying from project files to `_build` tree to prevent any data from being overwritten fixes #395 --- src/rebar_prv_common_test.erl | 42 ++++++++++++++++++++++++++++++++---------- test/rebar_ct_SUITE.erl | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index c1e263e..893f373 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -275,23 +275,25 @@ find_suite_dirs(Suites) -> %% eliminate duplicates lists:usort(AllDirs). -copy(State, Target) -> - case reduce_path(Target) == rebar_state:dir(State) of +copy(State, Dir) -> + From = reduce_path(Dir), + case From == rebar_state:dir(State) of true -> throw({error, suite_at_project_root}); false -> ok end, - case retarget_path(State, Target) of + case retarget_path(State, From) of %% directory lies outside of our project's file structure so %% don't copy it - Target -> Target; - NewTarget -> - %% unlink the directory if it's a symlink - case ec_file:is_symlink(NewTarget) of - true -> ok = ec_file:remove(NewTarget); + From -> From; + Target -> + %% recursively delete any symlinks in the target directory + %% if it exists so we don't smash files in the linked dirs + case ec_file:is_dir(Target) of + true -> remove_links(Target); false -> ok end, - ok = ec_file:copy(Target, NewTarget, [recursive]), - NewTarget + ok = ec_file:copy(From, Target, [recursive]), + Target end. compile_dir(State, Dir) -> @@ -338,6 +340,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) -> + case ec_file:is_symlink(Path) of + true -> + file:delete(Path); + false -> + lists:foreach(fun(ChildPath) -> + remove_links(ChildPath) + end, sub_dirs(Path)) + end. + +sub_dirs(Path) -> + {ok, SubDirs} = file:list_dir(Path), + [filename:join(Path, SubDir) || SubDir <- SubDirs]. + replace_src_dirs(State, Dirs) -> %% replace any `src_dirs` with the test dirs ErlOpts = rebar_state:get(State, erl_opts, []), diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl index 3c4aed3..0a86127 100644 --- a/test/rebar_ct_SUITE.erl +++ b/test/rebar_ct_SUITE.erl @@ -16,7 +16,8 @@ single_unmanaged_suite/1, multi_suite/1, all_suite/1, - single_dir_and_single_suite/1]). + single_dir_and_single_suite/1, + symlinked_dir_overwritten_fix/1]). -include_lib("common_test/include/ct.hrl"). @@ -36,7 +37,8 @@ groups() -> [{basic_app, [], [basic_app_default_dirs, single_unmanaged_suite, multi_suite, all_suite, - single_dir_and_single_suite]}]. + single_dir_and_single_suite, + symlinked_dir_overwritten_fix]}]. init_per_group(basic_app, Config) -> C = rebar_test_utils:init_rebar_state(Config, "ct_"), @@ -513,6 +515,36 @@ single_dir_and_single_suite(Config) -> Expect = Suite. +symlinked_dir_overwritten_fix(Config) -> + AppDir = ?config(apps, Config), + [Name1, _Name2] = ?config(appnames, Config), + + {ok, State} = rebar_test_utils:run_and_check(Config, [], ["as", "test", "compile"], return), + + LibDirs = rebar_dir:lib_dirs(State), + State1 = rebar_app_discover:do(State, LibDirs), + + Providers = rebar_state:providers(State1), + Namespace = rebar_state:namespace(State1), + CommandProvider = providers:get_provider(ct, Providers, Namespace), + GetOptSpec = providers:opts(CommandProvider), + {ok, GetOptResult} = getopt:parse(GetOptSpec, + ["--dir=" ++ filename:join([AppDir, + "apps", + Name1])]), + + State2 = rebar_state:command_parsed_args(State1, GetOptResult), + + Result = rebar_prv_common_test:setup_ct(State2), + + Expect = filename:absname(filename:join([AppDir, "_build", "test", "lib", Name1])), + Dir = proplists:get_value(dir, Result), + + Expect = Dir, + + {ok, _} = rebar_test_utils:run_and_check(Config, [], ["as", "test", "compile"], return). + + test_suite(Name) -> io_lib:format("-module(~ts_SUITE).\n" "-compile(export_all).\n" -- cgit v1.1