瀏覽代碼

Merge pull request #1207 from ferd/pkg-local-hash-lock

lock file contains expected hash for pkg dependencies
pull/1206/merge
Fred Hebert 8 年之前
committed by GitHub
父節點
當前提交
feed75ca91
共有 20 個檔案被更改,包括 379 行新增77 行删除
  1. +1
    -0
      rebar.config
  2. +15
    -1
      rebar.lock
  3. +1
    -0
      src/rebar.hrl
  4. +16
    -7
      src/rebar_app_utils.erl
  5. +82
    -12
      src/rebar_config.erl
  6. +6
    -0
      src/rebar_fetch.erl
  7. +1
    -1
      src/rebar_packages.erl
  8. +13
    -10
      src/rebar_pkg_resource.erl
  9. +1
    -1
      src/rebar_prv_deps.erl
  10. +5
    -1
      src/rebar_prv_install_deps.erl
  11. +6
    -5
      test/mock_pkg_resource.erl
  12. +1
    -1
      test/rebar_deps_SUITE.erl
  13. +1
    -1
      test/rebar_install_deps_SUITE.erl
  14. +72
    -6
      test/rebar_lock_SUITE.erl
  15. +45
    -7
      test/rebar_pkg_SUITE.erl
  16. +3
    -3
      test/rebar_pkg_alias_SUITE.erl
  17. +30
    -17
      test/rebar_test_utils.erl
  18. +40
    -3
      test/rebar_unlock_SUITE.erl
  19. +32
    -0
      test/rebar_unlock_SUITE_data/pkg.rebar.lock
  20. +8
    -1
      test/rebar_upgrade_SUITE.erl

+ 1
- 0
rebar.config 查看文件

@ -20,6 +20,7 @@
{"rebar/priv/templates/*", "_build/default/lib/"}]}.
{erl_opts, [{platform_define, "^[0-9]+", namespaced_types},
{platform_define, "^(19|2)", rand_only},
no_debug_info,
warnings_as_errors]}.

+ 15
- 1
rebar.lock 查看文件

@ -1,3 +1,4 @@
{"1.1.0",
[{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.0.4">>},0},
{<<"certifi">>,{pkg,<<"certifi">>,<<"0.4.0">>},0},
{<<"cf">>,{pkg,<<"cf">>,<<"0.2.1">>},0},
@ -7,4 +8,17 @@
{<<"getopt">>,{pkg,<<"getopt">>,<<"0.8.2">>},0},
{<<"providers">>,{pkg,<<"providers">>,<<"1.6.0">>},0},
{<<"relx">>,{pkg,<<"relx">>,<<"3.19.0">>},0},
{<<"ssl_verify_hostname">>,{pkg,<<"ssl_verify_hostname">>,<<"1.0.5">>},0}].
{<<"ssl_verify_hostname">>,{pkg,<<"ssl_verify_hostname">>,<<"1.0.5">>},0}]}.
[
{pkg_hash,[
{<<"bbmustache">>, <<"7BA94F971C5AFD7B6617918A4BB74705E36CAB36EB84B19B6A1B7EE06427AA38">>},
{<<"certifi">>, <<"A7966EFB868B179023618D29A407548F70C52466BF1849B9E8EBD0E34B7EA11F">>},
{<<"cf">>, <<"69D0B1349FD4D7D4DC55B7F407D29D7A840BF9A1EF5AF529F1EBE0CE153FC2AB">>},
{<<"cth_readable">>, <<"983913A8E8572310B7EAF5F2631148B7D70B3C090D2120DCFE777A93AA4165FB">>},
{<<"erlware_commons">>, <<"A04433071AD7D112EDEFC75AC77719DD3E6753E697AC09428FC83D7564B80B15">>},
{<<"eunit_formatters">>, <<"7A6FC351EB5B873E2356B8852EB751E20C13A72FBCA03393CF682B8483509573">>},
{<<"getopt">>, <<"B17556DB683000BA50370B16C0619DF1337E7AF7ECBF7D64FBF8D1D6BCE3109B">>},
{<<"providers">>, <<"DB0E2F9043AE60C0155205FCD238D68516331D0E5146155E33D1E79DC452964A">>},
{<<"relx">>, <<"286DD5244B4786F56AAC75D5C8E2D1FB4CFD306810D4EC8548F3AE1B3AADB8F7">>},
{<<"ssl_verify_hostname">>, <<"2E73E068CD6393526F9FA6D399353D7C9477D6886BA005F323B592D389FB47BE">>}]}
].

+ 1
- 0
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").

+ 16
- 7
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),

+ 82
- 12
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),

+ 6
- 0
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}) ->

+ 1
- 1
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)

+ 13
- 10
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."}.

+ 1
- 1
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

+ 5
- 1
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.

+ 6
- 5
test/mock_pkg_resource.erl 查看文件

@ -22,8 +22,9 @@ mock() -> mock([]).
| {not_in_index, [{App, Vsn}]}
| {pkgdeps, [{{App,Vsn}, [Dep]}]},
App :: string(),
Dep :: {App, string(), {pkg, App, Vsn}},
Vsn :: string().
Dep :: {App, string(), {pkg, App, Vsn, Hash}},
Vsn :: string(),
Hash :: string() | undefined.
mock(Opts) ->
meck:new(?MOD, [no_link]),
mock_lock(Opts),
@ -51,7 +52,7 @@ mock_update(Opts) ->
ToUpdate = proplists:get_value(upgrade, Opts, []),
meck:expect(
?MOD, needs_update,
fun(_Dir, {pkg, App, _Vsn}) ->
fun(_Dir, {pkg, App, _Vsn, _Hash}) ->
lists:member(binary_to_list(App), ToUpdate)
end).
@ -66,7 +67,7 @@ mock_vsn(_Opts) ->
%% @doc For each app to download, create a dummy app on disk instead.
%% The configuration for this one (passed in from `mock/1') includes:
%%
%% - Specify a version with `{pkg, _, Vsn}'
%% - Specify a version with `{pkg, _, Vsn, _}'
%% - Dependencies for each application must be passed of the form:
%% `{pkgdeps, [{"app1", [{app2, ".*", {pkg, ...}}]}]}' -- basically
%% the `pkgdeps' option takes a key/value list of terms to output directly
@ -76,7 +77,7 @@ mock_download(Opts) ->
Config = proplists:get_value(config, Opts, []),
meck:expect(
?MOD, download,
fun (Dir, {pkg, AppBin, Vsn}, _) ->
fun (Dir, {pkg, AppBin, Vsn, _}, _) ->
App = binary_to_list(AppBin),
filelib:ensure_dir(Dir),
AppDeps = proplists:get_value({App,Vsn}, Deps, []),

+ 1
- 1
test/rebar_deps_SUITE.erl 查看文件

@ -476,5 +476,5 @@ in_warnings(git, Warns, NameRaw, VsnRaw) ->
in_warnings(pkg, Warns, NameRaw, VsnRaw) ->
Name = iolist_to_binary(NameRaw),
Vsn = iolist_to_binary(VsnRaw),
1 =< length([1 || {_, [AppName, {pkg, _, AppVsn}]} <- Warns,
1 =< length([1 || {_, [AppName, {pkg, _, AppVsn, _}]} <- Warns,
AppName =:= Name, AppVsn =:= Vsn]).

+ 1
- 1
test/rebar_install_deps_SUITE.erl 查看文件

@ -475,5 +475,5 @@ in_warnings(git, Warns, NameRaw, VsnRaw) ->
in_warnings(pkg, Warns, NameRaw, VsnRaw) ->
Name = iolist_to_binary(NameRaw),
Vsn = iolist_to_binary(VsnRaw),
1 =< length([1 || {_, [AppName, {pkg, _, AppVsn}]} <- Warns,
1 =< length([1 || {_, [AppName, {pkg, _, AppVsn, _}]} <- Warns,
AppName =:= Name, AppVsn =:= Vsn]).

+ 72
- 6
test/rebar_lock_SUITE.erl 查看文件

@ -7,17 +7,69 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
all() -> [current_version, future_versions_no_attrs, future_versions_attrs].
all() -> [current_version,
beta_version, future_versions_no_attrs, future_versions_attrs].
current_version(Config) ->
%% Current version just dumps the locks as is on disk.
LockFile = filename:join(?config(priv_dir, Config), "current_version"),
Locks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>},3},
{<<"pkg2">>,{pkg,<<"name1">>,<<"1.1.6">>},2},
{<<"pkg3">>,{pkg,<<"name2">>,<<"3.0.6">>},1}
],
ExpandedNull = [
{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>,undefined},3},
{<<"pkg2">>,{pkg,<<"name1">>,<<"1.1.6">>,undefined},2},
{<<"pkg3">>,{pkg,<<"name2">>,<<"3.0.6">>,undefined},1}
],
%% Simulate a beta lockfile
file:write_file(LockFile, io_lib:format("~p.~n", [Locks])),
%% No properties fetched from a beta lockfile, expand locks
%% to undefined
?assertEqual(ExpandedNull,
rebar_config:consult_lock_file(LockFile)),
%% Adding hash data
Hashes = [{<<"pkg1">>, <<"tarballhash">>},
{<<"pkg3">>, <<"otherhash">>}],
ExpandedLocks = [
{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>,<<"tarballhash">>},3},
{<<"pkg2">>,{pkg,<<"name1">>,<<"1.1.6">>,undefined},2},
{<<"pkg3">>,{pkg,<<"name2">>,<<"3.0.6">>,<<"otherhash">>},1}
],
file:write_file(LockFile,
io_lib:format("~p.~n~p.~n",
[{"1.1.0", Locks},
[{pkg_hash, Hashes}]])),
?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)),
%% Then check that we can reverse that
ok = rebar_config:write_lock_file(LockFile, ExpandedLocks),
?assertEqual({ok, [{"1.1.0", Locks}, [{pkg_hash, Hashes}]]},
file:consult(LockFile)).
beta_version(Config) ->
%% Current version just dumps the locks as is on disk.
LockFile = filename:join(?config(priv_dir, Config), "current_version"),
Locks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>},3}],
ExpandedLocks = [
{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>,undefined},3}
],
file:write_file(LockFile, io_lib:format("~p.~n", [Locks])),
?assertEqual(Locks, rebar_config:consult_lock_file(LockFile)).
?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)).
future_versions_no_attrs(Config) ->
%% Future versions will keep the same core attribute in there, but
@ -27,10 +79,14 @@ future_versions_no_attrs(Config) ->
Locks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>},3}],
{<<"pkg1">>, {pkg,<<"name">>,<<"0.1.6">>},3}],
ExpandedLocks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>, {pkg,<<"name">>,<<"0.1.6">>,undefined},3}],
LockData = {"3.5.2", Locks},
file:write_file(LockFile, io_lib:format("~p.~n", [LockData])),
?assertEqual(Locks, rebar_config:consult_lock_file(LockFile)).
?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)).
future_versions_attrs(Config) ->
%% Future versions will keep the same core attribute in there, but
@ -41,6 +97,16 @@ future_versions_attrs(Config) ->
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>},3}],
ExpandedLocks = [{<<"app1">>, {git,"some_url", {ref,"some_ref"}}, 2},
{<<"app2">>, {git,"some_url", {ref,"some_ref"}}, 0},
{<<"app3">>, {hg,"some_url", {ref,"some_ref"}}, 1},
{<<"pkg1">>,{pkg,<<"name">>,<<"0.1.6">>, <<"tarballhash">>},3}],
Hashes = [{<<"pkg1">>, <<"tarballhash">>}],
LockData = {"3.5.2", Locks},
file:write_file(LockFile, io_lib:format("~p.~na.~n{b,c}.~n[d,e,f].~n", [LockData])),
?assertEqual(Locks, rebar_config:consult_lock_file(LockFile)).
file:write_file(LockFile,
io_lib:format("~p.~n~p.~ngarbage.~n",
[LockData,
[{a, x},
{pkg_hash, Hashes},
{b, y}]])),
?assertEqual(ExpandedLocks, rebar_config:consult_lock_file(LockFile)).

+ 45
- 7
test/rebar_pkg_SUITE.erl 查看文件

@ -11,6 +11,7 @@
-define(good_checksum, <<"1C6CE379D191FBAB41B7905075E0BF87CBBE23C77CECE775C5A0B786B2244C35">>).
all() -> [good_uncached, good_cached, badindexchk, badpkg,
badhash_nocache, badhash_cache,
bad_to_good, good_disconnect, bad_disconnect, pkgs_provider,
find_highest_matching].
@ -58,6 +59,19 @@ init_per_testcase(badpkg=Name, Config0) ->
{pkg, {<<"badpkg">>, <<"1.0.0">>}}
| Config0],
mock_config(Name, Config);
init_per_testcase(badhash_nocache=Name, Config0) ->
Config = [{good_cache, false},
{pkg, {<<"goodpkg">>, <<"1.0.0">>}}
| Config0],
mock_config(Name, Config);
init_per_testcase(badhash_cache=Name, Config0) ->
Pkg = {<<"goodpkg">>, <<"1.0.0">>},
Config1 = [{good_cache, true},
{pkg, Pkg}
| Config0],
Config = mock_config(Name, Config1),
copy_to_cache(Pkg, Config),
Config;
init_per_testcase(bad_to_good=Name, Config0) ->
Config1 = [{good_cache, false},
{pkg, {<<"goodpkg">>, <<"1.0.0">>}}
@ -103,7 +117,7 @@ good_uncached(Config) ->
{Pkg,Vsn} = ?config(pkg, Config),
State = ?config(state, Config),
?assertEqual({ok, true},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)),
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum}, State)),
Cache = ?config(cache_dir, Config),
?assert(filelib:is_regular(filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>))).
@ -116,7 +130,7 @@ good_cached(Config) ->
?assert(filelib:is_regular(CachedFile)),
{ok, Content} = file:read_file(CachedFile),
?assertEqual({ok, true},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)),
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum}, State)),
{ok, Content} = file:read_file(CachedFile).
badindexchk(Config) ->
@ -124,7 +138,7 @@ badindexchk(Config) ->
{Pkg,Vsn} = ?config(pkg, Config),
State = ?config(state, Config),
?assertMatch({bad_registry_checksum, _Path},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)),
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum}, State)),
%% The cached file is there for forensic purposes
Cache = ?config(cache_dir, Config),
?assert(filelib:is_regular(filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>))).
@ -134,11 +148,35 @@ badpkg(Config) ->
{Pkg,Vsn} = ?config(pkg, Config),
State = ?config(state, Config),
?assertMatch({bad_download, _Path},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)),
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum}, State)),
%% The cached file is there for forensic purposes
Cache = ?config(cache_dir, Config),
?assert(filelib:is_regular(filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>))).
badhash_nocache(Config) ->
Tmp = ?config(tmp_dir, Config),
{Pkg,Vsn} = ?config(pkg, Config),
State = ?config(state, Config),
?assertMatch({unexpected_hash, _Path, ?bad_checksum, ?good_checksum},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?bad_checksum}, State)),
%% The cached file is there for forensic purposes
Cache = ?config(cache_dir, Config),
?assert(filelib:is_regular(filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>))).
badhash_cache(Config) ->
Tmp = ?config(tmp_dir, Config),
{Pkg,Vsn} = ?config(pkg, Config),
Cache = ?config(cache_dir, Config),
State = ?config(state, Config),
CachedFile = filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>),
?assert(filelib:is_regular(CachedFile)),
{ok, Content} = file:read_file(CachedFile),
?assertMatch({unexpected_hash, _Path, ?bad_checksum, ?good_checksum},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?bad_checksum}, State)),
%% The cached file is there still, unchanged.
?assert(filelib:is_regular(CachedFile)),
?assertEqual({ok, Content}, file:read_file(CachedFile)).
bad_to_good(Config) ->
Tmp = ?config(tmp_dir, Config),
{Pkg,Vsn} = ?config(pkg, Config),
@ -148,7 +186,7 @@ bad_to_good(Config) ->
?assert(filelib:is_regular(CachedFile)),
{ok, Contents} = file:read_file(CachedFile),
?assertEqual({ok, true},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)),
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum}, State)),
%% Cache has refreshed
?assert({ok, Contents} =/= file:read_file(CachedFile)).
@ -161,7 +199,7 @@ good_disconnect(Config) ->
?assert(filelib:is_regular(CachedFile)),
{ok, Content} = file:read_file(CachedFile),
?assertEqual({ok, true},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)),
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum}, State)),
{ok, Content} = file:read_file(CachedFile).
bad_disconnect(Config) ->
@ -169,7 +207,7 @@ bad_disconnect(Config) ->
{Pkg,Vsn} = ?config(pkg, Config),
State = ?config(state, Config),
?assertEqual({fetch_fail, Pkg, Vsn},
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)).
rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn, ?good_checksum}, State)).
pkgs_provider(Config) ->
Config1 = rebar_test_utils:init_rebar_state(Config),

+ 3
- 3
test/rebar_pkg_alias_SUITE.erl 查看文件

@ -55,7 +55,7 @@ diff_alias(Config) ->
Config, RebarConfig, ["lock"],
{ok, [{lock, "fakelib"},{dep, "fakelib"}]}
),
{ok, [LockData]} = file:consult(Lockfile),
{ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile),
?assert(lists:any(fun({<<"fakelib">>,{pkg,<<"goodpkg">>,_},_}) -> true
; (_) -> false end, LockData)),
%% An second run yields the same
@ -63,13 +63,13 @@ diff_alias(Config) ->
Config, RebarConfig, ["lock"],
{ok, [{lock, "fakelib"},{dep, "fakelib"}]}
),
{ok, [LockData]} = file:consult(Lockfile),
{ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile),
%% So does an upgrade
rebar_test_utils:run_and_check(
Config, RebarConfig, ["upgrade"],
{ok, [{lock, "fakelib"},{dep, "fakelib"}]}
),
{ok, [LockData]} = file:consult(Lockfile).
{ok, [{_Vsn, LockData}|_]} = file:consult(Lockfile).
diff_alias_vsn(Config) -> diff_alias(Config).

+ 30
- 17
test/rebar_test_utils.erl 查看文件

@ -7,6 +7,13 @@
create_config/2, create_config/3, package_app/3]).
-export([create_random_name/1, create_random_vsn/0, write_src_file/2]).
%% Pick the right random module
-ifdef(rand_only).
-define(random, rand).
-else.
-define(random, random).
-endif.
%%%%%%%%%%%%%%
%%% Public %%%
%%%%%%%%%%%%%%
@ -126,20 +133,24 @@ create_config(_AppDir, ConfFilename, Contents) ->
%% @doc Util to create a random variation of a given name.
create_random_name(Name) ->
random_seed(),
Name ++ erlang:integer_to_list(random:uniform(1000000)).
Name ++ erlang:integer_to_list(?random:uniform(1000000)).
%% @doc Util to create a random variation of a given version.
create_random_vsn() ->
random_seed(),
lists:flatten([erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100)),
".", erlang:integer_to_list(random:uniform(100))]).
lists:flatten([erlang:integer_to_list(?random:uniform(100)),
".", erlang:integer_to_list(?random:uniform(100)),
".", erlang:integer_to_list(?random:uniform(100))]).
-ifdef(rand_only).
random_seed() ->
%% the rand module self-seeds
ok.
-else.
random_seed() ->
<<A:32, B:32, C:32>> = crypto:rand_bytes(12),
random:seed({A,B,C}).
-endif.
expand_deps(_, []) -> [];
expand_deps(git, [{Name, Deps} | Rest]) ->
@ -149,21 +160,21 @@ expand_deps(git, [{Name, Vsn, Deps} | Rest]) ->
Dep = {Name, Vsn, {git, "https://example.org/user/"++Name++".git", {tag, Vsn}}},
[{Dep, expand_deps(git, Deps)} | expand_deps(git, Rest)];
expand_deps(pkg, [{Name, Deps} | Rest]) ->
Dep = {pkg, Name, "0.0.0"},
Dep = {pkg, Name, "0.0.0", undefined},
[{Dep, expand_deps(pkg, Deps)} | expand_deps(pkg, Rest)];
expand_deps(pkg, [{Name, Vsn, Deps} | Rest]) ->
Dep = {pkg, Name, Vsn},
Dep = {pkg, Name, Vsn, undefined},
[{Dep, expand_deps(pkg, Deps)} | expand_deps(pkg, Rest)];
expand_deps(mixed, [{Name, Deps} | Rest]) ->
Dep = if hd(Name) >= $a, hd(Name) =< $z ->
{pkg, string:to_upper(Name), "0.0.0"}
{pkg, string:to_upper(Name), "0.0.0", undefined}
; hd(Name) >= $A, hd(Name) =< $Z ->
{Name, ".*", {git, "https://example.org/user/"++Name++".git", "master"}}
end,
[{Dep, expand_deps(mixed, Deps)} | expand_deps(mixed, Rest)];
expand_deps(mixed, [{Name, Vsn, Deps} | Rest]) ->
Dep = if hd(Name) >= $a, hd(Name) =< $z ->
{pkg, string:to_upper(Name), Vsn}
{pkg, string:to_upper(Name), Vsn, undefined}
; hd(Name) >= $A, hd(Name) =< $Z ->
{Name, Vsn, {git, "https://example.org/user/"++Name++".git", {tag, Vsn}}}
end,
@ -177,7 +188,7 @@ expand_deps(mixed, [{Name, Vsn, Deps} | Rest]) ->
flat_deps(Deps) -> flat_deps(Deps, [], []).
flat_deps([], Src, Pkg) -> {Src, Pkg};
flat_deps([{{pkg, Name, Vsn}, PkgDeps} | Rest], Src, Pkg) ->
flat_deps([{{pkg, Name, Vsn, undefined}, PkgDeps} | Rest], Src, Pkg) ->
Current = {{iolist_to_binary(Name), iolist_to_binary(Vsn)},
top_level_deps(PkgDeps)},
{[], FlatPkgDeps} = flat_deps(PkgDeps),
@ -195,7 +206,7 @@ vsn_from_ref({git, _, {_, Vsn}}) -> Vsn;
vsn_from_ref({git, _, Vsn}) -> Vsn.
top_level_deps([]) -> [];
top_level_deps([{{pkg, Name, Vsn}, _} | Deps]) ->
top_level_deps([{{pkg, Name, Vsn, undefined}, _} | Deps]) ->
[{list_to_atom(Name), Vsn} | top_level_deps(Deps)];
top_level_deps([{{Name, Vsn, Ref}, _} | Deps]) ->
[{list_to_atom(Name), Vsn, Ref} | top_level_deps(Deps)].
@ -306,9 +317,10 @@ check_results(AppDir, Expected, ProfileRun) ->
case lists:keyfind(iolist_to_binary(Name), 1, Locks) of
false ->
error({lock_not_found, Name});
{_LockName, {pkg, _, LockVsn}, _} ->
{_LockName, {pkg, _, LockVsn, Hash}, _} ->
?assertEqual(iolist_to_binary(Vsn),
iolist_to_binary(LockVsn));
iolist_to_binary(LockVsn)),
?assertNotEqual(undefined, Hash);
{_LockName, {_, _, {ref, LockVsn}}, _} ->
?assertEqual(iolist_to_binary(Vsn),
iolist_to_binary(LockVsn))
@ -318,9 +330,10 @@ check_results(AppDir, Expected, ProfileRun) ->
case lists:keyfind(iolist_to_binary(Name), 1, Locks) of
false ->
error({lock_not_found, Name});
{_LockName, {pkg, _, LockVsn}, _} ->
{_LockName, {pkg, _, LockVsn, Hash}, _} ->
?assertEqual(iolist_to_binary(Vsn),
iolist_to_binary(LockVsn));
iolist_to_binary(LockVsn)),
?assertNotEqual(undefined, Hash);
{_LockName, {_, _, {ref, LockVsn}}, _} ->
error({source_lock, {Name, LockVsn}})
end
@ -329,7 +342,7 @@ check_results(AppDir, Expected, ProfileRun) ->
case lists:keyfind(iolist_to_binary(Name), 1, Locks) of
false ->
error({lock_not_found, Name});
{_LockName, {pkg, _, LockVsn}, _} ->
{_LockName, {pkg, _, LockVsn, _}, _} ->
error({pkg_lock, {Name, LockVsn}});
{_LockName, {_, _, {ref, LockVsn}}, _} ->
?assertEqual(iolist_to_binary(Vsn),

+ 40
- 3
test/rebar_unlock_SUITE.erl 查看文件

@ -3,8 +3,14 @@
-include_lib("eunit/include/eunit.hrl").
-compile(export_all).
all() -> [unlock, unlock_all].
all() -> [pkgunlock, unlock, unlock_all].
init_per_testcase(pkgunlock, Config0) ->
Config = rebar_test_utils:init_rebar_state(Config0, "pkgunlock"),
Lockfile = filename:join(?config(apps, Config), "rebar.lock"),
ec_file:copy(filename:join(?config(data_dir, Config), "pkg.rebar.lock"),
Lockfile),
[{lockfile, Lockfile} | Config];
init_per_testcase(Case, Config0) ->
Config = rebar_test_utils:init_rebar_state(Config0, atom_to_list(Case)),
Lockfile = filename:join(?config(apps, Config), "rebar.lock"),
@ -15,6 +21,23 @@ init_per_testcase(Case, Config0) ->
end_per_testcase(_, Config) ->
Config.
pkgunlock(Config) ->
Locks = read_locks(Config),
Hashes = read_hashes(Config),
rebar_test_utils:run_and_check(Config, [], ["unlock", "fakeapp"], {ok, []}),
Locks = read_locks(Config),
Hashes = read_hashes(Config),
rebar_test_utils:run_and_check(Config, [], ["unlock", "bbmustache"], {ok, []}),
?assertEqual(Locks -- ["bbmustache"], read_locks(Config)),
?assertEqual(Hashes -- ["bbmustache"], read_hashes(Config)),
rebar_test_utils:run_and_check(Config, [], ["unlock", "cf,certifi"], {ok, []}),
?assertEqual(Locks -- ["bbmustache","cf","certifi"], read_locks(Config)),
?assertEqual(Hashes -- ["bbmustache","cf","certifi"], read_hashes(Config)),
rebar_test_utils:run_and_check(Config, [], ["unlock", string:join(Locks,",")], {ok, []}),
?assertEqual({error, enoent}, read_locks(Config)),
?assertEqual({error, enoent}, read_hashes(Config)),
ok.
unlock(Config) ->
Locks = read_locks(Config),
rebar_test_utils:run_and_check(Config, [], ["unlock", "fakeapp"], {ok, []}),
@ -35,6 +58,20 @@ unlock_all(Config) ->
read_locks(Config) ->
case file:consult(?config(lockfile, Config)) of
{ok, [Locks]} -> [binary_to_list(element(1,Lock)) || Lock <- Locks];
Other -> Other
{ok, _} ->
Locks = rebar_config:consult_lock_file(?config(lockfile, Config)),
[binary_to_list(element(1,Lock)) || Lock <- Locks];
Other ->
Other
end.
read_hashes(Config) ->
case file:consult(?config(lockfile, Config)) of
{ok, [{_Vsn, _Locks},Props|_]} ->
Hashes = proplists:get_value(pkg_hash, Props, []),
[binary_to_list(element(1,Hash)) || Hash <- Hashes];
{ok, [{_Vsn, _Locks}]} ->
[];
Other ->
Other
end.

+ 32
- 0
test/rebar_unlock_SUITE_data/pkg.rebar.lock 查看文件

@ -0,0 +1,32 @@
{"1.1.0",[{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.0.4">>},0},
{<<"certifi">>,{pkg,<<"certifi">>,<<"0.4.0">>},0},
{<<"cf">>,{pkg,<<"cf">>,<<"0.2.1">>},0},
{<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.2.2">>},0},
{<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"0.21.0">>},0},
{<<"eunit_formatters">>,{pkg,<<"eunit_formatters">>,<<"0.3.1">>},0},
{<<"getopt">>,{pkg,<<"getopt">>,<<"0.8.2">>},0},
{<<"providers">>,{pkg,<<"providers">>,<<"1.6.0">>},0},
{<<"relx">>,{pkg,<<"relx">>,<<"3.19.0">>},0},
{<<"ssl_verify_hostname">>,
{pkg,<<"ssl_verify_hostname">>,<<"1.0.5">>},
0}]}.
[{pkg_hash,[{<<"bbmustache">>,
<<"7BA94F971C5AFD7B6617918A4BB74705E36CAB36EB84B19B6A1B7EE06427AA38">>},
{<<"certifi">>,
<<"A7966EFB868B179023618D29A407548F70C52466BF1849B9E8EBD0E34B7EA11F">>},
{<<"cf">>,
<<"69D0B1349FD4D7D4DC55B7F407D29D7A840BF9A1EF5AF529F1EBE0CE153FC2AB">>},
{<<"cth_readable">>,
<<"983913A8E8572310B7EAF5F2631148B7D70B3C090D2120DCFE777A93AA4165FB">>},
{<<"erlware_commons">>,
<<"A04433071AD7D112EDEFC75AC77719DD3E6753E697AC09428FC83D7564B80B15">>},
{<<"eunit_formatters">>,
<<"7A6FC351EB5B873E2356B8852EB751E20C13A72FBCA03393CF682B8483509573">>},
{<<"getopt">>,
<<"B17556DB683000BA50370B16C0619DF1337E7AF7ECBF7D64FBF8D1D6BCE3109B">>},
{<<"providers">>,
<<"DB0E2F9043AE60C0155205FCD238D68516331D0E5146155E33D1E79DC452964A">>},
{<<"relx">>,
<<"286DD5244B4786F56AAC75D5C8E2D1FB4CFD306810D4EC8548F3AE1B3AADB8F7">>},
{<<"ssl_verify_hostname">>,
<<"2E73E068CD6393526F9FA6D399353D7C9477D6886BA005F323B592D389FB47BE">>}]}].

+ 8
- 1
test/rebar_upgrade_SUITE.erl 查看文件

@ -654,7 +654,14 @@ novsn_pkg(Config) ->
rewrite_locks({ok, Expectations}, Config) ->
AppDir = ?config(apps, Config),
LockFile = filename:join([AppDir, "rebar.lock"]),
{ok, [Locks]} = file:consult(LockFile),
Locks = case ?config(deps_type, Config) of
git ->
{ok, [LockData]} = file:consult(LockFile),
LockData;
pkg ->
{ok, [{_Vsn, LockData}|_]} = file:consult(LockFile),
LockData
end,
ExpLocks = [{list_to_binary(Name), Vsn}
|| {lock, Name, Vsn} <- Expectations],
NewLocks = lists:foldl(

Loading…
取消
儲存