summaryrefslogtreecommitdiff
path: root/src/rebar_pkg_resource.erl
diff options
context:
space:
mode:
authorLaszlo Toth <Laszlo.Toth@otpbank.hu>2018-04-11 17:03:34 +0200
committerLaszlo Toth <Laszlo.Toth@otpbank.hu>2018-04-11 17:03:34 +0200
commit97c48e86bb7ca8969fd19c999f55259e88d4a6db (patch)
tree6244d5991de8a5c6a041eb131ea4e0b4fb71973d /src/rebar_pkg_resource.erl
parenta03da56fb39bddcf6b5ef75cb5b5e40b5b5ab1d9 (diff)
(#1743): Add specs for dialyzer
Diffstat (limited to 'src/rebar_pkg_resource.erl')
-rw-r--r--src/rebar_pkg_resource.erl121
1 files changed, 118 insertions, 3 deletions
diff --git a/src/rebar_pkg_resource.erl b/src/rebar_pkg_resource.erl
index f77a81a..8806c8b 100644
--- a/src/rebar_pkg_resource.erl
+++ b/src/rebar_pkg_resource.erl
@@ -19,9 +19,26 @@
-include("rebar.hrl").
-include_lib("public_key/include/OTP-PUB-KEY.hrl").
+-type cached_result() :: {'bad_checksum',string()} |
+ {'bad_registry_checksum',string()} |
+ {'failed_extract',string()} |
+ {'ok','true'} |
+ {'unexpected_hash',string(),_,binary()}.
+
+-type download_result() :: {bad_download, binary() | string()} |
+ {fetch_fail, _, _} | cached_result().
+
+-spec lock(AppDir, Source) -> Res when
+ AppDir :: file:name(),
+ Source :: tuple(),
+ Res :: {atom(), string(), any()}.
lock(_AppDir, Source) ->
Source.
+-spec needs_update(Dir, Pkg) -> Res when
+ Dir :: file:name(),
+ Pkg :: {pkg, Name :: binary(), Vsn :: binary(), Hash :: binary()},
+ Res :: boolean().
needs_update(Dir, {pkg, _Name, Vsn, _Hash}) ->
[AppInfo] = rebar_app_discover:find_apps([Dir], all),
case rebar_app_info:original_vsn(AppInfo) =:= rebar_utils:to_list(Vsn) of
@@ -31,9 +48,20 @@ needs_update(Dir, {pkg, _Name, Vsn, _Hash}) ->
true
end.
+-spec download(TmpDir, Pkg, State) -> Res when
+ TmpDir :: file:name(),
+ Pkg :: {pkg, Name :: binary(), Vsn :: binary(), Hash :: binary()},
+ State :: rebar_state:t(),
+ Res :: {'error',_} | {'ok',_} | {'tarball',binary() | string()}.
download(TmpDir, Pkg, State) ->
download(TmpDir, Pkg, State, true).
+-spec download(TmpDir, Pkg, State, UpdateETag) -> Res when
+ TmpDir :: file:name(),
+ Pkg :: {pkg, Name :: binary(), Vsn :: binary(), Hash :: binary()},
+ State :: rebar_state:t(),
+ UpdateETag :: boolean(),
+ Res :: download_result().
download(TmpDir, Pkg={pkg, Name, Vsn, _Hash}, State, UpdateETag) ->
CDN = rebar_state:get(State, rebar_packages_cdn, ?DEFAULT_CDN),
{ok, PackageDir} = rebar_packages:package_dir(State),
@@ -48,6 +76,16 @@ download(TmpDir, Pkg={pkg, Name, Vsn, _Hash}, State, UpdateETag) ->
{fetch_fail, Name, Vsn}
end.
+-spec cached_download(TmpDir, CachePath, Pkg, Url, ETag, State, ETagPath, UpdateETag) -> Res when
+ TmpDir :: file:name(),
+ CachePath :: file:name(),
+ Pkg :: {pkg, Name :: binary(), Vsn :: binary(), Hash :: binary()},
+ Url :: string(),
+ ETag :: false | string(),
+ State :: rebar_state:t(),
+ ETagPath :: file:name(),
+ UpdateETag :: boolean(),
+ Res :: download_result().
cached_download(TmpDir, CachePath, Pkg={pkg, Name, Vsn, _Hash}, Url, ETag, State, ETagPath, UpdateETag) ->
case request(Url, ETag) of
{ok, cached} ->
@@ -65,6 +103,12 @@ cached_download(TmpDir, CachePath, Pkg={pkg, Name, Vsn, _Hash}, Url, ETag, State
{fetch_fail, Name, Vsn}
end.
+-spec serve_from_cache(TmpDir, CachePath, Pkg, State) -> Res when
+ TmpDir :: file:name(),
+ CachePath :: file:name(),
+ Pkg :: {pkg, Name :: binary(), Vsn :: binary(), Hash :: binary()},
+ State :: rebar_state:t(),
+ Res :: cached_result().
serve_from_cache(TmpDir, CachePath, Pkg, State) ->
{Files, Contents, Version, Meta} = extract(TmpDir, CachePath),
case checksums(Pkg, Files, Contents, Version, Meta, State) of
@@ -85,6 +129,15 @@ serve_from_cache(TmpDir, CachePath, Pkg, State) ->
{bad_checksum, CachePath}
end.
+-spec serve_from_download(TmpDir, CachePath, Package, ETag, Binary, State, ETagPath) -> Res when
+ TmpDir :: file:name(),
+ CachePath :: file:name(),
+ Package :: {pkg, Name :: binary(), Vsn :: binary(), Hash :: binary()},
+ ETag :: string(),
+ Binary :: binary(),
+ State :: rebar_state:t(),
+ ETagPath :: file:name(),
+ Res :: download_result().
serve_from_download(TmpDir, CachePath, Package, ETag, Binary, State, ETagPath) ->
?DEBUG("Writing ~p to cache at ~ts", [Package, CachePath]),
file:write_file(CachePath, Binary),
@@ -96,6 +149,14 @@ serve_from_download(TmpDir, CachePath, Package, ETag, Binary, State, ETagPath) -
{bad_download, CachePath}
end.
+-spec extract(TmpDir, CachePath) -> Res when
+ TmpDir :: file:name(),
+ CachePath :: file:name(),
+ Res :: {Files, Contents, Version, Meta},
+ Files :: list({file:name(), binary()}),
+ Contents :: binary(),
+ Version :: binary(),
+ Meta :: binary().
extract(TmpDir, CachePath) ->
ec_file:mkdir_p(TmpDir),
{ok, Files} = erl_tar:extract(CachePath, [memory]),
@@ -104,6 +165,18 @@ extract(TmpDir, CachePath) ->
{"metadata.config", Meta} = lists:keyfind("metadata.config", 1, Files),
{Files, Contents, Version, Meta}.
+-spec checksums(Pkg, Files, Contents, Version, Meta, State) -> Res when
+ Pkg :: {pkg, Name :: binary(), Vsn :: binary(), Hash :: binary()},
+ Files :: list({file:name(), binary()}),
+ Contents :: binary(),
+ Version :: binary(),
+ Meta :: binary(),
+ State :: rebar_state:t(),
+ Res :: {Hash, BinChecksum, RegistryChecksum, TarChecksum},
+ Hash :: binary(),
+ BinChecksum :: binary(),
+ RegistryChecksum :: any(),
+ TarChecksum :: binary().
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),
@@ -112,12 +185,18 @@ checksums(Pkg={pkg, _Name, _Vsn, Hash}, Files, Contents, Version, Meta, State) -
{"CHECKSUM", TarChecksum} = lists:keyfind("CHECKSUM", 1, Files),
{Hash, BinChecksum, RegistryChecksum, TarChecksum}.
+-spec make_vsn(Vsn) -> Res when
+ Vsn :: any(),
+ Res :: {'error',[1..255,...]}.
make_vsn(_) ->
{error, "Replacing version of type pkg not supported."}.
+-spec request(Url, ETag) -> Res when
+ Url :: string(),
+ ETag :: false | string(),
+ Res :: 'error' | {ok, cached} | {ok, any(), string()}.
request(Url, ETag) ->
HttpOptions = [{ssl, ssl_opts(Url)}, {relaxed, true} | rebar_utils:get_proxy_auth()],
-
case httpc:request(get, {Url, [{"if-none-match", "\"" ++ ETag ++ "\""} || ETag =/= false]++
[{"User-Agent", rebar_utils:user_agent()}]},
HttpOptions,
@@ -138,6 +217,9 @@ request(Url, ETag) ->
error
end.
+-spec etag(Path) -> Res when
+ Path :: file:name(),
+ Res :: false | string().
etag(Path) ->
case file:read_file(Path) of
{ok, Bin} ->
@@ -148,7 +230,9 @@ etag(Path) ->
%% @doc returns the SSL options adequate for the project based on
%% its configuration, including for validation of certs.
--spec ssl_opts(string()) -> [term()].
+-spec ssl_opts(Url) -> Res when
+ Url :: string(),
+ Res :: proplists:proplist().
ssl_opts(Url) ->
case get_ssl_config() of
ssl_verify_enabled ->
@@ -159,7 +243,10 @@ ssl_opts(Url) ->
%% @doc returns the SSL options adequate for the project based on
%% its configuration, including for validation of certs.
--spec ssl_opts(atom(), string()) -> [term()].
+-spec ssl_opts(Enabled, Url) -> Res when
+ Enabled :: atom(),
+ Url :: string(),
+ Res :: proplists:proplist().
ssl_opts(ssl_verify_enabled, Url) ->
case check_ssl_version() of
true ->
@@ -173,6 +260,9 @@ ssl_opts(ssl_verify_enabled, Url) ->
[{verify, verify_none}]
end.
+-spec partial_chain(Certs) -> Res when
+ Certs :: list(any()),
+ Res :: unknown_ca | {trusted_ca, any()}.
partial_chain(Certs) ->
Certs1 = [{Cert, public_key:pkix_decode_cert(Cert, otp)} || Cert <- Certs],
CACerts = certifi:cacerts(),
@@ -187,14 +277,23 @@ partial_chain(Certs) ->
unknown_ca
end.
+-spec extract_public_key_info(Cert) -> Res when
+ Cert :: #'OTPCertificate'{tbsCertificate::#'OTPTBSCertificate'{}},
+ Res :: any().
extract_public_key_info(Cert) ->
((Cert#'OTPCertificate'.tbsCertificate)#'OTPTBSCertificate'.subjectPublicKeyInfo).
+-spec check_cert(CACerts, Cert) -> Res when
+ CACerts :: list(any()),
+ Cert :: any(),
+ Res :: boolean().
check_cert(CACerts, Cert) ->
lists:any(fun(CACert) ->
extract_public_key_info(CACert) == extract_public_key_info(Cert)
end, CACerts).
+-spec check_ssl_version() ->
+ boolean().
check_ssl_version() ->
case application:get_key(ssl, vsn) of
{ok, Vsn} ->
@@ -203,6 +302,8 @@ check_ssl_version() ->
false
end.
+-spec get_ssl_config() ->
+ ssl_verify_disabled | ssl_verify_enabled.
get_ssl_config() ->
GlobalConfigFile = rebar_dir:global_config(),
Config = rebar_config:consult_file(GlobalConfigFile),
@@ -213,9 +314,14 @@ get_ssl_config() ->
ssl_verify_enabled
end.
+-spec parse_vsn(Vsn) -> Res when
+ Vsn :: string(),
+ Res :: {integer(), integer(), integer()}.
parse_vsn(Vsn) ->
version_pad(rebar_string:lexemes(Vsn, ".-")).
+-spec version_pad(list(nonempty_string())) -> Res when
+ Res :: {integer(), integer(), integer()}.
version_pad([Major]) ->
{list_to_integer(Major), 0, 0};
version_pad([Major, Minor]) ->
@@ -225,10 +331,19 @@ version_pad([Major, Minor, Patch]) ->
version_pad([Major, Minor, Patch | _]) ->
{list_to_integer(Major), list_to_integer(Minor), list_to_integer(Patch)}.
+-spec maybe_store_etag_in_cache(UpdateETag, Path, ETag) -> Res when
+ UpdateETag :: boolean(),
+ Path :: file:name(),
+ ETag :: string(),
+ Res :: ok.
maybe_store_etag_in_cache(false = _UpdateETag, _Path, _ETag) ->
ok;
maybe_store_etag_in_cache(true = _UpdateETag, Path, ETag) ->
store_etag_in_cache(Path, ETag).
+-spec store_etag_in_cache(File, ETag) -> Res when
+ File :: file:name(),
+ ETag :: string(),
+ Res :: ok.
store_etag_in_cache(Path, ETag) ->
ok = file:write_file(Path, ETag).