summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2016-10-04 22:34:22 -0400
committerFred Hebert <mononcqc@ferd.ca>2016-10-04 22:34:22 -0400
commit1f86ed1aed990438103c5f668c4ec930ab637fc9 (patch)
treef776e22401f1a593bd4f24fe189e6e854b2102e4
parent45d9127dc952430d4b519741cb2303953e302665 (diff)
Track package hash in memory index, add hash test
This adds tracking of package hash in the in-memory index rather than the current `undefined' values. According to the test added, this is not necessary for transitive package dep hash chcking, but does result in a more complete index search result when doing app lookups, and could yield some optimizations on hash checks by checking from the index structure before fetching a package.
-rw-r--r--src/rebar_prv_update.erl18
-rw-r--r--test/rebar_pkg_alias_SUITE.erl44
2 files changed, 60 insertions, 2 deletions
diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl
index ff7194a..75c609e 100644
--- a/src/rebar_prv_update.erl
+++ b/src/rebar_prv_update.erl
@@ -104,7 +104,8 @@ hex_to_index(State) ->
case lists:any(fun is_supported/1, BuildTools) of
true ->
DepsList = update_deps_list(Pkg, PkgVsn, Deps, Registry, State),
- ets:insert(?PACKAGE_TABLE, {{Pkg, PkgVsn}, DepsList, Checksum});
+ HashedDeps = update_deps_hashes(DepsList),
+ ets:insert(?PACKAGE_TABLE, {{Pkg, PkgVsn}, HashedDeps, Checksum});
false ->
true
end;
@@ -176,6 +177,21 @@ update_deps_list(Pkg, PkgVsn, Deps, HexRegistry, State) ->
DepsListAcc
end, [], Deps).
+update_deps_hashes(List) ->
+ [{Name, {pkg, PkgName, Vsn, lookup_hash(PkgName, Vsn, Hash)}}
+ || {Name, {pkg, PkgName, Vsn, Hash}} <- List].
+
+lookup_hash(Name, Vsn, undefined) ->
+ try
+ ets:lookup_element(?PACKAGE_TABLE, {Name, Vsn}, 3)
+ catch
+ _:_ ->
+ undefined
+ end;
+lookup_hash(_, _, Hash) ->
+ Hash.
+
+
rm_ws(<<" ", R/binary>>) ->
rm_ws(R);
rm_ws(R) ->
diff --git a/test/rebar_pkg_alias_SUITE.erl b/test/rebar_pkg_alias_SUITE.erl
index 903fdad..2b8ccd2 100644
--- a/test/rebar_pkg_alias_SUITE.erl
+++ b/test/rebar_pkg_alias_SUITE.erl
@@ -4,7 +4,8 @@
-include_lib("eunit/include/eunit.hrl").
-include_lib("kernel/include/file.hrl").
-all() -> [same_alias, diff_alias, diff_alias_vsn, transitive_alias].
+all() -> [same_alias, diff_alias, diff_alias_vsn, transitive_alias,
+ transitive_hash_mismatch].
%% {uuid, {pkg, uuid}} = uuid
%% {uuid, {pkg, alias}} = uuid on disk
@@ -38,6 +39,12 @@ init_per_testcase(transitive_alias, Config0) ->
AppDir = ?config(apps, Config),
rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{topdep, "1.0.0", {pkg, topdep}}]}]),
+ [{rebarconfig, RebarConf} | Config];
+init_per_testcase(transitive_hash_mismatch, Config0) ->
+ Config = rebar_test_utils:init_rebar_state(Config0,"transitive_alias_vsn_"),
+ AppDir = ?config(apps, Config),
+ rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
+ RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{topdep, "1.0.0", {pkg, topdep}}]}]),
[{rebarconfig, RebarConf} | Config].
end_per_testcase(_, Config) ->
@@ -120,6 +127,41 @@ transitive_alias(Config) ->
?assertNot(filelib:is_dir(PkgName)),
ok.
+transitive_hash_mismatch(Config) ->
+ %% ensure that the apps fetched under transitive aliases are
+ %% locked properly, but also that they are stored in the right
+ %% directory in the build dir to avoid breaking includes and
+ %% static analysis tools that rely on the location to work
+ AppDir = ?config(apps, Config),
+ Lockfile = filename:join([AppDir, "rebar.lock"]),
+ {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["lock"],
+ {ok, [{lock, "topdep"},{dep, "topdep"},
+ {lock,"transitive_app"},{dep,"transitive_app"}]}
+ ),
+ {ok, [LockData|Attrs]} = file:consult(Lockfile),
+ %% Change Lock hash data to cause a failure next time, but on transitive
+ %% deps only
+ NewLock = [LockData|lists:map(
+ fun([{pkg_hash, Hashes}|Rest]) ->
+ [{pkg_hash, [{<<"transitive_app">>, <<"fakehash">>}
+ | lists:keydelete(<<"transitive_app">>, 1, Hashes)]}
+ | Rest]
+ ; (Attr) ->
+ Attr
+ end, Attrs)],
+ {ok, Io} = file:open(Lockfile, [write]),
+ [io:format(Io, "~p.~n", [Attr]) || Attr <- NewLock],
+ file:close(Io),
+ ct:pal("lock: ~p", [file:consult(Lockfile)]),
+ ec_file:remove(filename:join([AppDir, "_build"]), [recursive]),
+ ?assertMatch(
+ {error, {rebar_fetch, {unexpected_hash, _, _, _}}},
+ rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], return)
+ ),
+ ok.
+
mock_config(Name, Config) ->
{ChkFake, Etag} = create_lib(Name, Config, "fakelib"),
{ChkTop, _} = create_lib(Name, Config, "topdep"),