summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar.hrl1
-rw-r--r--src/rebar3.erl5
-rw-r--r--src/rebar_app_discover.erl51
-rw-r--r--src/rebar_app_info.erl2
-rw-r--r--src/rebar_app_utils.erl107
-rw-r--r--src/rebar_config.erl2
-rw-r--r--src/rebar_dir.erl39
-rw-r--r--src/rebar_erlc_compiler.erl8
-rw-r--r--src/rebar_otp_app.erl86
-rw-r--r--src/rebar_packages.erl2
-rw-r--r--src/rebar_prv_dialyzer.erl3
-rw-r--r--src/rebar_prv_install_deps.erl268
-rw-r--r--src/rebar_prv_update.erl2
-rw-r--r--src/rebar_templater.erl24
-rw-r--r--src/rebar_utils.erl21
15 files changed, 266 insertions, 355 deletions
diff --git a/src/rebar.hrl b/src/rebar.hrl
index fdef438..bbd9a2f 100644
--- a/src/rebar.hrl
+++ b/src/rebar.hrl
@@ -22,7 +22,6 @@
-define(DEFAULT_RELEASE_DIR, "rel").
-define(DEFAULT_CONFIG_FILE, "rebar.config").
-define(LOCK_FILE, "rebar.lock").
--define(CONFIG_DIR, ".rebar3").
-ifdef(namespaced_types).
-type rebar_dict() :: dict:dict().
diff --git a/src/rebar3.erl b/src/rebar3.erl
index d9024bb..bd52fee 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -147,9 +147,8 @@ init_config() ->
Config1 = rebar_config:merge_locks(Config, rebar_config:consult_file(?LOCK_FILE)),
- %% If $HOME/.rebar3/config exists load and use as global config
- Home = rebar_dir:home_dir(),
- GlobalConfigFile = filename:join([Home, ?CONFIG_DIR, "config"]),
+ %% If $HOME/.config/rebar3/config exists load and use as global config
+ GlobalConfigFile = rebar_dir:global_config(),
State = case filelib:is_regular(GlobalConfigFile) of
true ->
?DEBUG("Load global config file ~p",
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index df2211e..f6ed91b 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -5,9 +5,7 @@
find_unbuilt_apps/1,
find_apps/1,
find_apps/2,
- find_app/2,
- validate_application_info/1,
- validate_application_info/2]).
+ find_app/2]).
-include_lib("providers/include/providers.hrl").
@@ -104,14 +102,14 @@ find_app(AppDir, Validate) ->
end,
case Validate of
valid ->
- case validate_application_info(AppInfo2) of
+ case rebar_app_utils:validate_application_info(AppInfo2) of
true ->
{true, AppInfo2};
_ ->
false
end;
invalid ->
- case validate_application_info(AppInfo2) of
+ case rebar_app_utils:validate_application_info(AppInfo2) of
true ->
false;
_ ->
@@ -157,46 +155,3 @@ create_app_info(AppDir, AppFile) ->
_ ->
error
end.
-
--spec validate_application_info(rebar_app_info:t()) -> boolean().
-validate_application_info(AppInfo) ->
- validate_application_info(AppInfo, rebar_app_info:app_details(AppInfo)).
-
-validate_application_info(AppInfo, AppDetail) ->
- EbinDir = rebar_app_info:ebin_dir(AppInfo),
- case rebar_app_info:app_file(AppInfo) of
- undefined ->
- false;
- AppFile ->
- case get_modules_list(AppFile, AppDetail) of
- {ok, List} ->
- has_all_beams(EbinDir, List);
- _Error ->
- ?PRV_ERROR({module_list, AppFile})
- end
- end.
-
--spec get_modules_list(file:filename_all(), proplists:proplist()) ->
- {ok, list()} |
- {warning, Reason::term()} |
- {error, Reason::term()}.
-get_modules_list(AppFile, AppDetail) ->
- case proplists:get_value(modules, AppDetail) of
- undefined ->
- {warning, {invalid_app_file, AppFile}};
- ModulesList ->
- {ok, ModulesList}
- end.
-
--spec has_all_beams(file:filename_all(), list()) -> true | providers:error().
-has_all_beams(EbinDir, [Module | ModuleList]) ->
- BeamFile = filename:join([EbinDir,
- ec_cnv:to_list(Module) ++ ".beam"]),
- case filelib:is_file(BeamFile) of
- true ->
- has_all_beams(EbinDir, ModuleList);
- false ->
- ?PRV_ERROR({missing_module, Module})
- end;
-has_all_beams(_, []) ->
- true.
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index 9d779be..7a01307 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -224,7 +224,7 @@ state(#app_info_t{state=State}) ->
-spec valid(t()) -> boolean().
valid(AppInfo=#app_info_t{valid=undefined}) ->
- case rebar_app_discover:validate_application_info(AppInfo) of
+ case rebar_app_utils:validate_application_info(AppInfo) of
true ->
true;
_ ->
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index 2b63519..cd1124a 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -28,13 +28,13 @@
-export([find/2,
find/3,
- is_app_dir/0, is_app_dir/1,
is_app_src/1,
app_src_to_app/1,
- load_app_file/2,
- app_vsn/2]).
+ validate_application_info/1,
+ validate_application_info/2]).
-include("rebar.hrl").
+-include_lib("providers/include/providers.hrl").
%% ===================================================================
%% Public API
@@ -51,35 +51,6 @@ find(Name, Vsn, Apps) ->
andalso rebar_app_info:original_vsn(App) =:= Vsn
end, Apps).
--spec is_app_dir() -> {true, file:name()} | false.
-is_app_dir() ->
- is_app_dir(rebar_dir:get_cwd()).
-
--spec is_app_dir(file:name()) -> {true, file:name()} | false.
-is_app_dir(Dir) ->
- SrcDir = filename:join([Dir, "src"]),
- AppSrc = filename:join([SrcDir, "*.app.src"]),
- case filelib:wildcard(AppSrc) of
- [AppSrcFile] ->
- {true, AppSrcFile};
- [] ->
- EbinDir = filename:join([Dir, "ebin"]),
- App = filename:join([EbinDir, "*.app"]),
- case filelib:wildcard(App) of
- [AppFile] ->
- {true, AppFile};
- [] ->
- false;
- _ ->
- ?ERROR("More than one .app file in ~s~n", [EbinDir]),
- false
- end;
- _ ->
- ?ERROR("More than one .app.src file in ~s~n", [SrcDir]),
- false
- end.
-
-
is_app_src(Filename) ->
%% If removing the extension .app.src yields a shorter name,
%% this is an .app.src file.
@@ -91,58 +62,38 @@ app_src_to_app(Filename) ->
filelib:ensure_dir(AppFile),
AppFile.
-app_vsn(Config, AppFile) ->
- case load_app_file(Config, AppFile) of
- {ok, Config1, _, AppInfo} ->
- AppDir = filename:dirname(filename:dirname(AppFile)),
- rebar_utils:vcs_vsn(Config1, get_value(vsn, AppInfo, AppFile),
- AppDir);
- {error, Reason} ->
- ?ABORT("Failed to extract vsn from ~s: ~p\n",
- [AppFile, Reason])
- end.
+-spec validate_application_info(rebar_app_info:t()) -> boolean().
+validate_application_info(AppInfo) ->
+ validate_application_info(AppInfo, rebar_app_info:app_details(AppInfo)).
-load_app_file(_State, undefined) -> {error, missing_app_file};
-load_app_file(State, Filename) ->
- AppFile = {app_file, Filename},
- case rebar_state:get(State, {appfile, AppFile}, undefined) of
+validate_application_info(AppInfo, AppDetail) ->
+ EbinDir = rebar_app_info:ebin_dir(AppInfo),
+ case rebar_app_info:app_file(AppInfo) of
undefined ->
- case consult_app_file(Filename) of
- {ok, [{application, AppName, AppData}]} ->
- State1 = rebar_state:set(State,
- {appfile, AppFile},
- {AppName, AppData}),
- {ok, State1, AppName, AppData};
- {error, _} = Error ->
- Error;
- Other ->
- {error, {unexpected_terms, Other}}
- end;
- {AppName, AppData} ->
- {ok, State, AppName, AppData}
+ false;
+ AppFile ->
+ case proplists:get_value(modules, AppDetail) of
+ undefined ->
+ ?PRV_ERROR({module_list, AppFile});
+ List ->
+ has_all_beams(EbinDir, List)
+
+ end
end.
%% ===================================================================
%% Internal functions
%% ===================================================================
-%% In the case of *.app.src we want to give the user the ability to
-%% dynamically script the application resource file (think dynamic version
-%% string, etc.), in a way similar to what can be done with the rebar
-%% config. However, in the case of *.app, rebar should not manipulate
-%% that file. This enforces that dichotomy between app and app.src.
-consult_app_file(Filename) ->
- case lists:suffix(".app.src", Filename) of
- false ->
- file:consult(Filename);
+-spec has_all_beams(file:filename_all(), list()) -> true | providers:error().
+has_all_beams(EbinDir, [Module | ModuleList]) ->
+ BeamFile = filename:join([EbinDir,
+ ec_cnv:to_list(Module) ++ ".beam"]),
+ case filelib:is_file(BeamFile) of
true ->
- {ok, rebar_config:consult_file(Filename)}
- end.
-
-get_value(Key, AppInfo, AppFile) ->
- case proplists:get_value(Key, AppInfo) of
- undefined ->
- ?ABORT("Failed to get app value '~p' from '~s'~n", [Key, AppFile]);
- Value ->
- Value
- end.
+ has_all_beams(EbinDir, ModuleList);
+ false ->
+ ?PRV_ERROR({missing_module, Module})
+ end;
+has_all_beams(_, []) ->
+ true.
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index 43730ea..36d6b18 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -91,7 +91,7 @@ try_consult(File) ->
{error, enoent} ->
[];
{error, Reason} ->
- ?ABORT("Failed to read config file ~s: ~p", [File, Reason])
+ ?ABORT("Failed to read config file ~s:~n ~p", [File, Reason])
end.
bs(Vars) ->
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index 58ce716..3962bf8 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -7,8 +7,13 @@
lib_dirs/1,
home_dir/0,
global_config_dir/1,
+ global_config/1,
+ global_config/0,
+ global_cache_dir/1,
+ local_cache_dir/0,
get_cwd/0,
- ensure_dir/1,
+ template_globals/1,
+ template_dir/1,
src_dirs/1,
ebin_dir/0,
processing_base_dir/1,
@@ -47,23 +52,31 @@ home_dir() ->
global_config_dir(State) ->
Home = home_dir(),
- rebar_state:get(State, global_rebar_dir, filename:join(Home, ?CONFIG_DIR)).
+ rebar_state:get(State, global_rebar_dir, filename:join([Home, ".config", "rebar3"])).
+
+global_config(State) ->
+ filename:join(global_config_dir(State), "config").
+
+global_config() ->
+ Home = home_dir(),
+ filename:join([Home, ".config", "rebar3", "config"]).
+
+global_cache_dir(State) ->
+ Home = home_dir(),
+ rebar_state:get(State, global_rebar_dir, filename:join([Home, ".cache", "rebar3"])).
+
+local_cache_dir() ->
+ filename:join(get_cwd(), ".rebar3").
get_cwd() ->
{ok, Dir} = file:get_cwd(),
Dir.
-%% TODO: filelib:ensure_dir/1 corrected in R13B04. Remove when we drop
-%% support for OTP releases older than R13B04.
-ensure_dir(Path) ->
- case filelib:ensure_dir(Path) of
- ok ->
- ok;
- {error,eexist} ->
- ok;
- Error ->
- Error
- end.
+template_globals(State) ->
+ filename:join([global_config_dir(State), "templates", "globals"]).
+
+template_dir(State) ->
+ filename:join([global_config_dir(State), "templates"]).
-spec src_dirs([string()]) -> [file:filename(), ...].
src_dirs([]) ->
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 330f20b..afdd6bd 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -270,7 +270,7 @@ opts_changed(Opts, Target) ->
code:purge(Mod),
lists:sort(Opts) =/= lists:sort(proplists:get_value(options,
Compile));
- {error, nofile} -> true
+ {error, _} -> true
end.
check_erlcinfo(_Config, #erlcinfo{vsn=?ERLCINFO_VSN}) ->
@@ -283,7 +283,7 @@ check_erlcinfo(Config, _) ->
[erlcinfo_file(Config)]).
erlcinfo_file(_Config) ->
- filename:join([rebar_dir:get_cwd(), ?CONFIG_DIR, ?ERLCINFO_FILE]).
+ filename:join(rebar_dir:local_cache_dir(), ?ERLCINFO_FILE).
init_erlcinfo(Config, Erls) ->
G = restore_erlcinfo(Config),
@@ -464,8 +464,8 @@ internal_erl_compile(Config, Dir, Source, OutDir, ErlOpts, G) ->
-spec compile_mib(file:filename(), file:filename(),
rebar_state:t()) -> 'ok'.
compile_mib(Source, Target, Config) ->
- ok = rebar_dir:ensure_dir(Target),
- ok = rebar_dir:ensure_dir(filename:join("include", "dummy.hrl")),
+ ok = filelib:ensure_dir(Target),
+ ok = filelib:ensure_dir(filename:join("include", "dummy.hrl")),
Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++
rebar_state:get(Config, mib_opts, []),
case snmpc:compile(Source, Opts) of
diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl
index 272d950..49579ae 100644
--- a/src/rebar_otp_app.erl
+++ b/src/rebar_otp_app.erl
@@ -27,8 +27,7 @@
-module(rebar_otp_app).
-export([compile/2,
- format_error/1,
- clean/2]).
+ format_error/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
@@ -42,52 +41,33 @@ compile(State, App) ->
%% written out as a ebin/*.app file. That resulting file will then
%% be validated as usual.
Dir = ec_cnv:to_list(rebar_app_info:dir(App)),
- {State2, App1} = case rebar_app_info:app_file_src(App) of
- undefined ->
- {State, App};
- AppFileSrc ->
- {State1, File} = preprocess(State, Dir, AppFileSrc),
- {State1, rebar_app_info:app_file(App, File)}
- end,
+ App1 = case rebar_app_info:app_file_src(App) of
+ undefined ->
+ App;
+ AppFileSrc ->
+ File = preprocess(State, Dir, AppFileSrc),
+ rebar_app_info:app_file(App, File)
+ end,
%% Load the app file and validate it.
- validate_app(State2, App1).
-
-
+ validate_app(State, App1).
format_error({file_read, File, Reason}) ->
io_lib:format("Failed to read ~s for processing: ~p", [File, Reason]);
format_error({invalid_name, File, AppName}) ->
io_lib:format("Invalid ~s: name of application (~p) must match filename.", [File, AppName]).
-clean(_State, File) ->
- %% If the app file is a .app.src, delete the generated .app file
- case rebar_app_utils:is_app_src(File) of
- true ->
- case file:delete(rebar_app_utils:app_src_to_app(File)) of
- ok ->
- ok;
- {error, enoent} ->
- %% The file not existing is OK, we can ignore the error.
- ok;
- Other ->
- Other
- end;
- false ->
- ok
- end.
-
%% ===================================================================
%% Internal functions
%% ===================================================================
validate_app(State, App) ->
AppFile = rebar_app_info:app_file(App),
- case rebar_app_utils:load_app_file(State, AppFile) of
- {ok, State1, AppName, AppData} ->
+ case consult_app_file(AppFile) of
+ {ok, [{application, AppName, AppData}]} ->
case validate_name(AppName, AppFile) of
ok ->
- validate_app_modules(State1, App, AppData);
+ validate_app_modules(State, App, AppData);
Error ->
Error
end;
@@ -102,7 +82,7 @@ validate_app_modules(State, App, AppData) ->
AppVsn = proplists:get_value(vsn, AppData),
case rebar_state:get(State, validate_app_modules, true) of
true ->
- case rebar_app_discover:validate_application_info(App, AppData) of
+ case rebar_app_utils:validate_application_info(App, AppData) of
true ->
{ok, rebar_app_info:original_vsn(App, AppVsn)};
Error ->
@@ -113,16 +93,16 @@ validate_app_modules(State, App, AppData) ->
end.
preprocess(State, Dir, AppSrcFile) ->
- case rebar_app_utils:load_app_file(State, AppSrcFile) of
- {ok, State1, AppName, AppData} ->
+ case consult_app_file(AppSrcFile) of
+ {ok, [{application, AppName, AppData}]} ->
%% Look for a configuration file with vars we want to
%% substitute. Note that we include the list of modules available in
%% ebin/ and update the app data accordingly.
- AppVars = load_app_vars(State1) ++ [{modules, ebin_modules(Dir)}],
+ AppVars = load_app_vars(State) ++ [{modules, ebin_modules(Dir)}],
A1 = apply_app_vars(AppVars, AppData),
%% AppSrcFile may contain instructions for generating a vsn number
- {State2, Vsn} = rebar_app_utils:app_vsn(State1, AppSrcFile),
+ Vsn = app_vsn(AppSrcFile),
A2 = lists:keystore(vsn, 1, A1, {vsn, Vsn}),
%% systools:make_relup/4 fails with {missing_param, registered}
@@ -140,7 +120,7 @@ preprocess(State, Dir, AppSrcFile) ->
%% on the code path
true = code:add_path(filename:absname(filename:dirname(AppFile))),
- {State2, AppFile};
+ AppFile;
{error, Reason} ->
?PRV_ERROR({file_read, AppSrcFile, Reason})
end.
@@ -185,3 +165,33 @@ ensure_registered(AppData) ->
%% We could further check whether the value is a list of atoms.
AppData
end.
+
+%% In the case of *.app.src we want to give the user the ability to
+%% dynamically script the application resource file (think dynamic version
+%% string, etc.), in a way similar to what can be done with the rebar
+%% config. However, in the case of *.app, rebar should not manipulate
+%% that file. This enforces that dichotomy between app and app.src.
+consult_app_file(Filename) ->
+ case lists:suffix(".app.src", Filename) of
+ false ->
+ file:consult(Filename);
+ true ->
+ {ok, rebar_config:consult_file(Filename)}
+ end.
+
+app_vsn(AppFile) ->
+ case consult_app_file(AppFile) of
+ {ok, [{application, _AppName, AppData}]} ->
+ AppDir = filename:dirname(filename:dirname(AppFile)),
+ rebar_utils:vcs_vsn(get_value(vsn, AppData, AppFile), AppDir);
+ {error, Reason} ->
+ ?ABORT("Failed to consult app file ~s: ~p\n", [AppFile, Reason])
+ end.
+
+get_value(Key, AppInfo, AppFile) ->
+ case proplists:get_value(Key, AppInfo) of
+ undefined ->
+ ?ABORT("Failed to get app value '~p' from '~s'~n", [Key, AppFile]);
+ Value ->
+ Value
+ end.
diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl
index 38dfbbf..5c67600 100644
--- a/src/rebar_packages.erl
+++ b/src/rebar_packages.erl
@@ -12,7 +12,7 @@
-spec get_packages(rebar_state:t()) -> {rebar_dict(), rebar_digraph()}.
get_packages(State) ->
- RebarDir = rebar_dir:global_config_dir(State),
+ RebarDir = rebar_dir:global_cache_dir(State),
RegistryDir = filename:join(RebarDir, "packages"),
DictFile = filename:join(RegistryDir, "dict"),
Edges = filename:join(RegistryDir, "edges"),
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 240427b..24abc4f 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -311,8 +311,7 @@ build_proj_plt(State, Plt, Files) ->
end.
get_base_plt_location(State) ->
- Home = rebar_dir:home_dir(),
- GlobalConfigDir = filename:join(Home, ?CONFIG_DIR),
+ GlobalConfigDir = rebar_dir:global_config_dir(State),
BaseDir = rebar_state:get(State, dialyzer_base_plt_dir, GlobalConfigDir),
BasePlt = rebar_state:get(State, dialyzer_base_plt, default_plt()),
filename:join(BaseDir, BasePlt).
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index 8db4761..6270660 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -74,15 +74,7 @@ do(State) ->
ProjectApps = rebar_state:project_apps(State),
{Apps, State1} =
- lists:foldl(fun(Profile, {AppsAcc, StateAcc}) ->
- Locks = rebar_state:get(StateAcc, {locks, Profile}, []),
- {ok, NewApps, NewState} =
- handle_deps(Profile
- ,StateAcc
- ,rebar_state:get(StateAcc, {deps, Profile}, [])
- ,Locks),
- {NewApps++AppsAcc, NewState}
- end, {[], State}, lists:reverse(Profiles)),
+ lists:foldl(fun deps_per_profile/2, {[], State}, lists:reverse(Profiles)),
Source = ProjectApps ++ Apps,
case find_cycles(Source) of
@@ -91,11 +83,9 @@ do(State) ->
{error, Error} ->
{error, Error};
no_cycle ->
- case rebar_digraph:compile_order(Source) of
- {ok, Sort} ->
- {ok, rebar_state:deps_to_build(State1,
- lists:dropwhile(fun rebar_app_info:valid/1,
- Sort -- ProjectApps))};
+ case compile_order(Source, ProjectApps) of
+ {ok, ToCompile} ->
+ {ok, rebar_state:deps_to_build(State1, ToCompile)};
{error, Error} ->
{error, Error}
end
@@ -106,13 +96,6 @@ do(State) ->
{error, Reason}
end.
-find_cycles(Apps) ->
- case rebar_digraph:compile_order(Apps) of
- {error, {cycles, Cycles}} -> {cycles, Cycles};
- {error, Error} -> {error, Error};
- {ok, _} -> no_cycle
- end.
-
-spec format_error(any()) -> iolist().
format_error({parse_dep, Dep}) ->
io_lib:format("Failed parsing dep ~p", [Dep]);
@@ -155,22 +138,8 @@ handle_deps(Profile, State, Deps, Upgrade, Locks) ->
{State1, SrcApps, PkgDeps1, Seen} =
update_src_deps(Profile, 0, SrcDeps, PkgDeps, [], State, Upgrade, sets:new(), Locks),
- {Solved, State2} = case PkgDeps1 of
- [] -> %% No pkg deps
- {[], State1};
- PkgDeps2 ->
- %% Find pkg deps needed
- S = case rebar_digraph:cull_deps(Graph, PkgDeps2) of
- {ok, [], _} ->
- throw({rebar_digraph, no_solution});
- {ok, Solution, []} ->
- Solution;
- {ok, Solution, Discarded} ->
- [warn_skip_pkg(Pkg) || Pkg <- Discarded],
- Solution
- end,
- update_pkg_deps(Profile, S, Packages, Upgrade, Seen, State1)
- end,
+ {Solved, State2} =
+ update_pkg_deps(Profile, Packages, PkgDeps1, Graph, Upgrade, Seen, State1),
AllDeps = lists:ukeymerge(2
,lists:ukeysort(2, SrcApps)
@@ -184,33 +153,74 @@ handle_deps(Profile, State, Deps, Upgrade, Locks) ->
%% Internal functions
%% ===================================================================
+deps_per_profile(Profile, {Apps, State}) ->
+ Locks = rebar_state:get(State, {locks, Profile}, []),
+ ProfileDeps = rebar_state:get(State, {deps, Profile}, []),
+ {ok, NewApps, NewState} = handle_deps(Profile, State, ProfileDeps, Locks),
+ {NewApps++Apps, NewState}.
+
+find_cycles(Apps) ->
+ case rebar_digraph:compile_order(Apps) of
+ {error, {cycles, Cycles}} -> {cycles, Cycles};
+ {error, Error} -> {error, Error};
+ {ok, _} -> no_cycle
+ end.
+
+compile_order(Source, ProjectApps) ->
+ case rebar_digraph:compile_order(Source) of
+ {ok, Sort} ->
+ %% Valid apps are compiled and good
+ {ok, lists:dropwhile(fun rebar_app_info:valid/1, Sort -- ProjectApps)};
+ {error, Error} ->
+ {error, Error}
+ end.
+
+update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State) ->
+ case PkgDeps of
+ [] -> %% No pkg deps
+ {[], State};
+ PkgDeps ->
+ %% Find pkg deps needed
+ S = case rebar_digraph:cull_deps(Graph, PkgDeps) of
+ {ok, [], _} ->
+ throw({rebar_digraph, no_solution});
+ {ok, Solution, []} ->
+ Solution;
+ {ok, Solution, Discarded} ->
+ [warn_skip_pkg(Pkg) || Pkg <- Discarded],
+ Solution
+ end,
+ update_pkg_deps(Profile, S, Packages, Upgrade, Seen, State)
+ end.
+
update_pkg_deps(Profile, Pkgs, Packages, Upgrade, Seen, State) ->
%% Create app_info record for each pkg dep
DepsDir = rebar_dir:deps_dir(State),
{Solved, _, State1}
= lists:foldl(fun(Pkg, {Acc, SeenAcc, StateAcc}) ->
- AppInfo = package_to_app(DepsDir
- ,Packages
- ,Pkg),
- {SeenAcc1, StateAcc1} = maybe_lock(Profile, AppInfo, SeenAcc, StateAcc, 0),
- case maybe_fetch(AppInfo, Upgrade, SeenAcc1, State) of
- true ->
- {[AppInfo | Acc], SeenAcc1, StateAcc1};
- false ->
- {Acc, SeenAcc1, StateAcc1}
- end
+ handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Acc, SeenAcc, StateAcc)
end, {[], Seen, State}, Pkgs),
{Solved, State1}.
+handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, State) ->
+ AppInfo = package_to_app(DepsDir, Packages, Pkg),
+ {NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, 0),
+ case maybe_fetch(AppInfo, Upgrade, NewSeen, NewState) of
+ true ->
+ {[AppInfo | Fetched], NewSeen, NewState};
+ false ->
+ {Fetched, NewSeen, NewState}
+ end.
+
+
maybe_lock(Profile, AppInfo, Seen, State, Level) ->
- Name = rebar_app_info:name(AppInfo),
case Profile of
default ->
+ Name = rebar_app_info:name(AppInfo),
case sets:is_element(Name, Seen) of
false ->
- AppName = rebar_app_info:name(AppInfo),
Locks = rebar_state:lock(State),
- case lists:any(fun(App) -> rebar_app_info:name(App) =:= AppName end, Locks) of
+ case lists:any(fun(App) -> rebar_app_info:name(App) =:= Name end, Locks) of
true ->
{sets:add_element(Name, Seen), State};
false ->
@@ -239,81 +249,77 @@ package_to_app(DepsDir, Packages, {Name, Vsn}) ->
-spec update_src_deps(atom(), non_neg_integer(), list(), list(), list(), rebar_state:t(), boolean(), sets:set(binary()), list()) -> {rebar_state:t(), list(), list(), sets:set(binary())}.
update_src_deps(Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, Locks) ->
- case lists:foldl(fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc}) ->
- %% If not seen, add to list of locks to write out
- Name = rebar_app_info:name(AppInfo),
- case sets:is_element(Name, SeenAcc) of
- true ->
- %% If from lock file don't print warning about skipping
- case lists:keymember(Name, 1, Locks) of
- false ->
- warn_skip_deps(AppInfo);
- true ->
- ok
- end,
- %% scan for app children here if upgrading
- case Upgrade of
- false ->
- {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc};
- true ->
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, LocksAcc1} =
- handle_dep(AppInfo
- ,SrcDepsAcc
- ,PkgDepsAcc
- ,SrcAppsAcc
- ,Level
- ,StateAcc
- ,LocksAcc),
-
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc, LocksAcc1}
- end;
- false ->
- {SeenAcc1, StateAcc1} = maybe_lock(Profile, AppInfo, SeenAcc, StateAcc, Level),
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, LocksAcc1} =
- case Upgrade of
- true ->
- %{true, UpgradeName, UpgradeLevel} ->
- handle_upgrade(AppInfo
- ,SrcDepsAcc
- ,PkgDepsAcc
- ,SrcAppsAcc
- ,Level
- ,StateAcc1
- ,LocksAcc);
- _ ->
- maybe_fetch(AppInfo, false, SeenAcc, StateAcc),
- handle_dep(AppInfo
- ,SrcDepsAcc
- ,PkgDepsAcc
- ,SrcAppsAcc
- ,Level
- ,StateAcc1
- ,LocksAcc)
- end,
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc1, LocksAcc1}
- end
- end,
- {[], PkgDeps, SrcApps, State, Seen, Locks},
- rebar_utils:sort_deps(SrcDeps)) of
+ case lists:foldl(
+ fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc}) ->
+ update_src_dep(AppInfo, Profile, Level,
+ SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc,
+ Upgrade, SeenAcc, Locks, LocksAcc)
+ end,
+ {[], PkgDeps, SrcApps, State, Seen, Locks},
+ rebar_utils:sort_deps(SrcDeps)) of
{[], NewPkgDeps, NewSrcApps, State1, Seen1, _NewLocks} ->
{State1, NewSrcApps, NewPkgDeps, Seen1};
{NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Seen1, NewLocks} ->
update_src_deps(Profile, Level+1, NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Upgrade, Seen1, NewLocks)
end.
+update_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
+ %% If not seen, add to list of locks to write out
+ Name = rebar_app_info:name(AppInfo),
+ case sets:is_element(Name, Seen) of
+ true ->
+ update_seen_src_dep(AppInfo, Level,
+ SrcDeps, PkgDeps, SrcApps,
+ State, Upgrade, Seen, BaseLocks, Locks);
+ false ->
+ update_unseen_src_dep(AppInfo, Profile, Level,
+ SrcDeps, PkgDeps, SrcApps,
+ State, Upgrade, Seen, Locks)
+
+ end.
+
+update_seen_src_dep(AppInfo, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
+ Name = rebar_app_info:name(AppInfo),
+ %% If seen from lock file don't print warning about skipping
+ case lists:keymember(Name, 1, BaseLocks) of
+ false ->
+ warn_skip_deps(AppInfo);
+ true ->
+ ok
+ end,
+ %% scan for app children here if upgrading
+ case Upgrade of
+ false ->
+ {SrcDeps, PkgDeps, SrcApps, State, Seen, Locks};
+ true ->
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, NewLocks}
+ = handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State, Locks),
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, Seen, NewLocks}
+ end.
+
+update_unseen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, Locks) ->
+ {NewSeen, State1} = maybe_lock(Profile, AppInfo, Seen, State, Level),
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewLocks}
+ = case Upgrade of
+ true ->
+ handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State1, Locks);
+ _ ->
+ maybe_fetch(AppInfo, false, Seen, State1),
+ handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State1, Locks)
+ end,
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewSeen, NewLocks}.
+
handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
Name = rebar_app_info:name(AppInfo),
case lists:keyfind(Name, 1, Locks) of
false ->
case maybe_fetch(AppInfo, true, sets:new(), State) of
true ->
- handle_dep(AppInfo
- ,SrcDeps
- ,PkgDeps
- ,SrcApps
- ,Level
- ,State
- ,Locks);
+ handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State, Locks);
false ->
{[AppInfo|SrcDeps], PkgDeps, SrcApps, State, Locks}
@@ -359,16 +365,15 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
sets:set(binary()), rebar_state:t()) -> boolean().
maybe_fetch(AppInfo, Upgrade, Seen, State) ->
AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
- Apps = rebar_app_discover:find_apps(["_checkouts"], all),
- case rebar_app_utils:find(rebar_app_info:name(AppInfo), Apps) of
- {ok, _} ->
- %% Don't fetch dep if it exists in the _checkouts dir
+ %% Don't fetch dep if it exists in the _checkouts dir
+ case in_checkouts(AppInfo) of
+ true ->
false;
- error ->
- case not app_exists(AppDir) of
- true ->
- fetch_app(AppInfo, AppDir, State);
+ false ->
+ case rebar_app_discover:find_app(AppDir, all) of
false ->
+ fetch_app(AppInfo, AppDir, State);
+ {true, _} ->
case sets:is_element(rebar_app_info:name(AppInfo), Seen) of
true ->
false;
@@ -378,6 +383,14 @@ maybe_fetch(AppInfo, Upgrade, Seen, State) ->
end
end.
+in_checkouts(AppInfo) ->
+ Apps = rebar_app_discover:find_apps(["_checkouts"], all),
+ case rebar_app_utils:find(rebar_app_info:name(AppInfo), Apps) of
+ {ok, _} -> true;
+ error -> false
+ end.
+
+
-spec parse_deps(binary(), list(), list(), list(), integer()) -> {[rebar_app_info:t()], [pkg_dep()]}.
parse_deps(DepsDir, Deps, State, Locks, Level) ->
lists:foldl(fun(Dep, Acc) ->
@@ -443,19 +456,6 @@ new_dep(DepsDir, Name, Vsn, Source, State) ->
rebar_state:overrides(S, ParentOverrides++Overrides)),
rebar_app_info:source(Dep1, Source).
-app_exists(AppDir) ->
- case rebar_app_utils:is_app_dir(filename:absname(AppDir)++"-*") of
- {true, _} ->
- true;
- _ ->
- case rebar_app_utils:is_app_dir(filename:absname(AppDir)) of
- {true, _} ->
- true;
- _ ->
- false
- end
- end.
-
fetch_app(AppInfo, AppDir, State) ->
?INFO("Fetching ~s (~p)", [rebar_app_info:name(AppInfo), rebar_app_info:source(AppInfo)]),
Source = rebar_app_info:source(AppInfo),
diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl
index f4985f3..20f6974 100644
--- a/src/rebar_prv_update.erl
+++ b/src/rebar_prv_update.erl
@@ -59,7 +59,7 @@ format_error(package_index_write) ->
"Failed to write package index.".
write_registry(Dict, {digraph, Edges, Vertices, Neighbors, _}, State) ->
- Dir = rebar_dir:global_config_dir(State),
+ Dir = rebar_dir:global_cache_dir(State),
RegistryDir = filename:join(Dir, "packages"),
filelib:ensure_dir(filename:join(RegistryDir, "dummy")),
ets:tab2file(Edges, filename:join(RegistryDir, "edges")),
diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl
index 47ce093..edfe3bd 100644
--- a/src/rebar_templater.erl
+++ b/src/rebar_templater.erl
@@ -48,13 +48,13 @@ new(Template, Vars, Force, State) ->
?DEBUG("Looking for ~p~n", [Template]),
case lists:keyfind(Template, 1, AvailTemplates) of
false -> {not_found, Template};
- TemplateTup -> create(TemplateTup, Files, Vars, Force)
+ TemplateTup -> create(TemplateTup, Files, Vars, Force, State)
end.
%% Give a list of templates with their expanded content
list_templates(State) ->
{AvailTemplates, Files} = find_templates(State),
- [list_template(Files, Template) || Template <- AvailTemplates].
+ [list_template(Files, Template, State) || Template <- AvailTemplates].
%% ===================================================================
%% Rendering API / legacy?
@@ -89,11 +89,11 @@ render(Template, Context) ->
%% ===================================================================
%% Expand a single template's value
-list_template(Files, {Name, Type, File}) ->
+list_template(Files, {Name, Type, File}, State) ->
TemplateTerms = consult(load_file(Files, Type, File)),
{Name, Type, File,
get_template_description(TemplateTerms),
- get_template_vars(TemplateTerms)}.
+ get_template_vars(TemplateTerms, State)}.
%% Load up the template description out from a list of attributes read in
%% a .template file.
@@ -105,12 +105,12 @@ get_template_description(TemplateTerms) ->
%% Load up the variables out from a list of attributes read in a .template file
%% and return them merged with the globally-defined and default variables.
-get_template_vars(TemplateTerms) ->
+get_template_vars(TemplateTerms, State) ->
Vars = case lists:keyfind(variables, 1, TemplateTerms) of
{_, Value} -> Value;
false -> []
end,
- override_vars(Vars, override_vars(global_variables(), default_variables())).
+ override_vars(Vars, override_vars(global_variables(State), default_variables())).
%% Provide a way to merge a set of variables with another one. The left-hand
%% set of variables takes precedence over the right-hand set.
@@ -142,9 +142,8 @@ default_variables() ->
%% Load variable definitions from the 'Globals' file in the home template
%% directory
-global_variables() ->
- Home = rebar_dir:home_dir(),
- GlobalFile = filename:join([Home, ?CONFIG_DIR, "templates", "globals"]),
+global_variables(State) ->
+ GlobalFile = rebar_dir:template_globals(State),
case file:consult(GlobalFile) of
{error, enoent} -> [];
{ok, Data} -> proplists:get_value(variables, Data, [])
@@ -157,9 +156,9 @@ drop_var_docs([{K,V}|Rest]) -> [{K,V} | drop_var_docs(Rest)].
%% Load the template index, resolve all variables, and then execute
%% the template.
-create({Template, Type, File}, Files, UserVars, Force) ->
+create({Template, Type, File}, Files, UserVars, Force, State) ->
TemplateTerms = consult(load_file(Files, Type, File)),
- Vars = drop_var_docs(override_vars(UserVars, get_template_vars(TemplateTerms))),
+ Vars = drop_var_docs(override_vars(UserVars, get_template_vars(TemplateTerms, State))),
TemplateCwd = filename:dirname(File),
execute_template(TemplateTerms, Files, {Template, Type, TemplateCwd}, Vars, Force).
@@ -270,8 +269,7 @@ find_escript_templates(Files) ->
%% Fetch template indexes that sit on disk in the user's HOME
find_disk_templates(State) ->
OtherTemplates = find_other_templates(State),
- Home = rebar_dir:home_dir(),
- HomeFiles = rebar_utils:find_files(filename:join([Home, ?CONFIG_DIR, "templates"]),
+ HomeFiles = rebar_utils:find_files(rebar_dir:template_dir(State),
?TEMPLATE_RE, true), % recursive
[{file, F} || F <- OtherTemplates ++ HomeFiles].
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 943c0d7..b3ae9ff 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -43,7 +43,7 @@
beams/1,
find_executable/1,
expand_code_path/0,
- vcs_vsn/3,
+ vcs_vsn/2,
deprecated/3,
deprecated/4,
erl_opts/1,
@@ -179,19 +179,6 @@ expand_code_path() ->
end, [], code:get_path()),
code:set_path(lists:reverse(CodePath)).
-vcs_vsn(Config, Vsn, Dir) ->
- Key = {Vsn, Dir},
- Cache = rebar_state:get(Config, vsn_cache, dict:new()),
- case dict:find(Key, Cache) of
- error ->
- VsnString = vcs_vsn_1(Vsn, Dir),
- Cache1 = dict:store(Key, VsnString, Cache),
- Config1 = rebar_state:set(Config, vsn_cache, Cache1),
- {Config1, VsnString};
- {ok, VsnString} ->
- {Config, VsnString}
- end.
-
deprecated(Old, New, Opts, When) when is_list(Opts) ->
case lists:member(Old, Opts) of
true ->
@@ -413,16 +400,16 @@ escript_foldl(Fun, Acc, File) ->
Error
end.
-vcs_vsn_1(Vcs, Dir) ->
+vcs_vsn(Vcs, Dir) ->
case vcs_vsn_cmd(Vcs, Dir) of
{plain, VsnString} ->
VsnString;
{cmd, CmdString} ->
vcs_vsn_invoke(CmdString, Dir);
unknown ->
- ?ABORT("vcs_vsn: Unknown vsn format: ~p\n", [Vcs]);
+ ?ABORT("vcs_vsn: Unknown vsn format: ~p", [Vcs]);
{error, Reason} ->
- ?ABORT("vcs_vsn: ~s\n", [Reason])
+ ?ABORT("vcs_vsn: ~s", [Reason])
end.
%% Temp work around for repos like relx that use "semver"