diff --git a/src/rebar_edoc.erl b/src/rebar_edoc.erl index c828d27..23200fc 100644 --- a/src/rebar_edoc.erl +++ b/src/rebar_edoc.erl @@ -67,7 +67,7 @@ doc(Config, File) -> end, %% Restore code path - true = code:set_path(CodePath), + true = rebar_utils:cleanup_code_path(CodePath), {ok, Config1}. %% =================================================================== diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 6ae927d..e4abd3d 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -355,7 +355,7 @@ doterl_compile(Config, OutDir, MoreSources, ErlOpts) -> fun(S, C) -> internal_erl_compile(C, S, OutDir1, ErlOpts, G) end), - true = code:set_path(CurrPath), + true = rebar_utils:cleanup_code_path(CurrPath), ok. %% diff --git a/src/rebar_erlydtl_compiler.erl b/src/rebar_erlydtl_compiler.erl index 10387f5..111180a 100644 --- a/src/rebar_erlydtl_compiler.erl +++ b/src/rebar_erlydtl_compiler.erl @@ -123,7 +123,7 @@ compile(Config, _AppFile) -> {recursive, option(recursive, DtlOpts)}]) end, ok, MultiDtlOpts), - true = code:set_path(OrigPath), + true = rebar_utils:cleanup_code_path(OrigPath), Result. %% =================================================================== diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 39dd35d..17ee62e 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -89,7 +89,7 @@ eunit(Config, _AppFile) -> ?EUNIT_DIR), case CompileOnly of "true" -> - true = code:set_path(CodePath), + true = rebar_utils:cleanup_code_path(CodePath), ?CONSOLE("Compiled modules for eunit~n", []); false -> run_eunit(Config, CodePath, SrcErls) @@ -192,7 +192,7 @@ run_eunit(Config, CodePath, SrcErls) -> end, %% Restore code path - true = code:set_path(CodePath), + true = rebar_utils:cleanup_code_path(CodePath), ok. ensure_dirs() -> diff --git a/src/rebar_qc.erl b/src/rebar_qc.erl index 2c565f1..12a411b 100644 --- a/src/rebar_qc.erl +++ b/src/rebar_qc.erl @@ -161,7 +161,7 @@ run(Config, QC, QCOpts) -> case CompileOnly of "true" -> - true = code:set_path(CodePath), + true = rebar_utils:cleanup_code_path(CodePath), ?CONSOLE("Compiled modules for qc~n", []); false -> run1(QC, QCOpts, Config, CodePath, SrcErls) @@ -187,7 +187,7 @@ run1(QC, QCOpts, Config, CodePath, SrcErls) -> rebar_cover_utils:close(CoverLog), ok = rebar_cover_utils:exit(), - true = code:set_path(CodePath), + true = rebar_utils:cleanup_code_path(CodePath), case QCResult of [] -> diff --git a/src/rebar_upgrade.erl b/src/rebar_upgrade.erl index 3a38a08..a092de8 100644 --- a/src/rebar_upgrade.erl +++ b/src/rebar_upgrade.erl @@ -75,7 +75,7 @@ ok = cleanup(NameVer), %% Restore original path - true = code:set_path(OrigPath), + true = rebar_utils:cleanup_code_path(OrigPath), {ok, Config}. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index f3a082d..a04798e 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -64,7 +64,8 @@ base_dir/1, processing_base_dir/1, processing_base_dir/2, - patch_env/2]). + patch_env/2, + cleanup_code_path/1]). %% for internal use only -export([otp_release/0]). @@ -603,3 +604,17 @@ filter_defines([{platform_define, ArchRegex, Key, Value} | Rest], Acc) -> end; filter_defines([Opt | Rest], Acc) -> filter_defines(Rest, [Opt | Acc]). + +cleanup_code_path(OrigPath) -> + CurrentPath = code:get_path(), + AddedPaths = CurrentPath -- OrigPath, + %% If someone has removed paths, it's hard to get them back into + %% the right order, but since this is currently rare, we can just + %% fall back to code:set_path/1. + case CurrentPath -- AddedPaths of + OrigPath -> + _ = [code:del_path(Path) || Path <- AddedPaths], + true; + _ -> + code:set_path(OrigPath) + end. diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl index 16e8cc4..0eb47c1 100644 --- a/src/rebar_xref.erl +++ b/src/rebar_xref.erl @@ -80,7 +80,7 @@ xref(Config, _) -> QueryNoWarn = lists:all(fun check_query/1, QueryChecks), %% Restore the original code path - true = code:set_path(OrigPath), + true = rebar_utils:cleanup_code_path(OrigPath), %% Stop xref stopped = xref:stop(xref), diff --git a/test/rebar_eunit_tests.erl b/test/rebar_eunit_tests.erl index bb64507..33f168c 100644 --- a/test/rebar_eunit_tests.erl +++ b/test/rebar_eunit_tests.erl @@ -325,6 +325,62 @@ basic_setup_test_() -> ["test/myapp_mymod_tests.erl", "src/myapp_mymod.erl"])}. +code_path_test_() -> + [{"Ensuring that fast code path cleanup is correct for adds", + setup, fun make_tmp_dir/0, + fun(_) -> remove_tmp_dir() end, + fun() -> + OPath = code:get_path(), + PathZ = ?TMP_DIR ++ "some_path", + PathA = ?TMP_DIR ++ "some_other_path", + ok = file:make_dir(PathZ), + ok = file:make_dir(PathA), + true = code:add_pathz(PathZ), + true = code:add_patha(PathA), + %% make sure that they've been added + ?assertEqual([PathA] ++ OPath ++ [PathZ], + code:get_path()), + true = rebar_utils:cleanup_code_path(OPath), + ?assertEqual(OPath, code:get_path()) + end}, + {"Ensuring that fast code path cleanup is correct for removes", + setup, fun make_tmp_dir/0, + fun(_) -> remove_tmp_dir() end, + fun() -> + OPath = code:get_path(), + Path1 = lists:nth(10, OPath), + Path2 = lists:nth(11, OPath), + true = code:del_path(Path1), + true = code:del_path(Path2), + %% make sure that they've been added + ?assertEqual(OPath -- [Path1, Path2], + code:get_path()), + true = rebar_utils:cleanup_code_path(OPath), + ?assertEqual(OPath, code:get_path()) + end}, + {"Ensuring that fast code path cleanup is equivalent for adds", + setup, fun make_tmp_dir/0, + fun(_) -> remove_tmp_dir() end, + fun() -> + OPath = code:get_path(), + PathZ = ?TMP_DIR ++ "some_path", + PathA = ?TMP_DIR ++ "some_other_path", + ok = file:make_dir(PathZ), + ok = file:make_dir(PathA), + true = code:add_pathz(PathZ), + true = code:add_patha(PathA), + %% make sure that they've been added + ?assertEqual([PathA] ++ OPath ++ [PathZ], + code:get_path()), + true = rebar_utils:cleanup_code_path(OPath), + CleanedPath = code:get_path(), + true = code:add_pathz(PathZ), + true = code:add_patha(PathA), + true = code:set_path(OPath), + ?assertEqual(CleanedPath, code:get_path()) + end}]. + + %% ==================================================================== %% Setup and Teardown %% ====================================================================