浏览代码

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.
pull/1337/head
Fred Hebert 8 年前
父节点
当前提交
1f86ed1aed
共有 2 个文件被更改,包括 60 次插入2 次删除
  1. +17
    -1
      src/rebar_prv_update.erl
  2. +43
    -1
      test/rebar_pkg_alias_SUITE.erl

+ 17
- 1
src/rebar_prv_update.erl 查看文件

@ -104,7 +104,8 @@ hex_to_index(State) ->
case lists:any(fun is_supported/1, BuildTools) of case lists:any(fun is_supported/1, BuildTools) of
true -> true ->
DepsList = update_deps_list(Pkg, PkgVsn, Deps, Registry, State), 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 -> false ->
true true
end; end;
@ -176,6 +177,21 @@ update_deps_list(Pkg, PkgVsn, Deps, HexRegistry, State) ->
DepsListAcc DepsListAcc
end, [], Deps). 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/binary>>) ->
rm_ws(R); rm_ws(R);
rm_ws(R) -> rm_ws(R) ->

+ 43
- 1
test/rebar_pkg_alias_SUITE.erl 查看文件

@ -4,7 +4,8 @@
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-include_lib("kernel/include/file.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, uuid}} = uuid
%% {uuid, {pkg, alias}} = uuid on disk %% {uuid, {pkg, alias}} = uuid on disk
@ -34,6 +35,12 @@ init_per_testcase(diff_alias_vsn, Config0) ->
RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, "1.0.0", {pkg, goodpkg}}]}]), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, "1.0.0", {pkg, goodpkg}}]}]),
[{rebarconfig, RebarConf} | Config]; [{rebarconfig, RebarConf} | Config];
init_per_testcase(transitive_alias, Config0) -> init_per_testcase(transitive_alias, 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];
init_per_testcase(transitive_hash_mismatch, Config0) ->
Config = rebar_test_utils:init_rebar_state(Config0,"transitive_alias_vsn_"), Config = rebar_test_utils:init_rebar_state(Config0,"transitive_alias_vsn_"),
AppDir = ?config(apps, Config), AppDir = ?config(apps, Config),
rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]),
@ -120,6 +127,41 @@ transitive_alias(Config) ->
?assertNot(filelib:is_dir(PkgName)), ?assertNot(filelib:is_dir(PkgName)),
ok. 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) -> mock_config(Name, Config) ->
{ChkFake, Etag} = create_lib(Name, Config, "fakelib"), {ChkFake, Etag} = create_lib(Name, Config, "fakelib"),
{ChkTop, _} = create_lib(Name, Config, "topdep"), {ChkTop, _} = create_lib(Name, Config, "topdep"),

正在加载...
取消
保存