summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/r3.erl5
-rw-r--r--src/rebar3.erl14
-rw-r--r--src/rebar_agent.erl33
-rw-r--r--src/rebar_app_discover.erl158
-rw-r--r--src/rebar_app_info.erl65
-rw-r--r--src/rebar_app_utils.erl34
-rw-r--r--src/rebar_base_compiler.erl16
-rw-r--r--src/rebar_config.erl18
-rw-r--r--src/rebar_core.erl10
-rw-r--r--src/rebar_dialyzer_format.erl228
-rw-r--r--src/rebar_digraph.erl4
-rw-r--r--src/rebar_dir.erl4
-rw-r--r--src/rebar_dist_utils.erl25
-rw-r--r--src/rebar_erlc_compiler.erl29
-rw-r--r--src/rebar_fetch.erl22
-rw-r--r--src/rebar_file_utils.erl45
-rw-r--r--src/rebar_git_resource.erl61
-rw-r--r--src/rebar_hg_resource.erl23
-rw-r--r--src/rebar_hooks.erl6
-rw-r--r--src/rebar_log.erl4
-rw-r--r--src/rebar_opts.erl4
-rw-r--r--src/rebar_otp_app.erl8
-rw-r--r--src/rebar_packages.erl12
-rw-r--r--src/rebar_pkg_resource.erl18
-rw-r--r--src/rebar_prv_app_discovery.erl12
-rw-r--r--src/rebar_prv_as.erl6
-rw-r--r--src/rebar_prv_bare_compile.erl8
-rw-r--r--src/rebar_prv_clean.erl5
-rw-r--r--src/rebar_prv_common_test.erl71
-rw-r--r--src/rebar_prv_compile.erl8
-rw-r--r--src/rebar_prv_cover.erl14
-rw-r--r--src/rebar_prv_deps.erl20
-rw-r--r--src/rebar_prv_deps_tree.erl4
-rw-r--r--src/rebar_prv_dialyzer.erl18
-rw-r--r--src/rebar_prv_edoc.erl8
-rw-r--r--src/rebar_prv_escriptize.erl37
-rw-r--r--src/rebar_prv_eunit.erl17
-rw-r--r--src/rebar_prv_install_deps.erl52
-rw-r--r--src/rebar_prv_local_install.erl8
-rw-r--r--src/rebar_prv_new.erl20
-rw-r--r--src/rebar_prv_packages.erl6
-rw-r--r--src/rebar_prv_path.erl22
-rw-r--r--src/rebar_prv_plugins.erl21
-rw-r--r--src/rebar_prv_plugins_upgrade.erl2
-rw-r--r--src/rebar_prv_report.erl14
-rw-r--r--src/rebar_prv_shell.erl5
-rw-r--r--src/rebar_prv_unlock.erl4
-rw-r--r--src/rebar_prv_update.erl10
-rw-r--r--src/rebar_prv_upgrade.erl60
-rw-r--r--src/rebar_prv_xref.erl62
-rw-r--r--src/rebar_relx.erl12
-rw-r--r--src/rebar_state.erl6
-rw-r--r--src/rebar_templater.erl29
-rw-r--r--src/rebar_utils.erl69
54 files changed, 883 insertions, 593 deletions
diff --git a/src/r3.erl b/src/r3.erl
index d0d6c47..bbf9eea 100644
--- a/src/r3.erl
+++ b/src/r3.erl
@@ -2,6 +2,7 @@
%%% calls from a shell.
-module(r3).
-export([do/1, do/2]).
+-export(['$handle_undefined_function'/2]).
%% @doc alias for `rebar_agent:do/1'
-spec do(atom()) -> ok | {error, term()}.
@@ -10,3 +11,7 @@ do(Command) -> rebar_agent:do(Command).
%% @doc alias for `rebar_agent:do/2'
-spec do(atom(), atom()) -> ok | {error, term()}.
do(Namespace, Command) -> rebar_agent:do(Namespace, Command).
+
+%% @private defer to rebar_agent
+'$handle_undefined_function'(Cmd, Args) ->
+ rebar_agent:'$handle_undefined_function'(Cmd, Args).
diff --git a/src/rebar3.erl b/src/rebar3.erl
index 56bf3e8..eec8968 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -176,18 +176,18 @@ init_config() ->
Verbosity = log_level(),
ok = rebar_log:init(command_line, Verbosity),
- Config = rebar_config:consult(),
+ Config = rebar_config:consult_root(),
Config1 = rebar_config:merge_locks(Config, rebar_config:consult_lock_file(?LOCK_FILE)),
%% If $HOME/.config/rebar3/rebar.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 ~s", [GlobalConfigFile]),
+ ?DEBUG("Load global config file ~ts", [GlobalConfigFile]),
try state_from_global_config(Config1, GlobalConfigFile)
catch
_:_ ->
- ?WARN("Global config ~s exists but can not be read. Ignoring global config values.", [GlobalConfigFile]),
+ ?WARN("Global config ~ts exists but can not be read. Ignoring global config values.", [GlobalConfigFile]),
rebar_state:new(Config1)
end;
false ->
@@ -270,7 +270,7 @@ log_level() ->
-spec version() -> ok.
version() ->
{ok, Vsn} = application:get_key(rebar, vsn),
- ?CONSOLE("rebar ~s on Erlang/OTP ~s Erts ~s",
+ ?CONSOLE("rebar ~ts on Erlang/OTP ~ts Erts ~ts",
[Vsn, erlang:system_info(otp_release), erlang:system_info(version)]).
%% @private set global flag based on getopt option boolean value
@@ -311,11 +311,11 @@ handle_error({error, {Module, Reason}}) ->
?DEBUG("Uncaught error: ~p ~p", [Module, Reason]),
?INFO("When submitting a bug report, please include the output of `rebar3 report \"your command\"`", []);
_ ->
- ?ERROR("~s", [Module:format_error(Reason)])
+ ?ERROR("~ts", [Module:format_error(Reason)])
end,
erlang:halt(1);
handle_error({error, Error}) when is_list(Error) ->
- ?ERROR("~s", [Error]),
+ ?ERROR("~ts", [Error]),
erlang:halt(1);
handle_error(Error) ->
%% Nothing should percolate up from rebar_core;
@@ -344,7 +344,7 @@ start_and_load_apps(Caller) ->
ensure_running(asn1, Caller),
ensure_running(public_key, Caller),
ensure_running(ssl, Caller),
- inets:start(),
+ ensure_running(inets, Caller),
inets:start(httpc, [{profile, rebar}]).
%% @doc Make sure a required app is running, or display an error message
diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl
index ed9e45d..b5dcfcf 100644
--- a/src/rebar_agent.erl
+++ b/src/rebar_agent.erl
@@ -2,6 +2,7 @@
%%% to statefully maintain loaded project state into a running VM.
-module(rebar_agent).
-export([start_link/1, do/1, do/2]).
+-export(['$handle_undefined_function'/2]).
-export([init/1,
handle_call/3, handle_cast/2, handle_info/2,
code_change/3, terminate/2]).
@@ -22,13 +23,24 @@ start_link(State) ->
%% @doc runs a given command in the agent's context.
-spec do(atom()) -> ok | {error, term()}.
do(Command) when is_atom(Command) ->
- gen_server:call(?MODULE, {cmd, Command}, infinity).
+ gen_server:call(?MODULE, {cmd, Command}, infinity);
+do(Args) when is_list(Args) ->
+ gen_server:call(?MODULE, {cmd, default, do, Args}, infinity).
%% @doc runs a given command in the agent's context, under a given
%% namespace.
-spec do(atom(), atom()) -> ok | {error, term()}.
do(Namespace, Command) when is_atom(Namespace), is_atom(Command) ->
- gen_server:call(?MODULE, {cmd, Namespace, Command}, infinity).
+ gen_server:call(?MODULE, {cmd, Namespace, Command}, infinity);
+do(Namespace, Args) when is_atom(Namespace), is_list(Args) ->
+ gen_server:call(?MODULE, {cmd, Namespace, do, Args}, infinity).
+
+'$handle_undefined_function'(Cmd, [Namespace, Args]) ->
+ gen_server:call(?MODULE, {cmd, Namespace, Cmd, Args}, infinity);
+'$handle_undefined_function'(Cmd, [Args]) ->
+ gen_server:call(?MODULE, {cmd, default, Cmd, Args}, infinity);
+'$handle_undefined_function'(Cmd, []) ->
+ gen_server:call(?MODULE, {cmd, default, Cmd}, infinity).
%%%%%%%%%%%%%%%%%
%%% CALLBACKS %%%
@@ -42,11 +54,15 @@ init(State) ->
%% @private
handle_call({cmd, Command}, _From, State=#state{state=RState, cwd=Cwd}) ->
MidState = maybe_show_warning(State),
- {Res, NewRState} = run(default, Command, RState, Cwd),
+ {Res, NewRState} = run(default, Command, "", RState, Cwd),
{reply, Res, MidState#state{state=NewRState}, hibernate};
handle_call({cmd, Namespace, Command}, _From, State = #state{state=RState, cwd=Cwd}) ->
MidState = maybe_show_warning(State),
- {Res, NewRState} = run(Namespace, Command, RState, Cwd),
+ {Res, NewRState} = run(Namespace, Command, "", RState, Cwd),
+ {reply, Res, MidState#state{state=NewRState}, hibernate};
+handle_call({cmd, Namespace, Command, Args}, _From, State = #state{state=RState, cwd=Cwd}) ->
+ MidState = maybe_show_warning(State),
+ {Res, NewRState} = run(Namespace, Command, Args, RState, Cwd),
{reply, Res, MidState#state{state=NewRState}, hibernate};
handle_call(_Call, _From, State) ->
{noreply, State}.
@@ -72,13 +88,14 @@ terminate(_Reason, _State) ->
%%%%%%%%%%%%%%%
%% @private runs the actual command and maintains the state changes
--spec run(atom(), atom(), rebar_state:t(), file:filename()) ->
+-spec run(atom(), atom(), string(), rebar_state:t(), file:filename()) ->
{ok, rebar_state:t()} | {{error, term()}, rebar_state:t()}.
-run(Namespace, Command, RState, Cwd) ->
+run(Namespace, Command, StrArgs, RState, Cwd) ->
try
case rebar_dir:get_cwd() of
Cwd ->
- Args = [atom_to_list(Namespace), atom_to_list(Command)],
+ PArgs = getopt:tokenize(StrArgs),
+ Args = [atom_to_list(Namespace), atom_to_list(Command)] ++ PArgs,
CmdState0 = refresh_state(RState, Cwd),
CmdState1 = rebar_state:set(CmdState0, task, atom_to_list(Command)),
CmdState = rebar_state:set(CmdState1, caller, api),
@@ -140,7 +157,7 @@ refresh_paths(RState) ->
{ok, Mods} ->
case {length(Mods), length(Mods -- Blacklist)} of
{X,X} ->
- ?DEBUG("reloading ~p from ~s", [Modules, Path]),
+ ?DEBUG("reloading ~p from ~ts", [Modules, Path]),
code:replace_path(App, Path),
reload_modules(Modules);
{_,_} ->
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index fd55960..cdd183c 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -7,8 +7,10 @@
find_unbuilt_apps/1,
find_apps/1,
find_apps/2,
+ find_apps/3,
find_app/2,
- find_app/3]).
+ find_app/3,
+ find_app/4]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
@@ -20,7 +22,9 @@
do(State, LibDirs) ->
BaseDir = rebar_state:dir(State),
Dirs = [filename:join(BaseDir, LibDir) || LibDir <- LibDirs],
- Apps = find_apps(Dirs, all),
+ RebarOpts = rebar_state:opts(State),
+ SrcDirs = rebar_dir:src_dirs(RebarOpts, ["src"]),
+ Apps = find_apps(Dirs, SrcDirs, all),
ProjectDeps = rebar_state:deps_names(State),
DepsDir = rebar_dir:deps_dir(State),
CurrentProfiles = rebar_state:current_profiles(State),
@@ -56,7 +60,7 @@ do(State, LibDirs) ->
rebar_state:project_apps(StateAcc1
,rebar_app_info:deps(AppInfo2, ProjectDeps1));
false ->
- ?INFO("Ignoring ~s", [Name]),
+ ?INFO("Ignoring ~ts", [Name]),
StateAcc
end
end, State1, SortedApps).
@@ -93,11 +97,11 @@ merge_deps(AppInfo, State) ->
%% the application they are defined at. If an umbrella structure is used and
%% they are deifned at the top level they will instead run in the context of
%% the State and at the top level, not as part of an application.
- Default = reset_hooks(rebar_state:default(State)),
+ CurrentProfiles = rebar_state:current_profiles(State),
+ Default = reset_hooks(rebar_state:default(State), CurrentProfiles),
{C, State1} = project_app_config(AppInfo, State),
AppInfo0 = rebar_app_info:update_opts(AppInfo, Default, C),
- CurrentProfiles = rebar_state:current_profiles(State1),
Name = rebar_app_info:name(AppInfo0),
%% We reset the opts here to default so no profiles are applied multiple times
@@ -167,44 +171,72 @@ project_app_config(AppInfo, State) ->
maybe_reset_hooks(Dir, Opts, State) ->
case ec_file:real_dir_path(rebar_dir:root_dir(State)) of
Dir ->
- reset_hooks(Opts);
+ CurrentProfiles = rebar_state:current_profiles(State),
+ reset_hooks(Opts, CurrentProfiles);
_ ->
Opts
end.
%% @doc make the hooks empty for a given set of options
--spec reset_hooks(Opts) -> Opts when Opts :: rebar_dict().
-reset_hooks(Opts) ->
- lists:foldl(fun(Key, OptsAcc) ->
- rebar_opts:set(OptsAcc, Key, [])
- end, Opts, [post_hooks, pre_hooks, provider_hooks, artifacts]).
-
-%% @doc find the directories for all apps
--spec all_app_dirs([file:name()]) -> [file:name()].
+-spec reset_hooks(Opts, Profiles) ->
+ Opts when
+ Opts :: rebar_dict(),
+ Profiles :: [atom()].
+reset_hooks(Opts, CurrentProfiles) ->
+ AllHooks = [post_hooks, pre_hooks, provider_hooks, artifacts],
+ Opts1 = lists:foldl(fun(Key, OptsAcc) ->
+ rebar_opts:set(OptsAcc, Key, [])
+ end, Opts, AllHooks),
+ Profiles = rebar_opts:get(Opts1, profiles, []),
+ Profiles1 = lists:map(fun({P, ProfileOpts}) ->
+ case lists:member(P, CurrentProfiles) of
+ true ->
+ {P, [X || X={Key, _} <- ProfileOpts,
+ not lists:member(Key, AllHooks)]};
+ false ->
+ {P, ProfileOpts}
+ end
+ end, Profiles),
+ rebar_opts:set(Opts1, profiles, Profiles1).
+
+%% @private find the directories for all apps, while detecting their source dirs
+%% Returns the app dir with the respective src_dirs for them, in that order,
+%% for every app found.
+-spec all_app_dirs([file:name()]) -> [{file:name(), [file:name()]}].
all_app_dirs(LibDirs) ->
lists:flatmap(fun(LibDir) ->
- app_dirs(LibDir)
+ SrcDirs = find_config_src(LibDir, ["src"]),
+ app_dirs(LibDir, SrcDirs)
end, LibDirs).
-%% @doc find the directories based on the library directories
--spec app_dirs([file:name()]) -> [file:name()].
-app_dirs(LibDir) ->
- Path1 = filename:join([LibDir,
- "src",
- "*.app.src"]),
-
- Path2 = filename:join([LibDir,
- "src",
- "*.app.src.script"]),
-
- Path3 = filename:join([LibDir,
- "ebin",
- "*.app"]),
+%% @private find the directories for all apps based on their source dirs
+%% Returns the app dir with the respective src_dirs for them, in that order,
+%% for every app found.
+-spec all_app_dirs([file:name()], [file:name()]) -> [{file:name(), [file:name()]}].
+all_app_dirs(LibDirs, SrcDirs) ->
+ lists:flatmap(fun(LibDir) -> app_dirs(LibDir, SrcDirs) end, LibDirs).
+
+%% @private find the directories based on the library directories.
+%% Returns the app dir with the respective src_dirs for them, in that order,
+%% for every app found.
+%%
+%% The function returns the src directories since they might have been
+%% detected in a top-level loop and we want to skip further detection
+%% starting now.
+-spec app_dirs([file:name()], [file:name()]) -> [{file:name(), [file:name()]}].
+app_dirs(LibDir, SrcDirs) ->
+ Paths = lists:append([
+ [filename:join([LibDir, SrcDir, "*.app.src"]),
+ filename:join([LibDir, SrcDir, "*.app.src.script"])]
+ || SrcDir <- SrcDirs
+ ]),
+ EbinPath = filename:join([LibDir, "ebin", "*.app"]),
lists:usort(lists:foldl(fun(Path, Acc) ->
- Files = filelib:wildcard(ec_cnv:to_list(Path)),
- [app_dir(File) || File <- Files] ++ Acc
- end, [], [Path1, Path2, Path3])).
+ Files = filelib:wildcard(rebar_utils:to_list(Path)),
+ [{app_dir(File), SrcDirs}
+ || File <- Files] ++ Acc
+ end, [], [EbinPath | Paths])).
%% @doc find all apps that haven't been built in a list of directories
-spec find_unbuilt_apps([file:filename_all()]) -> [rebar_app_info:t()].
@@ -222,16 +254,32 @@ find_apps(LibDirs) ->
%% app info records.
-spec find_apps([file:filename_all()], valid | invalid | all) -> [rebar_app_info:t()].
find_apps(LibDirs, Validate) ->
- rebar_utils:filtermap(fun(AppDir) ->
- find_app(AppDir, Validate)
- end, all_app_dirs(LibDirs)).
+ rebar_utils:filtermap(
+ fun({AppDir, AppSrcDirs}) ->
+ find_app(rebar_app_info:new(), AppDir, AppSrcDirs, Validate)
+ end,
+ all_app_dirs(LibDirs)
+ ).
+
+%% @doc for each directory passed, with the configured source directories,
+%% find all apps according to the validity rule passed in.
+%% Returns all the related app info records.
+-spec find_apps([file:filename_all()], [file:filename_all()], valid | invalid | all) -> [rebar_app_info:t()].
+find_apps(LibDirs, SrcDirs, Validate) ->
+ rebar_utils:filtermap(
+ fun({AppDir, AppSrcDirs}) ->
+ find_app(rebar_app_info:new(), AppDir, AppSrcDirs, Validate)
+ end,
+ all_app_dirs(LibDirs, SrcDirs)
+ ).
%% @doc check that a given app in a directory is there, and whether it's
%% valid or not based on the second argument. Returns the related
%% app info record.
-spec find_app(file:filename_all(), valid | invalid | all) -> {true, rebar_app_info:t()} | false.
find_app(AppDir, Validate) ->
- find_app(rebar_app_info:new(), AppDir, Validate).
+ SrcDirs = find_config_src(AppDir, ["src"]),
+ find_app(rebar_app_info:new(), AppDir, SrcDirs, Validate).
%% @doc check that a given app in a directory is there, and whether it's
%% valid or not based on the second argument. Returns the related
@@ -239,9 +287,29 @@ find_app(AppDir, Validate) ->
-spec find_app(rebar_app_info:t(), file:filename_all(), valid | invalid | all) ->
{true, rebar_app_info:t()} | false.
find_app(AppInfo, AppDir, Validate) ->
+ %% if no src dir is passed, figure it out from the app info, with a default
+ %% of src/
+ AppOpts = rebar_app_info:opts(AppInfo),
+ SrcDirs = rebar_dir:src_dirs(AppOpts, ["src"]),
+ find_app(AppInfo, AppDir, SrcDirs, Validate).
+
+%% @doc check that a given app in a directory is there, and whether it's
+%% valid or not based on the second argument. The third argument includes
+%% the directories where source files can be located. Returns the related
+%% app info record.
+-spec find_app(rebar_app_info:t(), file:filename_all(),
+ [file:filename_all()], valid | invalid | all) ->
+ {true, rebar_app_info:t()} | false.
+find_app(AppInfo, AppDir, SrcDirs, Validate) ->
AppFile = filelib:wildcard(filename:join([AppDir, "ebin", "*.app"])),
- AppSrcFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src"])),
- AppSrcScriptFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src.script"])),
+ AppSrcFile = lists:append(
+ [filelib:wildcard(filename:join([AppDir, SrcDir, "*.app.src"]))
+ || SrcDir <- SrcDirs]
+ ),
+ AppSrcScriptFile = lists:append(
+ [filelib:wildcard(filename:join([AppDir, SrcDir, "*.app.src.script"]))
+ || SrcDir <- SrcDirs]
+ ),
try_handle_app_file(AppInfo, AppFile, AppDir, AppSrcFile, AppSrcScriptFile, Validate).
%% @doc find the directory that an appfile has
@@ -318,7 +386,7 @@ try_handle_app_file(AppInfo0, [File], AppDir, AppSrcFile, _, Validate) ->
end
catch
throw:{error, {Module, Reason}} ->
- ?DEBUG("Falling back to app.src file because .app failed: ~s", [Module:format_error(Reason)]),
+ ?DEBUG("Falling back to app.src file because .app failed: ~ts", [Module:format_error(Reason)]),
try_handle_app_src_file(AppInfo0, File, AppDir, AppSrcFile, Validate)
end;
try_handle_app_file(_AppInfo, Other, _AppDir, _AppSrcFile, _, _Validate) ->
@@ -358,3 +426,15 @@ enable(State, AppInfo) ->
-spec to_atom(binary()) -> atom().
to_atom(Bin) ->
list_to_atom(binary_to_list(Bin)).
+
+%% @private when looking for unknown apps, it's possible they have a
+%% rebar.config file specifying non-standard src_dirs. Check for a
+%% possible config file and extract src_dirs from it.
+find_config_src(AppDir, Default) ->
+ case rebar_config:consult(AppDir) of
+ [] ->
+ Default;
+ Terms ->
+ %% TODO: handle profiles I guess, but we don't have that info
+ proplists:get_value(src_dirs, Terms, Default)
+ end.
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index fdaadb8..050ccc1 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -107,43 +107,43 @@ new() ->
-spec new(atom() | binary() | string()) ->
{ok, t()}.
new(AppName) ->
- {ok, #app_info_t{name=ec_cnv:to_binary(AppName)}}.
+ {ok, #app_info_t{name=rebar_utils:to_binary(AppName)}}.
%% @doc Build a new app info value with only the name and version set.
-spec new(atom() | binary() | string(), binary() | string()) ->
{ok, t()}.
new(AppName, Vsn) ->
- {ok, #app_info_t{name=ec_cnv:to_binary(AppName),
+ {ok, #app_info_t{name=rebar_utils:to_binary(AppName),
original_vsn=Vsn}}.
%% @doc build a complete version of the app info with all fields set.
-spec new(atom() | binary() | string(), binary() | string(), file:name()) ->
{ok, t()}.
new(AppName, Vsn, Dir) ->
- {ok, #app_info_t{name=ec_cnv:to_binary(AppName),
+ {ok, #app_info_t{name=rebar_utils:to_binary(AppName),
original_vsn=Vsn,
- dir=ec_cnv:to_list(Dir),
- out_dir=ec_cnv:to_list(Dir)}}.
+ dir=rebar_utils:to_list(Dir),
+ out_dir=rebar_utils:to_list(Dir)}}.
%% @doc build a complete version of the app info with all fields set.
-spec new(atom() | binary() | string(), binary() | string(), file:name(), list()) ->
{ok, t()}.
new(AppName, Vsn, Dir, Deps) ->
- {ok, #app_info_t{name=ec_cnv:to_binary(AppName),
+ {ok, #app_info_t{name=rebar_utils:to_binary(AppName),
original_vsn=Vsn,
- dir=ec_cnv:to_list(Dir),
- out_dir=ec_cnv:to_list(Dir),
+ dir=rebar_utils:to_list(Dir),
+ out_dir=rebar_utils:to_list(Dir),
deps=Deps}}.
%% @doc build a complete version of the app info with all fields set.
-spec new(atom() | binary(), atom() | binary() | string(), binary() | string(), file:name(), list()) ->
{ok, t()}.
new(Parent, AppName, Vsn, Dir, Deps) ->
- {ok, #app_info_t{name=ec_cnv:to_binary(AppName),
+ {ok, #app_info_t{name=rebar_utils:to_binary(AppName),
parent=Parent,
original_vsn=Vsn,
- dir=ec_cnv:to_list(Dir),
- out_dir=ec_cnv:to_list(Dir),
+ dir=rebar_utils:to_list(Dir),
+ out_dir=rebar_utils:to_list(Dir),
deps=Deps}}.
%% @doc update the opts based on the contents of a config
@@ -199,7 +199,7 @@ name(#app_info_t{name=Name}) ->
%% @doc set the name of the app.
-spec name(t(), atom() | binary() | string()) -> t().
name(AppInfo=#app_info_t{}, AppName) ->
- AppInfo#app_info_t{name=ec_cnv:to_binary(AppName)}.
+ AppInfo#app_info_t{name=rebar_utils:to_binary(AppName)}.
%% @doc get the dictionary of options for the app.
-spec opts(t()) -> rebar_dict().
@@ -248,16 +248,15 @@ set(AppInfo=#app_info_t{opts=Opts}, Key, Value) ->
%% @doc finds the .app.src file for an app, if any.
-spec app_file_src(t()) -> file:filename_all() | undefined.
-app_file_src(#app_info_t{app_file_src=undefined, dir=Dir, name=Name}) ->
- AppFileSrc = filename:join([ec_cnv:to_list(Dir), "src", ec_cnv:to_list(Name)++".app.src"]),
- case filelib:is_file(AppFileSrc) of
- true ->
- AppFileSrc;
- false ->
- undefined
+app_file_src(#app_info_t{app_file_src=undefined, dir=Dir, name=Name, opts=Opts}) ->
+ CandidatePaths = [filename:join([rebar_utils:to_list(Dir), Src, rebar_utils:to_list(Name)++".app.src"])
+ || Src <- rebar_opts:get(Opts, src_dirs, ["src"])],
+ case lists:dropwhile(fun(Path) -> not filelib:is_file(Path) end, CandidatePaths) of
+ [] -> undefined;
+ [AppFileSrc|_] -> AppFileSrc
end;
app_file_src(#app_info_t{app_file_src=AppFileSrc}) ->
- ec_cnv:to_list(AppFileSrc).
+ rebar_utils:to_list(AppFileSrc).
%% @doc sets the .app.src file for an app. An app without such a file
%% can explicitly be set with `undefined'.
@@ -265,12 +264,12 @@ app_file_src(#app_info_t{app_file_src=AppFileSrc}) ->
app_file_src(AppInfo=#app_info_t{}, undefined) ->
AppInfo#app_info_t{app_file_src=undefined};
app_file_src(AppInfo=#app_info_t{}, AppFileSrc) ->
- AppInfo#app_info_t{app_file_src=ec_cnv:to_list(AppFileSrc)}.
+ AppInfo#app_info_t{app_file_src=rebar_utils:to_list(AppFileSrc)}.
%% @doc finds the .app.src.script file for an app, if any.
-spec app_file_src_script(t()) -> file:filename_all() | undefined.
app_file_src_script(#app_info_t{app_file_src_script=undefined, dir=Dir, name=Name}) ->
- AppFileSrcScript = filename:join([ec_cnv:to_list(Dir), "src", ec_cnv:to_list(Name)++".app.src.script"]),
+ AppFileSrcScript = filename:join([rebar_utils:to_list(Dir), "src", rebar_utils:to_list(Name)++".app.src.script"]),
case filelib:is_file(AppFileSrcScript) of
true ->
AppFileSrcScript;
@@ -278,7 +277,7 @@ app_file_src_script(#app_info_t{app_file_src_script=undefined, dir=Dir, name=Nam
undefined
end;
app_file_src_script(#app_info_t{app_file_src_script=AppFileSrcScript}) ->
- ec_cnv:to_list(AppFileSrcScript).
+ rebar_utils:to_list(AppFileSrcScript).
%% @doc sets the .app.src.script file for an app. An app without such a file
%% can explicitly be set with `undefined'.
@@ -286,12 +285,12 @@ app_file_src_script(#app_info_t{app_file_src_script=AppFileSrcScript}) ->
app_file_src_script(AppInfo=#app_info_t{}, undefined) ->
AppInfo#app_info_t{app_file_src_script=undefined};
app_file_src_script(AppInfo=#app_info_t{}, AppFileSrcScript) ->
- AppInfo#app_info_t{app_file_src_script=ec_cnv:to_list(AppFileSrcScript)}.
+ AppInfo#app_info_t{app_file_src_script=rebar_utils:to_list(AppFileSrcScript)}.
%% @doc finds the .app file for an app, if any.
-spec app_file(t()) -> file:filename_all() | undefined.
app_file(#app_info_t{app_file=undefined, out_dir=Dir, name=Name}) ->
- AppFile = filename:join([ec_cnv:to_list(Dir), "ebin", ec_cnv:to_list(Name)++".app"]),
+ AppFile = filename:join([rebar_utils:to_list(Dir), "ebin", rebar_utils:to_list(Name)++".app"]),
case filelib:is_file(AppFile) of
true ->
AppFile;
@@ -318,7 +317,7 @@ app_details(AppInfo=#app_info_t{app_details=[]}) ->
rebar_file_utils:try_consult(AppFile)
catch
throw:{error, {Module, Reason}} ->
- ?DEBUG("Warning, falling back to .app.src because of: ~s",
+ ?DEBUG("Warning, falling back to .app.src because of: ~ts",
[Module:format_error(Reason)]),
rebar_file_utils:try_consult(app_file_src(AppInfo))
end
@@ -405,10 +404,10 @@ dir(#app_info_t{dir=Dir}) ->
%% @doc sets the directory that contains the app.
-spec dir(t(), file:name()) -> t().
dir(AppInfo=#app_info_t{out_dir=undefined}, Dir) ->
- AppInfo#app_info_t{dir=ec_cnv:to_list(Dir),
- out_dir=ec_cnv:to_list(Dir)};
+ AppInfo#app_info_t{dir=rebar_utils:to_list(Dir),
+ out_dir=rebar_utils:to_list(Dir)};
dir(AppInfo=#app_info_t{}, Dir) ->
- AppInfo#app_info_t{dir=ec_cnv:to_list(Dir)}.
+ AppInfo#app_info_t{dir=rebar_utils:to_list(Dir)}.
%% @doc returns the directory where build artifacts for the app
%% should go
@@ -420,17 +419,17 @@ out_dir(#app_info_t{out_dir=OutDir}) ->
%% should go
-spec out_dir(t(), file:name()) -> t().
out_dir(AppInfo=#app_info_t{}, OutDir) ->
- AppInfo#app_info_t{out_dir=ec_cnv:to_list(OutDir)}.
+ AppInfo#app_info_t{out_dir=rebar_utils:to_list(OutDir)}.
%% @doc gets the directory where ebin files for the app should go
-spec ebin_dir(t()) -> file:name().
ebin_dir(#app_info_t{out_dir=OutDir}) ->
- ec_cnv:to_list(filename:join(OutDir, "ebin")).
+ rebar_utils:to_list(filename:join(OutDir, "ebin")).
%% @doc gets the directory where private files for the app should go
-spec priv_dir(t()) -> file:name().
priv_dir(#app_info_t{out_dir=OutDir}) ->
- ec_cnv:to_list(filename:join(OutDir, "priv")).
+ rebar_utils:to_list(filename:join(OutDir, "priv")).
%% @doc returns whether the app is source app or a package app.
-spec resource_type(t()) -> pkg | src.
@@ -520,7 +519,7 @@ all(Dir, Context, [File|Artifacts]) ->
FilePath = filename:join(Dir, rebar_templater:render(File, Context)),
case filelib:is_regular(FilePath) of
false ->
- ?DEBUG("Missing artifact ~s", [FilePath]),
+ ?DEBUG("Missing artifact ~ts", [FilePath]),
{false, File};
true ->
all(Dir, Context, Artifacts)
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index 7154999..1d7ef5b 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -34,6 +34,7 @@
validate_application_info/2,
parse_deps/5,
parse_deps/6,
+ expand_deps_sources/2,
dep_to_app/7,
format_error/1]).
@@ -145,7 +146,7 @@ parse_dep(Dep, Parent, DepsDir, State, Locks, Level) ->
Dep ->
Dep
end,
- case lists:keyfind(ec_cnv:to_binary(Name), 1, Locks) of
+ case lists:keyfind(rebar_utils:to_binary(Name), 1, Locks) of
false ->
parse_dep(Parent, Dep, DepsDir, false, State);
LockedDep ->
@@ -167,18 +168,20 @@ parse_dep(Dep, Parent, DepsDir, State, Locks, Level) ->
IsLock :: boolean(),
State :: rebar_state:t().
parse_dep(Parent, {Name, Vsn, {pkg, PkgName}}, DepsDir, IsLock, State) ->
- {PkgName1, PkgVsn} = {ec_cnv:to_binary(PkgName), ec_cnv:to_binary(Vsn)},
+ {PkgName1, PkgVsn} = {rebar_utils:to_binary(PkgName),
+ rebar_utils:to_binary(Vsn)},
dep_to_app(Parent, DepsDir, Name, PkgVsn, {pkg, PkgName1, PkgVsn, undefined}, IsLock, State);
parse_dep(Parent, {Name, {pkg, PkgName}}, DepsDir, IsLock, State) ->
%% Package dependency with different package name from app name
- dep_to_app(Parent, DepsDir, Name, undefined, {pkg, ec_cnv:to_binary(PkgName), undefined, undefined}, IsLock, State);
+ dep_to_app(Parent, DepsDir, Name, undefined, {pkg, rebar_utils:to_binary(PkgName), undefined, undefined}, IsLock, State);
parse_dep(Parent, {Name, Vsn}, DepsDir, IsLock, State) when is_list(Vsn); is_binary(Vsn) ->
%% Versioned Package dependency
- {PkgName, PkgVsn} = {ec_cnv:to_binary(Name), ec_cnv:to_binary(Vsn)},
+ {PkgName, PkgVsn} = {rebar_utils:to_binary(Name),
+ rebar_utils:to_binary(Vsn)},
dep_to_app(Parent, DepsDir, PkgName, PkgVsn, {pkg, PkgName, PkgVsn, undefined}, IsLock, State);
parse_dep(Parent, Name, DepsDir, IsLock, State) when is_atom(Name); is_binary(Name) ->
%% Unversioned package dependency
- dep_to_app(Parent, DepsDir, ec_cnv:to_binary(Name), undefined, {pkg, ec_cnv:to_binary(Name), undefined, undefined}, IsLock, State);
+ dep_to_app(Parent, DepsDir, rebar_utils:to_binary(Name), undefined, {pkg, rebar_utils:to_binary(Name), undefined, undefined}, IsLock, State);
parse_dep(Parent, {Name, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->
dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
parse_dep(Parent, {Name, _Vsn, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->
@@ -212,12 +215,12 @@ parse_dep(_, Dep, _, _, _) ->
IsLock :: boolean(),
State :: rebar_state:t().
dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
- CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
+ CheckoutsDir = rebar_utils:to_list(rebar_dir:checkouts_dir(State, Name)),
AppInfo = case rebar_app_info:discover(CheckoutsDir) of
{ok, App} ->
rebar_app_info:source(rebar_app_info:is_checkout(App, true), checkout);
not_found ->
- Dir = ec_cnv:to_list(filename:join(DepsDir, Name)),
+ Dir = rebar_utils:to_list(filename:join(DepsDir, Name)),
{ok, AppInfo0} =
case rebar_app_info:discover(Dir) of
{ok, App} ->
@@ -225,7 +228,7 @@ dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
not_found ->
rebar_app_info:new(Parent, Name, Vsn, Dir, [])
end,
- update_source(AppInfo0, Source, State)
+ rebar_app_info:source(AppInfo0, Source)
end,
C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
AppInfo1 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C),
@@ -236,6 +239,13 @@ dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
AppInfo5 = rebar_app_info:profiles(AppInfo4, [default]),
rebar_app_info:is_lock(AppInfo5, IsLock).
+%% @doc Takes a given application app_info record along with the project.
+%% If the app is a package, resolve and expand the package definition.
+-spec expand_deps_sources(rebar_app_info:t(), rebar_state:t()) ->
+ rebar_app_info:t().
+expand_deps_sources(Dep, State) ->
+ update_source(Dep, rebar_app_info:source(Dep), State).
+
%% @doc sets the source for a given dependency or app along with metadata
%% around version if required.
-spec update_source(rebar_app_info:t(), Source, rebar_state:t()) ->
@@ -275,7 +285,7 @@ fetch_checksum(PkgName, PkgVsn, Hash, State) ->
rebar_packages:registry_checksum({pkg, PkgName, PkgVsn, Hash}, State)
catch
_:_ ->
- ?INFO("Package ~s-~s not found. Fetching registry updates and trying again...", [PkgName, PkgVsn]),
+ ?INFO("Package ~ts-~ts not found. Fetching registry updates and trying again...", [PkgName, PkgVsn]),
{ok, _} = rebar_prv_update:do(State),
rebar_packages:registry_checksum({pkg, PkgName, PkgVsn, Hash}, State)
end.
@@ -283,7 +293,7 @@ fetch_checksum(PkgName, PkgVsn, Hash, State) ->
%% @doc convert a given exception's payload into an io description.
-spec format_error(any()) -> iolist().
format_error({missing_package, Package}) ->
- io_lib:format("Package not found in registry: ~s", [Package]);
+ io_lib:format("Package not found in registry: ~ts", [Package]);
format_error({parse_dep, Dep}) ->
io_lib:format("Failed parsing dep ~p", [Dep]);
format_error(Error) ->
@@ -302,7 +312,7 @@ get_package(Dep, Vsn, State) ->
{ok, HighestDepVsn} ->
{Dep, HighestDepVsn};
none ->
- throw(?PRV_ERROR({missing_package, ec_cnv:to_binary(Dep)}))
+ throw(?PRV_ERROR({missing_package, rebar_utils:to_binary(Dep)}))
end.
%% @private checks that all the beam files have been properly
@@ -310,7 +320,7 @@ get_package(Dep, Vsn, State) ->
-spec has_all_beams(file:filename_all(), [module()]) ->
true | ?PRV_ERROR({missing_module, module()}).
has_all_beams(EbinDir, [Module | ModuleList]) ->
- BeamFile = filename:join([EbinDir, ec_cnv:to_list(Module) ++ ".beam"]),
+ BeamFile = filename:join([EbinDir, rebar_utils:to_list(Module) ++ ".beam"]),
case filelib:is_file(BeamFile) of
true ->
has_all_beams(EbinDir, ModuleList);
diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl
index 480e49c..3f273f1 100644
--- a/src/rebar_base_compiler.erl
+++ b/src/rebar_base_compiler.erl
@@ -199,15 +199,15 @@ compile_each([], _Config, _CompileFn) ->
compile_each([Source | Rest], Config, CompileFn) ->
case CompileFn(Source, Config) of
ok ->
- ?DEBUG("~sCompiled ~s", [rebar_utils:indent(1), filename:basename(Source)]);
+ ?DEBUG("~tsCompiled ~ts", [rebar_utils:indent(1), filename:basename(Source)]);
{ok, Warnings} ->
report(Warnings),
- ?DEBUG("~sCompiled ~s", [rebar_utils:indent(1), filename:basename(Source)]);
+ ?DEBUG("~tsCompiled ~ts", [rebar_utils:indent(1), filename:basename(Source)]);
skipped ->
- ?DEBUG("~sSkipped ~s", [rebar_utils:indent(1), filename:basename(Source)]);
+ ?DEBUG("~tsSkipped ~ts", [rebar_utils:indent(1), filename:basename(Source)]);
Error ->
NewSource = format_error_source(Source, Config),
- ?ERROR("Compiling ~s failed", [NewSource]),
+ ?ERROR("Compiling ~ts failed", [NewSource]),
maybe_report(Error),
?DEBUG("Compilation failed: ~p", [Error]),
?FAIL
@@ -258,7 +258,7 @@ maybe_report(_) ->
%% @private Outputs a bunch of strings, including a newline
-spec report([string()]) -> ok.
report(Messages) ->
- lists:foreach(fun(Msg) -> io:format("~s~n", [Msg]) end, Messages).
+ lists:foreach(fun(Msg) -> io:format("~ts~n", [Msg]) end, Messages).
%% private format compiler errors into proper outputtable strings
-spec format_errors(_, Extra, [err_or_warn()]) -> [string()] when
@@ -274,10 +274,10 @@ format_errors(_MainSource, Extra, Errors) ->
Extra :: string().
format_error(Source, Extra, {{Line, Column}, Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
- ?FMT("~s:~w:~w: ~s~s~n", [Source, Line, Column, Extra, ErrorDesc]);
+ ?FMT("~ts:~w:~w: ~ts~ts~n", [Source, Line, Column, Extra, ErrorDesc]);
format_error(Source, Extra, {Line, Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
- ?FMT("~s:~w: ~s~s~n", [Source, Line, Extra, ErrorDesc]);
+ ?FMT("~ts:~w: ~ts~ts~n", [Source, Line, Extra, ErrorDesc]);
format_error(Source, Extra, {Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
- ?FMT("~s: ~s~s~n", [Source, Extra, ErrorDesc]).
+ ?FMT("~ts: ~ts~ts~n", [Source, Extra, ErrorDesc]).
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index 97e27ab..7316d83 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -26,7 +26,7 @@
%% -------------------------------------------------------------------
-module(rebar_config).
--export([consult/0
+-export([consult_root/0
,consult/1
,consult_app_file/1
,consult_file/1
@@ -46,15 +46,15 @@
%% Public API
%% ===================================================================
-%% @doc reads the default config file.
--spec consult() -> [any()].
-consult() ->
+%% @doc reads the default config file at the top of a full project
+-spec consult_root() -> [any()].
+consult_root() ->
consult_file(config_file()).
%% @doc reads the default config file in a given directory.
-spec consult(file:name()) -> [any()].
consult(Dir) ->
- consult_file(filename:join(Dir, config_file())).
+ consult_file(filename:join(Dir, ?DEFAULT_CONFIG_FILE)).
%% @doc reads a given app file, including the `.script' variations,
%% if any can be found.
@@ -120,7 +120,7 @@ write_lock_file(LockFile, Locks) ->
file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks]));
_ ->
file:write_file(LockFile,
- io_lib:format("{~p,~n~p}.~n[~n~s~n].~n",
+ io_lib:format("{~p,~n~p}.~n[~n~ts~n].~n",
[?CONFIG_VERSION, NewLocks,
format_attrs(Attrs)]))
end.
@@ -359,7 +359,7 @@ check_newly_added_({Name, Source}, LockedDeps) ->
false
end;
check_newly_added_(Dep, LockedDeps) when is_atom(Dep) ->
- Name = ec_cnv:to_binary(Dep),
+ Name = rebar_utils:to_binary(Dep),
case lists:keyfind(Name, 1, LockedDeps) of
false ->
{true, Name};
@@ -368,8 +368,8 @@ check_newly_added_(Dep, LockedDeps) when is_atom(Dep) ->
0 ->
{true, Name};
_ ->
- ?WARN("Newly added dep ~s is locked at a lower level. "
- "If you really want to unlock it, use 'rebar3 upgrade ~s'",
+ ?WARN("Newly added dep ~ts is locked at a lower level. "
+ "If you really want to unlock it, use 'rebar3 upgrade ~ts'",
[Name, Name]),
false
end
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index 14c4906..3ef7a0d 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -119,11 +119,11 @@ process_command(State, Command) ->
State2 = rebar_state:command_parsed_args(State1, Args),
do(TargetProviders, State2);
{error, {invalid_option, Option}} ->
- {error, io_lib:format("Invalid option ~s on task ~p", [Option, Command])};
+ {error, io_lib:format("Invalid option ~ts on task ~p", [Option, Command])};
{error, {invalid_option_arg, {Option, Arg}}} ->
- {error, io_lib:format("Invalid argument ~s to option ~s", [Arg, Option])};
+ {error, io_lib:format("Invalid argument ~ts to option ~ts", [Arg, Option])};
{error, {missing_option_arg, Option}} ->
- {error, io_lib:format("Missing argument to option ~s", [Option])}
+ {error, io_lib:format("Missing argument to option ~ts", [Option])}
end
end
end.
@@ -173,6 +173,6 @@ do([ProviderName | Rest], State) ->
%% @doc convert a given exception's payload into an io description.
-spec format_error(any()) -> iolist().
format_error({bad_provider_namespace, {Namespace, Name}}) ->
- io_lib:format("Undefined command ~s in namespace ~s", [Name, Namespace]);
+ io_lib:format("Undefined command ~ts in namespace ~ts", [Name, Namespace]);
format_error({bad_provider_namespace, Name}) ->
- io_lib:format("Undefined command ~s", [Name]).
+ io_lib:format("Undefined command ~ts", [Name]).
diff --git a/src/rebar_dialyzer_format.erl b/src/rebar_dialyzer_format.erl
index 1d234c3..7cf4e63 100644
--- a/src/rebar_dialyzer_format.erl
+++ b/src/rebar_dialyzer_format.erl
@@ -31,7 +31,7 @@ format_warnings(Opts, Warnings) ->
format_warning_(_Opts, Warning = {_Tag, {File, Line}, Msg}, {File, Acc}) ->
try
String = message_to_string(Msg),
- {File, [lists:flatten(fmt("~!c~4w~!!: ~s", [Line, String])) | Acc]}
+ {File, [lists:flatten(fmt("~!c~4w~!!: ~ts", [Line, String])) | Acc]}
catch
Error:Reason ->
?DEBUG("Failed to pretty format warning: ~p:~p",
@@ -47,11 +47,11 @@ format_warning_(Opts, Warning = {_Tag, {SrcFile, Line}, Msg}, {_LastFile, Acc})
Dir = filename:dirname(File),
Root = filename:rootname(Base),
Ext = filename:extension(Base),
- Path = re:replace(Dir, "^.*/_build/", "_build/", [{return, list}]),
- Base1 = fmt("~!_c~s~!!~!__~s", [Root, Ext]),
- F = fmt("~!__~s", [filename:join(Path, Base1)]),
+ Path = re:replace(Dir, "^.*/_build/", "_build/", [{return, list}, unicode]),
+ Base1 = fmt("~!_c~ts~!!~!__~ts", [Root, Ext]),
+ F = fmt("~!__~ts", [filename:join(Path, Base1)]),
String = message_to_string(Msg),
- {SrcFile, [lists:flatten(fmt("~n~s~n~!c~4w~!!: ~s", [F, Line, String])) | Acc]}
+ {SrcFile, [lists:flatten(fmt("~n~ts~n~!c~4w~!!: ~ts", [F, Line, String])) | Acc]}
catch
Error:Reason ->
?DEBUG("Failed to pretty format warning: ~p:~p~n~p",
@@ -72,53 +72,53 @@ fmt(Fmt, Args) ->
%%----- Warnings for general discrepancies ----------------
message_to_string({apply, [Args, ArgNs, FailReason,
SigArgs, SigRet, Contract]}) ->
- fmt("~!^Fun application with arguments ~!!~s ",
+ fmt("~!^Fun application with arguments ~!!~ts ",
[bad_arg(ArgNs, Args)]) ++
call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet, Contract);
message_to_string({app_call, [M, F, Args, Culprit, ExpectedType, FoundType]}) ->
- fmt("~!^The call~!! ~s:~s~s ~!^requires that"
- "~!! ~s ~!^is of type ~!g~s~!^ not ~!r~s",
+ fmt("~!^The call~!! ~ts:~ts~ts ~!^requires that"
+ "~!! ~ts ~!^is of type ~!g~ts~!^ not ~!r~ts",
[M, F, Args, Culprit, ExpectedType, FoundType]);
message_to_string({bin_construction, [Culprit, Size, Seg, Type]}) ->
- fmt("~!^Binary construction will fail since the ~!b~s~!^ field~!!"
- " ~s~!^ in segment~!! ~s~!^ has type~!! ~s",
+ fmt("~!^Binary construction will fail since the ~!b~ts~!^ field~!!"
+ " ~ts~!^ in segment~!! ~ts~!^ has type~!! ~ts",
[Culprit, Size, Seg, Type]);
message_to_string({call, [M, F, Args, ArgNs, FailReason,
SigArgs, SigRet, Contract]}) ->
- fmt("~!^The call~!! ~w:~w~s ", [M, F, bad_arg(ArgNs, Args)]) ++
+ fmt("~!^The call~!! ~w:~w~ts ", [M, F, bad_arg(ArgNs, Args)]) ++
call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet, Contract);
message_to_string({call_to_missing, [M, F, A]}) ->
fmt("~!^Call to missing or unexported function ~!!~w:~w/~w",
[M, F, A]);
message_to_string({exact_eq, [Type1, Op, Type2]}) ->
- fmt("~!^The test ~!!~s ~s ~s~!^ can never evaluate to 'true'",
+ fmt("~!^The test ~!!~ts ~ts ~ts~!^ can never evaluate to 'true'",
[Type1, Op, Type2]);
message_to_string({fun_app_args, [Args, Type]}) ->
- fmt("~!^Fun application with arguments ~!!~s~!^ will fail"
- " since the function has type ~!!~s", [Args, Type]);
+ fmt("~!^Fun application with arguments ~!!~ts~!^ will fail"
+ " since the function has type ~!!~ts", [Args, Type]);
message_to_string({fun_app_no_fun, [Op, Type, Arity]}) ->
- fmt("~!^Fun application will fail since ~!!~s ~!^::~!! ~s"
+ fmt("~!^Fun application will fail since ~!!~ts ~!^::~!! ~ts"
" is not a function of arity ~!!~w", [Op, Type, Arity]);
message_to_string({guard_fail, []}) ->
"~!^Clause guard cannot succeed.~!!";
message_to_string({guard_fail, [Arg1, Infix, Arg2]}) ->
- fmt("~!^Guard test ~!!~s ~s ~s~!^ can never succeed",
+ fmt("~!^Guard test ~!!~ts ~ts ~ts~!^ can never succeed",
[Arg1, Infix, Arg2]);
message_to_string({neg_guard_fail, [Arg1, Infix, Arg2]}) ->
- fmt("~!^Guard test not(~!!~s ~s ~s~!^) can never succeed",
+ fmt("~!^Guard test not(~!!~ts ~ts ~ts~!^) can never succeed",
[Arg1, Infix, Arg2]);
message_to_string({guard_fail, [Guard, Args]}) ->
- fmt("~!^Guard test ~!!~w~s~!^ can never succeed",
+ fmt("~!^Guard test ~!!~w~ts~!^ can never succeed",
[Guard, Args]);
message_to_string({neg_guard_fail, [Guard, Args]}) ->
- fmt("~!^Guard test not(~!!~w~s~!^) can never succeed",
+ fmt("~!^Guard test not(~!!~w~ts~!^) can never succeed",
[Guard, Args]);
message_to_string({guard_fail_pat, [Pat, Type]}) ->
- fmt("~!^Clause guard cannot succeed. The ~!!~s~!^ was matched"
- " against the type ~!!~s", [Pat, Type]);
+ fmt("~!^Clause guard cannot succeed. The ~!!~ts~!^ was matched"
+ " against the type ~!!~ts", [Pat, Type]);
message_to_string({improper_list_constr, [TlType]}) ->
fmt("~!^Cons will produce an improper list"
- " since its ~!b2~!!nd~!^ argument is~!! ~s", [TlType]);
+ " since its ~!b2~!!nd~!^ argument is~!! ~ts", [TlType]);
message_to_string({no_return, [Type|Name]}) ->
NameString =
case Name of
@@ -126,59 +126,59 @@ message_to_string({no_return, [Type|Name]}) ->
[F, A] -> fmt("~!^Function ~!r~w/~w ", [F, A])
end,
case Type of
- no_match -> fmt("~s~!^has no clauses that will ever match",[NameString]);
- only_explicit -> fmt("~s~!^only terminates with explicit exception", [NameString]);
- only_normal -> fmt("~s~!^has no local return", [NameString]);
- both -> fmt("~s~!^has no local return", [NameString])
+ no_match -> fmt("~ts~!^has no clauses that will ever match",[NameString]);
+ only_explicit -> fmt("~ts~!^only terminates with explicit exception", [NameString]);
+ only_normal -> fmt("~ts~!^has no local return", [NameString]);
+ both -> fmt("~ts~!^has no local return", [NameString])
end;
message_to_string({record_constr, [RecConstr, FieldDiffs]}) ->
- fmt("~!^Record construction ~!!~s~!^ violates the"
- " declared type of field ~!!~s", [RecConstr, FieldDiffs]);
+ fmt("~!^Record construction ~!!~ts~!^ violates the"
+ " declared type of field ~!!~ts", [RecConstr, FieldDiffs]);
message_to_string({record_constr, [Name, Field, Type]}) ->
fmt("~!^Record construction violates the declared type for ~!!#~w{}~!^"
- " since ~!!~s~!^ cannot be of type ~!!~s",
+ " since ~!!~ts~!^ cannot be of type ~!!~ts",
[Name, Field, Type]);
message_to_string({record_matching, [String, Name]}) ->
- fmt("~!^The ~!!~s~!^ violates the"
+ fmt("~!^The ~!!~ts~!^ violates the"
" declared type for ~!!#~w{}", [String, Name]);
message_to_string({record_match, [Pat, Type]}) ->
- fmt("~!^Matching of ~!!~s~!^ tagged with a record name violates the"
- " declared type of ~!!~s", [Pat, Type]);
+ fmt("~!^Matching of ~!!~ts~!^ tagged with a record name violates the"
+ " declared type of ~!!~ts", [Pat, Type]);
message_to_string({pattern_match, [Pat, Type]}) ->
- fmt("~!^The ~s~!^ can never match the type ~!g~s",
+ fmt("~!^The ~ts~!^ can never match the type ~!g~ts",
[bad_pat(Pat), Type]);
message_to_string({pattern_match_cov, [Pat, Type]}) ->
- fmt("~!^The ~s~!^ can never match since previous"
- " clauses completely covered the type ~!g~s",
+ fmt("~!^The ~ts~!^ can never match since previous"
+ " clauses completely covered the type ~!g~ts",
[bad_pat(Pat), Type]);
message_to_string({unmatched_return, [Type]}) ->
- fmt("~!^Expression produces a value of type ~!!~s~!^,"
+ fmt("~!^Expression produces a value of type ~!!~ts~!^,"
" but this value is unmatched", [Type]);
message_to_string({unused_fun, [F, A]}) ->
fmt("~!^Function ~!r~w/~w~!!~!^ will never be called", [F, A]);
%%----- Warnings for specs and contracts -------------------
message_to_string({contract_diff, [M, F, _A, Contract, Sig]}) ->
- fmt("~!^Type specification ~!!~w:~w~s~!^"
- " is not equal to the success typing: ~!!~w:~w~s",
+ fmt("~!^Type specification ~!!~w:~w~ts~!^"
+ " is not equal to the success typing: ~!!~w:~w~ts",
[M, F, Contract, M, F, Sig]);
message_to_string({contract_subtype, [M, F, _A, Contract, Sig]}) ->
- fmt("~!^Type specification ~!!~w:~w~s~!^"
- " is a subtype of the success typing: ~!!~w:~w~s",
+ fmt("~!^Type specification ~!!~w:~w~ts~!^"
+ " is a subtype of the success typing: ~!!~w:~w~ts",
[M, F, Contract, M, F, Sig]);
message_to_string({contract_supertype, [M, F, _A, Contract, Sig]}) ->
- fmt("~!^Type specification ~!!~w:~w~s~!^"
- " is a supertype of the success typing: ~!!~w:~w~s",
+ fmt("~!^Type specification ~!!~w:~w~ts~!^"
+ " is a supertype of the success typing: ~!!~w:~w~ts",
[M, F, Contract, M, F, Sig]);
message_to_string({contract_range, [Contract, M, F, ArgStrings, Line, CRet]}) ->
- fmt("~!^The contract ~!!~w:~w~s~!^ cannot be right because the"
- " inferred return for ~!!~w~s~!^ on line ~!!~w~!^ is ~!!~s",
+ fmt("~!^The contract ~!!~w:~w~ts~!^ cannot be right because the"
+ " inferred return for ~!!~w~ts~!^ on line ~!!~w~!^ is ~!!~ts",
[M, F, Contract, F, ArgStrings, Line, CRet]);
message_to_string({invalid_contract, [M, F, A, Sig]}) ->
fmt("~!^Invalid type specification for function~!! ~w:~w/~w."
- "~!^ The success typing is~!! ~s", [M, F, A, Sig]);
+ "~!^ The success typing is~!! ~ts", [M, F, A, Sig]);
message_to_string({extra_range, [M, F, A, ExtraRanges, SigRange]}) ->
fmt("~!^The specification for ~!!~w:~w/~w~!^ states that the function"
- " might also return ~!!~s~!^ but the inferred return is ~!!~s",
+ " might also return ~!!~ts~!^ but the inferred return is ~!!~ts",
[M, F, A, ExtraRanges, SigRange]);
message_to_string({overlapping_contract, [M, F, A]}) ->
fmt("~!^Overloaded contract for ~!!~w:~w/~w~!^ has overlapping"
@@ -189,62 +189,62 @@ message_to_string({spec_missing_fun, [M, F, A]}) ->
[M, F, A]);
%%----- Warnings for opaque type violations -------------------
message_to_string({call_with_opaque, [M, F, Args, ArgNs, ExpArgs]}) ->
- fmt("~!^The call ~!!~w:~w~s~!^ contains ~!!~s~!^ when ~!!~s",
+ fmt("~!^The call ~!!~w:~w~ts~!^ contains ~!!~ts~!^ when ~!!~ts",
[M, F, bad_arg(ArgNs, Args), form_positions(ArgNs), form_expected(ExpArgs)]);
message_to_string({call_without_opaque, [M, F, Args, [{N,_,_}|_] = ExpectedTriples]}) ->
- fmt("~!^The call ~!!~w:~w~s ~!^does not have~!! ~s",
+ fmt("~!^The call ~!!~w:~w~ts ~!^does not have~!! ~ts",
[M, F, bad_arg(N, Args), form_expected_without_opaque(ExpectedTriples)]);
message_to_string({opaque_eq, [Type, _Op, OpaqueType]}) ->
- fmt("~!^Attempt to test for equality between a term of type ~!!~s~!^"
- " and a term of opaque type ~!!~s", [Type, OpaqueType]);
+ fmt("~!^Attempt to test for equality between a term of type ~!!~ts~!^"
+ " and a term of opaque type ~!!~ts", [Type, OpaqueType]);
message_to_string({opaque_guard, [Arg1, Infix, Arg2, ArgNs]}) ->
- fmt("~!^Guard test ~!!~s ~s ~s~!^ contains ~!!~s",
+ fmt("~!^Guard test ~!!~ts ~ts ~ts~!^ contains ~!!~ts",
[Arg1, Infix, Arg2, form_positions(ArgNs)]);
message_to_string({opaque_guard, [Guard, Args]}) ->
- fmt("~!^Guard test ~!!~w~s~!^ breaks the opaqueness of its"
+ fmt("~!^Guard test ~!!~w~ts~!^ breaks the opaqueness of its"
" argument", [Guard, Args]);
message_to_string({opaque_match, [Pat, OpaqueType, OpaqueTerm]}) ->
Term = if OpaqueType =:= OpaqueTerm -> "the term";
true -> OpaqueTerm
end,
- fmt("~!^The attempt to match a term of type ~!!~s~!^ against the"
- "~!! ~s~!^ breaks the opaqueness of ~!!~s",
+ fmt("~!^The attempt to match a term of type ~!!~ts~!^ against the"
+ "~!! ~ts~!^ breaks the opaqueness of ~!!~ts",
[OpaqueType, Pat, Term]);
message_to_string({opaque_neq, [Type, _Op, OpaqueType]}) ->
- fmt("~!^Attempt to test for inequality between a term of type ~!!~s"
- "~!^ and a term of opaque type ~!!~s", [Type, OpaqueType]);
+ fmt("~!^Attempt to test for inequality between a term of type ~!!~ts"
+ "~!^ and a term of opaque type ~!!~ts", [Type, OpaqueType]);
message_to_string({opaque_type_test, [Fun, Args, Arg, ArgType]}) ->
- fmt("~!^The type test ~!!~s~s~!^ breaks the opaqueness of the term "
- "~!!~s~s", [Fun, Args, Arg, ArgType]);
+ fmt("~!^The type test ~!!~ts~ts~!^ breaks the opaqueness of the term "
+ "~!!~ts~ts", [Fun, Args, Arg, ArgType]);
message_to_string({opaque_size, [SizeType, Size]}) ->
- fmt("~!^The size ~!!~s~!^ breaks the opaqueness of ~!!~s",
+ fmt("~!^The size ~!!~ts~!^ breaks the opaqueness of ~!!~ts",
[SizeType, Size]);
message_to_string({opaque_call, [M, F, Args, Culprit, OpaqueType]}) ->
- fmt("~!^The call ~!!~s:~s~s~!^ breaks the opaqueness of the term~!!"
- " ~s :: ~s", [M, F, Args, Culprit, OpaqueType]);
+ fmt("~!^The call ~!!~ts:~ts~ts~!^ breaks the opaqueness of the term~!!"
+ " ~ts :: ~ts", [M, F, Args, Culprit, OpaqueType]);
%%----- Warnings for concurrency errors --------------------
message_to_string({race_condition, [M, F, Args, Reason]}) ->
- fmt("~!^The call ~!!~w:~w~s ~s", [M, F, Args, Reason]);
+ fmt("~!^The call ~!!~w:~w~ts ~ts", [M, F, Args, Reason]);
%%----- Warnings for behaviour errors --------------------
message_to_string({callback_type_mismatch, [B, F, A, ST, CT]}) ->
- fmt("~!^The inferred return type of~!! ~w/~w (~s) ~!^"
- "has nothing in common with~!! ~s, ~!^which is the expected"
+ fmt("~!^The inferred return type of~!! ~w/~w (~ts) ~!^"
+ "has nothing in common with~!! ~ts, ~!^which is the expected"
" return type for the callback of~!! ~w ~!^behaviour",
[F, A, ST, CT, B]);
message_to_string({callback_arg_type_mismatch, [B, F, A, N, ST, CT]}) ->
- fmt("~!^The inferred type for the~!! ~s ~!^argument of~!!"
- " ~w/~w (~s) ~!^is not a supertype of~!! ~s~!^, which is"
+ fmt("~!^The inferred type for the~!! ~ts ~!^argument of~!!"
+ " ~w/~w (~ts) ~!^is not a supertype of~!! ~ts~!^, which is"
"expected type for this argument in the callback of the~!! ~w "
"~!^behaviour",
[ordinal(N), F, A, ST, CT, B]);
message_to_string({callback_spec_type_mismatch, [B, F, A, ST, CT]}) ->
- fmt("~!^The return type ~!!~s~!^ in the specification of ~!!"
- "~w/~w~!^ is not a subtype of ~!!~s~!^, which is the expected"
+ fmt("~!^The return type ~!!~ts~!^ in the specification of ~!!"
+ "~w/~w~!^ is not a subtype of ~!!~ts~!^, which is the expected"
" return type for the callback of ~!!~w~!^ behaviour",
[ST, F, A, CT, B]);
message_to_string({callback_spec_arg_type_mismatch, [B, F, A, N, ST, CT]}) ->
- fmt("~!^The specified type for the ~!!~s~!^ argument of ~!!"
- "~w/~w (~s)~!^ is not a supertype of ~!!~s~!^, which is"
+ fmt("~!^The specified type for the ~!!~ts~!^ argument of ~!!"
+ "~w/~w (~ts)~!^ is not a supertype of ~!!~ts~!^, which is"
" expected type for this argument in the callback of the ~!!~w"
"~!^ behaviour", [ordinal(N), F, A, ST, CT, B]);
message_to_string({callback_missing, [B, F, A]}) ->
@@ -274,26 +274,26 @@ call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet,
true ->
%% We do not know which argument(s) caused the failure
fmt("~!^will never return since the success typing arguments"
- " are ~!!~s", [SigArgs]);
+ " are ~!!~ts", [SigArgs]);
false ->
fmt("~!^will never return since it differs in the~!!"
- " ~s ~!^argument from the success typing"
- " arguments:~!! ~s",
+ " ~ts ~!^argument from the success typing"
+ " arguments:~!! ~ts",
[PositionString, good_arg(ArgNs, SigArgs)])
end;
only_contract ->
case (ArgNs =:= []) orelse IsOverloaded of
true ->
%% We do not know which arguments caused the failure
- fmt("~!^breaks the contract~!! ~s", [good_arg(ArgNs, Contract)]);
+ fmt("~!^breaks the contract~!! ~ts", [good_arg(ArgNs, Contract)]);
false ->
- fmt("~!^breaks the contract~!! ~s ~!^in the~!!"
- " ~s ~!^argument",
+ fmt("~!^breaks the contract~!! ~ts ~!^in the~!!"
+ " ~ts ~!^argument",
[good_arg(ArgNs, Contract), PositionString])
end;
both ->
fmt("~!^will never return since the success typing is "
- "~!!~s ~!^->~!! ~s ~!^and the contract is ~!!~s",
+ "~!!~ts ~!^->~!! ~ts ~!^and the contract is ~!!~ts",
[good_arg(ArgNs, SigArgs), SigRet,
good_arg(ArgNs, Contract)])
end.
@@ -301,8 +301,8 @@ call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet,
form_positions(ArgNs) ->
ArgS = form_position_string(ArgNs),
case ArgNs of
- [_] -> fmt("~!^an opaque term as ~!!~s~!^ argument", [ArgS]);
- [_,_|_] -> fmt("~!^opaque terms as ~!!~s~!^ arguments", [ArgS])
+ [_] -> fmt("~!^an opaque term as ~!!~ts~!^ argument", [ArgS]);
+ [_,_|_] -> fmt("~!^opaque terms as ~!!~ts~!^ arguments", [ArgS])
end.
%% We know which positions N are to blame;
@@ -310,9 +310,9 @@ form_positions(ArgNs) ->
form_expected_without_opaque([{N, T, TStr}]) ->
FStr = case erl_types:t_is_opaque(T) of
true ->
- "~!^an opaque term of type~!g ~s ~!^as ";
+ "~!^an opaque term of type~!g ~ts ~!^as ";
false ->
- "~!^a term of type ~!g~s ~!^(with opaque subterms) as "
+ "~!^a term of type ~!g~ts ~!^(with opaque subterms) as "
end ++ form_position_string([N]) ++ "~!^ argument",
fmt(FStr, [TStr]);
@@ -325,9 +325,9 @@ form_expected(ExpectedArgs) ->
[T] ->
TS = erl_types:t_to_string(T),
case erl_types:t_is_opaque(T) of
- true -> fmt("~!^an opaque term of type ~!!~s~!^ is"
+ true -> fmt("~!^an opaque term of type ~!!~ts~!^ is"
" expected", [TS]);
- false -> fmt("~!^a structured term of type ~!!~s~!^ is"
+ false -> fmt("~!^a structured term of type ~!!~ts~!^ is"
" expected", [TS])
end;
[_,_|_] -> fmt("~!^terms of different types are expected in these"
@@ -340,7 +340,7 @@ form_position_string(ArgNs) ->
[N1] -> ordinal(N1);
[_,_|_] ->
[Last|Prevs] = lists:reverse(ArgNs),
- ", " ++ Head = lists:flatten([fmt(", ~s",[ordinal(N)]) ||
+ ", " ++ Head = lists:flatten([fmt(", ~ts",[ordinal(N)]) ||
N <- lists:reverse(Prevs)]),
Head ++ " and " ++ ordinal(Last)
end.
@@ -352,11 +352,11 @@ ordinal(N) when is_integer(N) -> fmt("~!B~w~!!th", [N]).
%% Format a pattern ad highlight errorous part in red.
bad_pat("pattern " ++ P) ->
- fmt("pattern ~!r~s",[P]);
+ fmt("pattern ~!r~ts",[P]);
bad_pat("variable " ++ P) ->
- fmt("variable ~!r~s",[P]);
+ fmt("variable ~!r~ts",[P]);
bad_pat(P) ->
- fmt("~!r~s",[P]).
+ fmt("~!r~ts",[P]).
bad_arg(N, Args) ->
@@ -370,7 +370,7 @@ good_arg(N, Args) ->
colour_arg(N, C, Args) when is_integer(N) ->
colour_arg([N], C, Args);
colour_arg(Ns, C, Args) ->
- {Args1, Rest} =seperate_args(Args),
+ {Args1, Rest} =separate_args(Args),
Args2 = highlight(Ns, 1, C, Args1),
join_args(Args2) ++ Rest.
@@ -378,53 +378,53 @@ highlight([], _N, _C, Rest) ->
Rest;
highlight([N | Nr], N, g, [Arg | Rest]) ->
- [fmt("~!g~s", [Arg]) | highlight(Nr, N+1, g, Rest)];
+ [fmt("~!g~ts", [Arg]) | highlight(Nr, N+1, g, Rest)];
highlight([N | Nr], N, r, [Arg | Rest]) ->
- [fmt("~!r~s", [Arg]) | highlight(Nr, N+1, r, Rest)];
+ [fmt("~!r~ts", [Arg]) | highlight(Nr, N+1, r, Rest)];
highlight(Ns, N, C, [Arg | Rest]) ->
[Arg | highlight(Ns, N + 1, C, Rest)].
%% Arugments to functions and constraints are passed as
%% strings not as data, this function pulls them apart
-%% to allow interacting with them seperately and not
+%% to allow interacting with them separately and not
%% as one bug chunk of data.
-seperate_args([$( | S]) ->
- seperate_args([], S, "", []).
+separate_args([$( | S]) ->
+ separate_args([], S, "", []).
%% We strip this space since dialyzer is inconsistant in adding or not adding
%% it ....
-seperate_args([], [$,, $\s | R], Arg, Args) ->
- seperate_args([], R, [], [lists:reverse(Arg) | Args]);
+separate_args([], [$,, $\s | R], Arg, Args) ->
+ separate_args([], R, [], [lists:reverse(Arg) | Args]);
-seperate_args([], [$, | R], Arg, Args) ->
- seperate_args([], R, [], [lists:reverse(Arg) | Args]);
+separate_args([], [$, | R], Arg, Args) ->
+ separate_args([], R, [], [lists:reverse(Arg) | Args]);
-seperate_args([], [$) | Rest], Arg, Args) ->
+separate_args([], [$) | Rest], Arg, Args) ->
{lists:reverse([lists:reverse(Arg) | Args]), Rest};
-seperate_args([C | D], [C | R], Arg, Args) ->
- seperate_args(D, R, [C | Arg], Args);
+separate_args([C | D], [C | R], Arg, Args) ->
+ separate_args(D, R, [C | Arg], Args);
%% Brackets
-seperate_args(D, [${ | R], Arg, Args) ->
- seperate_args([$}|D], R, [${ | Arg], Args);
+separate_args(D, [${ | R], Arg, Args) ->
+ separate_args([$}|D], R, [${ | Arg], Args);
-seperate_args(D, [$( | R], Arg, Args) ->
- seperate_args([$)|D], R, [$( | Arg], Args);
+separate_args(D, [$( | R], Arg, Args) ->
+ separate_args([$)|D], R, [$( | Arg], Args);
-seperate_args(D, [$[ | R], Arg, Args) ->
- seperate_args([$]|D], R, [$[ | Arg], Args);
+separate_args(D, [$[ | R], Arg, Args) ->
+ separate_args([$]|D], R, [$[ | Arg], Args);
-seperate_args(D, [$< | R], Arg, Args) ->
- seperate_args([$>|D], R, [$< | Arg], Args);
+separate_args(D, [$< | R], Arg, Args) ->
+ separate_args([$>|D], R, [$< | Arg], Args);
%% 'strings'
-seperate_args(D, [$' | R], Arg, Args) ->
- seperate_args([$'|D], R, [$' | Arg], Args);
-seperate_args(D, [$" | R], Arg, Args) ->
- seperate_args([$"|D], R, [$" | Arg], Args);
+separate_args(D, [$' | R], Arg, Args) ->
+ separate_args([$'|D], R, [$' | Arg], Args);
+separate_args(D, [$" | R], Arg, Args) ->
+ separate_args([$"|D], R, [$" | Arg], Args);
-seperate_args(D, [C | R], Arg, Args) ->
- seperate_args(D, R, [C | Arg], Args).
+separate_args(D, [C | R], Arg, Args) ->
+ separate_args(D, R, [C | Arg], Args).
join_args(Args) ->
[$(, string:join(Args, ", "), $)].
diff --git a/src/rebar_digraph.erl b/src/rebar_digraph.erl
index a827735..776d7b8 100644
--- a/src/rebar_digraph.erl
+++ b/src/rebar_digraph.erl
@@ -53,9 +53,9 @@ add(Graph, {PkgName, Deps}) ->
lists:foreach(fun(DepName) ->
Name1 = case DepName of
{Name, _Vsn} ->
- ec_cnv:to_binary(Name);
+ rebar_utils:to_binary(Name);
Name ->
- ec_cnv:to_binary(Name)
+ rebar_utils:to_binary(Name)
end,
V3 = case digraph:vertex(Graph, Name1) of
false ->
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index b61bfcc..d0c7805 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -41,7 +41,7 @@ base_dir(State) ->
%% of profiles.
-spec profile_dir(rebar_dict(), [atom()]) -> file:filename_all().
profile_dir(Opts, Profiles) ->
- {BaseDir, ProfilesStrings} = case [ec_cnv:to_list(P) || P <- Profiles] of
+ {BaseDir, ProfilesStrings} = case [rebar_utils:to_list(P) || P <- Profiles] of
["global" | _] -> {?MODULE:global_cache_dir(Opts), [""]};
["bootstrap", "default"] -> {rebar_opts:get(Opts, base_dir, ?DEFAULT_BASE_DIR), ["default"]};
["default"] -> {rebar_opts:get(Opts, base_dir, ?DEFAULT_BASE_DIR), ["default"]};
@@ -363,7 +363,7 @@ warn_source_format_once(Format) ->
ok;
true ->
?WARN("Invalid argument ~p for compiler_source_format - "
- "assuming ~s~n", [Format, ?DEFAULT_COMPILER_SOURCE_FORMAT])
+ "assuming ~ts~n", [Format, ?DEFAULT_COMPILER_SOURCE_FORMAT])
end.
%% @private takes a filename and canonicalizes its path if it is a link.
diff --git a/src/rebar_dist_utils.erl b/src/rebar_dist_utils.erl
index 93edf9d..5de858e 100644
--- a/src/rebar_dist_utils.erl
+++ b/src/rebar_dist_utils.erl
@@ -51,14 +51,27 @@ find_options(State) ->
%%% PRIVATE %%%
%%%%%%%%%%%%%%%
start(Name, Type, Opts) ->
- check_epmd(net_kernel:start([Name, Type])),
+ case dist_up(net_kernel:start([Name, Type])) of
+ false ->
+ start_epmd(),
+ dist_up(net_kernel:start([Name, Type])) orelse warn_dist();
+ true ->
+ ok
+ end,
setup_cookie(Opts).
-check_epmd({error,{{shutdown, {_,net_kernel,{'EXIT',nodistribution}}},_}}) ->
- ?ERROR("Erlang Distribution failed, falling back to nonode@nohost. "
- "Verify that epmd is running and try again.",[]);
-check_epmd(_) ->
- ok.
+dist_up({error,{{shutdown,{_,net_kernel,{'EXIT',nodistribution}}},_}}) -> false;
+dist_up(_) -> true.
+
+start_epmd() ->
+ %% Indirectly boot EPMD through calling Erlang so that we don't risk
+ %% attaching it to the current proc
+ ?CONSOLE("Attempting to start epmd...", []),
+ os:cmd("erl -sname a -eval 'halt(0).'").
+
+warn_dist() ->
+ ?ERROR("Erlang Distribution failed, falling back to nonode@nohost.", []).
+
setup_cookie(Opts) ->
case {node(), proplists:get_value(setcookie, Opts, nocookie)} of
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index f7244dc..94cbe13 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -92,7 +92,7 @@ compile(AppInfo) when element(1, AppInfo) == app_info_t ->
%% @doc compile an individual application.
-spec compile(rebar_app_info:t(), compile_opts()) -> ok.
compile(AppInfo, CompileOpts) when element(1, AppInfo) == app_info_t ->
- Dir = ec_cnv:to_list(rebar_app_info:out_dir(AppInfo)),
+ Dir = rebar_utils:to_list(rebar_app_info:out_dir(AppInfo)),
RebarOpts = rebar_app_info:opts(AppInfo),
SrcOpts = [check_last_mod,
@@ -237,8 +237,8 @@ clean(AppInfo) ->
YrlFiles = rebar_utils:find_files(filename:join([AppDir, "src"]), ?RE_PREFIX".*\\.[x|y]rl\$"),
rebar_file_utils:delete_each(
- [ binary_to_list(iolist_to_binary(re:replace(F, "\\.[x|y]rl$", ".erl")))
- || F <- YrlFiles ]),
+ [rebar_utils:to_list(re:replace(F, "\\.[x|y]rl$", ".erl", [unicode]))
+ || F <- YrlFiles]),
BinDirs = ["ebin"|rebar_dir:extra_src_dirs(rebar_app_info:opts(AppInfo))],
ok = clean_dirs(AppDir, BinDirs),
@@ -279,7 +279,7 @@ gather_src(Opts, BaseDirParts, [Dir|Rest], Srcs, CompileOpts) ->
end,
DirRecursive = dir_recursive(Opts, RelDir, CompileOpts),
gather_src(Opts, BaseDirParts, Rest, Srcs ++ rebar_utils:find_files(Dir, ?RE_PREFIX".*\\.erl\$", DirRecursive), CompileOpts).
-
+
%% Get files which need to be compiled first, i.e. those specified in erl_first_files
%% and parse_transform options. Also produce specific erl_opts for these first
%% files, so that yet to be compiled parse transformations are excluded from it.
@@ -339,7 +339,7 @@ maybe_rm_beam_and_edge(G, OutDir, Source) ->
false;
false ->
Target = target_base(OutDir, Source) ++ ".beam",
- ?DEBUG("Source ~s is gone, deleting previous beam file if it exists ~s", [Source, Target]),
+ ?DEBUG("Source ~ts is gone, deleting previous beam file if it exists ~ts", [Source, Target]),
file:delete(Target),
digraph:del_vertex(G, Source),
true
@@ -351,10 +351,25 @@ opts_changed(NewOpts, Target) ->
false -> NewOpts
end,
case compile_info(Target) of
- {ok, Opts} -> lists:sort(Opts) =/= lists:sort(TotalOpts);
+ {ok, Opts} -> lists:any(fun effects_code_generation/1, lists:usort(TotalOpts) -- lists:usort(Opts));
_ -> true
end.
+effects_code_generation(Option) ->
+ case Option of
+ beam -> false;
+ report_warnings -> false;
+ report_errors -> false;
+ return_errors-> false;
+ return_warnings-> false;
+ warnings_as_errors -> false;
+ binary -> false;
+ verbose -> false;
+ {cwd,_} -> false;
+ {outdir, _} -> false;
+ _ -> true
+ end.
+
compile_info(Target) ->
case beam_lib:chunks(Target, [compile_info]) of
{ok, {_mod, Chunks}} ->
@@ -385,7 +400,7 @@ init_erlcinfo(InclDirs, Erls, Dir, OutDir) ->
try restore_erlcinfo(G, InclDirs, Dir)
catch
_:_ ->
- ?WARN("Failed to restore ~s file. Discarding it.~n", [erlcinfo_file(Dir)]),
+ ?WARN("Failed to restore ~ts file. Discarding it.~n", [erlcinfo_file(Dir)]),
file:delete(erlcinfo_file(Dir))
end,
Dirs = source_and_include_dirs(InclDirs, Erls),
diff --git a/src/rebar_fetch.erl b/src/rebar_fetch.erl
index 47bfe1d..f68a54d 100644
--- a/src/rebar_fetch.erl
+++ b/src/rebar_fetch.erl
@@ -41,12 +41,12 @@ download_source_(AppDir, Source, State) ->
Resources = rebar_state:resources(State),
Module = get_resource_type(Source, Resources),
TmpDir = ec_file:insecure_mkdtemp(),
- AppDir1 = ec_cnv:to_list(AppDir),
+ AppDir1 = rebar_utils:to_list(AppDir),
case Module:download(TmpDir, Source, State) of
{ok, _} ->
ec_file:mkdir_p(AppDir1),
code:del_path(filename:absname(filename:join(AppDir1, "ebin"))),
- ec_file:remove(filename:absname(AppDir1), [recursive]),
+ ok = rebar_file_utils:rm_rf(filename:absname(AppDir1)),
?DEBUG("Moving checkout ~p to ~p", [TmpDir, filename:absname(AppDir1)]),
ok = rebar_file_utils:mv(TmpDir, filename:absname(AppDir1)),
true;
@@ -66,25 +66,25 @@ needs_update(AppDir, Source, State) ->
end.
format_error({bad_download, CachePath}) ->
- io_lib:format("Download of package does not match md5sum from server: ~s", [CachePath]);
+ io_lib:format("Download of package does not match md5sum from server: ~ts", [CachePath]);
format_error({unexpected_hash, CachePath, Expected, Found}) ->
- io_lib:format("The checksum for package at ~s (~s) does not match the "
- "checksum previously locked (~s). Either unlock or "
+ io_lib:format("The checksum for package at ~ts (~ts) does not match the "
+ "checksum previously locked (~ts). Either unlock or "
"upgrade the package, or make sure you fetched it from "
"the same index from which it was initially fetched.",
[CachePath, Found, Expected]);
format_error({failed_extract, CachePath}) ->
- io_lib:format("Failed to extract package: ~s", [CachePath]);
+ io_lib:format("Failed to extract package: ~ts", [CachePath]);
format_error({bad_etag, Source}) ->
- io_lib:format("MD5 Checksum comparison failed for: ~s", [Source]);
+ io_lib:format("MD5 Checksum comparison failed for: ~ts", [Source]);
format_error({fetch_fail, Name, Vsn}) ->
- io_lib:format("Failed to fetch and copy dep: ~s-~s", [Name, Vsn]);
+ io_lib:format("Failed to fetch and copy dep: ~ts-~ts", [Name, Vsn]);
format_error({fetch_fail, Source}) ->
io_lib:format("Failed to fetch and copy dep: ~p", [Source]);
format_error({bad_checksum, File}) ->
- io_lib:format("Checksum mismatch against tarball in ~s", [File]);
+ io_lib:format("Checksum mismatch against tarball in ~ts", [File]);
format_error({bad_registry_checksum, File}) ->
- io_lib:format("Checksum mismatch against registry in ~s", [File]).
+ io_lib:format("Checksum mismatch against registry in ~ts", [File]).
get_resource_type({Type, Location}, Resources) ->
find_resource_module(Type, Location, Resources);
@@ -100,7 +100,7 @@ find_resource_module(Type, Location, Resources) ->
false ->
case code:which(Type) of
non_existing ->
- {error, io_lib:format("Cannot handle dependency ~s.~n"
+ {error, io_lib:format("Cannot handle dependency ~ts.~n"
" No module for resource type ~p", [Location, Type])};
_ ->
Type
diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl
index 8158312..d7716e5 100644
--- a/src/rebar_file_utils.erl
+++ b/src/rebar_file_utils.erl
@@ -84,7 +84,7 @@ consult_config(State, Filename) ->
[JoinedConfig].
format_error({bad_term_file, AppFile, Reason}) ->
- io_lib:format("Error reading file ~s: ~s", [AppFile, file:format_error(Reason)]).
+ io_lib:format("Error reading file ~ts: ~ts", [AppFile, file:format_error(Reason)]).
symlink_or_copy(Source, Target) ->
Link = case os:type() of
@@ -121,7 +121,7 @@ symlink_or_copy(Source, Target) ->
win32_symlink(Source, Target) ->
Res = rebar_utils:sh(
- ?FMT("cmd /c mklink /j \"~s\" \"~s\"",
+ ?FMT("cmd /c mklink /j \"~ts\" \"~ts\"",
[rebar_utils:escape_double_quotes(filename:nativename(Target)),
rebar_utils:escape_double_quotes(filename:nativename(Source))]),
[{use_stdout, false}, return_on_error]),
@@ -129,7 +129,7 @@ win32_symlink(Source, Target) ->
true -> ok;
false ->
{error, lists:flatten(
- io_lib:format("Failed to symlink ~s to ~s~n",
+ io_lib:format("Failed to symlink ~ts to ~ts~n",
[Source, Target]))}
end.
@@ -141,7 +141,7 @@ rm_rf(Target) ->
case os:type() of
{unix, _} ->
EscTarget = rebar_utils:escape_chars(Target),
- {ok, []} = rebar_utils:sh(?FMT("rm -rf ~s", [EscTarget]),
+ {ok, []} = rebar_utils:sh(?FMT("rm -rf ~ts", [EscTarget]),
[{use_stdout, false}, abort_on_error]),
ok;
{win32, _} ->
@@ -161,7 +161,7 @@ cp_r(Sources, Dest) ->
{unix, _} ->
EscSources = [rebar_utils:escape_chars(Src) || Src <- Sources],
SourceStr = string:join(EscSources, " "),
- {ok, []} = rebar_utils:sh(?FMT("cp -Rp ~s \"~s\"",
+ {ok, []} = rebar_utils:sh(?FMT("cp -Rp ~ts \"~ts\"",
[SourceStr, rebar_utils:escape_double_quotes(Dest)]),
[{use_stdout, false}, abort_on_error]),
ok;
@@ -176,7 +176,7 @@ mv(Source, Dest) ->
{unix, _} ->
EscSource = rebar_utils:escape_chars(Source),
EscDest = rebar_utils:escape_chars(Dest),
- case rebar_utils:sh(?FMT("mv ~s ~s", [EscSource, EscDest]),
+ case rebar_utils:sh(?FMT("mv ~ts ~ts", [EscSource, EscDest]),
[{use_stdout, false}, abort_on_error]) of
{ok, []} ->
ok;
@@ -234,7 +234,7 @@ robocopy_mv_and_rename(Source, Dest, SrcDir, SrcName, DestDir, DestName) ->
case ec_file:insecure_mkdtemp() of
{error, _Reason} ->
{error, lists:flatten(
- io_lib:format("Failed to move ~s to ~s (tmpdir failed)~n",
+ io_lib:format("Failed to move ~ts to ~ts (tmpdir failed)~n",
[Source, Dest]))};
TmpPath ->
case robocopy_file(SrcDir, TmpPath, SrcName) of
@@ -246,7 +246,7 @@ robocopy_mv_and_rename(Source, Dest, SrcDir, SrcName, DestDir, DestName) ->
case file:rename(TmpSrc, TmpDst) of
{error, _} ->
{error, lists:flatten(
- io_lib:format("Failed to move ~s to ~s (via rename)~n",
+ io_lib:format("Failed to move ~ts to ~ts (via rename)~n",
[Source, Dest]))};
ok ->
case robocopy_file(TmpPath, DestDir, DestName) of
@@ -258,7 +258,7 @@ robocopy_mv_and_rename(Source, Dest, SrcDir, SrcName, DestDir, DestName) ->
end.
robocopy_file(SrcPath, DestPath, FileName) ->
- Cmd = ?FMT("robocopy /move /e \"~s\" \"~s\" \"~s\"",
+ Cmd = ?FMT("robocopy /move /e \"~ts\" \"~ts\" \"~ts\"",
[rebar_utils:escape_double_quotes(SrcPath),
rebar_utils:escape_double_quotes(DestPath),
rebar_utils:escape_double_quotes(FileName)]),
@@ -266,7 +266,7 @@ robocopy_file(SrcPath, DestPath, FileName) ->
case win32_ok(Res) of
false ->
{error, lists:flatten(
- io_lib:format("Failed to move ~s to ~s~n",
+ io_lib:format("Failed to move ~ts to ~ts~n",
[filename:join(SrcPath, FileName),
filename:join(DestPath, FileName)]))};
true ->
@@ -274,7 +274,7 @@ robocopy_file(SrcPath, DestPath, FileName) ->
end.
robocopy_dir(Source, Dest) ->
- Cmd = ?FMT("robocopy /move /e \"~s\" \"~s\"",
+ Cmd = ?FMT("robocopy /move /e \"~ts\" \"~ts\"",
[rebar_utils:escape_double_quotes(Source),
rebar_utils:escape_double_quotes(Dest)]),
Res = rebar_utils:sh(Cmd,
@@ -283,7 +283,7 @@ robocopy_dir(Source, Dest) ->
true -> ok;
false ->
{error, lists:flatten(
- io_lib:format("Failed to move ~s to ~s~n",
+ io_lib:format("Failed to move ~ts to ~ts~n",
[Source, Dest]))}
end.
@@ -301,12 +301,19 @@ delete_each([File | Rest]) ->
{error, enoent} ->
delete_each(Rest);
{error, Reason} ->
- ?ERROR("Failed to delete file ~s: ~p\n", [File, Reason]),
+ ?ERROR("Failed to delete file ~ts: ~p\n", [File, Reason]),
?FAIL
end.
write_file_if_contents_differ(Filename, Bytes) ->
- ToWrite = iolist_to_binary(Bytes),
+ %% first try to convert directly to binaries,
+ %% but if it fails, we likely contain unicode and
+ %% need special treatment
+ ToWrite = try
+ iolist_to_binary(Bytes)
+ catch
+ error:badarg -> unicode:characters_to_binary(Bytes)
+ end,
case file:read_file(Filename) of
{ok, ToWrite} ->
ok;
@@ -401,13 +408,13 @@ split_dirname(Path) ->
delete_each_dir_win32([]) -> ok;
delete_each_dir_win32([Dir | Rest]) ->
- {ok, []} = rebar_utils:sh(?FMT("rd /q /s \"~s\"",
+ {ok, []} = rebar_utils:sh(?FMT("rd /q /s \"~ts\"",
[rebar_utils:escape_double_quotes(filename:nativename(Dir))]),
[{use_stdout, false}, return_on_error]),
delete_each_dir_win32(Rest).
xcopy_win32(Source,Dest)->
- %% "xcopy \"~s\" \"~s\" /q /y /e 2> nul", Changed to robocopy to
+ %% "xcopy \"~ts\" \"~ts\" /q /y /e 2> nul", Changed to robocopy to
%% handle long names. May have issues with older windows.
Cmd = case filelib:is_dir(Source) of
true ->
@@ -417,11 +424,11 @@ xcopy_win32(Source,Dest)->
%% must manually add the last fragment of a directory to the `Dest`
%% in order to properly replicate POSIX platforms
NewDest = filename:join([Dest, filename:basename(Source)]),
- ?FMT("robocopy \"~s\" \"~s\" /e /is 1> nul",
+ ?FMT("robocopy \"~ts\" \"~ts\" /e /is 1> nul",
[rebar_utils:escape_double_quotes(filename:nativename(Source)),
rebar_utils:escape_double_quotes(filename:nativename(NewDest))]);
false ->
- ?FMT("robocopy \"~s\" \"~s\" \"~s\" /e /is 1> nul",
+ ?FMT("robocopy \"~ts\" \"~ts\" \"~ts\" /e /is 1> nul",
[rebar_utils:escape_double_quotes(filename:nativename(filename:dirname(Source))),
rebar_utils:escape_double_quotes(filename:nativename(Dest)),
rebar_utils:escape_double_quotes(filename:basename(Source))])
@@ -432,7 +439,7 @@ xcopy_win32(Source,Dest)->
true -> ok;
false ->
{error, lists:flatten(
- io_lib:format("Failed to copy ~s to ~s~n",
+ io_lib:format("Failed to copy ~ts to ~ts~n",
[Source, Dest]))}
end.
diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl
index 201b8b6..a6b4d00 100644
--- a/src/rebar_git_resource.erl
+++ b/src/rebar_git_resource.erl
@@ -17,7 +17,7 @@
lock(AppDir, {git, Url, _}) ->
lock(AppDir, {git, Url});
lock(AppDir, {git, Url}) ->
- AbortMsg = lists:flatten(io_lib:format("Locking of git dependency failed in ~s", [AppDir])),
+ AbortMsg = lists:flatten(io_lib:format("Locking of git dependency failed in ~ts", [AppDir])),
Dir = rebar_utils:escape_double_quotes(AppDir),
{ok, VsnString} =
case os:type() of
@@ -38,39 +38,37 @@ needs_update(Dir, {git, Url, {tag, Tag}}) ->
[{cd, Dir}]),
Current1 = string:strip(string:strip(Current, both, $\n), both, $\r),
- ?DEBUG("Comparing git tag ~s with ~s", [Tag, Current1]),
+ ?DEBUG("Comparing git tag ~ts with ~ts", [Tag, Current1]),
not ((Current1 =:= Tag) andalso compare_url(Dir, Url));
needs_update(Dir, {git, Url, {branch, Branch}}) ->
%% Fetch remote so we can check if the branch has changed
SafeBranch = rebar_utils:escape_chars(Branch),
- {ok, _} = rebar_utils:sh(?FMT("git fetch origin ~s", [SafeBranch]),
+ {ok, _} = rebar_utils:sh(?FMT("git fetch origin ~ts", [SafeBranch]),
[{cd, Dir}]),
%% Check for new commits to origin/Branch
- {ok, Current} = rebar_utils:sh(?FMT("git log HEAD..origin/~s --oneline", [SafeBranch]),
+ {ok, Current} = rebar_utils:sh(?FMT("git log HEAD..origin/~ts --oneline", [SafeBranch]),
[{cd, Dir}]),
- ?DEBUG("Checking git branch ~s for updates", [Branch]),
+ ?DEBUG("Checking git branch ~ts for updates", [Branch]),
not ((Current =:= []) andalso compare_url(Dir, Url));
needs_update(Dir, {git, Url, "master"}) ->
needs_update(Dir, {git, Url, {branch, "master"}});
needs_update(Dir, {git, _, Ref}) ->
- {ok, Current} = rebar_utils:sh(?FMT("git rev-parse -q HEAD", []),
+ {ok, Current} = rebar_utils:sh(?FMT("git rev-parse --short=7 -q HEAD", []),
[{cd, Dir}]),
Current1 = string:strip(string:strip(Current, both, $\n), both, $\r),
Ref2 = case Ref of
{ref, Ref1} ->
Length = length(Current1),
- if
- Length >= 7 ->
- lists:sublist(Ref1, Length);
- true ->
- Ref1
+ case Length >= 7 of
+ true -> lists:sublist(Ref1, Length);
+ false -> Ref1
end;
- Ref1 ->
- Ref1
+ _ ->
+ Ref
end,
- ?DEBUG("Comparing git ref ~s with ~s", [Ref1, Current1]),
+ ?DEBUG("Comparing git ref ~ts with ~ts", [Ref2, Current1]),
(Current1 =/= Ref2).
compare_url(Dir, Url) ->
@@ -84,7 +82,7 @@ compare_url(Dir, Url) ->
parse_git_url(Url) ->
%% Checks for standard scp style git remote
- case re:run(Url, ?SCP_PATTERN, [{capture, [host, path], list}]) of
+ case re:run(Url, ?SCP_PATTERN, [{capture, [host, path], list}, unicode]) of
{match, [Host, Path]} ->
{ok, {Host, filename:rootname(Path, ".git")}};
nomatch ->
@@ -121,41 +119,41 @@ download(Dir, {git, Url, Rev}, _State) ->
%% Use different git clone commands depending on git --version
git_clone(branch,Vsn,Url,Dir,Branch) when Vsn >= {1,7,10}; Vsn =:= undefined ->
- rebar_utils:sh(?FMT("git clone ~s ~s -b ~s --single-branch",
+ rebar_utils:sh(?FMT("git clone ~ts ~ts -b ~ts --single-branch",
[rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir)),
rebar_utils:escape_chars(Branch)]),
[{cd, filename:dirname(Dir)}]);
git_clone(branch,_Vsn,Url,Dir,Branch) ->
- rebar_utils:sh(?FMT("git clone ~s ~s -b ~s",
+ rebar_utils:sh(?FMT("git clone ~ts ~ts -b ~ts",
[rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir)),
rebar_utils:escape_chars(Branch)]),
[{cd, filename:dirname(Dir)}]);
git_clone(tag,Vsn,Url,Dir,Tag) when Vsn >= {1,7,10}; Vsn =:= undefined ->
- rebar_utils:sh(?FMT("git clone ~s ~s -b ~s --single-branch",
+ rebar_utils:sh(?FMT("git clone ~ts ~ts -b ~ts --single-branch",
[rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir)),
rebar_utils:escape_chars(Tag)]),
[{cd, filename:dirname(Dir)}]);
git_clone(tag,_Vsn,Url,Dir,Tag) ->
- rebar_utils:sh(?FMT("git clone ~s ~s -b ~s",
+ rebar_utils:sh(?FMT("git clone ~ts ~ts -b ~ts",
[rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir)),
rebar_utils:escape_chars(Tag)]),
[{cd, filename:dirname(Dir)}]);
git_clone(ref,_Vsn,Url,Dir,Ref) ->
- rebar_utils:sh(?FMT("git clone -n ~s ~s",
+ rebar_utils:sh(?FMT("git clone -n ~ts ~ts",
[rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir))]),
[{cd, filename:dirname(Dir)}]),
- rebar_utils:sh(?FMT("git checkout -q ~s", [Ref]), [{cd, Dir}]);
+ rebar_utils:sh(?FMT("git checkout -q ~ts", [Ref]), [{cd, Dir}]);
git_clone(rev,_Vsn,Url,Dir,Rev) ->
- rebar_utils:sh(?FMT("git clone -n ~s ~s",
+ rebar_utils:sh(?FMT("git clone -n ~ts ~ts",
[rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir))]),
[{cd, filename:dirname(Dir)}]),
- rebar_utils:sh(?FMT("git checkout -q ~s", [rebar_utils:escape_chars(Rev)]),
+ rebar_utils:sh(?FMT("git checkout -q ~ts", [rebar_utils:escape_chars(Rev)]),
[{cd, Dir}]).
git_vsn() ->
@@ -170,7 +168,7 @@ git_vsn() ->
git_vsn_fetch() ->
case rebar_utils:sh("git --version",[]) of
{ok, VsnStr} ->
- case re:run(VsnStr, "git version\\h+(\\d)\\.(\\d)\\.(\\d).*",[{capture,[1,2,3],list}]) of
+ case re:run(VsnStr, "git version\\h+(\\d)\\.(\\d)\\.(\\d).*", [{capture,[1,2,3],list}, unicode]) of
{match,[Maj,Min,Patch]} ->
{list_to_integer(Maj),
list_to_integer(Min),
@@ -200,7 +198,7 @@ collect_default_refcount(Dir) ->
return_on_error,
{cd, Dir}]) of
{error, _} ->
- ?WARN("Getting log of git dependency failed in ~s. Falling back to version 0.0.0", [rebar_dir:get_cwd()]),
+ ?WARN("Getting log of git dependency failed in ~ts. Falling back to version 0.0.0", [rebar_dir:get_cwd()]),
{plain, "0.0.0"};
{ok, String} ->
RawRef = string:strip(String, both, $\n),
@@ -224,21 +222,20 @@ collect_default_refcount(Dir) ->
build_vsn_string(Vsn, RawRef, Count) ->
%% Cleanup the tag and the Ref information. Basically leading 'v's and
%% whitespace needs to go away.
- RefTag = [".ref", re:replace(RawRef, "\\s", "", [global])],
+ RefTag = [".ref", re:replace(RawRef, "\\s", "", [global, unicode])],
%% Create the valid [semver](http://semver.org) version from the tag
case Count of
0 ->
- erlang:binary_to_list(erlang:iolist_to_binary(Vsn));
+ rebar_utils:to_list(Vsn);
_ ->
- erlang:binary_to_list(erlang:iolist_to_binary([Vsn, "+build.",
- integer_to_list(Count), RefTag]))
+ rebar_utils:to_list([Vsn, "+build.", integer_to_list(Count), RefTag])
end.
get_patch_count(Dir, RawRef) ->
AbortMsg = "Getting rev-list of git dep failed in " ++ Dir,
- Ref = re:replace(RawRef, "\\s", "", [global]),
- Cmd = io_lib:format("git rev-list ~s..HEAD",
+ Ref = re:replace(RawRef, "\\s", "", [global, unicode]),
+ Cmd = io_lib:format("git rev-list ~ts..HEAD",
[rebar_utils:escape_chars(Ref)]),
{ok, PatchLines} = rebar_utils:sh(Cmd,
[{use_stdout, false},
@@ -254,7 +251,7 @@ parse_tags(Dir) ->
{error, _} ->
{undefined, "0.0.0"};
{ok, Line} ->
- case re:run(Line, "(\\(|\\s)(HEAD[^,]*,\\s)tag:\\s(v?([^,\\)]+))", [{capture, [3, 4], list}]) of
+ case re:run(Line, "(\\(|\\s)(HEAD[^,]*,\\s)tag:\\s(v?([^,\\)]+))", [{capture, [3, 4], list}, unicode]) of
{match,[Tag, Vsn]} ->
{Tag, Vsn};
nomatch ->
diff --git a/src/rebar_hg_resource.erl b/src/rebar_hg_resource.erl
index 7d03eda..42e634c 100644
--- a/src/rebar_hg_resource.erl
+++ b/src/rebar_hg_resource.erl
@@ -22,7 +22,7 @@ lock(AppDir, {hg, Url}) ->
needs_update(Dir, {hg, Url, {tag, Tag}}) ->
Ref = get_ref(Dir),
{ClosestTag, Distance} = get_tag_distance(Dir, Ref),
- ?DEBUG("Comparing hg tag ~s with ref ~s (closest tag is ~s at distance ~s)",
+ ?DEBUG("Comparing hg tag ~ts with ref ~ts (closest tag is ~ts at distance ~ts)",
[Tag, Ref, ClosestTag, Distance]),
not ((Distance =:= "0") andalso (Tag =:= ClosestTag)
andalso compare_url(Dir, Url));
@@ -45,7 +45,7 @@ needs_update(Dir, {hg, Url, Ref}) ->
Ref1 ->
Ref1
end,
- ?DEBUG("Comparing hg ref ~s with ~s", [Ref1, LocalRef]),
+ ?DEBUG("Comparing hg ref ~ts with ~ts", [Ref1, LocalRef]),
not ((LocalRef =:= TargetRef) andalso compare_url(Dir, Url)).
download(Dir, {hg, Url}, State) ->
@@ -56,28 +56,28 @@ download(Dir, {hg, Url, ""}, State) ->
download(Dir, {hg, Url, {branch, "default"}}, State);
download(Dir, {hg, Url, {branch, Branch}}, _State) ->
ok = filelib:ensure_dir(Dir),
- rebar_utils:sh(?FMT("hg clone -q -b ~s ~s ~s",
+ rebar_utils:sh(?FMT("hg clone -q -b ~ts ~ts ~ts",
[rebar_utils:escape_chars(Branch),
rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir))]),
[{cd, filename:dirname(Dir)}]);
download(Dir, {hg, Url, {tag, Tag}}, _State) ->
ok = filelib:ensure_dir(Dir),
- rebar_utils:sh(?FMT("hg clone -q -u ~s ~s ~s",
+ rebar_utils:sh(?FMT("hg clone -q -u ~ts ~ts ~ts",
[rebar_utils:escape_chars(Tag),
rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir))]),
[{cd, filename:dirname(Dir)}]);
download(Dir, {hg, Url, {ref, Ref}}, _State) ->
ok = filelib:ensure_dir(Dir),
- rebar_utils:sh(?FMT("hg clone -q -r ~s ~s ~s",
+ rebar_utils:sh(?FMT("hg clone -q -r ~ts ~ts ~ts",
[rebar_utils:escape_chars(Ref),
rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir))]),
[{cd, filename:dirname(Dir)}]);
download(Dir, {hg, Url, Rev}, _State) ->
ok = filelib:ensure_dir(Dir),
- rebar_utils:sh(?FMT("hg clone -q -r ~s ~s ~s",
+ rebar_utils:sh(?FMT("hg clone -q -r ~ts ~ts ~ts",
[rebar_utils:escape_chars(Rev),
rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir))]),
@@ -88,7 +88,7 @@ make_vsn(Dir) ->
Ref = get_ref(Dir),
Cmd = BaseHg ++ "log --template \"{latesttag}+build.{latesttagdistance}.rev.{node|short}\""
" --rev " ++ Ref,
- AbortMsg = io_lib:format("Version resolution of hg dependency failed in ~s", [Dir]),
+ AbortMsg = io_lib:format("Version resolution of hg dependency failed in ~ts", [Dir]),
{ok, VsnString} =
rebar_utils:sh(Cmd,
[{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
@@ -108,14 +108,14 @@ compare_url(Dir, Url) ->
parse_hg_url(CurrentUrl1) =:= parse_hg_url(Url).
get_ref(Dir) ->
- AbortMsg = io_lib:format("Get ref of hg dependency failed in ~s", [Dir]),
+ AbortMsg = io_lib:format("Get ref of hg dependency failed in ~ts", [Dir]),
{ok, RefString} =
rebar_utils:sh("hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++ "\" --debug id -i",
[{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
string:strip(RefString, both, $\n).
get_tag_distance(Dir, Ref) ->
- AbortMsg = io_lib:format("Get tag distance of hg dependency failed in ~s", [Dir]),
+ AbortMsg = io_lib:format("Get tag distance of hg dependency failed in ~ts", [Dir]),
{ok, LogString} =
rebar_utils:sh("hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++ "\" "
"log --template \"{latesttag}-{latesttagdistance}\n\" "
@@ -123,11 +123,12 @@ get_tag_distance(Dir, Ref) ->
[{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
Log = string:strip(LogString,
both, $\n),
- [Tag, Distance] = re:split(Log, "-([0-9]+)$", [{parts,0}, {return, list}]),
+ [Tag, Distance] = re:split(Log, "-([0-9]+)$",
+ [{parts,0}, {return,list}, unicode]),
{Tag, Distance}.
get_branch_ref(Dir, Branch) ->
- AbortMsg = io_lib:format("Get branch ref of hg dependency failed in ~s", [Dir]),
+ AbortMsg = io_lib:format("Get branch ref of hg dependency failed in ~ts", [Dir]),
{ok, BranchRefString} =
rebar_utils:sh("hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++
"\" log --template \"{node}\n\" --rev " ++ rebar_utils:escape_chars(Branch),
diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl
index d6a0e2b..48aa928 100644
--- a/src/rebar_hooks.erl
+++ b/src/rebar_hooks.erl
@@ -57,9 +57,9 @@ run_provider_hooks_(Dir, Type, Command, Providers, TypeHooks, State) ->
end.
format_error({bad_provider, Type, Command, {Name, Namespace}}) ->
- io_lib:format("Unable to run ~s hooks for '~p', command '~p' in namespace '~p' not found.", [Type, Command, Namespace, Name]);
+ io_lib:format("Unable to run ~ts hooks for '~p', command '~p' in namespace '~p' not found.", [Type, Command, Namespace, Name]);
format_error({bad_provider, Type, Command, Name}) ->
- io_lib:format("Unable to run ~s hooks for '~p', command '~p' not found.", [Type, Command, Name]).
+ io_lib:format("Unable to run ~ts hooks for '~p', command '~p' not found.", [Type, Command, Name]).
%% @doc The following environment variables are exported when running
%% a hook (absolute paths):
@@ -143,7 +143,7 @@ join_dirs(BaseDir, Dirs) ->
string:join([ filename:join(BaseDir, Dir) || Dir <- Dirs ], ":").
re_version(Path) ->
- case re:run(Path, "^.*-(?<VER>[^/-]*)$", [{capture, [1], list}]) of
+ case re:run(Path, "^.*-(?<VER>[^/-]*)$", [{capture,[1],list}, unicode]) of
nomatch -> "";
{match, [Ver]} -> Ver
end.
diff --git a/src/rebar_log.erl b/src/rebar_log.erl
index b1a70c2..9150346 100644
--- a/src/rebar_log.erl
+++ b/src/rebar_log.erl
@@ -57,6 +57,8 @@ intensity() ->
high;
"low" ->
low;
+ "none" ->
+ none;
_ ->
?DFLT_INTENSITY
end,
@@ -92,7 +94,7 @@ get_level() ->
log(Level = error, Str, Args) ->
{ok, LogState} = application:get_env(rebar, log),
- ec_cmd_log:Level(LogState, lists:flatten(cf:format("~!^~s~n", [Str])), Args);
+ ec_cmd_log:Level(LogState, lists:flatten(cf:format("~!^~ts~n", [Str])), Args);
log(Level, Str, Args) ->
{ok, LogState} = application:get_env(rebar, log),
ec_cmd_log:Level(LogState, Str++"~n", Args).
diff --git a/src/rebar_opts.erl b/src/rebar_opts.erl
index 444b760..589dbb8 100644
--- a/src/rebar_opts.erl
+++ b/src/rebar_opts.erl
@@ -118,6 +118,10 @@ merge_opt({plugins, _}, NewValue, _OldValue) ->
NewValue;
merge_opt(profiles, NewValue, OldValue) ->
dict:to_list(merge_opts(dict:from_list(NewValue), dict:from_list(OldValue)));
+merge_opt(erl_first_files, Value, Value) ->
+ Value;
+merge_opt(erl_first_files, NewValue, OldValue) ->
+ OldValue ++ NewValue;
merge_opt(mib_first_files, Value, Value) ->
Value;
merge_opt(mib_first_files, NewValue, OldValue) ->
diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl
index ddaa44b..ed573f2 100644
--- a/src/rebar_otp_app.erl
+++ b/src/rebar_otp_app.erl
@@ -58,11 +58,11 @@ compile(State, App) ->
validate_app(State, App1).
format_error({missing_app_file, Filename}) ->
- io_lib:format("App file is missing: ~s", [Filename]);
+ io_lib:format("App file is missing: ~ts", [Filename]);
format_error({file_read, File, Reason}) ->
- io_lib:format("Failed to read required file ~s for processing: ~s", [File, file:format_error(Reason)]);
+ io_lib:format("Failed to read required file ~ts for processing: ~ts", [File, file:format_error(Reason)]);
format_error({invalid_name, File, AppName}) ->
- io_lib:format("Invalid ~s: name of application (~p) must match filename.", [File, AppName]).
+ io_lib:format("Invalid ~ts: name of application (~p) must match filename.", [File, AppName]).
%% ===================================================================
%% Internal functions
@@ -222,7 +222,7 @@ app_vsn(AppData, AppFile, State) ->
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]);
+ ?ABORT("Failed to get app value '~p' from '~ts'~n", [Key, AppFile]);
Value ->
Value
end.
diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl
index 4cce5a8..cba1d16 100644
--- a/src/rebar_packages.erl
+++ b/src/rebar_packages.erl
@@ -72,12 +72,12 @@ deps(Name, Vsn, State) ->
deps_(Name, Vsn, State) ->
?MODULE:verify_table(State),
- ets:lookup_element(?PACKAGE_TABLE, {ec_cnv:to_binary(Name), ec_cnv:to_binary(Vsn)}, 2).
+ ets:lookup_element(?PACKAGE_TABLE, {rebar_utils:to_binary(Name), rebar_utils:to_binary(Vsn)}, 2).
handle_missing_package(Dep, State, Fun) ->
case Dep of
{Name, Vsn} ->
- ?INFO("Package ~s-~s not found. Fetching registry updates and trying again...", [Name, Vsn]);
+ ?INFO("Package ~ts-~ts not found. Fetching registry updates and trying again...", [Name, Vsn]);
_ ->
?INFO("Package ~p not found. Fetching registry updates and trying again...", [Dep])
end,
@@ -128,7 +128,7 @@ registry_checksum({pkg, Name, Vsn, _Hash}, State) ->
ets:lookup_element(?PACKAGE_TABLE, {Name, Vsn}, 3)
catch
_:_ ->
- throw(?PRV_ERROR({missing_package, ec_cnv:to_binary(Name), ec_cnv:to_binary(Vsn)}))
+ throw(?PRV_ERROR({missing_package, rebar_utils:to_binary(Name), rebar_utils:to_binary(Vsn)}))
end.
%% Hex supports use of ~> to specify the version required for a dependency.
@@ -207,17 +207,17 @@ handle_single_vsn(Pkg, PkgVsn, Dep, Vsn, Constraint) ->
false ->
case {Pkg, PkgVsn} of
{undefined, undefined} ->
- ?WARN("Only existing version of ~s is ~s which does not match constraint ~~> ~s. "
+ ?DEBUG("Only existing version of ~ts is ~ts which does not match constraint ~~> ~ts. "
"Using anyway, but it is not guaranteed to work.", [Dep, Vsn, Constraint]);
_ ->
- ?WARN("[~s:~s] Only existing version of ~s is ~s which does not match constraint ~~> ~s. "
+ ?DEBUG("[~ts:~ts] Only existing version of ~ts is ~ts which does not match constraint ~~> ~ts. "
"Using anyway, but it is not guaranteed to work.", [Pkg, PkgVsn, Dep, Vsn, Constraint])
end,
{ok, Vsn}
end.
format_error({missing_package, Name, Vsn}) ->
- io_lib:format("Package not found in registry: ~s-~s.", [ec_cnv:to_binary(Name), ec_cnv:to_binary(Vsn)]);
+ io_lib:format("Package not found in registry: ~ts-~ts.", [rebar_utils:to_binary(Name), rebar_utils:to_binary(Vsn)]);
format_error({missing_package, Dep}) ->
io_lib:format("Package not found in registry: ~p.", [Dep]).
diff --git a/src/rebar_pkg_resource.erl b/src/rebar_pkg_resource.erl
index 88419bd..d588f24 100644
--- a/src/rebar_pkg_resource.erl
+++ b/src/rebar_pkg_resource.erl
@@ -21,7 +21,7 @@ lock(_AppDir, Source) ->
needs_update(Dir, {pkg, _Name, Vsn, _Hash}) ->
[AppInfo] = rebar_app_discover:find_apps([Dir], all),
- case rebar_app_info:original_vsn(AppInfo) =:= ec_cnv:to_list(Vsn) of
+ case rebar_app_info:original_vsn(AppInfo) =:= rebar_utils:to_list(Vsn) of
true ->
false;
false ->
@@ -43,13 +43,13 @@ download(TmpDir, Pkg={pkg, Name, Vsn, _Hash}, State) ->
cached_download(TmpDir, CachePath, Pkg={pkg, Name, Vsn, _Hash}, Url, ETag, State) ->
case request(Url, ETag) of
{ok, cached} ->
- ?INFO("Version cached at ~s is up to date, reusing it", [CachePath]),
+ ?INFO("Version cached at ~ts is up to date, reusing it", [CachePath]),
serve_from_cache(TmpDir, CachePath, Pkg, State);
{ok, Body, NewETag} ->
- ?INFO("Downloaded package, caching at ~s", [CachePath]),
+ ?INFO("Downloaded package, caching at ~ts", [CachePath]),
serve_from_download(TmpDir, CachePath, Pkg, NewETag, Body, State);
error when ETag =/= false ->
- ?INFO("Download error, using cached file at ~s", [CachePath]),
+ ?INFO("Download error, using cached file at ~ts", [CachePath]),
serve_from_cache(TmpDir, CachePath, Pkg, State);
error ->
{fetch_fail, Name, Vsn}
@@ -76,13 +76,13 @@ serve_from_cache(TmpDir, CachePath, Pkg, State) ->
end.
serve_from_download(TmpDir, CachePath, Package, ETag, Binary, State) ->
- ?DEBUG("Writing ~p to cache at ~s", [Package, CachePath]),
+ ?DEBUG("Writing ~p to cache at ~ts", [Package, CachePath]),
file:write_file(CachePath, Binary),
case etag(CachePath) of
ETag ->
serve_from_cache(TmpDir, CachePath, Package, State);
FileETag ->
- ?DEBUG("Downloaded file ~s ETag ~s doesn't match returned ETag ~s", [CachePath, ETag, FileETag]),
+ ?DEBUG("Downloaded file ~ts ETag ~ts doesn't match returned ETag ~ts", [CachePath, ETag, FileETag]),
{bad_download, CachePath}
end.
@@ -114,11 +114,11 @@ request(Url, ETag) ->
[{body_format, binary}],
rebar) of
{ok, {{_Version, 200, _Reason}, Headers, Body}} ->
- ?DEBUG("Successfully downloaded ~s", [Url]),
+ ?DEBUG("Successfully downloaded ~ts", [Url]),
{"etag", ETag1} = lists:keyfind("etag", 1, Headers),
{ok, Body, string:strip(ETag1, both, $")};
{ok, {{_Version, 304, _Reason}, _Headers, _Body}} ->
- ?DEBUG("Cached copy of ~s still valid", [Url]),
+ ?DEBUG("Cached copy of ~ts still valid", [Url]),
{ok, cached};
{ok, {{_Version, Code, _Reason}, _Headers, _Body}} ->
?DEBUG("Request to ~p failed: status code ~p", [Url, Code]),
@@ -154,7 +154,7 @@ ssl_opts(Url) ->
ssl_opts(ssl_verify_enabled, Url) ->
case check_ssl_version() of
true ->
- {ok, {_, _, Hostname, _, _, _}} = http_uri:parse(ec_cnv:to_list(Url)),
+ {ok, {_, _, Hostname, _, _, _}} = http_uri:parse(rebar_utils:to_list(Url)),
VerifyFun = {fun ssl_verify_hostname:verify_fun/3, [{check_hostname, Hostname}]},
CACerts = certifi:cacerts(),
[{verify, verify_peer}, {depth, 2}, {cacerts, CACerts}
diff --git a/src/rebar_prv_app_discovery.erl b/src/rebar_prv_app_discovery.erl
index 1954214..3f10a3f 100644
--- a/src/rebar_prv_app_discovery.erl
+++ b/src/rebar_prv_app_discovery.erl
@@ -49,19 +49,19 @@ do(State) ->
-spec format_error(any()) -> iolist().
format_error({multiple_app_files, Files}) ->
- io_lib:format("Multiple app files found in one app dir: ~s", [string:join(Files, " and ")]);
+ io_lib:format("Multiple app files found in one app dir: ~ts", [string:join(Files, " and ")]);
format_error({invalid_app_file, File, Reason}) ->
case Reason of
{Line, erl_parse, Description} ->
- io_lib:format("Invalid app file ~s at line ~b: ~p",
+ io_lib:format("Invalid app file ~ts at line ~b: ~p",
[File, Line, lists:flatten(Description)]);
_ ->
- io_lib:format("Invalid app file ~s: ~p", [File, Reason])
+ io_lib:format("Invalid app file ~ts: ~p", [File, Reason])
end;
%% Provide a slightly more informative error message for consult of app file failure
format_error({rebar_file_utils, {bad_term_file, AppFile, Reason}}) ->
- io_lib:format("Error in app file ~s: ~s", [rebar_dir:make_relative_path(AppFile,
- rebar_dir:get_cwd()),
- file:format_error(Reason)]);
+ io_lib:format("Error in app file ~ts: ~ts", [rebar_dir:make_relative_path(AppFile,
+ rebar_dir:get_cwd()),
+ file:format_error(Reason)]);
format_error(Reason) ->
io_lib:format("~p", [Reason]).
diff --git a/src/rebar_prv_as.erl b/src/rebar_prv_as.erl
index e7c6d68..562ce99 100644
--- a/src/rebar_prv_as.erl
+++ b/src/rebar_prv_as.erl
@@ -64,7 +64,7 @@ args_to_profiles_and_tasks(Args) ->
first_profile([]) -> {[], []};
first_profile([ProfileList|Rest]) ->
- case re:split(ProfileList, ",", [{return, list}, {parts, 2}]) of
+ case re:split(ProfileList, ",", [{return, list}, {parts, 2}, unicode]) of
%% `foo, bar`
[P, ""] -> profiles(Rest, [P]);
%% `foo,bar`
@@ -75,7 +75,7 @@ first_profile([ProfileList|Rest]) ->
profiles([], Acc) -> {lists:reverse(Acc), rebar_utils:args_to_tasks([])};
profiles([ProfileList|Rest], Acc) ->
- case re:split(ProfileList, ",", [{return, list}, {parts, 2}]) of
+ case re:split(ProfileList, ",", [{return, list}, {parts, 2}, unicode]) of
%% `foo, bar`
[P, ""] -> profiles(Rest, [P|Acc]);
%% `foo,bar`
@@ -101,5 +101,5 @@ warn_on_empty_profile(Profiles, State) ->
ProjectApps = rebar_state:project_apps(State),
DefinedProfiles = rebar_state:get(State, profiles, []) ++
lists:flatten([rebar_app_info:get(AppInfo, profiles, []) || AppInfo <- ProjectApps]),
- [?WARN("No entry for profile ~s in config.", [Profile]) ||
+ [?WARN("No entry for profile ~ts in config.", [Profile]) ||
Profile <- Profiles, not(lists:keymember(list_to_atom(Profile), 1, DefinedProfiles))].
diff --git a/src/rebar_prv_bare_compile.erl b/src/rebar_prv_bare_compile.erl
index 201620a..6f1ac16 100644
--- a/src/rebar_prv_bare_compile.erl
+++ b/src/rebar_prv_bare_compile.erl
@@ -29,7 +29,8 @@ init(State) ->
{example, ""},
{short_desc, ""},
{desc, ""},
- {opts, [{paths, $p, "paths", string, "Wildcard path of ebin directories to add to code path"}]}])),
+ {opts, [{paths, $p, "paths", string, "Wildcard paths of ebin directories to add to code path, separated by a colon"},
+ {separator, $s, "separator", string, "In case of multiple return paths, the separator character to use to join them."}]}])),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
@@ -39,8 +40,9 @@ do(State) ->
%% Add code paths from --paths to the beginning of the code path
{RawOpts, _} = rebar_state:command_parsed_args(State),
Paths = proplists:get_value(paths, RawOpts),
- CodePaths = filelib:wildcard(Paths),
- code:add_pathsa(CodePaths),
+ Sep = proplists:get_value(separator, RawOpts, " "),
+ [ code:add_pathsa(filelib:wildcard(PathWildcard))
+ || PathWildcard <- string:tokens(Paths, Sep) ],
[AppInfo] = rebar_state:project_apps(State),
AppInfo1 = rebar_app_info:out_dir(AppInfo, rebar_dir:get_cwd()),
diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl
index 8f31fdd..aa0b5af 100644
--- a/src/rebar_prv_clean.erl
+++ b/src/rebar_prv_clean.erl
@@ -44,7 +44,8 @@ do(State) ->
case All of
true ->
DepsDir = rebar_dir:deps_dir(State1),
- AllApps = rebar_app_discover:find_apps([filename:join(DepsDir, "*")], all),
+ DepsDirs = filelib:wildcard(filename:join(DepsDir, "*")),
+ AllApps = rebar_app_discover:find_apps(DepsDirs, all),
clean_apps(State1, Providers, AllApps);
false ->
ProjectApps = rebar_state:project_apps(State1),
@@ -67,7 +68,7 @@ format_error(Reason) ->
clean_apps(State, Providers, Apps) ->
[begin
- ?INFO("Cleaning out ~s...", [rebar_app_info:name(AppInfo)]),
+ ?INFO("Cleaning out ~ts...", [rebar_app_info:name(AppInfo)]),
AppDir = rebar_app_info:dir(AppInfo),
AppInfo1 = rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, AppInfo, State),
rebar_erlc_compiler:clean(AppInfo1),
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 2ac8fc7..bf788d2 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -41,7 +41,14 @@ do(State) ->
Tests = prepare_tests(State),
case compile(State, Tests) of
%% successfully compiled apps
- {ok, S} -> do(S, Tests);
+ {ok, S} ->
+ {RawOpts, _} = rebar_state:command_parsed_args(S),
+ case proplists:get_value(compile_only, RawOpts, false) of
+ true ->
+ {ok, S};
+ false ->
+ do(S, Tests)
+ end;
%% this should look like a compiler error, not a ct error
Error -> Error
end.
@@ -93,7 +100,7 @@ format_error({error, Reason}) ->
format_error({error_running_tests, Reason}) ->
format_error({error, Reason});
format_error({failures_running_tests, {Failed, AutoSkipped}}) ->
- io_lib:format("Failures occured running tests: ~b", [Failed+AutoSkipped]);
+ io_lib:format("Failures occurred running tests: ~b", [Failed+AutoSkipped]);
format_error({badconfig, {Msg, {Value, Key}}}) ->
io_lib:format(Msg, [Value, Key]);
format_error({badconfig, Msg}) ->
@@ -431,18 +438,21 @@ test_dirs(State, Apps, Opts) ->
set_compile_dirs(State, Apps, join(Suites, Dir));
{_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"}
end;
- Specs0 ->
- case get_dirs_from_specs(Specs0) of
- {ok,{Specs,SuiteDirs}} ->
- {State1,Apps1} = set_compile_dirs1(State, Apps,
- {dir, SuiteDirs}),
- {State2,Apps2} = set_compile_dirs1(State1, Apps1,
- {spec, Specs}),
- [maybe_copy_spec(State2,Apps2,S) || S <- Specs],
- {ok, rebar_state:project_apps(State2, Apps2)};
- Error ->
- Error
- end
+ Spec when is_integer(hd(Spec)) ->
+ spec_test_dirs(State, Apps, [Spec]);
+ Specs ->
+ spec_test_dirs(State, Apps, Specs)
+ end.
+
+spec_test_dirs(State, Apps, Specs0) ->
+ case get_dirs_from_specs(Specs0) of
+ {ok,{Specs,SuiteDirs}} ->
+ {State1,Apps1} = set_compile_dirs1(State, Apps, {dir, SuiteDirs}),
+ {State2,Apps2} = set_compile_dirs1(State1, Apps1, {spec, Specs}),
+ [maybe_copy_spec(State2,Apps2,S) || S <- Specs],
+ {ok, rebar_state:project_apps(State2, Apps2)};
+ Error ->
+ Error
end.
join(Suite, Dir) when is_integer(hd(Suite)) ->
@@ -564,9 +574,6 @@ get_tests_from_specs(Specs) ->
case ct_testspec:collect_tests_from_file(Specs,true) of
Tests when is_list(Tests) ->
{ok,[{S,ct_testspec:prepare_tests(R)} || {S,R} <- Tests]};
- R when is_tuple(R), element(1,R)==testspec ->
- %% R15
- {ok,[{Specs,ct_testspec:prepare_tests(R)}]};
Error ->
Error
end
@@ -650,7 +657,11 @@ handle_results(_) ->
sum_results({Passed, Failed, {UserSkipped, AutoSkipped}},
{Passed2, Failed2, {UserSkipped2, AutoSkipped2}}) ->
{Passed+Passed2, Failed+Failed2,
- {UserSkipped+UserSkipped2, AutoSkipped+AutoSkipped2}}.
+ {UserSkipped+UserSkipped2, AutoSkipped+AutoSkipped2}};
+sum_results(_, {error, Reason}) ->
+ {error, Reason};
+sum_results(Unknown, _) ->
+ {error, Unknown}.
handle_quiet_results(_, {error, _} = Result) ->
handle_results(Result);
@@ -673,7 +684,10 @@ format_result({Passed, 0, {0, 0}}) ->
format_result({Passed, Failed, Skipped}) ->
Format = [format_failed(Failed), format_skipped(Skipped),
format_passed(Passed)],
- ?CONSOLE("~s", [Format]).
+ ?CONSOLE("~ts", [Format]);
+format_result(_Unknown) ->
+ %% Happens when CT itself encounters a bug
+ ok.
format_failed(0) ->
[];
@@ -705,17 +719,17 @@ maybe_write_coverdata(State) ->
rebar_prv_cover:maybe_write_coverdata(State1, ?PROVIDER).
ct_opts(_State) ->
- [{dir, undefined, "dir", string, help(dir)}, %% comma-seperated list
- {suite, undefined, "suite", string, help(suite)}, %% comma-seperated list
- {group, undefined, "group", string, help(group)}, %% comma-seperated list
- {testcase, undefined, "case", string, help(testcase)}, %% comma-seperated list
+ [{dir, undefined, "dir", string, help(dir)}, %% comma-separated list
+ {suite, undefined, "suite", string, help(suite)}, %% comma-separated list
+ {group, undefined, "group", string, help(group)}, %% comma-separated list
+ {testcase, undefined, "case", string, help(testcase)}, %% comma-separated list
{label, undefined, "label", string, help(label)}, %% String
- {config, undefined, "config", string, help(config)}, %% comma-seperated list
- {spec, undefined, "spec", string, help(spec)}, %% comma-seperated list
+ {config, undefined, "config", string, help(config)}, %% comma-separated list
+ {spec, undefined, "spec", string, help(spec)}, %% comma-separated list
{join_specs, undefined, "join_specs", boolean, help(join_specs)},
{allow_user_terms, undefined, "allow_user_terms", boolean, help(allow_user_terms)}, %% Bool
{logdir, undefined, "logdir", string, help(logdir)}, %% dir
- {logopts, undefined, "logopts", string, help(logopts)}, %% comma seperated list
+ {logopts, undefined, "logopts", string, help(logopts)}, %% comma-separated list
{verbosity, undefined, "verbosity", integer, help(verbosity)}, %% Integer
{cover, $c, "cover", {boolean, false}, help(cover)},
{repeat, undefined, "repeat", integer, help(repeat)}, %% integer
@@ -736,9 +750,12 @@ ct_opts(_State) ->
{name, undefined, "name", atom, help(name)},
{sname, undefined, "sname", atom, help(sname)},
{setcookie, undefined, "setcookie", atom, help(setcookie)},
- {sys_config, undefined, "sys_config", string, help(sys_config)} %% comma-seperated list
+ {sys_config, undefined, "sys_config", string, help(sys_config)}, %% comma-separated list
+ {compile_only, undefined, "compile_only", boolean, help(compile_only)}
].
+help(compile_only) ->
+ "Compile modules in the project with the test configuration but do not run the tests";
help(dir) ->
"List of additional directories containing test suites";
help(suite) ->
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index effc763..959ecb0 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -73,7 +73,7 @@ do(State) ->
-spec format_error(any()) -> iolist().
format_error({missing_artifact, File}) ->
- io_lib:format("Missing artifact ~s", [File]);
+ io_lib:format("Missing artifact ~ts", [File]);
format_error(Reason) ->
io_lib:format("~p", [Reason]).
@@ -114,7 +114,7 @@ compile(State, AppInfo) ->
compile(State, rebar_state:providers(State), AppInfo).
compile(State, Providers, AppInfo) ->
- ?INFO("Compiling ~s", [rebar_app_info:name(AppInfo)]),
+ ?INFO("Compiling ~ts", [rebar_app_info:name(AppInfo)]),
AppDir = rebar_app_info:dir(AppInfo),
AppInfo1 = rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, AppInfo, State),
@@ -173,8 +173,8 @@ has_all_artifacts(AppInfo1) ->
end.
copy_app_dirs(AppInfo, OldAppDir, AppDir) ->
- case ec_cnv:to_binary(filename:absname(OldAppDir)) =/=
- ec_cnv:to_binary(filename:absname(AppDir)) of
+ case rebar_utils:to_binary(filename:absname(OldAppDir)) =/=
+ rebar_utils:to_binary(filename:absname(AppDir)) of
true ->
EbinDir = filename:join([OldAppDir, "ebin"]),
%% copy all files from ebin if it exists
diff --git a/src/rebar_prv_cover.erl b/src/rebar_prv_cover.erl
index 865c557..fca7c40 100644
--- a/src/rebar_prv_cover.erl
+++ b/src/rebar_prv_cover.erl
@@ -215,18 +215,18 @@ print_analysis(Analysis, true) ->
format_table(Stats, CoverFiles) ->
MaxLength = max(lists:foldl(fun max_length/2, 0, Stats), 20),
Header = header(MaxLength),
- Seperator = seperator(MaxLength),
+ Separator = separator(MaxLength),
TotalLabel = format("total", MaxLength),
TotalCov = format(calculate_total(Stats), 8),
- [io_lib:format("~ts~n~ts~n~ts~n", [Seperator, Header, Seperator]),
+ [io_lib:format("~ts~n~ts~n~ts~n", [Separator, Header, Separator]),
lists:map(fun({Mod, Coverage}) ->
Name = format(Mod, MaxLength),
Cov = format(Coverage, 8),
io_lib:format(" | ~ts | ~ts |~n", [Name, Cov])
end, Stats),
- io_lib:format("~ts~n", [Seperator]),
+ io_lib:format("~ts~n", [Separator]),
io_lib:format(" | ~ts | ~ts |~n", [TotalLabel, TotalCov]),
- io_lib:format("~ts~n", [Seperator]),
+ io_lib:format("~ts~n", [Separator]),
io_lib:format(" coverage calculated from:~n", []),
lists:map(fun(File) ->
io_lib:format(" ~ts~n", [File])
@@ -242,7 +242,7 @@ max_length({ModName, _}, Min) ->
header(Width) ->
[" | ", format("module", Width), " | ", format("coverage", 8), " |"].
-seperator(Width) ->
+separator(Width) ->
[" |--", io_lib:format("~*c", [Width, $-]), "--|------------|"].
format(String, Width) -> io_lib:format("~*.ts", [Width, String]).
@@ -278,7 +278,7 @@ write_index(State, Coverage) ->
write_index_section(_F, []) -> ok;
write_index_section(F, [{Section, DataFile, Mods}|Rest]) ->
%% Write the report
- ok = file:write(F, ?FMT("<h1>~s summary</h1>\n", [Section])),
+ ok = file:write(F, ?FMT("<h1>~ts summary</h1>\n", [Section])),
ok = file:write(F, "coverage calculated from:\n<ul>"),
ok = lists:foreach(fun(D) -> ok = file:write(F, io_lib:format("<li>~ts</li>", [D])) end,
DataFile),
@@ -303,7 +303,7 @@ strip_coverdir(File) ->
2))).
cover_compile(State, apps) ->
- ExclApps = [list_to_binary(A) || A <- rebar_state:get(State, cover_excl_apps, [])],
+ ExclApps = [rebar_utils:to_binary(A) || A <- rebar_state:get(State, cover_excl_apps, [])],
Apps = filter_checkouts_and_excluded(rebar_state:project_apps(State), ExclApps),
AppDirs = app_dirs(Apps),
cover_compile(State, lists:filter(fun(D) -> ec_file:is_dir(D) end, AppDirs));
diff --git a/src/rebar_prv_deps.erl b/src/rebar_prv_deps.erl
index 9ff2bfa..a88b014 100644
--- a/src/rebar_prv_deps.erl
+++ b/src/rebar_prv_deps.erl
@@ -55,7 +55,7 @@ merge(Deps, SourceDeps) ->
normalize(Name) when is_binary(Name) ->
Name;
normalize(Name) when is_atom(Name) ->
- ec_cnv:to_binary(Name);
+ atom_to_binary(Name, unicode);
normalize(Dep) when is_tuple(Dep) ->
Name = element(1, Dep),
setelement(1, Dep, normalize(Name)).
@@ -87,31 +87,31 @@ display_deps(State, Deps) ->
%% packages
display_dep(_State, {Name, Vsn}) when is_list(Vsn) ->
- ?CONSOLE("~s* (package ~s)", [ec_cnv:to_binary(Name), ec_cnv:to_binary(Vsn)]);
+ ?CONSOLE("~ts* (package ~ts)", [rebar_utils:to_binary(Name), rebar_utils:to_binary(Vsn)]);
display_dep(_State, Name) when is_binary(Name) ->
- ?CONSOLE("~s* (package)", [Name]);
+ ?CONSOLE("~ts* (package)", [Name]);
display_dep(_State, {Name, Source}) when is_tuple(Source) ->
- ?CONSOLE("~s* (~s source)", [ec_cnv:to_binary(Name), type(Source)]);
+ ?CONSOLE("~ts* (~ts source)", [rebar_utils:to_binary(Name), type(Source)]);
display_dep(_State, {Name, _Vsn, Source}) when is_tuple(Source) ->
- ?CONSOLE("~s* (~s source)", [ec_cnv:to_binary(Name), type(Source)]);
+ ?CONSOLE("~ts* (~ts source)", [rebar_utils:to_binary(Name), type(Source)]);
display_dep(_State, {Name, _Vsn, Source, _Opts}) when is_tuple(Source) ->
- ?CONSOLE("~s* (~s source)", [ec_cnv:to_binary(Name), type(Source)]);
+ ?CONSOLE("~ts* (~ts source)", [rebar_utils:to_binary(Name), type(Source)]);
%% Locked
display_dep(State, {Name, Source={pkg, _, Vsn}, Level}) when is_integer(Level) ->
DepsDir = rebar_dir:deps_dir(State),
- AppDir = filename:join([DepsDir, ec_cnv:to_binary(Name)]),
+ AppDir = filename:join([DepsDir, rebar_utils:to_binary(Name)]),
NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source, State) of
true -> "*";
false -> ""
end,
- ?CONSOLE("~s~s (locked package ~s)", [Name, NeedsUpdate, Vsn]);
+ ?CONSOLE("~ts~ts (locked package ~ts)", [Name, NeedsUpdate, Vsn]);
display_dep(State, {Name, Source, Level}) when is_tuple(Source), is_integer(Level) ->
DepsDir = rebar_dir:deps_dir(State),
- AppDir = filename:join([DepsDir, ec_cnv:to_binary(Name)]),
+ AppDir = filename:join([DepsDir, rebar_utils:to_binary(Name)]),
NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source, State) of
true -> "*";
false -> ""
end,
- ?CONSOLE("~s~s (locked ~s source)", [Name, NeedsUpdate, type(Source)]).
+ ?CONSOLE("~ts~ts (locked ~ts source)", [Name, NeedsUpdate, type(Source)]).
type(Source) when is_tuple(Source) -> element(1, Source).
diff --git a/src/rebar_prv_deps_tree.erl b/src/rebar_prv_deps_tree.erl
index c0c8bab..7c6978b 100644
--- a/src/rebar_prv_deps_tree.erl
+++ b/src/rebar_prv_deps_tree.erl
@@ -90,7 +90,7 @@ type(Source, Verbose) when is_tuple(Source) ->
{pkg, _} ->
"hex package";
{Other, false} ->
- io_lib:format("~s repo", [Other]);
+ io_lib:format("~ts repo", [Other]);
{_, true} ->
- io_lib:format("~s", [element(2, Source)])
+ io_lib:format("~ts", [element(2, Source)])
end.
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 21d7f5a..a74eefb 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -116,18 +116,18 @@ maybe_fix_env() ->
-spec format_error(any()) -> iolist().
format_error({error_processing_apps, Error}) ->
- io_lib:format("Error in dialyzing apps: ~s", [Error]);
+ io_lib:format("Error in dialyzing apps: ~ts", [Error]);
format_error({dialyzer_warnings, Warnings}) ->
- io_lib:format("Warnings occured running dialyzer: ~b", [Warnings]);
+ io_lib:format("Warnings occurred running dialyzer: ~b", [Warnings]);
format_error({unknown_application, App}) ->
- io_lib:format("Could not find application: ~s", [App]);
+ io_lib:format("Could not find application: ~ts", [App]);
format_error({unknown_module, Mod}) ->
- io_lib:format("Could not find module: ~s", [Mod]);
+ io_lib:format("Could not find module: ~ts", [Mod]);
format_error({duplicate_module, Mod, File1, File2}) ->
- io_lib:format("Duplicates of module ~s: ~s ~s", [Mod, File1, File2]);
+ io_lib:format("Duplicates of module ~ts: ~ts ~ts", [Mod, File1, File2]);
format_error({output_file_error, File, Error}) ->
Error1 = file:format_error(Error),
- io_lib:format("Failed to write to ~s: ~s", [File, Error1]);
+ io_lib:format("Failed to write to ~ts: ~ts", [File, Error1]);
format_error(Reason) ->
io_lib:format("~p", [Reason]).
@@ -155,7 +155,7 @@ do(State, Plt) ->
0 ->
{ok, State2};
TotalWarnings ->
- ?INFO("Warnings written to ~s", [Output]),
+ ?INFO("Warnings written to ~ts", [Output]),
throw({dialyzer_warnings, TotalWarnings})
end.
@@ -229,7 +229,7 @@ apps_files([AppName | DepApps], SkipApps, Files) ->
apps_files(DepApps, SkipApps, Files);
false ->
AppFiles = app_files(AppName),
- ?DEBUG("~s modules: ~p", [AppName, dict:fetch_keys(AppFiles)]),
+ ?DEBUG("~ts modules: ~p", [AppName, dict:fetch_keys(AppFiles)]),
Files2 = merge_files(Files, AppFiles),
apps_files(DepApps, [AppName | SkipApps], Files2)
end.
@@ -505,7 +505,7 @@ format_warnings(Opts, Output, Warnings) ->
length(Warnings).
console_warnings(Warnings) ->
- _ = [?CONSOLE("~s", [Warning]) || Warning <- Warnings],
+ _ = [?CONSOLE("~ts", [Warning]) || Warning <- Warnings],
ok.
file_warnings(_, []) ->
diff --git a/src/rebar_prv_edoc.erl b/src/rebar_prv_edoc.erl
index 97f70a9..9517335 100644
--- a/src/rebar_prv_edoc.erl
+++ b/src/rebar_prv_edoc.erl
@@ -42,8 +42,8 @@ do(State) ->
Res = try
lists:foldl(fun(AppInfo, EdocOptsAcc) ->
rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, AppInfo, State),
- AppName = ec_cnv:to_list(rebar_app_info:name(AppInfo)),
- ?INFO("Running edoc for ~s", [AppName]),
+ AppName = rebar_utils:to_list(rebar_app_info:name(AppInfo)),
+ ?INFO("Running edoc for ~ts", [AppName]),
AppDir = rebar_app_info:dir(AppInfo),
AppRes = (catch edoc:application(list_to_atom(AppName), AppDir, EdocOptsAcc)),
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, AppInfo, State),
@@ -74,7 +74,7 @@ do(State) ->
-spec format_error(any()) -> iolist().
format_error({app_failed, AppName}) ->
- io_lib:format("Failed to generate documentation for app '~s'", [AppName]);
+ io_lib:format("Failed to generate documentation for app '~ts'", [AppName]);
format_error(Reason) ->
io_lib:format("~p", [Reason]).
@@ -89,4 +89,4 @@ add_to_paths([], Path) ->
add_to_paths([{doc_path, Paths}|T], Path) ->
[{doc_path, [Path | Paths]} | T];
add_to_paths([H|T], Path) ->
- [H | add_to_paths(Path, T)].
+ [H | add_to_paths(T, Path)].
diff --git a/src/rebar_prv_escriptize.erl b/src/rebar_prv_escriptize.erl
index 7ee20c2..cffbbdc 100644
--- a/src/rebar_prv_escriptize.erl
+++ b/src/rebar_prv_escriptize.erl
@@ -75,7 +75,7 @@ do(State) ->
end;
Name ->
AllApps = rebar_state:all_deps(State)++rebar_state:project_apps(State),
- case rebar_app_utils:find(ec_cnv:to_binary(Name), AllApps) of
+ case rebar_app_utils:find(rebar_utils:to_binary(Name), AllApps) of
{ok, AppInfo} ->
escriptize(State, AppInfo);
_ ->
@@ -87,12 +87,12 @@ do(State) ->
escriptize(State0, App) ->
AppName = rebar_app_info:name(App),
- AppNameStr = ec_cnv:to_list(AppName),
+ AppNameStr = rebar_utils:to_list(AppName),
%% Get the output filename for the escript -- this may include dirs
Filename = filename:join([rebar_dir:base_dir(State0), "bin",
rebar_state:get(State0, escript_name, AppName)]),
- ?DEBUG("Creating escript file ~s", [Filename]),
+ ?DEBUG("Creating escript file ~ts", [Filename]),
ok = filelib:ensure_dir(Filename),
State = rebar_state:escript_path(State0, Filename),
@@ -116,7 +116,7 @@ escriptize(State0, App) ->
ExtraFiles = usort(InclBeams ++ InclExtra),
Files = get_nonempty(EbinFiles ++ ExtraFiles),
- DefaultEmuArgs = ?FMT("%%! -escript main ~s -pz ~s/~s/ebin\n",
+ DefaultEmuArgs = ?FMT("%%! -escript main ~ts -pz ~ts/~ts/ebin\n",
[AppNameStr, AppNameStr, AppNameStr]),
EscriptSections =
[ {shebang,
@@ -130,9 +130,15 @@ escriptize(State0, App) ->
throw(?PRV_ERROR({escript_creation_failed, AppName, EscriptError}))
end,
- %% Finally, update executable perms for our script
- {ok, #file_info{mode = Mode}} = file:read_file_info(Filename),
- ok = file:change_mode(Filename, Mode bor 8#00111),
+ %% Finally, update executable perms for our script on *nix or write out
+ %% script files on win32
+ case os:type() of
+ {unix, _} ->
+ {ok, #file_info{mode = Mode}} = file:read_file_info(Filename),
+ ok = file:change_mode(Filename, Mode bor 8#00111);
+ {win32, _} ->
+ write_windows_script(Filename)
+ end,
{ok, State}.
-spec format_error(any()) -> iolist().
@@ -157,7 +163,7 @@ get_apps_beams(Apps, AllApps) ->
get_apps_beams([], _, Acc) ->
Acc;
get_apps_beams([App | Rest], AllApps, Acc) ->
- case rebar_app_utils:find(ec_cnv:to_binary(App), AllApps) of
+ case rebar_app_utils:find(rebar_utils:to_binary(App), AllApps) of
{ok, App1} ->
OutDir = filename:absname(rebar_app_info:ebin_dir(App1)),
Beams = get_app_beams(App, OutDir),
@@ -229,7 +235,7 @@ get_nonempty(Files) ->
[{FName,FBin} || {FName,FBin} <- Files, FBin =/= <<>>].
find_deps(AppNames, AllApps) ->
- BinAppNames = [ec_cnv:to_binary(Name) || Name <- AppNames],
+ BinAppNames = [rebar_utils:to_binary(Name) || Name <- AppNames],
[ec_cnv:to_atom(Name) ||
Name <- find_deps_of_deps(BinAppNames, AllApps, BinAppNames)].
@@ -239,7 +245,7 @@ find_deps_of_deps([Name|Names], Apps, Acc) ->
?DEBUG("processing ~p", [Name]),
{ok, App} = rebar_app_utils:find(Name, Apps),
DepNames = proplists:get_value(applications, rebar_app_info:app_details(App), []),
- BinDepNames = [ec_cnv:to_binary(Dep) || Dep <- DepNames,
+ BinDepNames = [rebar_utils:to_binary(Dep) || Dep <- DepNames,
%% ignore system libs; shouldn't include them.
DepDir <- [code:lib_dir(Dep)],
DepDir =:= {error, bad_name} orelse % those are all local
@@ -258,3 +264,14 @@ def(Rm, State, Key, Default) ->
rm_newline(String) ->
[C || C <- String, C =/= $\n].
+
+write_windows_script(Target) ->
+ CmdPath = if is_binary(Target) -> <<Target/binary, ".cmd">>;
+ is_list(Target) -> Target ++ ".cmd"
+ end,
+ CmdScript=
+ "@echo off\r\n"
+ "setlocal\r\n"
+ "set rebarscript=%~f0\r\n"
+ "escript.exe \"%rebarscript:.cmd=%\" %*\r\n",
+ ok = file:write_file(CmdPath, CmdScript).
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index 7d44137..65addc3 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -83,13 +83,16 @@ run_tests(State, Tests) ->
EUnitOpts = resolve_eunit_opts(State),
?DEBUG("eunit_tests ~p", [T]),
?DEBUG("eunit_opts ~p", [EUnitOpts]),
- Result = eunit:test(T, EUnitOpts),
- ok = maybe_write_coverdata(State),
- case handle_results(Result) of
- {error, Reason} ->
- ?PRV_ERROR(Reason);
- ok ->
- {ok, State}
+ try eunit:test(T, EUnitOpts) of
+ Result ->
+ ok = maybe_write_coverdata(State),
+ case handle_results(Result) of
+ {error, Reason} ->
+ ?PRV_ERROR(Reason);
+ ok ->
+ {ok, State}
+ end
+ catch error:badarg -> ?PRV_ERROR({error, badarg})
end.
-spec format_error(any()) -> iolist().
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index c9fe0ad..65aabff 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -104,22 +104,22 @@ do_(State) ->
%% @doc convert a given exception's payload into an io description.
-spec format_error(any()) -> iolist().
format_error({dep_app_not_found, AppDir, AppName}) ->
- io_lib:format("Dependency failure: Application ~s not found at the top level of directory ~s", [AppName, AppDir]);
+ io_lib:format("Dependency failure: Application ~ts not found at the top level of directory ~ts", [AppName, AppDir]);
format_error({load_registry_fail, Dep}) ->
- io_lib:format("Error loading registry to resolve version of ~s. Try fixing by running 'rebar3 update'", [Dep]);
+ io_lib:format("Error loading registry to resolve version of ~ts. Try fixing by running 'rebar3 update'", [Dep]);
format_error({bad_constraint, Name, Constraint}) ->
- io_lib:format("Unable to parse version for package ~s: ~s", [Name, Constraint]);
+ io_lib:format("Unable to parse version for package ~ts: ~ts", [Name, Constraint]);
format_error({parse_dep, Dep}) ->
io_lib:format("Failed parsing dep ~p", [Dep]);
format_error({not_rebar_package, Package, Version}) ->
- io_lib:format("Package not buildable with rebar3: ~s-~s", [Package, Version]);
+ io_lib:format("Package not buildable with rebar3: ~ts-~ts", [Package, Version]);
format_error({missing_package, Package, Version}) ->
- io_lib:format("Package not found in registry: ~s-~s", [Package, Version]);
+ io_lib:format("Package not found in registry: ~ts-~ts", [Package, Version]);
format_error({missing_package, Package}) ->
- io_lib:format("Package not found in registry: ~s", [Package]);
+ io_lib:format("Package not found in registry: ~ts", [Package]);
format_error({cycles, Cycles}) ->
Prints = [["applications: ",
- [io_lib:format("~s ", [Dep]) || Dep <- Cycle],
+ [io_lib:format("~ts ", [Dep]) || Dep <- Cycle],
"depend on each other\n"]
|| Cycle <- Cycles],
["Dependency cycle(s) detected:\n", Prints];
@@ -140,7 +140,9 @@ handle_deps_as_profile(Profile, State, Deps, Upgrade) ->
DepsDir = profile_dep_dir(State, Profile),
Deps1 = rebar_app_utils:parse_deps(DepsDir, Deps, State, Locks, Level),
ProfileLevelDeps = [{Profile, Deps1, Level}],
- handle_profile_level(ProfileLevelDeps, [], sets:new(), Upgrade, Locks, State).
+ RootSeen = sets:from_list([rebar_app_info:name(AppInfo)
+ || AppInfo <- rebar_state:project_apps(State)]),
+ handle_profile_level(ProfileLevelDeps, [], RootSeen, RootSeen, Upgrade, Locks, State).
%% ===================================================================
%% Internal functions
@@ -153,7 +155,9 @@ deps_per_profile(Profiles, Upgrade, State) ->
Deps = lists:foldl(fun(Profile, DepAcc) ->
[parsed_profile_deps(State, Profile, Level) | DepAcc]
end, [], Profiles),
- handle_profile_level(Deps, [], sets:new(), Upgrade, Locks, State).
+ RootSeen = sets:from_list([rebar_app_info:name(AppInfo)
+ || AppInfo <- rebar_state:project_apps(State)]),
+ handle_profile_level(Deps, [], RootSeen, RootSeen, Upgrade, Locks, State).
parsed_profile_deps(State, Profile, Level) ->
ParsedDeps = rebar_state:get(State, {parsed_deps, Profile}, []),
@@ -162,17 +166,27 @@ parsed_profile_deps(State, Profile, Level) ->
%% Level-order traversal of all dependencies, across profiles.
%% If profiles x,y,z are present, then the traversal will go:
%% x0, y0, z0, x1, y1, z1, ..., xN, yN, zN.
-handle_profile_level([], Apps, _Seen, _Upgrade, _Locks, State) ->
+%%
+%% There are two 'seen' sets: one for the top-level apps (`RootSeen') and
+%% one for all dependencies (`Seen'). The former is used to know when
+%% to skip the resolving of dependencies altogether (since they're already
+%% top-level apps), while the latter is used to prevent reprocessing
+%% deps more than one.
+handle_profile_level([], Apps, _RootSeen, _Seen, _Upgrade, _Locks, State) ->
{Apps, State};
-handle_profile_level([{Profile, Deps, Level} | Rest], Apps, Seen, Upgrade, Locks, State) ->
+handle_profile_level([{Profile, Deps, Level} | Rest], Apps, RootSeen, Seen, Upgrade, Locks, State) ->
+ Deps0 = [rebar_app_utils:expand_deps_sources(Dep, State)
+ || Dep <- Deps,
+ %% skip top-level apps being double-declared
+ not sets:is_element(rebar_app_info:name(Dep), RootSeen)],
{Deps1, Apps1, State1, Seen1} =
- update_deps(Profile, Level, Deps, Apps
+ update_deps(Profile, Level, Deps0, Apps
,State, Upgrade, Seen, Locks),
Deps2 = case Deps1 of
[] -> Rest;
_ -> Rest ++ [{Profile, Deps1, Level+1}]
end,
- handle_profile_level(Deps2, Apps1, sets:union(Seen, Seen1), Upgrade, Locks, State1).
+ handle_profile_level(Deps2, Apps1, RootSeen, sets:union(Seen, Seen1), Upgrade, Locks, State1).
find_cycles(Apps) ->
case rebar_digraph:compile_order(Apps) of
@@ -291,7 +305,7 @@ handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->
-spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),
sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}.
maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
- AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
+ AppDir = rebar_utils:to_list(rebar_app_info:dir(AppInfo)),
%% Don't fetch dep if it exists in the _checkouts dir
case rebar_app_info:is_checkout(AppInfo) of
true ->
@@ -346,7 +360,7 @@ symlink_dep(State, From, To) ->
ok ->
RelativeFrom = make_relative_to_root(State, From),
RelativeTo = make_relative_to_root(State, To),
- ?INFO("Linking ~s to ~s", [RelativeFrom, RelativeTo]),
+ ?INFO("Linking ~ts to ~ts", [RelativeFrom, RelativeTo]),
ok;
exists ->
ok
@@ -359,7 +373,7 @@ make_relative_to_root(State, Path) when is_list(Path) ->
rebar_dir:make_relative_path(Path, Root).
fetch_app(AppInfo, AppDir, State) ->
- ?INFO("Fetching ~s (~p)", [rebar_app_info:name(AppInfo),
+ ?INFO("Fetching ~ts (~p)", [rebar_app_info:name(AppInfo),
format_source(rebar_app_info:source(AppInfo))]),
Source = rebar_app_info:source(AppInfo),
true = rebar_fetch:download_source(AppDir, Source, State).
@@ -384,12 +398,12 @@ maybe_upgrade(AppInfo, AppDir, Upgrade, State) ->
true ->
case rebar_fetch:needs_update(AppDir, Source, State) of
true ->
- ?INFO("Upgrading ~s (~p)", [rebar_app_info:name(AppInfo), rebar_app_info:source(AppInfo)]),
+ ?INFO("Upgrading ~ts (~p)", [rebar_app_info:name(AppInfo), rebar_app_info:source(AppInfo)]),
true = rebar_fetch:download_source(AppDir, Source, State);
false ->
case Upgrade of
true ->
- ?INFO("No upgrade needed for ~s", [rebar_app_info:name(AppInfo)]),
+ ?INFO("No upgrade needed for ~ts", [rebar_app_info:name(AppInfo)]),
false;
false ->
false
@@ -400,7 +414,7 @@ maybe_upgrade(AppInfo, AppDir, Upgrade, State) ->
end.
warn_skip_deps(AppInfo, State) ->
- Msg = "Skipping ~s (from ~p) as an app of the same name "
+ Msg = "Skipping ~ts (from ~p) as an app of the same name "
"has already been fetched",
Args = [rebar_app_info:name(AppInfo),
rebar_app_info:source(AppInfo)],
diff --git a/src/rebar_prv_local_install.erl b/src/rebar_prv_local_install.erl
index 1b58859..282c548 100644
--- a/src/rebar_prv_local_install.erl
+++ b/src/rebar_prv_local_install.erl
@@ -60,7 +60,7 @@ format_error(Reason) ->
bin_contents(OutputDir) ->
<<"#!/usr/bin/env sh
-erl -pz ", (ec_cnv:to_binary(OutputDir))/binary,"/*/ebin +sbtu +A0 -noshell -boot start_clean -s rebar3 main $REBAR3_ERL_ARGS -extra \"$@\"
+erl -pz ", (rebar_utils:to_binary(OutputDir))/binary,"/*/ebin +sbtu +A0 -noshell -boot start_clean -s rebar3 main $REBAR3_ERL_ARGS -extra \"$@\"
">>.
extract_escript(State, ScriptPath) ->
@@ -73,7 +73,7 @@ extract_escript(State, ScriptPath) ->
OutputDir = filename:join(rebar_dir:global_cache_dir(Opts), "lib"),
filelib:ensure_dir(filename:join(OutputDir, "empty")),
- ?INFO("Extracting rebar3 libs to ~s...", [OutputDir]),
+ ?INFO("Extracting rebar3 libs to ~ts...", [OutputDir]),
zip:extract(Archive, [{cwd, OutputDir}]),
BinDir = filename:join(rebar_dir:global_cache_dir(Opts), "bin"),
@@ -84,12 +84,12 @@ extract_escript(State, ScriptPath) ->
uid = Uid,
gid = Gid}} = file:read_file_info(ScriptPath),
- ?INFO("Writing rebar3 run script ~s...", [BinFile]),
+ ?INFO("Writing rebar3 run script ~ts...", [BinFile]),
file:write_file(BinFile, bin_contents(OutputDir)),
ok = file:write_file_info(BinFile, #file_info{mode=33277,
uid=Uid,
gid=Gid}),
- ?INFO("Add to $PATH for use: export PATH=$PATH:~s", [BinDir]),
+ ?INFO("Add to $PATH for use: export PATH=~ts:$PATH", [BinDir]),
{ok, State}.
diff --git a/src/rebar_prv_new.erl b/src/rebar_prv_new.erl
index 152a56e..f632362 100644
--- a/src/rebar_prv_new.erl
+++ b/src/rebar_prv_new.erl
@@ -60,7 +60,7 @@ do(State) ->
-spec format_error(any()) -> iolist().
format_error({consult, File, Reason}) ->
- io_lib:format("Error consulting file at ~s for reason ~p", [File, Reason]);
+ io_lib:format("Error consulting file at ~ts for reason ~p", [File, Reason]);
format_error(Reason) ->
io_lib:format("~p", [Reason]).
@@ -70,7 +70,7 @@ format_error(Reason) ->
list_templates(State) ->
lists:foldl(fun({error, {consult, File, Reason}}, Acc) ->
- ?WARN("Error consulting template file ~s for reason ~p",
+ ?WARN("Error consulting template file ~ts for reason ~p",
[File, Reason]),
Acc
; (Tpl, Acc) ->
@@ -116,16 +116,16 @@ show_short_templates(List) ->
lists:map(fun show_short_template/1, lists:sort(List)).
show_short_template({Name, Type, _Location, Description, _Vars}) ->
- io:format("~s (~s): ~s~n",
+ io:format("~ts (~ts): ~ts~n",
[Name,
format_type(Type),
format_description(Description)]).
show_template({Name, Type, Location, Description, Vars}) ->
- io:format("~s:~n"
- "\t~s~n"
- "\tDescription: ~s~n"
- "\tVariables:~n~s~n",
+ io:format("~ts:~n"
+ "\t~ts~n"
+ "\tDescription: ~ts~n"
+ "\tVariables:~n~ts~n",
[Name,
format_type(Type, Location),
format_description(Description),
@@ -141,9 +141,9 @@ format_type(escript, _) ->
format_type(builtin, _) ->
"built-in template";
format_type(plugin, Loc) ->
- io_lib:format("plugin template (~s)", [Loc]);
+ io_lib:format("plugin template (~ts)", [Loc]);
format_type(file, Loc) ->
- io_lib:format("custom template (~s)", [Loc]).
+ io_lib:format("custom template (~ts)", [Loc]).
format_description(Description) ->
case Description of
@@ -156,4 +156,4 @@ format_vars(Vars) -> [format_var(Var) || Var <- Vars].
format_var({Var, Default}) ->
io_lib:format("\t\t~p=~p~n",[Var, Default]);
format_var({Var, Default, Doc}) ->
- io_lib:format("\t\t~p=~p (~s)~n", [Var, Default, Doc]).
+ io_lib:format("\t\t~p=~p (~ts)~n", [Var, Default, Doc]).
diff --git a/src/rebar_prv_packages.erl b/src/rebar_prv_packages.erl
index 7217ab8..6e8e683 100644
--- a/src/rebar_prv_packages.erl
+++ b/src/rebar_prv_packages.erl
@@ -30,7 +30,7 @@ do(State) ->
rebar_packages:packages(State),
case rebar_state:command_args(State) of
[Name] ->
- print_packages(get_packages(iolist_to_binary(Name)));
+ print_packages(get_packages(rebar_utils:to_binary(Name)));
_ ->
print_packages(sort_packages())
end,
@@ -47,7 +47,7 @@ print_packages(Pkgs) ->
,ec_semver:parse(B))
end, Vsns),
VsnStr = join(SortedVsns, <<", ">>),
- ?CONSOLE("~s:~n Versions: ~s~n", [Name, VsnStr])
+ ?CONSOLE("~ts:~n Versions: ~ts~n", [Name, VsnStr])
end, Pkgs).
sort_packages() ->
@@ -71,4 +71,4 @@ join([Bin | T], Sep) ->
info(Description) ->
- io_lib:format("~s.~n", [Description]).
+ io_lib:format("~ts.~n", [Description]).
diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl
index 4259eec..75d38eb 100644
--- a/src/rebar_prv_path.erl
+++ b/src/rebar_prv_path.erl
@@ -27,7 +27,7 @@ init(State) ->
{example, "rebar3 path"},
{short_desc, "Print paths to build dirs in current profile."},
{desc, "Print paths to build dirs in current profile."},
- {opts, eunit_opts(State)}])),
+ {opts, path_opts(State)}])),
{ok, State1}.
@@ -75,23 +75,23 @@ paths([{src, true}|Rest], Apps, State, Acc) ->
paths([{rel, true}|Rest], Apps, State, Acc) ->
paths(Rest, Apps, State, [rel_dir(State)|Acc]).
-base_dir(State) -> io_lib:format("~s", [rebar_dir:base_dir(State)]).
-bin_dir(State) -> io_lib:format("~s/bin", [rebar_dir:base_dir(State)]).
-lib_dir(State) -> io_lib:format("~s", [rebar_dir:deps_dir(State)]).
-rel_dir(State) -> io_lib:format("~s/rel", [rebar_dir:base_dir(State)]).
+base_dir(State) -> io_lib:format("~ts", [rebar_dir:base_dir(State)]).
+bin_dir(State) -> io_lib:format("~ts/bin", [rebar_dir:base_dir(State)]).
+lib_dir(State) -> io_lib:format("~ts", [rebar_dir:deps_dir(State)]).
+rel_dir(State) -> io_lib:format("~ts/rel", [rebar_dir:base_dir(State)]).
ebin_dirs(Apps, State) ->
- lists:map(fun(App) -> io_lib:format("~s/~s/ebin", [rebar_dir:deps_dir(State), App]) end, Apps).
+ lists:map(fun(App) -> io_lib:format("~ts/~ts/ebin", [rebar_dir:deps_dir(State), App]) end, Apps).
priv_dirs(Apps, State) ->
- lists:map(fun(App) -> io_lib:format("~s/~s/priv", [rebar_dir:deps_dir(State), App]) end, Apps).
+ lists:map(fun(App) -> io_lib:format("~ts/~ts/priv", [rebar_dir:deps_dir(State), App]) end, Apps).
src_dirs(Apps, State) ->
- lists:map(fun(App) -> io_lib:format("~s/~s/src", [rebar_dir:deps_dir(State), App]) end, Apps).
+ lists:map(fun(App) -> io_lib:format("~ts/~ts/src", [rebar_dir:deps_dir(State), App]) end, Apps).
print_paths_if_exist(Paths, State) ->
{RawOpts, _} = rebar_state:command_parsed_args(State),
Sep = proplists:get_value(separator, RawOpts, " "),
RealPaths = lists:filter(fun(P) -> ec_file:is_dir(P) end, Paths),
- io:format("~s", [string:join(RealPaths, Sep)]).
+ io:format("~ts", [string:join(RealPaths, Sep)]).
project_deps(State) ->
Profiles = rebar_state:current_profiles(State),
@@ -107,7 +107,7 @@ normalize(AppName) when is_list(AppName) -> AppName;
normalize(AppName) when is_atom(AppName) -> atom_to_list(AppName);
normalize(AppName) when is_binary(AppName) -> binary_to_list(AppName).
-eunit_opts(_State) ->
+path_opts(_State) ->
[{app, undefined, "app", string, help(app)},
{base, undefined, "base", boolean, help(base)},
{bin, undefined, "bin", boolean, help(bin)},
@@ -118,7 +118,7 @@ eunit_opts(_State) ->
{src, undefined, "src", boolean, help(src)},
{rel, undefined, "rel", boolean, help(rel)}].
-help(app) -> "Comma seperated list of applications to return paths for.";
+help(app) -> "Comma separated list of applications to return paths for.";
help(base) -> "Return the `base' path of the current profile.";
help(bin) -> "Return the `bin' path of the current profile.";
help(ebin) -> "Return all `ebin' paths of the current profile's applications.";
diff --git a/src/rebar_prv_plugins.erl b/src/rebar_prv_plugins.erl
index 7e6b88e..4bea3b3 100644
--- a/src/rebar_prv_plugins.erl
+++ b/src/rebar_prv_plugins.erl
@@ -34,14 +34,17 @@ do(State) ->
GlobalConfigFile = rebar_dir:global_config(),
GlobalConfig = rebar_state:new(rebar_config:consult_file(GlobalConfigFile)),
GlobalPlugins = rebar_state:get(GlobalConfig, plugins, []),
+ GlobalSrcDirs = rebar_state:get(GlobalConfig, src_dirs, ["src"]),
GlobalPluginsDir = filename:join([rebar_dir:global_cache_dir(rebar_state:opts(State)), "plugins", "*"]),
- GlobalApps = rebar_app_discover:find_apps([GlobalPluginsDir], all),
+ GlobalApps = rebar_app_discover:find_apps([GlobalPluginsDir], GlobalSrcDirs, all),
display_plugins("Global plugins", GlobalApps, GlobalPlugins),
+ RebarOpts = rebar_state:opts(State),
+ SrcDirs = rebar_dir:src_dirs(RebarOpts, ["src"]),
Plugins = rebar_state:get(State, plugins, []),
- PluginsDir = filename:join(rebar_dir:plugins_dir(State), "*"),
- CheckoutsDir = filename:join(rebar_dir:checkouts_dir(State), "*"),
- Apps = rebar_app_discover:find_apps([CheckoutsDir, PluginsDir], all),
+ PluginsDirs = filelib:wildcard(filename:join(rebar_dir:plugins_dir(State), "*")),
+ CheckoutsDirs = filelib:wildcard(filename:join(rebar_dir:checkouts_dir(State), "*")),
+ Apps = rebar_app_discover:find_apps(CheckoutsDirs++PluginsDirs, SrcDirs, all),
display_plugins("Local plugins", Apps, Plugins),
{ok, State}.
@@ -52,19 +55,19 @@ format_error(Reason) ->
display_plugins(_Header, _Apps, []) ->
ok;
display_plugins(Header, Apps, Plugins) ->
- ?CONSOLE("--- ~s ---", [Header]),
+ ?CONSOLE("--- ~ts ---", [Header]),
display_plugins(Apps, Plugins),
?CONSOLE("", []).
display_plugins(Apps, Plugins) ->
lists:foreach(fun(Plugin) ->
- Name = if is_atom(Plugin) -> ec_cnv:to_binary(Plugin);
- is_tuple(Plugin) -> ec_cnv:to_binary(element(1, Plugin))
+ Name = if is_atom(Plugin) -> atom_to_binary(Plugin, unicode);
+ is_tuple(Plugin) -> rebar_utils:to_binary(element(1, Plugin))
end,
case rebar_app_utils:find(Name, Apps) of
{ok, _App} ->
- ?CONSOLE("~s", [Name]);
+ ?CONSOLE("~ts", [Name]);
error ->
- ?DEBUG("Unable to find plugin ~s", [Name])
+ ?DEBUG("Unable to find plugin ~ts", [Name])
end
end, Plugins).
diff --git a/src/rebar_prv_plugins_upgrade.erl b/src/rebar_prv_plugins_upgrade.erl
index 03521c7..7420c83 100644
--- a/src/rebar_prv_plugins_upgrade.erl
+++ b/src/rebar_prv_plugins_upgrade.erl
@@ -44,7 +44,7 @@ do(State) ->
format_error(no_plugin_arg) ->
io_lib:format("Must give an installed plugin to upgrade as an argument", []);
format_error({not_found, Plugin}) ->
- io_lib:format("Plugin to upgrade not found: ~s", [Plugin]);
+ io_lib:format("Plugin to upgrade not found: ~ts", [Plugin]);
format_error(Reason) ->
io_lib:format("~p", [Reason]).
diff --git a/src/rebar_prv_report.erl b/src/rebar_prv_report.erl
index d6c8b60..73e9624 100644
--- a/src/rebar_prv_report.erl
+++ b/src/rebar_prv_report.erl
@@ -44,7 +44,7 @@ do(State) ->
{ok, Vsn} = application:get_key(rebar, vsn),
{ok, Apps} = application:get_key(rebar, applications),
[application:load(App) || App <- Apps],
- Vsns = [io_lib:format("~p: ~s~n", [App, AVsn])
+ Vsns = [io_lib:format("~p: ~ts~n", [App, AVsn])
|| App <- lists:sort(Apps),
{ok, AVsn} <- [application:get_key(App, vsn)]],
%% Show OS and versions
@@ -59,10 +59,10 @@ do(State) ->
%%
?CONSOLE(
"Rebar3 report~n"
- " version ~s~n"
- " generated at ~s~n"
+ " version ~ts~n"
+ " generated at ~ts~n"
"=================~n"
- "Please submit this along with your issue at ~s "
+ "Please submit this along with your issue at ~ts "
"(and feel free to edit out private information, if any)~n"
"-----------------~n"
"Task: ~ts~n"
@@ -75,11 +75,11 @@ do(State) ->
"Library directory: ~ts~n"
"-----------------~n"
"Loaded Applications:~n"
- "~s~n"
+ "~ts~n"
"-----------------~n"
"Escript path: ~ts~n"
"Providers:~n"
- " ~s",
+ " ~ts",
[Vsn, time_to_string(UTC),
?ISSUES_URL, Command, Task,
OS, ERTS, Root, Lib,
@@ -100,4 +100,4 @@ time_to_string({{Y,M,D},{H,Min,S}}) ->
[Y,M,D,H,Min,S])).
parse_task(Str) ->
- hd(re:split(Str, " ")).
+ hd(re:split(Str, " ", [unicode])).
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index c1bf735..c958dde 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -360,8 +360,10 @@ boot_apps(Apps) ->
ok.
normalize_load_apps([]) -> [];
+normalize_load_apps([{_App, none} | T]) -> normalize_load_apps(T);
normalize_load_apps([{App, _} | T]) -> [App | normalize_load_apps(T)];
normalize_load_apps([{App, _Vsn, load} | T]) -> [App | normalize_load_apps(T)];
+normalize_load_apps([{_App, _Vsn, none} | T]) -> normalize_load_apps(T);
normalize_load_apps([{App, _Vsn, Operator} | T]) when is_atom(Operator) ->
[App | normalize_load_apps(T)];
normalize_load_apps([App | T]) when is_atom(App) -> [App | normalize_load_apps(T)].
@@ -369,12 +371,13 @@ normalize_load_apps([App | T]) when is_atom(App) -> [App | normalize_load_apps(T
normalize_boot_apps([]) -> [];
normalize_boot_apps([{_App, load} | T]) -> normalize_boot_apps(T);
normalize_boot_apps([{_App, _Vsn, load} | T]) -> normalize_boot_apps(T);
+normalize_boot_apps([{_App, none} | T]) -> normalize_boot_apps(T);
+normalize_boot_apps([{_App, _Vsn, none} | T]) -> normalize_boot_apps(T);
normalize_boot_apps([{App, _Vsn, Operator} | T]) when is_atom(Operator) ->
[App | normalize_boot_apps(T)];
normalize_boot_apps([{App, _Vsn} | T]) -> [App | normalize_boot_apps(T)];
normalize_boot_apps([App | T]) when is_atom(App) -> [App | normalize_boot_apps(T)].
-
remove_error_handler(0) ->
?WARN("Unable to remove simple error_logger handler", []);
remove_error_handler(N) ->
diff --git a/src/rebar_prv_unlock.erl b/src/rebar_prv_unlock.erl
index 7ff0d89..51c57ab 100644
--- a/src/rebar_prv_unlock.erl
+++ b/src/rebar_prv_unlock.erl
@@ -66,7 +66,7 @@ format_error(Reason) ->
handle_unlocks(State, Locks, LockFile) ->
{Args, _} = rebar_state:command_parsed_args(State),
- Names = parse_names(ec_cnv:to_binary(proplists:get_value(package, Args, <<"">>))),
+ Names = parse_names(rebar_utils:to_binary(proplists:get_value(package, Args, <<"">>))),
case [Lock || Lock = {Name, _, _} <- Locks, not lists:member(Name, Names)] of
[] ->
file:delete(LockFile);
@@ -77,7 +77,7 @@ handle_unlocks(State, Locks, LockFile) ->
end.
parse_names(Bin) ->
- case lists:usort(re:split(Bin, <<" *, *">>, [trim])) of
+ case lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode])) of
[<<"">>] -> []; % nothing submitted
Other -> Other
end.
diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl
index 046c864..a019c5a 100644
--- a/src/rebar_prv_update.erl
+++ b/src/rebar_prv_update.erl
@@ -150,7 +150,7 @@ update_deps_list(Pkg, PkgVsn, Deps, HexRegistry, State) ->
%% and doubled since spaces seem not to be
%% enforced
{false, Vsn} ->
- ?WARN("[~s:~s], Bad dependency version for ~s: ~s.",
+ ?WARN("[~ts:~ts], Bad dependency version for ~ts: ~ts.",
[Pkg, PkgVsn, Dep, Vsn]),
DepsListAcc;
{_, <<"~>", Vsn/binary>>} ->
@@ -202,14 +202,14 @@ valid_vsn(Vsn) ->
SemVerRegExp = "v?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?"
"(-[0-9a-z-]+(\\.[0-9a-z-]+)*)?(\\+[0-9a-z-]+(\\.[0-9a-z-]+)*)?",
SupportedVersions = "^(>=?|<=?|~>|==)?\\s*" ++ SemVerRegExp ++ "$",
- re:run(Vsn, SupportedVersions) =/= nomatch.
+ re:run(Vsn, SupportedVersions, [unicode]) =/= nomatch.
highest_matching({Pkg, PkgVsn, Dep, App}, Vsn, HexRegistry, State, DepsListAcc) ->
case rebar_packages:find_highest_matching(Pkg, PkgVsn, Dep, Vsn, HexRegistry, State) of
{ok, HighestDepVsn} ->
[{App, {pkg, Dep, HighestDepVsn, undefined}} | DepsListAcc];
none ->
- ?WARN("[~s:~s] Missing registry entry for package ~s. Try to fix with `rebar3 update`",
+ ?WARN("[~ts:~ts] Missing registry entry for package ~ts. Try to fix with `rebar3 update`",
[Pkg, PkgVsn, Dep]),
DepsListAcc
end.
@@ -220,7 +220,7 @@ cmp({_Pkg, _PkgVsn, Dep, _App} = Dep1, Vsn, HexRegistry, State, DepsListAcc, Cmp
cmp_(undefined, _MinVsn, [], DepsListAcc, {Pkg, PkgVsn, Dep, _App}, _CmpFun) ->
- ?WARN("[~s:~s] Missing registry entry for package ~s. Try to fix with `rebar3 update`",
+ ?WARN("[~ts:~ts] Missing registry entry for package ~ts. Try to fix with `rebar3 update`",
[Pkg, PkgVsn, Dep]),
DepsListAcc;
cmp_(HighestDepVsn, _MinVsn, [], DepsListAcc, {_Pkg, _PkgVsn, Dep, App}, _CmpFun) ->
@@ -241,7 +241,7 @@ cmpl({_Pkg, _PkgVsn, Dep, _App} = Dep1, Vsn, HexRegistry, State, DepsListAcc, Cm
cmpl_(undefined, Vsn, Vsns, DepsListAcc, Dep1, CmpFun).
cmpl_(undefined, _MaxVsn, [], DepsListAcc, {Pkg, PkgVsn, Dep, _App}, _CmpFun) ->
- ?WARN("[~s:~s] Missing registry entry for package ~s. Try to fix with `rebar3 update`",
+ ?WARN("[~ts:~ts] Missing registry entry for package ~ts. Try to fix with `rebar3 update`",
[Pkg, PkgVsn, Dep]),
DepsListAcc;
diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl
index 18c307b..5a7dff8 100644
--- a/src/rebar_prv_upgrade.erl
+++ b/src/rebar_prv_upgrade.erl
@@ -32,7 +32,7 @@ init(State) ->
{deps, ?DEPS},
{example, "rebar3 upgrade [cowboy[,ranch]]"},
{short_desc, "Upgrade dependencies."},
- {desc, "Upgrade project dependecies. Mentioning no application "
+ {desc, "Upgrade project dependencies. Mentioning no application "
"will upgrade all dependencies. To upgrade specific dependencies, "
"their names can be listed in the command."},
{opts, [
@@ -68,9 +68,11 @@ do(State) ->
ProfileDeps = rebar_state:get(State, {deps, default}, []),
Deps = [Dep || Dep <- TopDeps ++ ProfileDeps, % TopDeps > ProfileDeps
is_atom(Dep) orelse is_atom(element(1, Dep))],
- Names = parse_names(ec_cnv:to_binary(proplists:get_value(package, Args, <<"">>)), Locks),
+ Names = parse_names(rebar_utils:to_binary(proplists:get_value(package, Args, <<"">>)), Locks),
DepsDict = deps_dict(rebar_state:all_deps(State)),
- case prepare_locks(Names, Deps, Locks, [], DepsDict) of
+ AltDeps = find_non_default_deps(Deps, State),
+ FilteredNames = cull_default_names_if_profiles(Names, Deps, State),
+ case prepare_locks(FilteredNames, Deps, Locks, [], DepsDict, AltDeps) of
{error, Reason} ->
{error, Reason};
{Locks0, _Unlocks0} ->
@@ -107,7 +109,7 @@ format_error(Reason) ->
io_lib:format("~p", [Reason]).
parse_names(Bin, Locks) ->
- case lists:usort(re:split(Bin, <<" *, *">>, [trim])) of
+ case lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode])) of
%% Nothing submitted, use *all* apps
[<<"">>] -> [Name || {Name, _, 0} <- Locks];
[] -> [Name || {Name, _, 0} <- Locks];
@@ -115,20 +117,45 @@ parse_names(Bin, Locks) ->
Other -> Other
end.
-prepare_locks([], _, Locks, Unlocks, _Dict) ->
+%% Find alternative deps in non-default profiles since they may
+%% need to be passed through (they are never locked)
+find_non_default_deps(Deps, State) ->
+ AltProfiles = rebar_state:current_profiles(State) -- [default],
+ AltProfileDeps = lists:append([
+ rebar_state:get(State, {deps, Profile}, []) || Profile <- AltProfiles]
+ ),
+ [Dep || Dep <- AltProfileDeps,
+ is_atom(Dep) orelse is_atom(element(1, Dep))
+ andalso not lists:member(Dep, Deps)].
+
+%% If any alt profiles are used, remove the default profiles from
+%% the upgrade list and warn about it.
+cull_default_names_if_profiles(Names, Deps, State) ->
+ case rebar_state:current_profiles(State) of
+ [default] ->
+ Names;
+ _ ->
+ ?INFO("Dependencies in the default profile will not be upgraded", []),
+ lists:filter(fun(Name) ->
+ AtomName = binary_to_atom(Name, utf8),
+ rebar_utils:tup_find(AtomName, Deps) == false
+ end, Names)
+ end.
+
+prepare_locks([], _, Locks, Unlocks, _Dict, _AltDeps) ->
{Locks, Unlocks};
-prepare_locks([Name|Names], Deps, Locks, Unlocks, Dict) ->
+prepare_locks([Name|Names], Deps, Locks, Unlocks, Dict, AltDeps) ->
AtomName = binary_to_atom(Name, utf8),
case lists:keyfind(Name, 1, Locks) of
{_, _, 0} = Lock ->
case rebar_utils:tup_find(AtomName, Deps) of
false ->
- ?WARN("Dependency ~s has been removed and will not be upgraded", [Name]),
- prepare_locks(Names, Deps, Locks, Unlocks, Dict);
+ ?WARN("Dependency ~ts has been removed and will not be upgraded", [Name]),
+ prepare_locks(Names, Deps, Locks, Unlocks, Dict, AltDeps);
Dep ->
{Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks, Dict),
prepare_locks(Names, Deps, NewLocks,
- [{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict)
+ [{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict, AltDeps)
end;
{_, _, Level} = Lock when Level > 0 ->
case rebar_utils:tup_find(AtomName, Deps) of
@@ -137,10 +164,15 @@ prepare_locks([Name|Names], Deps, Locks, Unlocks, Dict) ->
Dep -> % Dep has been promoted
{Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks, Dict),
prepare_locks(Names, Deps, NewLocks,
- [{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict)
+ [{Name, Source, 0} | NewUnlocks ++ Unlocks], Dict, AltDeps)
end;
false ->
- ?PRV_ERROR({unknown_dependency, Name})
+ case rebar_utils:tup_find(AtomName, AltDeps) of
+ false ->
+ ?PRV_ERROR({unknown_dependency, Name});
+ _ -> % non-default profile dependency found, pass through
+ prepare_locks(Names, Deps, Locks, Unlocks, Dict, AltDeps)
+ end
end.
prepare_lock(Dep, Lock, Locks, Dict) ->
@@ -149,7 +181,7 @@ prepare_lock(Dep, Lock, Locks, Dict) ->
{Name, _, Src} -> {Name, Src};
_ when is_atom(Dep) ->
%% version-free package. Must unlock whatever matches in locks
- {_, Vsn, _} = lists:keyfind(ec_cnv:to_binary(Dep), 1, Locks),
+ {_, Vsn, _} = lists:keyfind(rebar_utils:to_binary(Dep), 1, Locks),
{Dep, Vsn}
end,
Children = all_children(Name1, Dict),
@@ -165,7 +197,7 @@ unlock_children(Children, Locks) ->
unlock_children(_, [], Locks, Unlocks) ->
{Locks, Unlocks};
unlock_children(Children, [App = {Name,_,_} | Apps], Locks, Unlocks) ->
- case lists:member(ec_cnv:to_binary(Name), Children) of
+ case lists:member(rebar_utils:to_binary(Name), Children) of
true ->
unlock_children(Children, Apps, Locks, [App | Unlocks]);
false ->
@@ -183,7 +215,7 @@ all_children(Name, Dict) ->
lists:flatten(all_children_(Name, Dict)).
all_children_(Name, Dict) ->
- case dict:find(ec_cnv:to_binary(Name), Dict) of
+ case dict:find(rebar_utils:to_binary(Name), Dict) of
{ok, Children} ->
[Children | [all_children_(Child, Dict) || Child <- Children]];
error ->
diff --git a/src/rebar_prv_xref.erl b/src/rebar_prv_xref.erl
index c4e72e7..2405ebb 100644
--- a/src/rebar_prv_xref.erl
+++ b/src/rebar_prv_xref.erl
@@ -36,6 +36,7 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
+ OldPath = code:get_path(),
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
XrefChecks = prepare(State),
XrefIgnores = rebar_state:get(State, xref_ignores, []),
@@ -47,7 +48,7 @@ do(State) ->
QueryChecks = rebar_state:get(State, xref_queries, []),
QueryResults = lists:foldl(fun check_query/2, [], QueryChecks),
stopped = xref:stop(xref),
- rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
+ rebar_utils:cleanup_code_path(OldPath),
case XrefResults =:= [] andalso QueryResults =:= [] of
true ->
{ok, State};
@@ -70,7 +71,7 @@ short_desc() ->
desc() ->
io_lib:format(
- "~s~n"
+ "~ts~n"
"~n"
"Valid rebar.config options:~n"
" ~p~n"
@@ -97,8 +98,11 @@ prepare(State) ->
rebar_state:get(State, xref_warnings, false)},
{verbose, rebar_log:is_verbose(State)}]),
- [{ok, _} = xref:add_directory(xref, rebar_app_info:ebin_dir(App))
- || App <- rebar_state:project_apps(State)],
+ [{ok, _} = xref:add_directory(xref, Dir)
+ || App <- rebar_state:project_apps(State),
+ %% the directory may not exist in rare cases of a compile
+ %% hook of a dep running xref prior to the full job being done
+ Dir <- [rebar_app_info:ebin_dir(App)], filelib:is_dir(Dir)],
%% Get list of xref checks we want to run
ConfXrefChecks = rebar_state:get(State, xref_checks,
@@ -165,8 +169,15 @@ keyall(Key, List) ->
lists:flatmap(fun({K, L}) when Key =:= K -> L; (_) -> [] end, List).
get_behaviour_callbacks(exports_not_used, Attributes) ->
- [B:behaviour_info(callbacks) || B <- keyall(behaviour, Attributes) ++
- keyall(behavior, Attributes)];
+ lists:map(fun(Mod) ->
+ try
+ Mod:behaviour_info(callbacks)
+ catch
+ error:undef ->
+ ?WARN("Behaviour ~p is used but cannot be found.", [Mod]),
+ []
+ end
+ end, keyall(behaviour, Attributes) ++ keyall(behavior, Attributes));
get_behaviour_callbacks(_XrefCheck, _Attributes) ->
[].
@@ -193,7 +204,7 @@ display_results(XrefResults, QueryResults) ->
lists:map(fun display_query_result/1, QueryResults)].
display_query_result({Query, Answer, Value}) ->
- io_lib:format("Query ~s~n answer ~p~n did not match ~p~n",
+ io_lib:format("Query ~ts~n answer ~p~n did not match ~p~n",
[Query, Answer, Value]).
display_xref_results_for_type({Type, XrefResults}) ->
@@ -214,37 +225,37 @@ display_xref_result_fun(Type) ->
end,
case Type of
undefined_function_calls ->
- io_lib:format("~sWarning: ~s calls undefined function ~s (Xref)\n",
+ io_lib:format("~tsWarning: ~ts calls undefined function ~ts (Xref)\n",
[Source, SMFA, TMFA]);
undefined_functions ->
- io_lib:format("~sWarning: ~s is undefined function (Xref)\n",
+ io_lib:format("~tsWarning: ~ts is undefined function (Xref)\n",
[Source, SMFA]);
locals_not_used ->
- io_lib:format("~sWarning: ~s is unused local function (Xref)\n",
+ io_lib:format("~tsWarning: ~ts is unused local function (Xref)\n",
[Source, SMFA]);
exports_not_used ->
- io_lib:format("~sWarning: ~s is unused export (Xref)\n",
+ io_lib:format("~tsWarning: ~ts is unused export (Xref)\n",
[Source, SMFA]);
deprecated_function_calls ->
- io_lib:format("~sWarning: ~s calls deprecated function ~s (Xref)\n",
+ io_lib:format("~tsWarning: ~ts calls deprecated function ~ts (Xref)\n",
[Source, SMFA, TMFA]);
deprecated_functions ->
- io_lib:format("~sWarning: ~s is deprecated function (Xref)\n",
+ io_lib:format("~tsWarning: ~ts is deprecated function (Xref)\n",
[Source, SMFA]);
Other ->
- io_lib:format("~sWarning: ~s - ~s xref check: ~s (Xref)\n",
+ io_lib:format("~tsWarning: ~ts - ~ts xref check: ~ts (Xref)\n",
[Source, SMFA, TMFA, Other])
end
end.
format_mfa({M, F, A}) ->
- ?FMT("~s:~s/~w", [M, F, A]).
+ ?FMT("~ts:~ts/~w", [M, F, A]).
format_mfa_source(MFA) ->
case find_mfa_source(MFA) of
{module_not_found, function_not_found} -> "";
- {Source, function_not_found} -> ?FMT("~s: ", [Source]);
- {Source, Line} -> ?FMT("~s:~w: ", [Source, Line])
+ {Source, function_not_found} -> ?FMT("~ts: ", [Source]);
+ {Source, Line} -> ?FMT("~ts:~w: ", [Source, Line])
end.
%%
@@ -270,12 +281,21 @@ find_mfa_source({M, F, A}) ->
end.
find_function_source(M, F, A, Bin) ->
- AbstractCode = beam_lib:chunks(Bin, [abstract_code]),
- {ok, {M, [{abstract_code, {raw_abstract_v1, Code}}]}} = AbstractCode,
+ ChunksLookup = beam_lib:chunks(Bin, [abstract_code]),
+ {ok, {M, [{abstract_code, AbstractCodeLookup}]}} = ChunksLookup,
+ case AbstractCodeLookup of
+ no_abstract_code ->
+ % There isn't much else we can do at this point
+ {module_not_found, function_not_found};
+ {raw_abstract_v1, AbstractCode} ->
+ find_function_source_in_abstract_code(F, A, AbstractCode)
+ end.
+
+find_function_source_in_abstract_code(F, A, AbstractCode) ->
%% Extract the original source filename from the abstract code
- [{attribute, _, file, {Source, _}} | _] = Code,
+ [{attribute, _, file, {Source, _}} | _] = AbstractCode,
%% Extract the line number for a given function def
- Fn = [E || E <- Code,
+ Fn = [E || E <- AbstractCode,
safe_element(1, E) == function,
safe_element(3, E) == F,
safe_element(4, E) == A],
diff --git a/src/rebar_relx.erl b/src/rebar_relx.erl
index 5c653a3..17c0bd6 100644
--- a/src/rebar_relx.erl
+++ b/src/rebar_relx.erl
@@ -6,6 +6,10 @@
-export([do/4,
format_error/1]).
+-ifdef(TEST).
+-export([merge_overlays/1]).
+-endif.
+
-include("rebar.hrl").
%% ===================================================================
@@ -26,19 +30,21 @@ do(Module, Command, Provider, State) ->
AllOptions = string:join([Command | Options], " "),
Cwd = rebar_state:dir(State),
Providers = rebar_state:providers(State),
+ RebarOpts = rebar_state:opts(State),
+ ErlOpts = rebar_opts:erl_opts(RebarOpts),
rebar_hooks:run_project_and_app_hooks(Cwd, pre, Provider, Providers, State),
try
case rebar_state:get(State, relx, []) of
[] ->
relx:main([{lib_dirs, LibDirs}
,{caller, api}
- ,{log_level, LogLevel} | output_dir(OutputDir, Options)], AllOptions);
+ ,{log_level, LogLevel} | output_dir(OutputDir, Options)] ++ ErlOpts, AllOptions);
Config ->
Config1 = merge_overlays(Config),
relx:main([{lib_dirs, LibDirs}
,{config, Config1}
,{caller, api}
- ,{log_level, LogLevel} | output_dir(OutputDir, Options)], AllOptions)
+ ,{log_level, LogLevel} | output_dir(OutputDir, Options)] ++ ErlOpts, AllOptions)
end,
rebar_hooks:run_project_and_app_hooks(Cwd, post, Provider, Providers, State),
{ok, State}
@@ -62,5 +68,5 @@ merge_overlays(Config) ->
(_) -> false
end, Config),
%% Have profile overlay entries come before others to match how profiles work elsewhere
- NewOverlay = lists:reverse(lists:flatmap(fun({overlay, Overlay}) -> Overlay end, Overlays)),
+ NewOverlay = lists:flatmap(fun({overlay, Overlay}) -> Overlay end, lists:reverse(Overlays)),
[{overlay, NewOverlay} | Others].
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index 9683709..3314a11 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -182,7 +182,7 @@ all(_, []) ->
all(Dir, [File|Artifacts]) ->
case filelib:is_regular(filename:join(Dir, File)) of
false ->
- ?DEBUG("Missing artifact ~s", [filename:join(Dir, File)]),
+ ?DEBUG("Missing artifact ~ts", [filename:join(Dir, File)]),
{false, File};
true ->
all(Dir, Artifacts)
@@ -302,9 +302,9 @@ dir(State=#state_t{}, Dir) ->
deps_names(Deps) when is_list(Deps) ->
lists:map(fun(Dep) when is_tuple(Dep) ->
- ec_cnv:to_binary(element(1, Dep));
+ rebar_utils:to_binary(element(1, Dep));
(Dep) when is_atom(Dep) ->
- ec_cnv:to_binary(Dep)
+ rebar_utils:to_binary(Dep)
end, Deps);
deps_names(State) ->
Deps = rebar_state:get(State, deps, []),
diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl
index 9b33ec5..75190ec 100644
--- a/src/rebar_templater.erl
+++ b/src/rebar_templater.erl
@@ -129,7 +129,7 @@ default_author_and_email() ->
%% Ok, try mecurial
case rebar_utils:sh("hg showconfig ui.username", [return_on_error]) of
{ok, NameEmail} ->
- case re:run(NameEmail, "^(.*) <(.*)>$", [{capture, [1,2], list}]) of
+ case re:run(NameEmail, "^(.*) <(.*)>$", [{capture, [1,2], list}, unicode]) of
{match, [Name, Email]} ->
{Name, Email};
_ ->
@@ -169,7 +169,7 @@ maybe_warn_about_name(Vars) ->
invalid ->
?WARN("The 'name' variable is often associated with Erlang "
"module names and/or file names. The value submitted "
- "(~s) isn't an unquoted Erlang atom. Templates "
+ "(~ts) isn't an unquoted Erlang atom. Templates "
"generated may contain errors.",
[Name]);
valid ->
@@ -189,7 +189,7 @@ validate_atom(Str) ->
%% Run template instructions one at a time.
execute_template([], _, {Template,_,_}, _, _) ->
- ?DEBUG("Template ~s applied", [Template]),
+ ?DEBUG("Template ~ts applied", [Template]),
ok;
%% We can't execute the description
execute_template([{description, _} | Terms], Files, Template, Vars, Force) ->
@@ -242,7 +242,7 @@ execute_template([{template, From, To} | Terms], Files, {Template, Type, Cwd}, V
execute_template(Terms, Files, {Template, Type, Cwd}, Vars, Force);
%% Unknown
execute_template([Instruction|Terms], Files, Tpl={Template,_,_}, Vars, Force) ->
- ?WARN("Unknown template instruction ~p in template ~s",
+ ?WARN("Unknown template instruction ~p in template ~ts",
[Instruction, Template]),
execute_template(Terms, Files, Tpl, Vars, Force).
@@ -305,7 +305,7 @@ cache_escript_files(State) ->
find_escript_templates(Files) ->
[{escript, Name}
|| {Name, _Bin} <- Files,
- re:run(Name, ?TEMPLATE_RE, [{capture, none}]) == match].
+ re:run(Name, ?TEMPLATE_RE, [{capture, none}, unicode]) == match].
find_localinstall_templates(_State) ->
Templates = rebar_utils:find_files(code:priv_dir(rebar), ?TEMPLATE_RE),
@@ -334,8 +334,19 @@ find_plugin_templates(State) ->
|| App <- rebar_state:all_plugin_deps(State),
Priv <- [rebar_app_info:priv_dir(App)],
Priv =/= undefined,
+ File <- rebar_utils:find_files(Priv, ?TEMPLATE_RE)]
+ ++ %% and add global plugins too
+ [{plugin, File}
+ || PSource <- rebar_state:get(State, {plugins, global}, []),
+ Plugin <- [plugin_provider(PSource)],
+ is_atom(Plugin),
+ Priv <- [code:priv_dir(Plugin)],
+ Priv =/= undefined,
File <- rebar_utils:find_files(Priv, ?TEMPLATE_RE)].
+plugin_provider(P) when is_atom(P) -> P;
+plugin_provider(T) when is_tuple(T) -> element(1, T).
+
%% Take an existing list of templates and tag them by name the way
%% the user would enter it from the CLI
tag_names(List) ->
@@ -363,7 +374,7 @@ prioritize_templates([{Name, Type, File} | Rest], Valid) ->
prioritize_templates(Rest, Valid);
{_, file, _} ->
?DEBUG("Skipping template ~p, due to presence of a custom "
- "template at ~s", [Name, File]),
+ "template at ~ts", [Name, File]),
prioritize_templates(Rest, Valid)
end.
@@ -418,10 +429,10 @@ write_file(Output, Data, Force) ->
ok = filelib:ensure_dir(Output),
case {Force, FileExists} of
{true, true} ->
- ?INFO("Writing ~s (forcibly overwriting)",
+ ?INFO("Writing ~ts (forcibly overwriting)",
[Output]);
_ ->
- ?INFO("Writing ~s", [Output])
+ ?INFO("Writing ~ts", [Output])
end,
case file:write_file(Output, Data) of
ok ->
@@ -438,4 +449,4 @@ write_file(Output, Data, Force) ->
%% Render a binary to a string, using mustache and the specified context
%%
render(Bin, Context) ->
- bbmustache:render(ec_cnv:to_binary(Bin), Context, [{key_type, atom}]).
+ bbmustache:render(rebar_utils:to_binary(Bin), Context, [{key_type, atom}]).
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index c357e94..016847e 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -55,6 +55,8 @@
get_arch/0,
wordsize/0,
deps_to_binary/1,
+ to_binary/1,
+ to_list/1,
tup_dedup/1,
tup_umerge/2,
tup_sort/1,
@@ -115,7 +117,7 @@ filtermap(F, [Hd|Tail]) ->
filtermap(F, []) when is_function(F, 1) -> [].
is_arch(ArchRegex) ->
- case re:run(get_arch(), ArchRegex, [{capture, none}]) of
+ case re:run(get_arch(), ArchRegex, [{capture, none}, unicode]) of
match ->
true;
nomatch ->
@@ -142,7 +144,7 @@ wordsize() ->
end.
sh_send(Command0, String, Options0) ->
- ?INFO("sh_send info:\n\tcwd: ~p\n\tcmd: ~s < ~s\n",
+ ?INFO("sh_send info:\n\tcwd: ~p\n\tcmd: ~ts < ~ts\n",
[rebar_dir:get_cwd(), Command0, String]),
?DEBUG("\topts: ~p\n", [Options0]),
@@ -171,7 +173,7 @@ sh_send(Command0, String, Options0) ->
%% Val = string() | false
%%
sh(Command0, Options0) ->
- ?DEBUG("sh info:\n\tcwd: ~p\n\tcmd: ~s\n", [rebar_dir:get_cwd(), Command0]),
+ ?DEBUG("sh info:\n\tcwd: ~p\n\tcmd: ~ts\n", [rebar_dir:get_cwd(), Command0]),
?DEBUG("\topts: ~p\n", [Options0]),
DefaultOptions = [{use_stdout, false}, debug_and_abort_on_error],
@@ -184,7 +186,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, eof],
- ?DEBUG("Port Cmd: ~s\nPort Opts: ~p\n", [Command, PortSettings]),
+ ?DEBUG("Port Cmd: ~ts\nPort Opts: ~p\n", [Command, PortSettings]),
Port = open_port({spawn, Command}, PortSettings),
try
@@ -232,7 +234,7 @@ deprecated(Old, New, When) ->
<<"WARNING: deprecated ~p option used~n"
"Option '~p' has been deprecated~n"
"in favor of '~p'.~n"
- "'~p' will be removed ~s.~n">>,
+ "'~p' will be removed ~ts.~n">>,
[Old, Old, New, Old, When]).
%% for use by `do` task
@@ -244,11 +246,17 @@ args_to_tasks(Args) -> new_task(Args, []).
deps_to_binary([]) ->
[];
deps_to_binary([{Name, _, Source} | T]) ->
- [{ec_cnv:to_binary(Name), Source} | deps_to_binary(T)];
+ [{to_binary(Name), Source} | deps_to_binary(T)];
deps_to_binary([{Name, Source} | T]) ->
- [{ec_cnv:to_binary(Name), Source} | deps_to_binary(T)];
+ [{to_binary(Name), Source} | deps_to_binary(T)];
deps_to_binary([Name | T]) ->
- [ec_cnv:to_binary(Name) | deps_to_binary(T)].
+ [to_binary(Name) | deps_to_binary(T)].
+
+to_binary(A) when is_atom(A) -> atom_to_binary(A, unicode);
+to_binary(Str) -> unicode:characters_to_binary(Str).
+
+to_list(A) when is_atom(A) -> atom_to_list(A);
+to_list(Str) -> unicode:characters_to_list(Str).
tup_dedup(List) ->
tup_dedup_(tup_sort(List)).
@@ -396,10 +404,10 @@ check_min_otp_version(MinOtpVersion) ->
case ParsedVsn >= ParsedMin of
true ->
- ?DEBUG("~s satisfies the requirement for minimum OTP version ~s",
+ ?DEBUG("~ts satisfies the requirement for minimum OTP version ~ts",
[OtpRelease, MinOtpVersion]);
false ->
- ?ABORT("OTP release ~s or later is required. Version in use: ~s",
+ ?ABORT("OTP release ~ts or later is required. Version in use: ~ts",
[MinOtpVersion, OtpRelease])
end.
@@ -415,16 +423,16 @@ check_blacklisted_otp_versions(BlacklistedRegexes) ->
abort_if_blacklisted(BlacklistedRegex, OtpRelease) ->
case re:run(OtpRelease, BlacklistedRegex, [{capture, none}]) of
match ->
- ?ABORT("OTP release ~s matches blacklisted version ~s",
+ ?ABORT("OTP release ~ts matches blacklisted version ~ts",
[OtpRelease, BlacklistedRegex]);
nomatch ->
- ?DEBUG("~s does not match blacklisted OTP version ~s",
+ ?DEBUG("~ts does not match blacklisted OTP version ~ts",
[OtpRelease, BlacklistedRegex])
end.
user_agent() ->
{ok, Vsn} = application:get_key(rebar, vsn),
- ?FMT("Rebar/~s (OTP/~s)", [Vsn, otp_release()]).
+ ?FMT("Rebar/~ts (OTP/~ts)", [Vsn, otp_release()]).
reread_config(ConfigList) ->
%% NB: we attempt to mimic -config here, which survives app reload,
@@ -457,7 +465,7 @@ version_tuple(OtpRelease) ->
{match, [_Full, Maj]} ->
{list_to_integer(Maj), 0, 0};
nomatch ->
- ?ABORT("Minimum OTP release unable to be parsed: ~s", [OtpRelease])
+ ?ABORT("Minimum OTP release unable to be parsed: ~ts", [OtpRelease])
end.
otp_release() ->
@@ -510,7 +518,7 @@ patch_on_windows(Cmd, Env) ->
end, Cmd, Env),
%% Remove left-over vars
re:replace(Cmd1, "\\\$\\w+|\\\${\\w+}", "",
- [global, {return, list}]);
+ [global, {return, list}, unicode]);
_ ->
Cmd
end.
@@ -529,7 +537,7 @@ expand_env_variable(InStr, VarName, RawVarValue) ->
VarValue = re:replace(RawVarValue, "\\\\", "\\\\\\\\", ReOpts),
%% Use a regex to match/replace:
%% Given variable "FOO": match $FOO\s | $FOOeol | ${FOO}
- RegEx = io_lib:format("\\\$(~s(\\W|$)|{~s})", [VarName, VarName]),
+ RegEx = io_lib:format("\\\$(~ts(\\W|$)|{~ts})", [VarName, VarName]),
re:replace(InStr, RegEx, [VarValue, "\\2"], ReOpts)
end.
@@ -554,7 +562,7 @@ expand_sh_flag(use_stdout) ->
{output_handler,
fun(Line, Acc) ->
%% Line already has a newline so don't use ?CONSOLE which adds one
- io:format("~s", [Line]),
+ io:format("~ts", [Line]),
[Line | Acc]
end};
expand_sh_flag({use_stdout, false}) ->
@@ -577,23 +585,23 @@ log_msg_and_abort(Message) ->
-spec debug_log_msg_and_abort(string()) -> err_handler().
debug_log_msg_and_abort(Message) ->
fun(Command, {Rc, Output}) ->
- ?DEBUG("sh(~s)~n"
+ ?DEBUG("sh(~ts)~n"
"failed with return code ~w and the following output:~n"
- "~s", [Command, Rc, Output]),
+ "~ts", [Command, Rc, Output]),
?ABORT(Message, [])
end.
-spec log_and_abort(string(), {integer(), string()}) -> no_return().
log_and_abort(Command, {Rc, Output}) ->
- ?ABORT("sh(~s)~n"
+ ?ABORT("sh(~ts)~n"
"failed with return code ~w and the following output:~n"
- "~s", [Command, Rc, Output]).
+ "~ts", [Command, Rc, Output]).
-spec debug_and_abort(string(), {integer(), string()}) -> no_return().
debug_and_abort(Command, {Rc, Output}) ->
- ?DEBUG("sh(~s)~n"
+ ?DEBUG("sh(~ts)~n"
"failed with return code ~w and the following output:~n"
- "~s", [Command, Rc, Output]),
+ "~ts", [Command, Rc, Output]),
throw(rebar_abort).
sh_loop(Port, Fun, Acc) ->
@@ -662,7 +670,7 @@ vcs_vsn(Vcs, Dir, Resources) ->
unknown ->
?ABORT("vcs_vsn: Unknown vsn format: ~p", [Vcs]);
{error, Reason} ->
- ?ABORT("vcs_vsn: ~s", [Reason])
+ ?ABORT("vcs_vsn: ~ts", [Reason])
end.
%% Temp work around for repos like relx that use "semver"
@@ -779,7 +787,7 @@ cleanup_code_path(OrigPath) ->
new_task([], Acc) -> lists:reverse(Acc);
new_task([TaskList|Rest], Acc) ->
- case re:split(TaskList, ",", [{return, list}, {parts, 2}]) of
+ case re:split(TaskList, ",", [{return, list}, {parts, 2}, unicode]) of
%% `do` consumes all remaining args
["do" = Task] ->
lists:reverse([{Task, Rest}|Acc]);
@@ -806,7 +814,7 @@ arg_or_flag(["-" ++ _ = Flag|Rest], [{Task, Args}|Acc]) ->
end;
%% an argument or a sequence of arguments
arg_or_flag([ArgList|Rest], [{Task, Args}|Acc]) ->
- case re:split(ArgList, ",", [{return, list}, {parts, 2}]) of
+ case re:split(ArgList, ",", [{return, list}, {parts, 2}, unicode]) of
%% single arg terminated by a comma
[Arg, ""] -> new_task(Rest, [{Task,
lists:reverse([Arg|Args])}|Acc]);
@@ -857,15 +865,18 @@ url_append_path(Url, ExtraPath) ->
escape_chars(Str) when is_atom(Str) ->
escape_chars(atom_to_list(Str));
escape_chars(Str) ->
- re:replace(Str, "([ ()?`!$&;])", "\\\\&", [global, {return, list}]).
+ re:replace(Str, "([ ()?`!$&;\"\'])", "\\\\&",
+ [global, {return, list}, unicode]).
%% "escape inside these"
escape_double_quotes(Str) ->
- re:replace(Str, "([\"\\\\`!$&*;])", "\\\\&", [global, {return, list}]).
+ re:replace(Str, "([\"\\\\`!$&*;])", "\\\\&",
+ [global, {return, list}, unicode]).
%% "escape inside these" but allow *
escape_double_quotes_weak(Str) ->
- re:replace(Str, "([\"\\\\`!$&;])", "\\\\&", [global, {return, list}]).
+ re:replace(Str, "([\"\\\\`!$&;])", "\\\\&",
+ [global, {return, list}, unicode]).
info_useless(Old, New) ->
[?INFO("App ~ts is no longer needed and can be deleted.", [Name])