summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar.hrl1
-rw-r--r--src/rebar3.erl4
-rw-r--r--src/rebar_app_utils.erl23
-rw-r--r--src/rebar_config.erl94
-rw-r--r--src/rebar_fetch.erl6
-rw-r--r--src/rebar_file_utils.erl4
-rw-r--r--src/rebar_git_resource.erl2
-rw-r--r--src/rebar_packages.erl2
-rw-r--r--src/rebar_pkg_resource.erl23
-rw-r--r--src/rebar_prv_deps.erl2
-rw-r--r--src/rebar_prv_deps_tree.erl2
-rw-r--r--src/rebar_prv_dialyzer.erl43
-rw-r--r--src/rebar_prv_escriptize.erl24
-rw-r--r--src/rebar_prv_install_deps.erl6
14 files changed, 185 insertions, 51 deletions
diff --git a/src/rebar.hrl b/src/rebar.hrl
index 4d69c7b..f96ed5e 100644
--- a/src/rebar.hrl
+++ b/src/rebar.hrl
@@ -23,6 +23,7 @@
-define(DEFAULT_TEST_DEPS_DIR, "test/lib").
-define(DEFAULT_RELEASE_DIR, "rel").
-define(DEFAULT_CONFIG_FILE, "rebar.config").
+-define(CONFIG_VERSION, "1.1.0").
-define(DEFAULT_CDN, "https://repo.hex.pm/").
-define(REMOTE_PACKAGE_DIR, "tarballs").
-define(REMOTE_REGISTRY_FILE, "registry.ets.gz").
diff --git a/src/rebar3.erl b/src/rebar3.erl
index 82b4472..d3ea15f 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -221,10 +221,10 @@ set_options(State, {Options, NonOptArgs}) ->
%%
log_level() ->
case os:getenv("QUIET") of
- false ->
+ Q when Q == false; Q == "" ->
DefaultLevel = rebar_log:default_level(),
case os:getenv("DEBUG") of
- false ->
+ D when D == false; D == "" ->
DefaultLevel;
_ ->
DefaultLevel + 3
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index 957526e..d256cac 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -119,17 +119,17 @@ parse_dep(Dep, Parent, DepsDir, State, Locks, Level) ->
parse_dep(Parent, {Name, Vsn, {pkg, PkgName}}, DepsDir, IsLock, State) ->
{PkgName1, PkgVsn} = {ec_cnv:to_binary(PkgName), ec_cnv:to_binary(Vsn)},
- dep_to_app(Parent, DepsDir, Name, PkgVsn, {pkg, PkgName1, PkgVsn}, IsLock, State);
+ 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}, IsLock, State);
+ dep_to_app(Parent, DepsDir, Name, undefined, {pkg, ec_cnv: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)},
- dep_to_app(Parent, DepsDir, PkgName, PkgVsn, {pkg, PkgName, PkgVsn}, IsLock, State);
+ 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}, IsLock, State);
+ dep_to_app(Parent, DepsDir, ec_cnv:to_binary(Name), undefined, {pkg, ec_cnv: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) ->
@@ -143,7 +143,9 @@ parse_dep(Parent, {Name, Source, Opts}, DepsDir, IsLock, State) when is_tuple(So
?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
parse_dep(Parent, {Name, {pkg, PkgName, Vsn}, Level}, DepsDir, IsLock, State) when is_integer(Level) ->
- dep_to_app(Parent, DepsDir, Name, Vsn, {pkg, PkgName, Vsn}, IsLock, State);
+ dep_to_app(Parent, DepsDir, Name, Vsn, {pkg, PkgName, Vsn, undefined}, IsLock, State);
+parse_dep(Parent, {Name, {pkg, PkgName, Vsn, Hash}, Level}, DepsDir, IsLock, State) when is_integer(Level) ->
+ dep_to_app(Parent, DepsDir, Name, Vsn, {pkg, PkgName, Vsn, Hash}, IsLock, State);
parse_dep(Parent, {Name, Source, Level}, DepsDir, IsLock, State) when is_tuple(Source)
, is_integer(Level) ->
dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
@@ -175,7 +177,7 @@ dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
AppInfo5 = rebar_app_info:profiles(AppInfo4, [default]),
rebar_app_info:is_lock(AppInfo5, IsLock).
-update_source(AppInfo, {pkg, PkgName, PkgVsn}, State) ->
+update_source(AppInfo, {pkg, PkgName, PkgVsn, Hash}, State) ->
{PkgName1, PkgVsn1} = case PkgVsn of
undefined ->
get_package(PkgName, "0", State);
@@ -185,7 +187,14 @@ update_source(AppInfo, {pkg, PkgName, PkgVsn}, State) ->
_ ->
{PkgName, PkgVsn}
end,
- AppInfo1 = rebar_app_info:source(AppInfo, {pkg, PkgName1, PkgVsn1}),
+ %% store the expected hash for the dependency
+ Hash1 = case Hash of
+ undefined -> % unknown, define the hash since we know the dep
+ rebar_packages:registry_checksum({pkg, PkgName1, PkgVsn1, Hash}, State);
+ _ -> % keep as is
+ Hash
+ end,
+ AppInfo1 = rebar_app_info:source(AppInfo, {pkg, PkgName1, PkgVsn1, Hash1}),
Deps = rebar_packages:deps(PkgName1
,PkgVsn1
,State),
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index 836980e..b50c030 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -56,35 +56,105 @@ consult_lock_file(File) ->
[] ->
[];
[Locks] when is_list(Locks) -> % beta lock file
- Locks;
+ read_attrs(beta, Locks, []);
[{Vsn, Locks}|Attrs] when is_list(Locks) -> % versioned lock file
- %% Make sure the warning above is to be shown whenever a version
- %% newer than the current one is being used, as we can't parse
- %% all the contents of the lock file properly.
+ %% Because this is the first version of rebar3 to introduce a lock
+ %% file, all versionned lock files with a different versions have
+ %% to be newer.
+ case Vsn of
+ ?CONFIG_VERSION ->
+ ok;
+ _ ->
+ %% Make sure the warning below is to be shown whenever a version
+ %% newer than the current one is being used, as we can't parse
+ %% all the contents of the lock file properly.
+ warn_vsn_once()
+ end,
+ read_attrs(Vsn, Locks, Attrs)
+ end.
+
+warn_vsn_once() ->
+ Warn = application:get_env(rebar, warn_config_vsn) =/= {ok, false},
+ application:set_env(rebar, warn_config_vsn, false),
+ case Warn of
+ false -> ok;
+ true ->
?WARN("Rebar3 detected a lock file from a newer version. "
"It will be loaded in compatibility mode, but important "
"information may be missing or lost. It is recommended to "
- "upgrade Rebar3.", []),
- read_attrs(Vsn, Locks, Attrs)
+ "upgrade Rebar3.", [])
end.
+
write_lock_file(LockFile, Locks) ->
- NewLocks = write_attrs(Locks),
+ {NewLocks, Attrs} = write_attrs(Locks),
%% Write locks in the beta format, at least until it's been long
%% enough we can start modifying the lock format.
- file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])).
+ case Attrs of
+ [] -> % write the old beta copy to avoid changes
+ 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",
+ [?CONFIG_VERSION, NewLocks,
+ format_attrs(Attrs)]))
+ end.
-read_attrs(_Vsn, Locks, _Attrs) ->
+%% Attributes have a special formatting to ensure there's only one per
+%% line in terms of pkg_hash, so we disturb source diffing as little
+%% as possible.
+format_attrs([]) -> [];
+format_attrs([{pkg_hash, Vals}|T]) ->
+ [io_lib:format("{pkg_hash,[~n",[]), format_hashes(Vals), "]}",
+ maybe_comma(T) | format_attrs(T)];
+format_attrs([H|T]) ->
+ [io_lib:format("~p~s", [H, maybe_comma(T)]) | format_attrs(T)].
+
+format_hashes([]) -> [];
+format_hashes([{Pkg,Hash}|T]) ->
+ [" {", io_lib:format("~p",[Pkg]), ", ", io_lib:format("~p", [Hash]), "}",
+ maybe_comma(T) | format_hashes(T)].
+
+maybe_comma([]) -> "";
+maybe_comma([_|_]) -> io_lib:format(",~n", []).
+
+read_attrs(_Vsn, Locks, Attrs) ->
%% Beta copy does not know how to expand attributes, but
%% is ready to support it.
- Locks.
+ expand_locks(Locks, extract_pkg_hashes(Attrs)).
+
+extract_pkg_hashes(Attrs) ->
+ Props = case Attrs of
+ [First|_] -> First;
+ [] -> []
+ end,
+ proplists:get_value(pkg_hash, Props, []).
+
+expand_locks([], _Hashes) ->
+ [];
+expand_locks([{Name, {pkg,PkgName,Vsn}, Lvl} | Locks], Hashes) ->
+ Hash = proplists:get_value(Name, Hashes),
+ [{Name, {pkg,PkgName,Vsn,Hash}, Lvl} | expand_locks(Locks, Hashes)];
+expand_locks([Lock|Locks], Hashes) ->
+ [Lock | expand_locks(Locks, Hashes)].
write_attrs(Locks) ->
%% No attribute known that needs to be taken out of the structure,
%% just return terms as is.
- Locks.
-
+ {NewLocks, Hashes} = split_locks(Locks, [], []),
+ case Hashes of
+ [] -> {NewLocks, []};
+ _ -> {NewLocks, [{pkg_hash, lists:sort(Hashes)}]}
+ end.
+split_locks([], Locks, Hashes) ->
+ {lists:reverse(Locks), Hashes};
+split_locks([{Name, {pkg,PkgName,Vsn,undefined}, Lvl} | Locks], LAcc, HAcc) ->
+ split_locks(Locks, [{Name,{pkg,PkgName,Vsn},Lvl}|LAcc], HAcc);
+split_locks([{Name, {pkg,PkgName,Vsn,Hash}, Lvl} | Locks], LAcc, HAcc) ->
+ split_locks(Locks, [{Name,{pkg,PkgName,Vsn},Lvl}|LAcc], [{Name, Hash}|HAcc]);
+split_locks([Lock|Locks], LAcc, HAcc) ->
+ split_locks(Locks, [Lock|LAcc], HAcc).
consult_file(File) ->
Terms = consult_file_(File),
diff --git a/src/rebar_fetch.erl b/src/rebar_fetch.erl
index b80c125..47bfe1d 100644
--- a/src/rebar_fetch.erl
+++ b/src/rebar_fetch.erl
@@ -67,6 +67,12 @@ needs_update(AppDir, Source, State) ->
format_error({bad_download, CachePath}) ->
io_lib:format("Download of package does not match md5sum from server: ~s", [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 "
+ "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]);
format_error({bad_etag, Source}) ->
diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl
index 667be62..104c047 100644
--- a/src/rebar_file_utils.erl
+++ b/src/rebar_file_utils.erl
@@ -177,11 +177,11 @@ mv(Source, Dest) ->
{win32, _} ->
Cmd = case filelib:is_dir(Source) of
true ->
- ?FMT("robocopy /move /s \"~s\" \"~s\" 1> nul",
+ ?FMT("robocopy /move /e \"~s\" \"~s\" 1> nul",
[rebar_utils:escape_double_quotes(filename:nativename(Source)),
rebar_utils:escape_double_quotes(filename:nativename(Dest))]);
false ->
- ?FMT("robocopy /move /s \"~s\" \"~s\" \"~s\" 1> nul",
+ ?FMT("robocopy /move /e \"~s\" \"~s\" \"~s\" 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))])
diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl
index f0f5f03..acb9ec0 100644
--- a/src/rebar_git_resource.erl
+++ b/src/rebar_git_resource.erl
@@ -22,7 +22,7 @@ lock(AppDir, {git, Url}) ->
{ok, VsnString} =
case os:type() of
{win32, _} ->
- rebar_utils:sh("git rev-parse --git-dir=\"" ++ Dir ++ "/.git\" --work-tree=\"" ++ Dir ++ "\" --verify HEAD",
+ rebar_utils:sh("git --git-dir=\"" ++ Dir ++ "/.git\" --work-tree=\"" ++ Dir ++ "\" rev-parse --verify HEAD",
[{use_stdout, false}, {debug_abort_on_error, AbortMsg}]);
_ ->
rebar_utils:sh("git --git-dir=\"" ++ Dir ++ "/.git\" rev-parse --verify HEAD",
diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl
index d4b8a14..8b4611b 100644
--- a/src/rebar_packages.erl
+++ b/src/rebar_packages.erl
@@ -122,7 +122,7 @@ package_dir(State) ->
Error
end.
-registry_checksum({pkg, Name, Vsn}, State) ->
+registry_checksum({pkg, Name, Vsn, _Hash}, State) ->
try
?MODULE:verify_table(State),
ets:lookup_element(?PACKAGE_TABLE, {Name, Vsn}, 3)
diff --git a/src/rebar_pkg_resource.erl b/src/rebar_pkg_resource.erl
index ec7e09d..5817817 100644
--- a/src/rebar_pkg_resource.erl
+++ b/src/rebar_pkg_resource.erl
@@ -19,7 +19,7 @@
lock(_AppDir, Source) ->
Source.
-needs_update(Dir, {pkg, _Name, Vsn}) ->
+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
true ->
@@ -28,7 +28,7 @@ needs_update(Dir, {pkg, _Name, Vsn}) ->
true
end.
-download(TmpDir, Pkg={pkg, Name, Vsn}, State) ->
+download(TmpDir, Pkg={pkg, Name, Vsn, _Hash}, State) ->
CDN = rebar_state:get(State, rebar_packages_cdn, ?DEFAULT_CDN),
{ok, PackageDir} = rebar_packages:package_dir(State),
Package = binary_to_list(<<Name/binary, "-", Vsn/binary, ".tar">>),
@@ -40,7 +40,7 @@ download(TmpDir, Pkg={pkg, Name, Vsn}, State) ->
{fetch_fail, Name, Vsn}
end.
-cached_download(TmpDir, CachePath, Pkg={pkg, Name, Vsn}, Url, ETag, 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]),
@@ -58,17 +58,20 @@ cached_download(TmpDir, CachePath, Pkg={pkg, Name, Vsn}, Url, ETag, State) ->
serve_from_cache(TmpDir, CachePath, Pkg, State) ->
{Files, Contents, Version, Meta} = extract(TmpDir, CachePath),
case checksums(Pkg, Files, Contents, Version, Meta, State) of
- {Chk, Chk, Chk} ->
+ {Chk, Chk, Chk, Chk} ->
ok = erl_tar:extract({binary, Contents}, [{cwd, TmpDir}, compressed]),
{ok, true};
- {_Bin, Chk, Chk} ->
+ {_Hash, Chk, Chk, Chk} ->
+ ?DEBUG("Expected hash ~p does not match checksums ~p", [_Hash, Chk]),
+ {unexpected_hash, CachePath, _Hash, Chk};
+ {Chk, _Bin, Chk, Chk} ->
?DEBUG("Checksums: registry: ~p, pkg: ~p", [Chk, _Bin]),
{failed_extract, CachePath};
- {Chk, _Reg, Chk} ->
+ {Chk, Chk, _Reg, Chk} ->
?DEBUG("Checksums: registry: ~p, pkg: ~p", [_Reg, Chk]),
{bad_registry_checksum, CachePath};
- {_Bin, _Reg, _Tar} ->
- ?DEBUG("Checksums: registry: ~p, pkg: ~p, meta: ~p", [_Reg, _Bin, _Tar]),
+ {_Hash, _Bin, _Reg, _Tar} ->
+ ?DEBUG("Checksums: expected: ~p, registry: ~p, pkg: ~p, meta: ~p", [_Hash, _Reg, _Bin, _Tar]),
{bad_checksum, CachePath}
end.
@@ -92,13 +95,13 @@ extract(TmpDir, CachePath) ->
{"metadata.config", Meta} = lists:keyfind("metadata.config", 1, Files),
{Files, Contents, Version, Meta}.
-checksums(Pkg, Files, Contents, Version, Meta, State) ->
+checksums(Pkg={pkg, _Name, _Vsn, Hash}, Files, Contents, Version, Meta, State) ->
Blob = <<Version/binary, Meta/binary, Contents/binary>>,
<<X:256/big-unsigned>> = crypto:hash(sha256, Blob),
BinChecksum = list_to_binary(string:to_upper(lists:flatten(io_lib:format("~64.16.0b", [X])))),
RegistryChecksum = rebar_packages:registry_checksum(Pkg, State),
{"CHECKSUM", TarChecksum} = lists:keyfind("CHECKSUM", 1, Files),
- {BinChecksum, RegistryChecksum, TarChecksum}.
+ {Hash, BinChecksum, RegistryChecksum, TarChecksum}.
make_vsn(_) ->
{error, "Replacing version of type pkg not supported."}.
diff --git a/src/rebar_prv_deps.erl b/src/rebar_prv_deps.erl
index 9ff2bfa..c865276 100644
--- a/src/rebar_prv_deps.erl
+++ b/src/rebar_prv_deps.erl
@@ -97,7 +97,7 @@ display_dep(_State, {Name, _Vsn, Source}) when is_tuple(Source) ->
display_dep(_State, {Name, _Vsn, Source, _Opts}) when is_tuple(Source) ->
?CONSOLE("~s* (~s source)", [ec_cnv:to_binary(Name), type(Source)]);
%% Locked
-display_dep(State, {Name, Source={pkg, _, Vsn}, Level}) when is_integer(Level) ->
+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)]),
NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source, State) of
diff --git a/src/rebar_prv_deps_tree.erl b/src/rebar_prv_deps_tree.erl
index cefa60a..c0c8bab 100644
--- a/src/rebar_prv_deps_tree.erl
+++ b/src/rebar_prv_deps_tree.erl
@@ -70,7 +70,7 @@ print_children(Prefix, [{Name, Vsn, Source} | Rest], Dict, Verbose) ->
[Prefix, " "];
_ ->
io:format("~ts~ts", [Prefix, <<226,148,156,226,148,128,32>>]), %Binary for ├─ utf8%
- [Prefix, "│ "]
+ [Prefix, <<226,148,130,32,32>>] %Binary for │ utf8%
end,
io:format("~ts~ts~ts (~ts)~n", [Name, <<226,148,128>>, Vsn, type(Source, Verbose)]), %Binary for ─ utf8%
case dict:find(Name, Dict) of
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 622ee60..82d2d07 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -249,10 +249,15 @@ ebin_files(EbinDir) ->
File <- filelib:wildcard(Wildcard, EbinDir)].
read_plt(_State, Plt) ->
- case dialyzer:plt_info(Plt) of
- {ok, Info} ->
- Files = proplists:get_value(files, Info, []),
+ Vsn = dialyzer_version(),
+ case plt_files(Plt) of
+ {ok, Files} when Vsn < {2, 9, 0} ->
+ % Before dialyzer-2.9 (OTP 18.3) removing a beam file from the PLT
+ % that no longer exists would crash. Therefore force a rebuild of
+ % PLT if any files no longer exist.
read_plt_files(Plt, Files);
+ {ok, _} = Result when Vsn >= {2, 9, 0} ->
+ Result;
{error, no_such_file} ->
error;
{error, read_error} ->
@@ -260,6 +265,14 @@ read_plt(_State, Plt) ->
throw({dialyzer_error, Error})
end.
+plt_files(Plt) ->
+ case dialyzer:plt_info(Plt) of
+ {ok, Info} ->
+ {ok, proplists:get_value(files, Info, [])};
+ {error, _} = Error ->
+ Error
+ end.
+
%% If any file no longer exists dialyzer will fail when updating the PLT.
read_plt_files(Plt, Files) ->
case [File || File <- Files, not filelib:is_file(File)] of
@@ -353,8 +366,19 @@ update_base_plt(State, BasePlt, Output, BaseFiles) ->
build_plt(State, BasePlt, Output, BaseFiles)
end.
+build_plt(State, Plt, _, []) ->
+ ?INFO("Building with no files in ~p...", [Plt]),
+ Opts = [{get_warnings, false},
+ {output_plt, Plt},
+ {apps, [erts]}],
+ % Create a PLT with erts files and then remove erts files to be left with an
+ % empty PLT. Dialyzer will crash when trying to build a PLT with an empty
+ % file list.
+ _ = dialyzer:run([{analysis_type, plt_build} | Opts]),
+ _ = dialyzer:run([{analysis_type, plt_remove}, {init_plt, Plt} | Opts]),
+ {0, State};
build_plt(State, Plt, Output, Files) ->
- ?INFO("Adding ~b files to ~p...", [length(Files), Plt]),
+ ?INFO("Building with ~b files in ~p...", [length(Files), Plt]),
GetWarnings = get_config(State, get_warnings, false),
Opts = [{analysis_type, plt_build},
{get_warnings, GetWarnings},
@@ -369,12 +393,15 @@ succ_typings(State, Plt, Output) ->
{0, State};
_ ->
Apps = rebar_state:project_apps(State),
- succ_typings(State, Plt, Output, Apps)
+ ?INFO("Doing success typing analysis...", []),
+ Files = apps_to_files(Apps),
+ succ_typings(State, Plt, Output, Files)
end.
-succ_typings(State, Plt, Output, Apps) ->
- ?INFO("Doing success typing analysis...", []),
- Files = apps_to_files(Apps),
+succ_typings(State, Plt, _, []) ->
+ ?INFO("Analyzing no files with ~p...", [Plt]),
+ {0, State};
+succ_typings(State, Plt, Output, Files) ->
?INFO("Analyzing ~b files with ~p...", [length(Files), Plt]),
Opts = [{analysis_type, succ_typings},
{get_warnings, true},
diff --git a/src/rebar_prv_escriptize.erl b/src/rebar_prv_escriptize.erl
index 32f5508..d8704f6 100644
--- a/src/rebar_prv_escriptize.erl
+++ b/src/rebar_prv_escriptize.erl
@@ -90,9 +90,9 @@ escriptize(State0, App) ->
%% Look for a list of other applications (dependencies) to include
%% in the output file. We then use the .app files for each of these
%% to pull in all the .beam files.
- InclApps = lists:usort([ec_cnv:to_atom(AppName) | rebar_state:get(State, escript_incl_apps, [])
- ++ all_deps(State)]),
+ TopInclApps = lists:usort([ec_cnv:to_atom(AppName) | rebar_state:get(State, escript_incl_apps, [])]),
AllApps = rebar_state:all_deps(State)++rebar_state:project_apps(State),
+ InclApps = find_deps(TopInclApps, AllApps),
InclBeams = get_apps_beams(InclApps, AllApps),
%% Look for a list of extra files to include in the output file.
@@ -219,9 +219,23 @@ usort(List) ->
get_nonempty(Files) ->
[{FName,FBin} || {FName,FBin} <- Files, FBin =/= <<>>].
-all_deps(State) ->
- [list_to_existing_atom(binary_to_list(rebar_app_info:name(App)))
- || App <- rebar_state:all_deps(State)].
+find_deps(AppNames, AllApps) ->
+ BinAppNames = [ec_cnv:to_binary(Name) || Name <- AppNames],
+ [ec_cnv:to_atom(Name) ||
+ Name <- find_deps_of_deps(BinAppNames, AllApps, BinAppNames)].
+
+%% Should look at the app files to find direct dependencies
+find_deps_of_deps([], _, Acc) -> Acc;
+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,
+ %% ignore system libs; shouldn't include them.
+ not lists:prefix(code:root_dir(), code:lib_dir(Dep))]
+ -- ([Name|Names]++Acc), % avoid already seen deps
+ ?DEBUG("new deps of ~p found to be ~p", [Name, BinDepNames]),
+ find_deps_of_deps(BinDepNames ++ Names, Apps, BinDepNames ++ Acc).
def(Rm, State, Key, Default) ->
Value0 = rebar_state:get(State, Key, Default),
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index 5e6aa4c..a8a7ea0 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -352,10 +352,14 @@ 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), rebar_app_info:source(AppInfo)]),
+ ?INFO("Fetching ~s (~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).
+format_source({pkg, Name, Vsn, _Hash}) -> {pkg, Name, Vsn};
+format_source(Source) -> Source.
+
%% This is called after the dep has been downloaded and unpacked, if it hadn't been already.
%% So this is the first time for newly downloaded apps that its .app/.app.src data can
%% be read in an parsed.