New upstream version 3.18.0

This commit is contained in:
Philipp Huebner 2022-01-08 15:36:34 +01:00
parent 36bc1e1299
commit b15a9b3527
62 changed files with 776 additions and 348 deletions

View File

@ -6,7 +6,7 @@ FROM erlang:20.3.8.1-alpine as builder
# "The LABEL instruction adds metadata to an image."
LABEL stage=builder
# Install git for fetching non-hex depenencies. Also allows rebar3
# Install git for fetching non-hex dependencies. Also allows rebar3
# to find it's own git version.
# Add any other Alpine libraries needed to compile the project here.
# See https://wiki.alpinelinux.org/wiki/Local_APK_cache for details

View File

@ -1,6 +1,6 @@
bbmustache
===========
[![Build Status](https://travis-ci.org/soranoba/bbmustache.svg?branch=master)](https://travis-ci.org/soranoba/bbmustache)
[![CircleCI](https://circleci.com/gh/soranoba/bbmustache/tree/master.svg?style=svg)](https://circleci.com/gh/soranoba/bbmustache/tree/master)
[![hex.pm version](https://img.shields.io/hexpm/v/bbmustache.svg)](https://hex.pm/packages/bbmustache)
Binary pattern match Based Mustache template engine for Erlang/OTP.

View File

@ -2,6 +2,7 @@
{erl_opts, [
{platform_define, "^[0-9]+", namespaced_types},
{platform_define, "^20", unicode_supported},
warnings_as_errors,
warn_export_all,
warn_untyped_record
@ -16,6 +17,7 @@
{edoc_opts, [
{doclet, edown_doclet},
{app_default, "http://www.erlang.org/doc/man"},
{dialyzer_specs, all},
{report_missing_type, true},
{report_type_mismatch, true},
@ -38,7 +40,7 @@
{deps,
[
{jsone, "1.4.6"},
{mustache_spec, ".*", {git, "git://github.com/soranoba/spec.git", {tag, "v1.1.3-erl"}}}
{mustache_spec, ".*", {git, "git://github.com/soranoba/spec.git", {tag, "v1.2.1-erl"}}}
]},
{plugins, [rebar3_raw_deps]}
]},
@ -52,7 +54,7 @@
]},
{doc, [{deps,
[
{edown, ".*", {git, "git://github.com/uwiger/edown.git", {branch, "master"}}}
{edown, ".*", {git, "git://github.com/uwiger/edown.git", {tag, "0.8.3"}}}
]}
]},
{bench, [{deps,

View File

@ -1,6 +1,6 @@
{application,bbmustache,
[{description,"Binary pattern match Based Mustache template engine for Erlang/OTP"},
{vsn,"1.10.0"},
{vsn,"1.12.2"},
{registered,[]},
{applications,[kernel,stdlib]},
{maintainers,["Hinagiku Soranoba"]},

View File

@ -70,23 +70,11 @@
%%
%% In addition, `.' have a special meaning. <br />
%% (1) `parent.child' ... find the child in the parent. <br />
%% (2) `.' ... It means this. However, the type of correspond is only `[integer() | float() | binary() | string() | atom()]'. Otherwise, the behavior is undefined.
%% (2) `.' ... It means current context.
%%
-type source() :: binary().
%% If you use lamda expressions, the original text is necessary.
%%
%% ```
%% e.g.
%% template:
%% {{#lamda}}a{{b}}c{{/lamda}}
%% parse result:
%% {'#', <<"lamda">>, [<<"a">>, {'n', <<"b">>}, <<"c">>], <<"a{{b}}c">>}
%% '''
%%
%% NOTE:
%% Since the binary reference is used internally, it is not a capacitively large waste.
%% However, the greater the number of tags used, it should use the wasted memory.
-type tag() :: {n, [key()]}
| {'&', [key()]}
@ -94,6 +82,19 @@
| {'^', [key()], [tag()]}
| {'>', key(), Indent :: source()}
| binary(). % plain text
%% Tag is the internal data structure of the result of parsing the mustache template.
%%
%% ```
%% e.g.
%% template:
%% {{#lamda}}a{{b}}c{{/lamda}}
%% parse result:
%% {'#', [<<"lamda">>], [<<"a">>, {'n', <<"b">>}, <<"c">>], <<"a{{b}}c">>}
%% '''
%%
%% NOTE:
%% Since the binary reference is used internally, it is not a capacitively large waste.
%% However, the greater the number of tags used, it uses the wasted memory.
-record(?MODULE,
{
@ -235,7 +236,7 @@ compile(Template, Data) ->
%% All keys MUST be same type.
-spec compile(template(), data(), [compile_option()]) -> binary().
compile(#?MODULE{data = Tags} = T, Data, Options) ->
Ret = compile_impl(Tags, Data, [], T#?MODULE{options = Options, data = []}),
Ret = compile_impl(Tags, Data, [], T#?MODULE{options = Options, data = [], context_stack = [Data]}),
iolist_to_binary(lists:reverse(Ret)).
%% @doc Default value serializer for templtated values
@ -246,10 +247,12 @@ default_value_serializer(Float) when is_float(Float) ->
%% NOTE: It is the same behaviour as io_lib:format("~p", [Float]), but it is fast than.
%% http://www.cs.indiana.edu/~dyb/pubs/FP-Printing-PLDI96.pdf
io_lib_format:fwrite_g(Float);
default_value_serializer(Atom) when is_atom(Atom) ->
list_to_binary(atom_to_list(Atom));
default_value_serializer(X) when is_map(X); is_tuple(X) ->
error(unsupported_term, [X]);
default_value_serializer(X) when X =:= null; X =:= nil ->
[];
default_value_serializer(X) when is_atom(X) ->
unicode:characters_to_binary(atom_to_list(X));
default_value_serializer(X) ->
X.
@ -272,7 +275,7 @@ compile_impl([], _, Result, _) ->
Result;
compile_impl([{n, Keys} | T], Data, Result, State) ->
ValueSerializer = proplists:get_value(value_serializer, State#?MODULE.options, fun default_value_serializer/1),
Value = iolist_to_binary(ValueSerializer(get_data_recursive(Keys, Data, <<>>, State))),
Value = unicode:characters_to_binary(ValueSerializer(get_data_recursive(Keys, Data, <<>>, State))),
EscapeFun = proplists:get_value(escape_fun, State#?MODULE.options, fun escape/1),
compile_impl(T, Data, ?ADD(EscapeFun(Value), Result), State);
compile_impl([{'&', Keys} | T], Data, Result, State) ->
@ -280,24 +283,27 @@ compile_impl([{'&', Keys} | T], Data, Result, State) ->
compile_impl(T, Data, ?ADD(ValueSerializer(get_data_recursive(Keys, Data, <<>>, State)), Result), State);
compile_impl([{'#', Keys, Tags, Source} | T], Data, Result, State) ->
Value = get_data_recursive(Keys, Data, false, State),
NestedState = State#?MODULE{context_stack = [Data | State#?MODULE.context_stack]},
case is_recursive_data(Value) of
true ->
NestedState = State#?MODULE{context_stack = [Value | State#?MODULE.context_stack]},
case {is_falsy(Value), is_recursive_data(Value)} of
{true, _} -> compile_impl(T, Data, Result, State);
{_, true} ->
compile_impl(T, Data, compile_impl(Tags, Value, Result, NestedState), State);
_ when is_list(Value) ->
compile_impl(T, Data, lists:foldl(fun(X, Acc) -> compile_impl(Tags, X, Acc, NestedState) end,
Result, Value), State);
_ when Value =:= false ->
compile_impl(T, Data, Result, State);
_ when is_function(Value, 2) ->
_ when is_list(Value) ->
NextResult = lists:foldl(fun(X, Acc) ->
%% It doesn't need to add Value to context_stack because List is not context.
LoopState = State#?MODULE{context_stack = [X | State#?MODULE.context_stack]},
compile_impl(Tags, X, Acc, LoopState)
end, Result, Value),
compile_impl(T, Data, NextResult, State);
_ when is_function(Value, 2) ->
Ret = Value(Source, fun(Text) -> render(Text, Data, State#?MODULE.options) end),
compile_impl(T, Data, ?ADD(Ret, Result), State);
_ ->
compile_impl(T, Data, compile_impl(Tags, Data, Result, State), State)
_ ->
compile_impl(T, Data, compile_impl(Tags, Value, Result, NestedState), State)
end;
compile_impl([{'^', Keys, Tags} | T], Data, Result, State) ->
Value = get_data_recursive(Keys, Data, false, State),
case Value =:= [] orelse Value =:= false of
case is_falsy(Value) of
true -> compile_impl(T, Data, compile_impl(Tags, Data, Result, State), State);
false -> compile_impl(T, Data, Result, State)
end;
@ -504,6 +510,11 @@ split_tag(#state{start = StartDelimiter, stop = StopDelimiter}, Bin) ->
end
end.
%% @doc Returns true if treated as false. Otherwise it returns false.
-spec is_falsy(term()) -> boolean().
is_falsy(Value) ->
Value =:= [] orelse Value =:= false orelse Value =:= nil orelse Value =:= null orelse Value =:= <<"">>.
%% @doc if it is standalone line, remove spaces from edge.
-spec standalone(#state{}, binary(), [tag()]) -> {#state{}, StashPre :: binary(), Post :: binary(), [tag()]}.
standalone(#state{standalone = false} = State, Post, [Pre | Result]) ->
@ -632,7 +643,7 @@ convert_keytype(KeyBin, #?MODULE{options = Options}) ->
%% @doc fetch the value of the specified `Keys' from {@link data/0}
%%
%% - If `Keys' is `[<<".">>]', it returns `Data'.
%% - If `Keys' is `[<<".">>]', it returns current context.
%% - If raise_on_context_miss enabled, it raise an exception when missing `Keys'. Otherwise, it returns `Default'.
-spec get_data_recursive([key()], data(), Default :: term(), template()) -> term().
get_data_recursive(Keys, Data, Default, Template) ->
@ -649,8 +660,8 @@ get_data_recursive(Keys, Data, Default, Template) ->
-spec get_data_recursive_impl([key()], data(), template()) -> {ok, term()} | error.
get_data_recursive_impl([], Data, _) ->
{ok, Data};
get_data_recursive_impl([<<".">>], Data, _) ->
{ok, Data};
get_data_recursive_impl([<<".">>], _, #?MODULE{context_stack = [Context | _]}) ->
{ok, Context};
get_data_recursive_impl([Key | RestKey] = Keys, Data, #?MODULE{context_stack = Stack} = State) ->
case is_recursive_data(Data) andalso find_data(convert_keytype(Key, State), Data) of
{ok, ChildData} ->

View File

@ -188,48 +188,6 @@ l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
-----END CERTIFICATE-----
# Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority
# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority
# Label: "QuoVadis Root CA"
# Serial: 985026699
# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24
# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9
# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73
-----BEGIN CERTIFICATE-----
MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC
TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0
aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0
aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz
MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw
IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR
dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp
li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D
rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ
WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug
F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU
xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC
Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv
dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw
ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl
IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh
c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy
ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI
KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T
KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq
y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p
dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD
VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL
MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk
fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8
7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R
cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y
mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW
xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK
SnQ2+Q==
-----END CERTIFICATE-----
# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited
# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited
# Label: "QuoVadis Root CA 2"
@ -345,33 +303,6 @@ JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
-----END CERTIFICATE-----
# Issuer: CN=Sonera Class2 CA O=Sonera
# Subject: CN=Sonera Class2 CA O=Sonera
# Label: "Sonera Class 2 Root CA"
# Serial: 29
# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb
# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27
# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27
-----BEGIN CERTIFICATE-----
MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx
MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV
BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o
Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt
5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s
3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej
vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu
8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw
DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG
MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil
zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/
3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD
FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6
Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2
ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M
-----END CERTIFICATE-----
# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
# Label: "XRamp Global CA Root"
@ -1593,35 +1524,6 @@ LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
-----END CERTIFICATE-----
# Issuer: O=Trustis Limited OU=Trustis FPS Root CA
# Subject: O=Trustis Limited OU=Trustis FPS Root CA
# Label: "Trustis FPS Root CA"
# Serial: 36053640375399034304724988975563710553
# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d
# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04
# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d
-----BEGIN CERTIFICATE-----
MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL
ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx
MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc
MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+
AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH
iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj
vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA
0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB
OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/
BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E
FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01
GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW
zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4
1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE
f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F
jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN
ZetX2fNXlrtIzYE=
-----END CERTIFICATE-----
# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327
# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327
# Label: "Buypass Class 2 Root CA"
@ -4207,3 +4109,254 @@ DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ
7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8
+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A=
-----END CERTIFICATE-----
# Issuer: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH
# Subject: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH
# Label: "GLOBALTRUST 2020"
# Serial: 109160994242082918454945253
# MD5 Fingerprint: 8a:c7:6f:cb:6d:e3:cc:a2:f1:7c:83:fa:0e:78:d7:e8
# SHA1 Fingerprint: d0:67:c1:13:51:01:0c:aa:d0:c7:6a:65:37:31:16:26:4f:53:71:a2
# SHA256 Fingerprint: 9a:29:6a:51:82:d1:d4:51:a2:e3:7f:43:9b:74:da:af:a2:67:52:33:29:f9:0f:9a:0d:20:07:c3:34:e2:3c:9a
-----BEGIN CERTIFICATE-----
MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG
A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw
FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx
MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u
aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b
RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z
YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3
QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw
yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+
BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ
SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH
r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0
4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me
dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw
q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2
nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu
H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC
XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd
6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf
+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi
kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7
wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB
TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C
MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn
4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I
aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy
qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
-----END CERTIFICATE-----
# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz
# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz
# Label: "ANF Secure Server Root CA"
# Serial: 996390341000653745
# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96
# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74
# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99
-----BEGIN CERTIFICATE-----
MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV
BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk
YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV
BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN
MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF
UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD
VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v
dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj
cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q
yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH
2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX
H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL
zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR
p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz
W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/
SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn
LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3
n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B
u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L
9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej
rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK
pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0
vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq
OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ
/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9
2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI
+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2
MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo
tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
-----END CERTIFICATE-----
# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
# Label: "Certum EC-384 CA"
# Serial: 160250656287871593594747141429395092468
# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1
# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed
# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6
-----BEGIN CERTIFICATE-----
MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw
CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw
JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT
EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0
WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT
LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX
BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE
KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm
Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj
QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8
EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J
UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn
nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
-----END CERTIFICATE-----
# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
# Label: "Certum Trusted Root CA"
# Serial: 40870380103424195783807378461123655149
# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29
# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5
# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd
-----BEGIN CERTIFICATE-----
MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6
MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu
MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV
BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw
MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg
U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo
b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG
SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ
n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q
p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq
NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF
8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3
HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa
mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi
7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF
ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P
qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ
v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6
Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD
ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4
WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo
zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR
5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ
GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf
5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq
0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D
P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM
qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP
0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf
E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
-----END CERTIFICATE-----
# Issuer: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique
# Subject: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique
# Label: "TunTrust Root CA"
# Serial: 108534058042236574382096126452369648152337120275
# MD5 Fingerprint: 85:13:b9:90:5b:36:5c:b6:5e:b8:5a:f8:e0:31:57:b4
# SHA1 Fingerprint: cf:e9:70:84:0f:e0:73:0f:9d:f6:0c:7f:2c:4b:ee:20:46:34:9c:bb
# SHA256 Fingerprint: 2e:44:10:2a:b5:8c:b8:54:19:45:1c:8e:19:d9:ac:f3:66:2c:af:bc:61:4b:6a:53:96:0a:30:f7:d0:e2:eb:41
-----BEGIN CERTIFICATE-----
MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL
BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg
Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv
b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG
EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u
IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ
KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ
n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd
2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF
VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ
GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF
li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU
r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2
eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb
MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg
jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB
7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW
5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE
ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z
xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu
QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4
FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH
22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP
xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn
dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5
Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b
nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ
CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH
u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj
d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
-----END CERTIFICATE-----
# Issuer: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA
# Subject: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA
# Label: "HARICA TLS RSA Root CA 2021"
# Serial: 76817823531813593706434026085292783742
# MD5 Fingerprint: 65:47:9b:58:86:dd:2c:f0:fc:a2:84:1f:1e:96:c4:91
# SHA1 Fingerprint: 02:2d:05:82:fa:88:ce:14:0c:06:79:de:7f:14:10:e9:45:d7:a5:6d
# SHA256 Fingerprint: d9:5d:0e:8e:da:79:52:5b:f9:be:b1:1b:14:d2:10:0d:32:94:98:5f:0c:62:d9:fa:bd:9c:d9:99:ec:cb:7b:1d
-----BEGIN CERTIFICATE-----
MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs
MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg
Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL
MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv
b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l
mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE
4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv
a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M
pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw
Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b
LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY
AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB
AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq
E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr
W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ
CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU
X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3
f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja
H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP
JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P
zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt
jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0
/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT
BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79
aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW
xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU
63ZTGI0RmLo=
-----END CERTIFICATE-----
# Issuer: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA
# Subject: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA
# Label: "HARICA TLS ECC Root CA 2021"
# Serial: 137515985548005187474074462014555733966
# MD5 Fingerprint: ae:f7:4c:e5:66:35:d1:b7:9b:8c:22:93:74:d3:4b:b0
# SHA1 Fingerprint: bc:b0:c1:9d:e9:98:92:70:19:38:57:e9:8d:a7:b4:5d:6e:ee:01:48
# SHA256 Fingerprint: 3f:99:cc:47:4a:cf:ce:4d:fe:d5:87:94:66:5e:47:8d:15:47:73:9f:2e:78:0f:1b:b4:ca:9b:13:30:97:d4:01
-----BEGIN CERTIFICATE-----
MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw
CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh
cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v
dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG
A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg
Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7
KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y
STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw
AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD
AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw
SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN
nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
-----END CERTIFICATE-----

View File

@ -1,6 +1,6 @@
{application,certifi,
[{description,"CA bundle adapted from Mozilla by https://certifi.io"},
{vsn,"2.6.1"},
{vsn,"2.8.0"},
{registered,[]},
{applications,[kernel,stdlib]},
{env,[]},

View File

@ -10,9 +10,9 @@ reproducible_module_test() ->
cacerts_test_() ->
Certs = [Cert1, Cert2, Cert3 | _] = certifi:cacerts(),
[?_assertEqual(127, length(Certs))
,?_assertMatch(<<48,130,2,11,48,130,1,145,160,3,2,1,2,2,18,17,210,187,186,51,_/binary>>, Cert1)
,?_assertMatch(<<48,130,5,90,48,130,3,66,160,3,2,1,2,2,18,17,210,187,185,215,_/binary>>, Cert2)
,?_assertMatch(<< 48,130,2,110,48,130,1,243,160,3,2,1,2,2,16,98,246,50,108, _ / binary>>, Cert3)
[?_assertEqual(128, length(Certs))
,?_assertMatch(<<48,130,5,192,48,130,3,168,160,3,2,1,2,2,16,30,191,89,80,184,_/binary>>, Cert1)
,?_assertMatch(<<48,130,2,101,48,130,1,235,160,3,2,1,2,2,16,120,143,39,92,_/binary>>, Cert2)
,?_assertMatch(<<48,130,5,239,48,130,3,215,160,3,2,1,2,2,8,13,211,227,188,_/binary>>, Cert3)
,?_assertMatch(<<48,130,3,117,48,130,2,93,160,3,2,1,2,2,11,4,0,0,0,0,1,21,75,90,195,148,48,13,6,_/binary>>, lists:last(Certs))
].

View File

@ -1,6 +1,9 @@
providers
providers [![GitHub Actions CI][ci-img]][ci]
=====
[ci]: https://github.com/tsloughter/providers
[ci-img]: https://github.com/tsloughter/providers/workflows/build/badge.svg
An Erlang providers library.
Build

View File

@ -1,5 +1,5 @@
{erl_opts, [{platform_define, "R14", no_callback_support}
,debug_info]}.
{deps, [{getopt, "1.0.1"}]}.
{deps, [{getopt, "1.0.1"}, {erlware_commons, "1.4.0"}]}.

View File

@ -1,6 +1,14 @@
{"1.1.0",
[{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}]}.
{"1.2.0",
[{<<"cf">>,{pkg,<<"cf">>,<<"0.3.1">>},1},
{<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"1.4.0">>},0},
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}]}.
[
{pkg_hash,[
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]}
{<<"cf">>, <<"5CB902239476E141EA70A740340233782D363A31EEA8AD37049561542E6CD641">>},
{<<"erlware_commons">>, <<"F9EE38412E1413944BE78736DDB9BDB4C0664ABA5133563F4F3B359A8ED0AD52">>},
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]},
{pkg_hash_ext,[
{<<"cf">>, <<"315E8D447D3A4B02BCDBFA397AD03BBB988A6E0AA6F44D3ADD0F4E3C3BF97672">>},
{<<"erlware_commons">>, <<"185ECF5CF43BAB3A013DDB3614CE7BBA7F6C7A827904E64E57DA54FCDFDCE2E6">>},
{<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}]}
].

View File

@ -1,6 +1,6 @@
{application,providers,
[{description,"Providers provider."},
{vsn,"1.8.1"},
{vsn,"1.9.0"},
{registered,[]},
{applications,[kernel,stdlib,getopt]},
{licenses,["Apache 2.0"]},

View File

@ -155,7 +155,7 @@ help(#provider{opts=Opts
case Opts of
[] ->
io:format("Usage: rebar3 ~s~p~n", [StrNS, Name]);
io:format("Usage: rebar3 ~ts~ts~n", [StrNS, Name]);
_ ->
getopt:usage(Opts, "rebar3 " ++ StrNS ++ atom_to_list(Name), "", [])
end.
@ -172,7 +172,7 @@ help(Name, Providers, Namespace) when is_atom(Name) ->
help(Provider).
format_error({provider_not_found, Namespace, ProviderName}) ->
io_lib:format("Unable to resolve provider ~s in namespace ~s", [ProviderName, Namespace]).
io_lib:format("Unable to resolve provider ~ts in namespace ~ts", [ProviderName, Namespace]).
%% @doc format an error produced from a provider.
-spec format_error(t(), Reason::term()) -> iolist().
@ -311,7 +311,7 @@ namespace_help(Dict, [NS|Namespaces]) ->
if Help =:= [] ->
no_public_providers;
NS =/= default ->
io:format("~n~p <task>:~n", [NS]),
io:format("~n~ts <task>:~n", [NS]),
display_help(Help);
NS =:= default ->
display_help(Help)
@ -323,5 +323,5 @@ display_help(Help) ->
lists:foreach(fun({Name, ShortDesc}) ->
Length = length(Name),
Spacing = lists:duplicate(Longest - Length + 8, " "),
io:format("~s~s~s~n", [Name, Spacing, ShortDesc])
io:format("~ts~ts~ts~n", [Name, Spacing, ShortDesc])
end, Help).

View File

@ -208,8 +208,8 @@ find_erts_dir() {
__erts_version="$("$__erl" -boot no_dot_erlang -sasl errlog_type error -noshell -eval "$erts_version_code")"
ERTS_DIR="${__erl_root}/erts-${__erts_version}"
if [ -d "$ERTS_DIR" ]; then
ERTS_VSN=${__erts_version}
echo "Exact ERTS version (${ERTS_VSN}) match not found, instead using ${__erts_version}. The release may fail to run." 1>&2
ERTS_VSN=${__erts_version}
else
echo "Can not run the release. There is no ERTS bundled with the release or found on the system."
exit 1
@ -328,8 +328,8 @@ erl_rpc() {
DYNAMIC_NAME="-r"
fi
if [ "$ERL_DIST_PORT" ]; then
result=$("$ERL_RPC" "${DYNAMIC_NAME}" -c "${COOKIE}" -address "${ERL_DIST_PORT}" -timeout "${RELX_RPC_TIMEOUT}" -a "${command}")
if [ "$ADDRESS" ]; then
result=$("$ERL_RPC" "${DYNAMIC_NAME}" -c "${COOKIE}" -address "${ADDRESS}" -timeout "${RELX_RPC_TIMEOUT}" -a "${command}")
else
result=$("$ERL_RPC" "$NAME_TYPE" "$NAME" "${DYNAMIC_NAME}" -c "${COOKIE}" -timeout "${RELX_RPC_TIMEOUT}" -a "${command}")
fi
@ -352,7 +352,7 @@ erl_eval() {
command=$*
if [ "$ERL_DIST_PORT" ]; then
result=$(echo "${command}" | "$ERL_RPC" "${DYNAMIC_NAME}" -c "${COOKIE}" -address "${ERL_DIST_PORT}" -timeout "${RELX_RPC_TIMEOUT}" -e)
result=$(echo "${command}" | "$ERL_RPC" "${DYNAMIC_NAME}" -c "${COOKIE}" -address "${ADDRESS}" -timeout "${RELX_RPC_TIMEOUT}" -e)
else
result=$(echo "${command}" | "$ERL_RPC" "$NAME_TYPE" "$NAME" "${DYNAMIC_NAME}" -c "${COOKIE}" -timeout "${RELX_RPC_TIMEOUT}" -e)
fi
@ -410,6 +410,22 @@ relx_escript() {
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
}
# Convert {127,0,0,1} to 127.0.0.1 (inet:ntoa/1)
addr_tuple_to_str() {
addr="$1"
saved_IFS="$IFS"
IFS="{,}'\" "
# shellcheck disable=SC2086
eval set -- $addr
IFS="$saved_IFS"
case $# in
4) printf '%u.%u.%u.%u' "$@";;
8) printf '%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x:%.4x' "$@";;
*) echo "Cannot parse IP address tuple: '$addr'" 1>&2;;
esac
}
make_out_file_path() {
# Use output directory provided in the RELX_OUT_FILE_PATH environment variable
# (default to the current location of vm.args and sys.config)
@ -435,6 +451,7 @@ replace_os_vars() {
slen=split(var,arr,":-")
v=arr[1]
e=ENVIRON[v]
gsub("&","\\\\\\&",e)
if(slen > 1 && e=="") {
i=index(var, ":-"arr[2])
def=substr(var,i+2)
@ -596,7 +613,7 @@ RELX_CONFIG_PATH=$(check_replace_os_vars sys.config "$RELX_CONFIG_PATH")
# - nonexisting -args_files
# - circular dependencies of -args_files
# - relative paths in -args_file parameters
# - multiple/mixed occurences of -name and -sname parameters
# - multiple/mixed occurrences of -name and -sname parameters
# - missing -name or -sname parameters
# If all checks pass, extract the target node name
set +e
@ -673,8 +690,17 @@ EPMD_MODULE="$(grep '^-epmd_module' "$VMARGS_PATH" || true)"
if [ "$EPMD_MODULE" ]; then
DIST_ARGS="${DIST_ARGS} ${EPMD_MODULE}"
fi
INET_DIST_USE_INTERFACE="$(grep '^-kernel *inet_dist_use_interface' "$VMARGS_PATH" || true)"
if [ "$INET_DIST_USE_INTERFACE" ]; then
DIST_ARGS="${DIST_ARGS} ${INET_DIST_USE_INTERFACE}"
fi
if [ "$ERL_DIST_PORT" ]; then
if [ "$INET_DIST_USE_INTERFACE" ]; then
ADDRESS="$(addr_tuple_to_str "${INET_DIST_USE_INTERFACE#*inet_dist_use_interface }"):$ERL_DIST_PORT"
else
ADDRESS="$ERL_DIST_PORT"
fi
if [ "11.1" = "$(printf "%s\n11.1" "${ERTS_VSN}" | sort -V | head -n1)" ] ; then
# unless set by the user, set start_epmd to false when ERL_DIST_PORT is used
if [ ! "$START_EPMD" ]; then
@ -683,6 +709,13 @@ if [ "$ERL_DIST_PORT" ]; then
EXTRA_DIST_ARGS="-erl_epmd_port ${ERL_DIST_PORT}"
fi
else
ERL_DIST_PORT_WARNING="ERL_DIST_PORT is set and used to set the port, but doing so on ERTS version ${ERTS_VSN} means remsh/rpc will not work for this release"
if ! command -v logger > /dev/null 2>&1
then
echo "WARNING: ${ERL_DIST_PORT_WARNING}"
else
logger -p warning -t "${REL_NAME}[$$]" "${ERL_DIST_PORT_WARNING}"
fi
EXTRA_DIST_ARGS="-kernel inet_dist_listen_min ${ERL_DIST_PORT} -kernel inet_dist_listen_max ${ERL_DIST_PORT}"
fi
fi

View File

@ -45,6 +45,7 @@
%% used in tests
{rlx_app_info, new, 5},
{rlx_app_info, new, 6},
{rlx_app_info, new, 7},
{rlx_file_utils, type, 1},
{rlx_file_utils, write, 2},
{rlx_release, applications, 1},

View File

@ -1,8 +1,8 @@
{application,relx,
[{description,"Release assembler for Erlang/OTP Releases"},
{vsn,"4.5.0"},
{vsn,"4.6.0"},
{modules,[]},
{registered,[]},
{applications,[kernel,stdlib,bbmustache]},
{licenses,["Apache-2"]},
{licenses,["Apache-2.0"]},
{links,[{"Github","https://github.com/erlware/relx"}]}]}.

View File

@ -184,7 +184,7 @@ pick_release(State) ->
pick_release_version(undefined, State) ->
pick_release(State);
pick_release_version(RelName, State) ->
%% Here we will just get the lastest version for name RelName and run that.
%% Here we will just get the latest version for name RelName and run that.
AllReleases = maps:to_list(rlx_state:configured_releases(State)),
SpecificReleases = [Rel || Rel={{PossibleRelName, _}, _} <- AllReleases, PossibleRelName =:= RelName],
case lists:sort(fun release_sort/2, SpecificReleases) of
@ -202,7 +202,7 @@ release_sort({{RelName, RelVsnA}, _},
rlx_util:parsed_vsn_lte(rlx_util:parse_vsn(RelVsnB), rlx_util:parse_vsn(RelVsnA));
release_sort({{RelA, _}, _}, {{RelB, _}, _}) ->
%% The release names are different. When the releases are named differently
%% we can not just take the lastest version. You *must* provide a default
%% we can not just take the latest version. You *must* provide a default
%% release name at least. So we throw an error here that the top can catch
%% and return
error(?RLX_ERROR({multiple_release_names, RelA, RelB})).

View File

@ -38,11 +38,13 @@
-export([new/5,
new/6,
new/7,
name/1,
vsn/1,
dir/1,
applications/1,
included_applications/1,
optional_applications/1,
link/1,
link/2,
format_error/1,
@ -57,6 +59,7 @@
applications := [atom()],
included_applications := [atom()],
optional_applications := [atom()],
dir := file:name() | undefined,
link := boolean() | undefined,
@ -73,15 +76,23 @@
-spec new(atom(), string(), file:name(), [atom()], [atom()]) -> t().
new(Name, Vsn, Dir, Applications, IncludedApplications) ->
new(Name, Vsn, Dir, Applications, IncludedApplications, dep).
new(Name, Vsn, Dir, Applications, IncludedApplications, [], dep).
-spec new(atom(), string(), file:name(), [atom()], [atom()], app_type()) -> t().
new(Name, Vsn, Dir, Applications, IncludedApplications, AppType) ->
-spec new(atom(), string(), file:name(), [atom()], [atom()], [atom()] | atom()) -> t().
new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications)
when is_list(OptionalApplications) ->
new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications, dep);
new(Name, Vsn, Dir, Applications, IncludedApplications, AppType) when is_atom(AppType) ->
new(Name, Vsn, Dir, Applications, IncludedApplications, [], AppType).
-spec new(atom(), string(), file:name(), [atom()], [atom()], [atom()], app_type()) -> t().
new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications, AppType) ->
#{name => Name,
vsn => Vsn,
applications => Applications,
included_applications => IncludedApplications,
optional_applications => OptionalApplications,
dir => Dir,
link => false,
@ -108,6 +119,10 @@ applications(#{applications := Deps}) ->
included_applications(#{included_applications := Deps}) ->
Deps.
-spec optional_applications(t()) -> [atom()].
optional_applications(#{included_applications := Deps}) ->
Deps.
-spec link(t()) -> boolean().
link(#{link := Link}) ->
Link.

View File

@ -129,13 +129,20 @@ rewrite_app_file(State, App, TargetDir) ->
Name = rlx_app_info:name(App),
Applications = rlx_app_info:applications(App),
IncludedApplications = rlx_app_info:included_applications(App),
OptionalApplications = rlx_app_info:optional_applications(App),
%% TODO: should really read this in when creating rlx_app:t() and keep it
AppFile = filename:join([TargetDir, "ebin", [Name, ".app"]]),
{ok, [{application, AppName, AppData0}]} = file:consult(AppFile),
?log_debug("Rewriting .app file: ~s", [AppFile]),
[{application, AppName, AppData0}] = case file:consult(AppFile) of
{ok, AppTerms} ->
AppTerms;
{error, ConsultError} ->
erlang:error(?RLX_ERROR({consult_app_file, AppFile, ConsultError}))
end,
%% maybe replace excluded apps
AppData1 = maybe_exclude_apps(Applications, IncludedApplications,
AppData1 = maybe_exclude_apps(Applications, IncludedApplications, OptionalApplications,
AppData0, rlx_state:exclude_apps(State)),
AppData2 = maybe_exclude_modules(AppData1, proplists:get_value(Name,
@ -150,17 +157,23 @@ rewrite_app_file(State, App, TargetDir) ->
erlang:error(?RLX_ERROR({rewrite_app_file, AppFile, Error}))
end.
maybe_exclude_apps(_Applications, _IncludedApplications, AppData, []) ->
maybe_exclude_apps(_Applications, _IncludedApplications, _OptionalApplications, AppData, []) ->
AppData;
maybe_exclude_apps(Applications, IncludedApplications, AppData, ExcludeApps) ->
maybe_exclude_apps(Applications, IncludedApplications, OptionalApplications, AppData, ExcludeApps) ->
AppData1 = lists:keyreplace(applications,
1,
AppData,
{applications, Applications -- ExcludeApps}),
lists:keyreplace(included_applications,
AppData2 = lists:keyreplace(included_applications,
1,
AppData1,
{included_applications, IncludedApplications -- ExcludeApps}),
%% not absolutely necessary since they are already seen as optional, but may as well
lists:keyreplace(optional_applications,
1,
AppData1,
{included_applications, IncludedApplications -- ExcludeApps}).
AppData2,
{optional_applications, OptionalApplications -- ExcludeApps}).
maybe_exclude_modules(AppData, []) ->
AppData;
@ -829,7 +842,7 @@ copy_to_start(RelDir, Name) ->
ok ->
ok;
{error, Reason} ->
%% it isn't absolutely necesary for start.boot to exist so just warn
%% it isn't absolutely necessary for start.boot to exist so just warn
?log_warn("Unable to copy boot file ~s to start.boot: ~p", [BootFile, Reason]),
ok
end.
@ -1086,5 +1099,11 @@ format_error({strip_release, Reason}) ->
format_error({rewrite_app_file, AppFile, Error}) ->
io_lib:format("Unable to rewrite .app file ~s due to ~p",
[AppFile, Error]);
format_error({consult_app_file, AppFile, enoent}) ->
io_lib:format("Unable to consult .app file ~ts (file not found).",
[AppFile]);
format_error({consult_app_file, AppFile, Error}) ->
io_lib:format("Unable to consult .app file ~ts due to ~ts",
[AppFile, file:format_error(Error)]);
format_error({create_RELEASES, Reason}) ->
io_lib:format("Unable to create RELEASES file needed by release_handler: ~p", [Reason]).

View File

@ -214,7 +214,7 @@ generate_state_vars(Release, State) ->
{vm_args, rlx_state:vm_args(State)},
{sys_config, rlx_state:sys_config(State)},
{root_dir, rlx_state:root_dir(State)}
%% include a var for each application. makes it easier to copy a file from an applcation
%% include a var for each application. makes it easier to copy a file from an application
| [{rlx_app_info:name(AppInfo), rlx_app_info:dir(AppInfo)}
|| AppInfo <- rlx_release:applications(Release)]].

View File

@ -44,34 +44,63 @@ solve_release(Release, State0) ->
{false, [SystemLibs | LibDirs]}
end,
Pkgs = subset(Goals, AllApps, LibDirs1, CheckCodeLibDirs),
Pkgs1 = remove_exclude_apps(Pkgs, State1),
set_resolved(Release, Pkgs1, State1)
ExcludeApps = rlx_state:exclude_apps(State1),
Pkgs = subset(Goals, AllApps, LibDirs1, CheckCodeLibDirs, ExcludeApps),
set_resolved(Release, Pkgs, State1)
end.
%% find the app_info records for each application and its deps needed for the release
subset(Apps, World, LibDirs, CheckCodeLibDirs) ->
subset(Apps, World, sets:new(), LibDirs, CheckCodeLibDirs, []).
subset(Goals, World, LibDirs, CheckCodeLibDirs, ExcludeApps) ->
{Apps, _} = fold_apps(Goals, World, sets:new(), LibDirs, CheckCodeLibDirs, [], ExcludeApps),
Apps.
subset([], _World, _Seen, _LibDirs, _CheckCodeLibDirs, Acc) ->
Acc;
subset([Goal | Rest], World, Seen, LibDirs, CheckCodeLibDirs, Acc) ->
subset(Goal, World, Seen, LibDirs, CheckCodeLibDirs, OptionalApplications, ExcludeApps) ->
{Name, Vsn} = name_version(Goal),
case sets:is_element(Name, Seen) of
true ->
subset(Rest, World, Seen, LibDirs, CheckCodeLibDirs, Acc);
{[], Seen};
_ ->
AppInfo=#{applications := Applications,
included_applications := IncludedApplications} =
find_app(Name, Vsn, World, LibDirs, CheckCodeLibDirs),
subset(Rest ++ Applications ++ IncludedApplications,
World,
sets:add_element(Name, Seen),
LibDirs,
CheckCodeLibDirs,
Acc ++ [AppInfo])
case find_app(Name, Vsn, World, LibDirs, CheckCodeLibDirs) of
not_found ->
case lists:member(Name, OptionalApplications) of
true ->
%% don't add to Seen since optional applications are only
%% per-application and not global, so another app could
%% depend on this dependency
{[], Seen};
false ->
erlang:error(?RLX_ERROR({app_not_found, Name, Vsn}))
end;
AppInfo=#{applications := Applications,
included_applications := IncludedApplications,
optional_applications := OptionalApplications0} ->
{Apps, Seen2} = fold_apps(Applications ++ IncludedApplications ++ OptionalApplications0,
World,
sets:add_element(Name, Seen),
LibDirs,
CheckCodeLibDirs,
OptionalApplications0,
ExcludeApps),
%% don't add excluded apps
%% TODO: should an excluded app's deps also be excluded?
case lists:member(Name, ExcludeApps) of
true ->
{Apps, Seen2};
false ->
%% place the deps of the App before it
{Apps ++ [AppInfo], Seen2}
end
end
end.
fold_apps(Apps, World, Seen, LibDirs, CheckCodeLibDirs, OptionalApplications, ExcludeApps) ->
lists:foldl(fun(App, {AppAcc, SeenAcc}) ->
{NewApps, SeenAcc1} = subset(App, World, SeenAcc, LibDirs,
CheckCodeLibDirs, OptionalApplications, ExcludeApps),
%% put new apps after the existing list to keep the user defined order
{AppAcc ++ NewApps, SeenAcc1}
end, {[], Seen}, Apps).
set_resolved(Release0, Pkgs, State) ->
case rlx_release:realize(Release0, Pkgs) of
@ -100,19 +129,6 @@ name_version(Name) when is_atom(Name) ->
name_version({Name, #{vsn := Vsn}}) ->
{Name, Vsn}.
remove_exclude_apps(AllApps, State) ->
ExcludeApps = rlx_state:exclude_apps(State),
lists:foldl(fun(AppName, Acc) ->
find_and_remove(AppName, Acc)
end, AllApps, ExcludeApps).
find_and_remove(_, []) ->
[];
find_and_remove(ExcludeName, [#{name := Name} | Rest]) when ExcludeName =:= Name ->
Rest;
find_and_remove(ExcludeName, [H | Rest]) ->
[H | find_and_remove(ExcludeName, Rest)].
%% Applications are first searched for in the `Apps' variable which is a map
%% of application name to `rlx_app_info' map. This variable is passed to `relx'
%% function calls to build the release or tarball
@ -144,7 +160,7 @@ search_for_app(Name, Vsn, LibDirs, CheckCodeLibDirs) ->
%% app not found in any lib dir we are configured to search
%% and user set a custom `system_libs' directory so we do
%% not look in `code:lib_dir'
erlang:error(?RLX_ERROR({app_not_found, Name, Vsn}));
not_found;
AppInfo ->
case check_app(Name, Vsn, AppInfo) of
true ->
@ -175,13 +191,13 @@ find_app_in_dir(Name, Vsn, [Dir | Rest]) ->
find_app_in_code_path(Name, Vsn) ->
case code:lib_dir(Name) of
{error, bad_name} ->
erlang:error(?RLX_ERROR({app_not_found, Name, Vsn}));
not_found;
Dir ->
case to_app(Name, Vsn, filename:join([Dir, "ebin", [Name, ".app"]])) of
{true, AppInfo} ->
AppInfo;
false ->
erlang:error(?RLX_ERROR({app_not_found, Name, Vsn}))
not_found
end
end.
@ -200,6 +216,7 @@ to_app(Name, Vsn, AppFilePath) ->
end,
Applications = proplists:get_value(applications, AppData, []),
IncludedApplications = proplists:get_value(included_applications, AppData, []),
OptionalApplications = proplists:get_value(optional_applications, AppData, []),
case lists:keyfind(vsn, 1, AppData) of
{_, Vsn1} when Vsn =:= undefined ;
@ -209,6 +226,7 @@ to_app(Name, Vsn, AppFilePath) ->
applications => Applications,
included_applications => IncludedApplications,
optional_applications => OptionalApplications,
dir => filename:dirname(filename:dirname(AppFilePath)),
link => false}};

View File

@ -66,7 +66,7 @@ parse_vsn(Vsn) ->
"(\\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$", [{capture, [1,2,4,6,8], list}]) of
%% OTP application's leave out patch version when it is .0
%% this regex currently drops prerelease and build if the patch version is left out
%% so 3.11-0+meta would reutrn {{3,11,0},{[], []}} intsead of {{3,1,0},{"0","meta"}}
%% so 3.11-0+meta would return {{3,11,0},{[], []}} intsead of {{3,1,0},{"0","meta"}}
{match, [Major, Minor, [], PreRelease, Build]} ->
{{list_to_integer(Major), list_to_integer(Minor), 0}, {PreRelease, Build}};
{match, [Major, Minor, Patch, PreRelease, Build]} ->

View File

@ -44,7 +44,7 @@ main(_) ->
bootstrap_rebar3(),
%% Build rebar.app from rebar.app.src
{ok, App} = rebar_app_info:new(rebar, "3.17.0", filename:absname("_build/default/lib/rebar/")),
{ok, App} = rebar_app_info:new(rebar, "3.18.0", filename:absname("_build/default/lib/rebar/")),
rebar_otp_app:compile(rebar_state:new(), App),
%% Because we are compiling files that are loaded already we want to silence

Binary file not shown.

View File

@ -61,7 +61,7 @@ end
##
## plugins <task>:
## list List local and global plugins for this project
## upgrade Uprade plugins
## upgrade Upgrade plugins
##
## Run 'rebar3 help <TASK>' for details.
# general options
@ -190,7 +190,7 @@ complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l system_libs
complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l version -d "Print relx version"
complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s r -l root -d "The project root directory"
complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a tree -d "Print depdency tree."
complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a tree -d "Print dependency tree."
complete -f -c 'rebar3' -n '__fish_rebar3_needs_command tree' -s v -l verbose -d "Print repo and branch/tag/ref for git and hg deps."

View File

@ -18,9 +18,9 @@ C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so
UNAME_SYS := $(shell uname -s)
ifeq ($(UNAME_SYS), Darwin)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -finline-functions -Wall
LDFLAGS ?= -flat_namespace -undefined suppress
else ifeq ($(UNAME_SYS), FreeBSD)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes

View File

@ -3,11 +3,11 @@
{deps, [{erlware_commons, "1.5.0"},
{ssl_verify_fun, "1.1.6"},
{certifi, "2.6.1"},
{providers, "1.8.1"},
{certifi, "2.8.0"},
{providers, "1.9.0"},
{getopt, "1.0.1"},
{bbmustache, "1.10.0"},
{relx, "4.5.0"},
{bbmustache, "1.12.2"},
{relx, "4.6.0"},
{cf, "0.3.1"},
{cth_readable, "1.5.1"},
{eunit_formatters, "0.5.0"}]}.
@ -23,7 +23,7 @@
{escript_name, rebar3}.
{escript_wrappers_windows, ["cmd", "powershell"]}.
{escript_comment, "%%Rebar3 3.17.0\n"}.
{escript_comment, "%%Rebar3 3.18.0\n"}.
{escript_emu_args, "%%! +sbtu +A1\n"}.
%% escript_incl_priv is for internal rebar-private use only.
%% Do not use outside rebar. Config interface is not stable.

View File

@ -1,35 +1,35 @@
{"1.2.0",
[{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.10.0">>},0},
{<<"certifi">>,{pkg,<<"certifi">>,<<"2.6.1">>},0},
[{<<"bbmustache">>,{pkg,<<"bbmustache">>,<<"1.12.2">>},0},
{<<"certifi">>,{pkg,<<"certifi">>,<<"2.8.0">>},0},
{<<"cf">>,{pkg,<<"cf">>,<<"0.3.1">>},0},
{<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.5.1">>},0},
{<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"1.5.0">>},0},
{<<"eunit_formatters">>,{pkg,<<"eunit_formatters">>,<<"0.5.0">>},0},
{<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0},
{<<"providers">>,{pkg,<<"providers">>,<<"1.8.1">>},0},
{<<"relx">>,{pkg,<<"relx">>,<<"4.5.0">>},0},
{<<"providers">>,{pkg,<<"providers">>,<<"1.9.0">>},0},
{<<"relx">>,{pkg,<<"relx">>,<<"4.6.0">>},0},
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},0}]}.
[
{pkg_hash,[
{<<"bbmustache">>, <<"DDC927463F0E95D66CDAC889153AF08015D609124D6D79006C248AD2DE7F6ECD">>},
{<<"certifi">>, <<"DBAB8E5E155A0763EEA978C913CA280A6B544BFA115633FA20249C3D396D9493">>},
{<<"bbmustache">>, <<"0CABDCE0DB9FE6D3318131174B9F2B351328A4C0AFBEB3E6E99BB0E02E9B621D">>},
{<<"certifi">>, <<"D4FB0A6BB20B7C9C3643E22507E42F356AC090A1DCEA9AB99E27E0376D695EBA">>},
{<<"cf">>, <<"5CB902239476E141EA70A740340233782D363A31EEA8AD37049561542E6CD641">>},
{<<"cth_readable">>, <<"F511EFCFDE04A48B014A9197FFF1B4C4860E4E35CDB8E2F3AE3C4178E20299B1">>},
{<<"erlware_commons">>, <<"918C56D8FB3BE52AF0DF138ED6E0755E764AD4467CD7D025761F7D0A17D3DEC1">>},
{<<"eunit_formatters">>, <<"6A9133943D36A465D804C1C5B6E6839030434B8879C5600D7DDB5B3BAD4CCB59">>},
{<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>},
{<<"providers">>, <<"70B4197869514344A8A60E2B2A4EF41CA03DEF43CFB1712ECF076A0F3C62F083">>},
{<<"relx">>, <<"2BF90A855023023EDD000641033D1AB9F4EBD4314D1739F691E16FE03CB35B85">>},
{<<"providers">>, <<"46F6645B0C677B1029E02B013BFD69092A2232854DAF359F2378FA42AC0BEC0D">>},
{<<"relx">>, <<"939DB831A63CC35A7850C99DCC758FE9F3900E32E1DAB7CBB34E5306CAF53168">>},
{<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>}]},
{pkg_hash_ext,[
{<<"bbmustache">>, <<"43EFFA3FD4BB9523157AF5A9E2276C493495B8459FC8737144AA186CB13CE2EE">>},
{<<"certifi">>, <<"524C97B4991B3849DD5C17A631223896272C6B0AF446778BA4675A1DFF53BB7E">>},
{<<"bbmustache">>, <<"688B33A4D5CC2D51F575ADF0B3683FC40A38314A2F150906EDCFC77F5B577B3B">>},
{<<"certifi">>, <<"6AC7EFC1C6F8600B08D625292D4BBF584E14847CE1B6B5C44D983D273E1097EA">>},
{<<"cf">>, <<"315E8D447D3A4B02BCDBFA397AD03BBB988A6E0AA6F44D3ADD0F4E3C3BF97672">>},
{<<"cth_readable">>, <<"686541A22EFE6CA5A41A047B39516C2DD28FB3CADE5F24A2F19145B3967F9D80">>},
{<<"erlware_commons">>, <<"3E7C6FB2BA4C29B0DD5DFE9D031B66449E2088ECEC1A81465BD9FDE05ED7D0DB">>},
{<<"eunit_formatters">>, <<"D6C8BA213424944E6E05BBC097C32001CDD0ABE3925D02454F229B20D68763C9">>},
{<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>},
{<<"providers">>, <<"E45745ADE9C476A9A469EA0840E418AB19360DC44F01A233304E118A44486BA0">>},
{<<"relx">>, <<"DDB58F20CCE6CA63F5A2725E925816DD7213476698A3F3C3CB4FA8C272202C52">>},
{<<"providers">>, <<"D287E874406A1505608642B0A3DB5B68D6ADA3F2AB001AEC87E7F4D7C79FC017">>},
{<<"relx">>, <<"2FF8131C63093C621C6B37DC52D1B2848A938886584B4B701D35BDBE4377F509">>},
{<<"ssl_verify_fun">>, <<"BDB0D2471F453C88FF3908E7686F86F9BE327D065CC1EC16FA4540197EA04680">>}]}
].

View File

@ -3,7 +3,7 @@
{application, rebar,
[{description, "Rebar: Erlang Build Tool"},
{vsn, "3.17.0"},
{vsn, "3.18.0"},
{modules, []},
{registered, []},
{applications, [kernel,

View File

@ -160,18 +160,19 @@ run_aux(State, RawArgs) ->
State4 = rebar_state:set(State3, base_dir,
filename:join(filename:absname(rebar_state:dir(State3)), BaseDir)),
State5 = case os:getenv("REBAR_CACHE_DIR") of
false ->
State4;
ConfigFile ->
rebar_state:set(State4, global_rebar_dir, ConfigFile)
end,
{ok, Providers} = application:get_env(rebar, providers),
%% Providers can modify profiles stored in opts, so set default after initializing providers
State5 = rebar_state:create_logic_providers(Providers, State4),
State6 = rebar_state:create_logic_providers(Providers, State5),
%% Initializing project_plugins which can override default providers
State6 = rebar_plugins:project_plugins_install(State5),
State7 = rebar_plugins:top_level_install(State6),
State8 = case os:getenv("REBAR_CACHE_DIR") of
false ->
State7;
ConfigFile ->
rebar_state:set(State7, global_rebar_dir, ConfigFile)
end,
State7 = rebar_plugins:project_plugins_install(State6),
State8 = rebar_plugins:top_level_install(State7),
State9 = rebar_state:default(State8, rebar_state:opts(State8)),

View File

@ -58,7 +58,7 @@ error(Str, Args) -> ?ERROR(Str, Args).
expand_env_variable(InStr, VarName, RawVarValue) ->
rebar_utils:expand_env_variable(InStr, VarName, RawVarValue).
%% @doc returns the sytem architecture, in strings like
%% @doc returns the system architecture, in strings like
%% `"19.0.4-x86_64-unknown-linux-gnu-64"'.
-spec get_arch() -> string().
get_arch() ->

View File

@ -54,7 +54,7 @@ do(State, LibDirs) ->
end, State, lists:reverse(CurrentProfiles)),
%% Handle sub project apps deps
%% Sort apps so we get the same merged deps config everytime
%% Sort apps so we get the same merged deps config every time
SortedApps = rebar_utils:sort_deps(Apps),
lists:foldl(fun(AppInfo, StateAcc) ->
Name = rebar_app_info:name(AppInfo),
@ -415,6 +415,7 @@ create_app_info(AppInfo, AppDir, AppFile) ->
AppVsn = proplists:get_value(vsn, AppDetails),
Applications = proplists:get_value(applications, AppDetails, []),
IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
OptionalApplications = proplists:get_value(optional_applications, AppDetails, []),
AppInfo1 = rebar_app_info:name(
rebar_app_info:vsn(
rebar_app_info:original_vsn(
@ -422,14 +423,15 @@ create_app_info(AppInfo, AppDir, AppFile) ->
AppInfo2 = rebar_app_info:applications(
rebar_app_info:app_details(AppInfo1, AppDetails), Applications),
AppInfo3 = rebar_app_info:included_applications(AppInfo2, IncludedApplications),
Valid = case rebar_app_utils:validate_application_info(AppInfo3) =:= true
andalso rebar_app_info:has_all_artifacts(AppInfo3) =:= true of
AppInfo4 = rebar_app_info:optional_applications(AppInfo3, OptionalApplications),
Valid = case rebar_app_utils:validate_application_info(AppInfo4) =:= true
andalso rebar_app_info:has_all_artifacts(AppInfo4) =:= true of
true ->
true;
_ ->
false
end,
rebar_app_info:dir(rebar_app_info:valid(AppInfo3, Valid), AppDir);
rebar_app_info:dir(rebar_app_info:valid(AppInfo4, Valid), AppDir);
_Invalid ->
throw({error, {?MODULE, {cannot_read_app_file, AppFile}}})
catch
@ -438,7 +440,7 @@ create_app_info(AppInfo, AppDir, AppFile) ->
end.
%% @doc Read in and parse the .app file if it is availabe. Do the same for
%% @doc Read in and parse the .app file if it is available. Do the same for
%% the .app.src file if it exists.
-spec try_handle_resource_files(AppInfo, AppDir, ResourceFiles, valid | invalid | all) ->
{true, AppInfo} | false when
@ -463,7 +465,7 @@ try_handle_resource_files(_AppInfo, _AppDir, [], _Validate) ->
false.
%% @doc Read in and parse the .app file if it is availabe. Do the same for
%% @doc Read in and parse the .app file if it is available. Do the same for
%% the .app.src file if it exists.
-spec try_handle_app_file(AppInfo, AppDir, File, AppSrcFile, valid | invalid | all) ->
{true, AppInfo} | false when

View File

@ -32,6 +32,8 @@
applications/2,
included_applications/1,
included_applications/2,
optional_applications/1,
optional_applications/2,
profiles/1,
profiles/2,
deps/1,
@ -94,6 +96,7 @@
app_details=[] :: list(),
applications=[] :: list(),
included_applications=[] :: [atom()],
optional_applications=[] :: [atom()],
deps=[] :: list(),
profiles=[default] :: [atom()],
default=dict:new() :: rebar_dict(),
@ -119,7 +122,7 @@
%% API
%% ============================================================================
%% @doc Build a new, empty, app info value. This is not of a lot of use and you
%% probably wont be doing this much.
%% probably won't be doing this much.
-spec new() -> t().
new() ->
#app_info_t{}.
@ -181,6 +184,7 @@ new(Parent, AppName, Vsn, Dir, Deps) ->
vsn := app_vsn(),
applications := [atom()],
included_applications := [atom()],
optional_applications := [atom()],
dir := file:name(),
out_dir := file:name(),
ebin_dir := file:name(),
@ -189,12 +193,14 @@ app_to_map(#app_info_t{name=Name,
vsn=Vsn,
applications=Applications,
included_applications=IncludedApplications,
optional_applications=OptionalApplications,
out_dir=OutDir,
ebin_dir=EbinDir}) ->
#{name => ec_cnv:to_atom(Name),
vsn => Vsn,
applications => Applications,
included_applications => IncludedApplications,
optional_applications => OptionalApplications,
dir => OutDir,
out_dir => OutDir,
ebin_dir => EbinDir,
@ -468,6 +474,17 @@ included_applications(#app_info_t{included_applications=Applications}) ->
included_applications(AppInfo=#app_info_t{}, Applications) ->
AppInfo#app_info_t{included_applications=Applications}.
%% @doc returns the list of optional_applications the app depends on.
-spec optional_applications(t()) -> list().
optional_applications(#app_info_t{optional_applications=Applications}) ->
Applications.
%% @doc sets the list of optional applications the app depends on.
%% Should be obtained from the app file.
-spec optional_applications(t(), list()) -> t().
optional_applications(AppInfo=#app_info_t{}, Applications) ->
AppInfo#app_info_t{optional_applications=Applications}.
%% @doc returns the list of active profiles
-spec profiles(t()) -> list().
profiles(#app_info_t{profiles=Profiles}) ->

View File

@ -63,7 +63,7 @@ needed_files(Graph, FoundFiles, _, AppInfo) ->
NeededErlFiles = case needed_files(Graph, ErlOpts, RebarOpts, OutDir, EbinDir, ParseTransforms) of
[] ->
needed_files(Graph, ErlOpts, RebarOpts, OutDir, EbinDir, Rest);
_ ->
_ ->
%% at least one parse transform in the opts needs updating, so recompile all
FoundFiles
end,
@ -258,6 +258,7 @@ target_base(OutDir, Source) ->
filename:join(OutDir, filename:basename(Source, ".erl")).
opts_changed(Graph, NewOpts, Target, TargetBase) ->
ModuleName = list_to_atom(filename:basename(TargetBase)),
{ok, CompileVsn} = application:get_key(compiler, vsn),
TotalOpts = case erlang:function_exported(compile, env_compiler_options, 0) of
true -> [{compiler_version, CompileVsn}] ++ NewOpts ++ compile:env_compiler_options();
@ -272,10 +273,10 @@ opts_changed(Graph, NewOpts, Target, TargetBase) ->
_ -> []
end
end,
lists:any(fun effects_code_generation/1,
lists:any(fun(Option) -> effects_code_generation(ModuleName, Option) end,
lists:usort(TotalOpts) -- lists:usort(TargetOpts)).
effects_code_generation(Option) ->
effects_code_generation(ModuleName, Option) ->
case Option of
beam -> false;
report_warnings -> false;
@ -288,6 +289,7 @@ effects_code_generation(Option) ->
verbose -> false;
{cwd,_} -> false;
{outdir, _} -> false;
{parse_transform, ModuleName} -> false;
no_spawn_compiler_process -> false;
_ -> true
end.
@ -334,7 +336,7 @@ atoms_in_erl_first_files_warning(Atoms) ->
W = "You have provided atoms as file entries in erl_first_files; "
"erl_first_files only expects lists of filenames as strings. "
"The following modules (~p) may not work as expected and it is advised "
"that you change these entires to string format "
"that you change these entries to string format "
"(e.g., \"src/module.erl\") ",
?WARN(W, [Atoms]).

View File

@ -56,7 +56,7 @@ atoms_in_mib_first_files_warning(Atoms) ->
W = "You have provided atoms as file entries in mib_first_files; "
"mib_first_files only expects lists of filenames as strings. "
"The following MIBs (~p) may not work as expected and it is advised "
"that you change these entires to string format "
"that you change these entries to string format "
"(e.g., \"mibs/SOME-MIB.mib\") ",
?WARN(W, [Atoms]).

View File

@ -32,10 +32,16 @@ needed_files(_, FoundFiles, Mappings, AppInfo) ->
dependencies(_, _, _) ->
[].
compile(Source, [{_, OutDir}], _, Opts) ->
BaseName = filename:basename(Source, ".yrl"),
Target = filename:join([OutDir, BaseName]),
AllOpts = [{parserfile, Target}, {return, true} | Opts],
compile(Source, [{_, OutDir}], _, Opts0) ->
Opts = case proplists:get_value(parserfile, Opts0) of
undefined ->
BaseName = filename:basename(Source, ".yrl"),
Target = filename:join([OutDir, BaseName]),
[{parserfile, Target} | Opts0];
_ ->
Opts0
end,
AllOpts = [{return, true} | Opts],
case yecc:file(Source, AllOpts) of
{ok, _} ->
ok;

View File

@ -68,7 +68,7 @@ process_namespace(State, Command) ->
not_found ->
case providers:get_providers_by_namespace(Command, Providers) of
[] ->
{error, io_lib:format("Command ~p not found", [Command])};
{error, io_lib:format("Command ~ts not found", [atom_to_list(Command)])};
_ ->
%% Replay 'do' as a command of that namespace
{ok, rebar_state:namespace(State, Command), do}
@ -98,10 +98,10 @@ process_command(State, Command) ->
not_found when Command =/= do ->
case Namespace of
default ->
{error, io_lib:format("Command ~p not found", [Command])};
{error, io_lib:format("Command ~ts not found", [atom_to_list(Command)])};
_ ->
{error, io_lib:format("Command ~p not found in namespace ~p",
[Command, Namespace])}
{error, io_lib:format("Command ~ts not found in namespace ~ts",
[atom_to_list(Command), atom_to_list(Namespace)])}
end;
not_found when Command =:= do, Namespace =/= default ->
do([{default, do} | TargetProviders], State);
@ -120,7 +120,7 @@ process_command(State, Command) ->
State2 = rebar_state:command_parsed_args(State1, Args),
do(TargetProviders, State2);
{error, {invalid_option, Option}} ->
{error, io_lib:format("Invalid option ~ts on task ~p", [Option, Command])};
{error, io_lib:format("Invalid option ~ts on task ~ts", [Option, atom_to_list(Command)])};
{error, {invalid_option_arg, {Option, Arg}}} ->
{error, io_lib:format("Invalid argument ~ts to option ~ts", [Arg, Option])};
{error, {missing_option_arg, Option}} ->
@ -137,7 +137,7 @@ process_command(State, Command) ->
do([], State) ->
{ok, State};
do([ProviderName | Rest], State) ->
?DEBUG("Running provider: ~p", [friendly_provider(ProviderName)]),
?DEBUG("Running provider: ~tp", [friendly_provider(ProviderName)]),
%% Special providers like 'as', 'do' or some hooks may be passed
%% as a tuple {Namespace, Name}, otherwise not. Handle them
%% on a per-need basis.

View File

@ -8,7 +8,7 @@
%%% out the cody bits
%%% * red: things that went bad, i.e. the wrong argument in a
%%% call. It allows to quickly catching where in the code
%%% ane error is.
%%% and error is.
%%% * green: the 'good' stuff, i.e. what was expected as an argument
%%% the 'red vs green' resambles the diff view 'remove vs add'
%%% * blue: argument positions.
@ -412,14 +412,14 @@ highlight([N | Nr], N, r, [Arg | Rest]) ->
highlight(Ns, N, C, [Arg | Rest]) ->
[Arg | highlight(Ns, N + 1, C, Rest)].
%% Arugments to functions and constraints are passed as
%% Arguments to functions and constraints are passed as
%% strings not as data, this function pulls them apart
%% to allow interacting with them separately and not
%% as one bug chunk of data.
separate_args([$( | S]) ->
separate_args([], S, "", []).
%% We strip this space since dialyzer is inconsistant in adding or not adding
%% We strip this space since dialyzer is inconsistent in adding or not adding
%% it ....
separate_args([], [$,, $\s | R], Arg, Args) ->
separate_args([], R, [], [lists:reverse(Arg) | Args]);

View File

@ -292,8 +292,8 @@ all_src_dirs(Opts, SrcDefault, ExtraDefault) ->
%%% @doc
%%% Return the list of options for the given src directory
%%% If the same option is given multiple times for a directory in the
%%% config, the priority order is: first occurence of `src_dirs'
%%% followed by first occurence of `extra_src_dirs'.
%%% config, the priority order is: first occurrence of `src_dirs'
%%% followed by first occurrence of `extra_src_dirs'.
-spec src_dir_opts(rebar_dict(), file:filename_all()) -> [{atom(),term()}].
src_dir_opts(Opts, Dir) ->
RawSrcDirs = raw_src_dirs(src_dirs, Opts, []),

View File

@ -831,7 +831,7 @@ atoms_in_erl_first_files_warning(Atoms) ->
W = "You have provided atoms as file entries in erl_first_files; "
"erl_first_files only expects lists of filenames as strings. "
"The following modules (~p) may not work as expected and it is advised "
"that you change these entires to string format "
"that you change these entries to string format "
"(e.g., \"src/module.erl\") ",
?WARN(W, [Atoms]).

View File

@ -17,7 +17,7 @@
make_vsn_/1,
git_vsn/0]).
%% For backward compatibilty
%% For backward compatibility
-export ([download/3]).
-include("rebar.hrl").
@ -141,7 +141,7 @@ download(TmpDir, AppInfo, State, _) ->
{error, Error}
end.
%% For backward compatibilty
%% For backward compatibility
download(Dir, AppInfo, State) ->
download_(Dir, AppInfo, State).
@ -180,7 +180,16 @@ maybe_warn_local_url(Url) ->
end.
%% Use different git clone commands depending on git --version
git_clone(branch, GitVsn, Url, Dir, Branch) when GitVsn >= {1,7,10}; GitVsn =:= undefined ->
git_clone(branch, GitVsn, Url, Dir, Branch) when GitVsn >= {2,3,0}; GitVsn =:= undefined ->
rebar_utils:sh(?FMT("git clone ~ts ~ts ~ts -b ~ts --single-branch",
[git_clone_options(),
rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir)),
rebar_utils:escape_chars(Branch)]),
[{cd, filename:dirname(Dir)},
{env, [{"GIT_TERMINAL_PROMPT", "0"}]}]),
ok;
git_clone(branch, GitVsn, Url, Dir, Branch) when GitVsn >= {1,7,10} ->
rebar_utils:sh(?FMT("git clone ~ts ~ts ~ts -b ~ts --single-branch",
[git_clone_options(),
rebar_utils:escape_chars(Url),
@ -196,7 +205,16 @@ git_clone(branch, _GitVsn, Url, Dir, Branch) ->
rebar_utils:escape_chars(Branch)]),
[{cd, filename:dirname(Dir)}]),
ok;
git_clone(tag, GitVsn, Url, Dir, Tag) when GitVsn >= {1,7,10}; GitVsn =:= undefined ->
git_clone(tag, GitVsn, Url, Dir, Tag) when GitVsn >= {2,3,0}; GitVsn =:= undefined ->
rebar_utils:sh(?FMT("git clone ~ts ~ts ~ts -b ~ts --single-branch",
[git_clone_options(),
rebar_utils:escape_chars(Url),
rebar_utils:escape_chars(filename:basename(Dir)),
rebar_utils:escape_chars(Tag)]),
[{cd, filename:dirname(Dir)},
{env, [{"GIT_TERMINAL_PROMPT", "0"}]}]),
ok;
git_clone(tag, GitVsn, Url, Dir, Tag) when GitVsn >= {1,7,10} ->
rebar_utils:sh(?FMT("git clone ~ts ~ts ~ts -b ~ts --single-branch",
[git_clone_options(),
rebar_utils:escape_chars(Url),
@ -335,11 +353,17 @@ get_patch_count(Dir, RawRef) ->
Ref = re:replace(RawRef, "\\s", "", [global, unicode]),
Cmd = io_lib:format("git rev-list --count ~ts..HEAD",
[rebar_utils:escape_chars(Ref)]),
{ok, PatchLines} = rebar_utils:sh(Cmd,
[{use_stdout, false},
{cd, Dir},
{debug_abort_on_error, AbortMsg}]),
{ok, list_to_integer(rebar_string:trim(PatchLines))}.
{ok, Output} = rebar_utils:sh(Cmd,
[{use_stdout, false},
{cd, Dir},
{debug_abort_on_error, AbortMsg}]),
case rebar_string:split(Output, "\n") of
[PatchLines, []] ->
{ok, list_to_integer(PatchLines)};
[Warning, PatchLines] ->
?WARN("Extra message from git rev-list: ~ts", [Warning]),
{ok, list_to_integer(rebar_string:trim(PatchLines))}
end.
parse_tags(Dir) ->
@ -390,4 +414,3 @@ check_type_support() ->
ok
end
end.

View File

@ -11,7 +11,7 @@
make_vsn/2]).
%% For backward compatibilty
%% For backward compatibility
-export([ download/3
]).
@ -77,7 +77,7 @@ download(TmpDir, AppInfo, State, _) ->
{error, Error}
end.
%% For backward compatibilty
%% For backward compatibility
download(Dir, AppInfo, State) ->
download_(Dir, AppInfo, State).

View File

@ -428,7 +428,7 @@ cmp_(BestMatch, MinVsn, [Vsn | R], CmpFun) ->
end.
%% We need to treat this differently since we want a version that is LOWER but
%% the higest possible one.
%% the highest possible one.
cmpl(Dep, Vsn, Repo, HexRegistry, State, CmpFun) ->
case get_package_versions(Dep, Vsn, Repo, HexRegistry, State) of
[] ->

View File

@ -135,7 +135,7 @@ format_error({bad_registry_checksum, Name, Vsn, Expected, Found}) ->
%% Download the pkg belonging to the given address. If the etag of the pkg
%% is the same what we stored in the etag file previously return {ok, cached},
%% if the file has changed (so the etag is not the same anymore) return
%% {ok, Contents, NewEtag}, otherwise if some error occured return error.
%% {ok, Contents, NewEtag}, otherwise if some error occurred return error.
%% @end
%%------------------------------------------------------------------------------
-spec request(rebar_hex_repos:repo(), binary(), binary(), false | binary())

View File

@ -340,7 +340,7 @@ build_custom_builder_app(AppInfo, State) ->
ProjectBuilders = rebar_state:project_builders(State),
case lists:keyfind(Type, 1, ProjectBuilders) of
{_, Module} ->
%% load plugins since thats where project builders would be,
%% load plugins since that's where project builders would be,
%% prevents parallelism at this level.
rebar_paths:set_paths([deps, plugins], State),
Res = Module:build(AppInfo),

View File

@ -25,16 +25,18 @@ init(State) ->
{deps, ?DEPS},
{example, "rebar3 plugins upgrade <plugin>"},
{short_desc, "Upgrade plugins"},
{desc, "List or upgrade plugins"},
{desc, "List or upgrade plugins. Use the -a/--all option to upgrade"
" all plugins."},
{opts, [{plugin, undefined, undefined, string,
"Plugin to upgrade"}]}])),
"Plugin to upgrade"},
{all, $a, "all", undefined, "Upgrade all plugins."}]}])),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
case proplists:get_value(plugin, Args, none) of
none ->
case handle_args(State) of
{false, undefined} -> throw(?PRV_ERROR(no_arg));
{true, _} ->
{_, LocalPluginsNames} = rebar_prv_plugins:list_local_plugins(State),
lists:foldl(
fun (LocalPluginName, {ok, StateAcc}) ->
@ -42,16 +44,23 @@ do(State) ->
end,
{ok, State},
LocalPluginsNames);
Plugin ->
upgrade(Plugin, State)
{false, Plugin} -> upgrade(Plugin, State)
end.
-spec format_error(any()) -> iolist().
format_error({not_found, Plugin}) ->
io_lib:format("Plugin to upgrade not found: ~ts", [Plugin]);
format_error(no_arg) ->
"Specify a plugin to upgrade, or --all to upgrade them all";
format_error(Reason) ->
io_lib:format("~p", [Reason]).
handle_args(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
All = proplists:get_value(all, Args, false),
Plugin = proplists:get_value(plugin, Args),
{All, Plugin}.
upgrade(Plugin, State) ->
Profiles = rebar_state:current_profiles(State),
case find_plugin(Plugin, Profiles, State) of

View File

@ -26,12 +26,12 @@ init(State) ->
{deps, ?DEPS},
{example, ""},
{short_desc, "Unlock dependencies."},
{desc, "Unlock project dependencies. Mentioning no application "
"will unlock all dependencies. To unlock specific dependencies, "
{desc, "Unlock project dependencies. Use the --all option "
"to unlock all dependencies. To unlock specific dependencies, "
"their name can be listed in the command."},
{opts, [
{opts, [{all, $a, "all", undefined, "Unlock all dependencies and remove the lock file."},
{package, undefined, undefined, string,
"List of packages to unlock. If not specified, all dependencies are unlocked."}
"List of packages to unlock."}
]}
])
),
@ -57,24 +57,41 @@ format_error({file, Reason}) ->
io_lib:format("Lock file editing failed for reason ~p", [Reason]);
format_error(unknown_lock_format) ->
"Lock file format unknown";
format_error(no_arg) ->
"Specify a list of dependencies to unlock, or --all to unlock them all";
format_error(Reason) ->
io_lib:format("~p", [Reason]).
handle_unlocks(State, Locks, LockFile) ->
{Args, _} = rebar_state:command_parsed_args(State),
Names = parse_names(rebar_utils:to_binary(proplists:get_value(package, Args, <<"">>))),
case [Lock || Lock = {Name, _, _} <- Locks, not lists:member(Name, Names)] of
[] ->
case handle_args(State) of
%% a list of dependencies or --all is required
{false, []} ->
throw(?PRV_ERROR(no_arg));
%% if --all is specified, delete the lock file
{true, _} ->
file:delete(LockFile),
{ok, []};
_ when Names =:= [] -> % implicitly all locks
file:delete(LockFile),
{ok, []};
NewLocks ->
rebar_config:write_lock_file(LockFile, NewLocks),
{ok, NewLocks}
%% otherwise, unlock the given list of dependency names. if none are left, delete the lock file
{false, Names} ->
case [Lock || Lock = {Name, _, _} <- Locks, not lists:member(Name, Names)] of
[] ->
file:delete(LockFile),
{ok, []};
_ when Names =:= [] -> % implicitly all locks
file:delete(LockFile),
{ok, []};
NewLocks ->
rebar_config:write_lock_file(LockFile, NewLocks),
{ok, NewLocks}
end
end.
handle_args(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
All = proplists:get_value(all, Args, false),
Names = parse_names(rebar_utils:to_binary(proplists:get_value(package, Args, <<"">>))),
{All, Names}.
parse_names(Bin) ->
case lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode])) of
[<<"">>] -> []; % nothing submitted

View File

@ -32,12 +32,12 @@ init(State) ->
{deps, ?DEPS},
{example, "rebar3 upgrade [cowboy[,ranch]]"},
{short_desc, "Upgrade dependencies."},
{desc, "Upgrade project dependencies. Mentioning no application "
"will upgrade all dependencies. To upgrade specific dependencies, "
{desc, "Upgrade project dependencies. Use the -a/--all option to "
"upgrade all dependencies. To upgrade specific dependencies, "
"their names can be listed in the command."},
{opts, [
{opts, [{all, $a, "all", undefined, "Upgrade all dependencies."},
{package, undefined, undefined, string,
"List of packages to upgrade. If not specified, all dependencies are upgraded."}
"List of packages to upgrade."}
]}])),
{ok, State1}.
@ -56,7 +56,6 @@ do(State) ->
end.
do_(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
Locks = rebar_state:get(State, {locks, default}, []),
%% We have 3 sources of dependencies to upgrade from:
%% 1. the top-level rebar.config (in `deps', dep name is an atom)
@ -81,8 +80,12 @@ do_(State) ->
ProfileDeps = rebar_state:get(State, {deps, default}, []),
Deps = [Dep || Dep <- TopDeps ++ ProfileDeps, % TopDeps > ProfileDeps
is_atom(Dep) orelse is_atom(element(1, Dep))],
Names = parse_names(rebar_utils:to_binary(proplists:get_value(package, Args, <<"">>)), Locks),
Names = case handle_args(State) of
{false, undefined} -> throw(?PRV_ERROR(no_arg));
{true, _} -> [Name || {Name, _, 0} <- Locks];
{false, Packages} -> Bin = rebar_utils:to_binary(Packages),
lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode]))
end,
DepsDict = deps_dict(rebar_state:all_deps(State)),
AltDeps = find_non_default_deps(Deps, State),
FilteredNames = cull_default_names_if_profiles(Names, Deps, State),
@ -127,9 +130,17 @@ format_error({transitive_dependency, Name}) ->
format_error({checkout_dependency, Name}) ->
io_lib:format("Dependency ~ts is a checkout dependency under _checkouts/ and checkouts cannot be upgraded.",
[Name]);
format_error(no_arg) ->
"Specify a list of dependencies to upgrade, or --all to upgrade them all";
format_error(Reason) ->
io_lib:format("~p", [Reason]).
handle_args(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
All = proplists:get_value(all, Args, false),
Package = proplists:get_value(package, Args),
{All, Package}.
%% fetch updates for package deps that have been unlocked for upgrade
update_pkg_deps([], _, _) ->
ok;
@ -160,15 +171,6 @@ update_package(Name, RepoConfig, State) ->
ok
end.
parse_names(Bin, Locks) ->
case lists:usort(re:split(Bin, <<" *, *">>, [trim, unicode])) of
%% Nothing submitted, use *all* apps
[<<"">>] -> [Name || {Name, _, 0} <- Locks];
[] -> [Name || {Name, _, 0} <- Locks];
%% Regular options
Other -> Other
end.
%% Find alternative deps in non-default profiles since they may
%% need to be passed through (they are never locked)
find_non_default_deps(Deps, State) ->

View File

@ -118,6 +118,8 @@ format_error(all_relup) ->
"Option --all can not be applied to `relup` command";
format_error({config_file, Filename, Error}) ->
io_lib:format("Failed to read config file ~ts: ~p", [Filename, Error]);
format_error({release_not_found, Relname}) ->
io_lib:format("No releases exists in the system for ~s!", [Relname]);
format_error(Error) ->
io_lib:format("~p", [Error]).
@ -154,8 +156,9 @@ rel_handler({ok, _}, _) ->
ok.
releases_to_build(Provider, Opts, RelxState)->
case proplists:get_value(all, Opts, undefined) of
undefined ->
case {proplists:get_value(all, Opts, undefined),
proplists:get_value(relnames, Opts, undefined)} of
{undefined, undefined} ->
case proplists:get_value(relname, Opts, undefined) of
undefined ->
[undefined];
@ -167,10 +170,20 @@ releases_to_build(Provider, Opts, RelxState)->
[{list_to_atom(R), RelVsn}]
end
end;
true when Provider =:= relup ->
{true, _} when Provider =:= relup ->
erlang:error(?PRV_ERROR(all_relup));
true ->
highest_unique_releases(rlx_state:configured_releases(RelxState))
{true, _} ->
highest_unique_releases(rlx_state:configured_releases(RelxState));
{_, Filter} ->
Releases = highest_unique_releases(rlx_state:configured_releases(RelxState)),
WantReleases = [list_to_atom(Rel) || Rel <- string:split(Filter, ",", all)],
[
case proplists:lookup(Relname, Releases) of
none -> erlang:error(?PRV_ERROR({release_not_found, Relname}));
Rel -> Rel
end
|| Relname <- WantReleases
]
end.
%% takes a map of relx configured releases and returns a list of the highest
@ -249,9 +262,10 @@ app_info_to_relx(#{name := Name,
vsn := Vsn,
applications := Applications,
included_applications := IncludedApplications,
optional_applications := OptionalApplications,
dir := Dir,
link := false}, AppType) ->
rlx_app_info:new(Name, Vsn, Dir, Applications, IncludedApplications, AppType).
rlx_app_info:new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications, AppType).
-spec opt_spec_list() -> [getopt:option_spec()].
opt_spec_list() ->
@ -280,4 +294,5 @@ opt_spec_list() ->
{sys_config, undefined, "sys_config", string, "Path to a file to use for sys.config"},
{system_libs, undefined, "system_libs", string, "Boolean or path to dir of Erlang system libs"},
{version, undefined, "version", undefined, "Print relx version"},
{root_dir, $r, "root", string, "The project root directory"}].
{root_dir, $r, "root", string, "The project root directory"},
{relnames, $m, "relnames", string, "Like --all, but only build the releases in the list, e.g. --relnames rel1,rel2"}].

View File

@ -481,8 +481,9 @@ add_provider(State=#state_t{providers=Providers, allow_provider_overrides=false}
case lists:any(fun(P) ->
case {providers:impl(P), providers:namespace(P)} of
{Name, Namespace} ->
?DEBUG("Not adding provider ~p ~p from module ~p because it already exists from module ~p",
[Namespace, Name, Module, providers:module(P)]),
?DEBUG("Not adding provider ~ts ~ts from module ~ts because it already exists from module ~ts",
[atom_to_list(Namespace), atom_to_list(Name),
atom_to_list(Module), atom_to_list(providers:module(P))]),
true;
_ ->
false

View File

@ -90,7 +90,7 @@ get_template_vars(TemplateTerms, State) ->
%% Provide a way to merge a set of variables with another one. The left-hand
%% set of variables takes precedence over the right-hand set.
%% In the case where left-hand variable description contains overriden defaults, but
%% In the case where left-hand variable description contains overridden defaults, but
%% the right-hand one contains additional data such as documentation, the resulting
%% variable description will contain the widest set of information possible.
override_vars([], General) -> General;

View File

@ -97,7 +97,7 @@ sort_deps(Deps) ->
%% We need a sort stable, based on the name. So that for multiple deps on
%% the same level with the same name, we keep the order the parents had.
%% `lists:keysort/2' is documented as stable in the stdlib.
%% The list of deps is revered when we get it. For the proper stable
%% The list of deps is reversed when we get it. For the proper stable
%% result, re-reverse it.
lists:keysort(?APP_NAME_INDEX, lists:reverse(Deps)).
@ -129,7 +129,7 @@ is_arch(ArchRegex) ->
false
end.
%% @doc returns the sytem architecture, in strings like
%% @doc returns the system architecture, in strings like
%% `"19.0.4-x86_64-unknown-linux-gnu-64"'.
-spec get_arch() -> string().
get_arch() ->

View File

@ -36,7 +36,7 @@
%% Options used when reading a tar archive.
-record(read_opts, {
cwd :: string(), %% Current working directory.
keep_old_files = false :: boolean(), %% Owerwrite or not.
keep_old_files = false :: boolean(), %% Overwrite or not.
files = all, %% Set of files to extract (or all)
output = file :: 'file' | 'memory',
open_mode = [], %% Open mode options.
@ -202,7 +202,7 @@
%% These constants (except S_IFMT) are
%% used to determine what type of device
%% a file is. Namely, `S_IFMT band file_info.mode`
%% will equal one of these contants, and tells us
%% will equal one of these constants, and tells us
%% which type it is. The stdlib file_info record
%% does not differentiate between device types, and
%% will not allow us to differentiate between sockets

View File

@ -1,4 +1,4 @@
{alias, [{help, [version]}, % should be skipped, but be overriden by plugin
{alias, [{help, [version]}, % should be skipped, but be overridden by plugin
{test, [compile, {eunit, "-c"}, cover]}]}.
{plugins, [rebar_alias]}. % should be overridden

View File

@ -24,7 +24,7 @@ command(Config) ->
Name = rebar_test_utils:create_random_name("alias_command_"),
Vsn = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
RebarConfig = [{alias, [{test, [compile, unlock]}]}],
RebarConfig = [{alias, [{test, [compile, {unlock,"-a"}]}]}],
%% compile job ran
rebar_test_utils:run_and_check(Config, RebarConfig,
@ -64,7 +64,7 @@ many(Config) ->
Vsn = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
RebarConfig = [{alias, [{test, [{eunit,"-c"}, cover]},
{nolock, [compile, unlock]}]}],
{nolock, [compile, {unlock,"-a"}]}]}],
%% test job ran (compiled and succeeded)
rebar_test_utils:run_and_check(Config, RebarConfig,

View File

@ -40,6 +40,7 @@ all() ->
include_file_relative_to_working_directory_test, include_file_in_src_test,
include_file_in_src_test_multiapp,
recompile_when_parse_transform_as_opt_changes,
dont_recompile_when_parse_transform_as_opt_unchanged,
recompile_when_parse_transform_inline_changes,
regex_filter_skip, regex_filter_regression,
recursive, no_recursive, extra_recursion,
@ -2720,6 +2721,48 @@ recompile_when_parse_transform_as_opt_changes(Config) ->
?assert(ModTime =/= NewModTime).
dont_recompile_when_parse_transform_as_opt_unchanged(Config) ->
AppDir = ?config(apps, Config),
Name = rebar_test_utils:create_random_name("parse_transform_opt_"),
Vsn = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
ok = filelib:ensure_dir(filename:join([AppDir, "src", "dummy"])),
ModSrc = <<"-module(example).\n"
"-export([foo/2]).\n"
"foo(_, _) -> ok.">>,
ok = file:write_file(filename:join([AppDir, "src", "example.erl"]),
ModSrc),
ParseTransform = <<"-module(example_parse_transform).\n"
"-export([parse_transform/2]).\n"
"parse_transform(AST, _) -> AST.">>,
ok = file:write_file(filename:join([AppDir, "src", "example_parse_transform.erl"]),
ParseTransform),
RebarConfig = [{erl_opts, [{parse_transform, example_parse_transform}]}],
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
EbinDir = filename:join([AppDir, "_build", "default", "lib", Name, "ebin"]),
{ok, Files} = rebar_utils:list_dir(EbinDir),
ModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- Files, filename:basename(F, ".beam") == "example"],
timer:sleep(1000),
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}),
{ok, NewFiles} = rebar_utils:list_dir(EbinDir),
NewModTime = [filelib:last_modified(filename:join([EbinDir, F]))
|| F <- NewFiles, filename:basename(F, ".beam") == "example"],
?assert(ModTime =:= NewModTime).
recursive(Config) ->
AppDir = ?config(apps, Config),

View File

@ -53,7 +53,7 @@ groups() ->
mv_file_dir_same, mv_file_dir_diff, mv_no_clobber]}].
init_per_group(reset_dir, Config) ->
TmpDir = rebar_file_utils:system_tmpdir(["rebar_file_utils_SUITE", "resetable"]),
TmpDir = rebar_file_utils:system_tmpdir(["rebar_file_utils_SUITE", "resettable"]),
[{tmpdir, TmpDir} | Config];
init_per_group(tmpdir, Config) ->
PreviousTmpDir = os:getenv("TMPDIR"),

View File

@ -89,7 +89,7 @@ diff_alias(Config) ->
{ok, [{Vsn, LockData}|_]} = file:consult(Lockfile),
%% So does an upgrade
rebar_test_utils:run_and_check(
Config, RebarConfig, ["upgrade"],
Config, RebarConfig, ["upgrade", "--all"],
{ok, [{lock, "fakelib"},{dep, "fakelib"}]}
),
{ok, [{Vsn, LockData}|_]} = file:consult(Lockfile).
@ -128,7 +128,7 @@ transitive_alias(Config) ->
?assertNot(filelib:is_dir(PkgName)),
%% So does an upgrade
rebar_test_utils:run_and_check(
Config, RebarConfig, ["upgrade"],
Config, RebarConfig, ["upgrade", "--all"],
{ok, [{lock, "topdep"},{dep, "topdep"},
{lock,"transitive_app"},{dep,"transitive_app"}]}
),

View File

@ -12,6 +12,7 @@
list/1,
upgrade/1,
upgrade_project_plugin/1,
upgrade_no_args/1,
sub_app_plugins/1,
sub_app_plugin_overrides/1,
project_plugins/1,
@ -191,7 +192,7 @@ upgrade(Config) ->
{{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]}
]),
%% beam file to verify plugin is acutally compiled
%% beam file to verify plugin is actually compiled
PluginBeam = filename:join([AppDir, "_build", "default", "plugins",
PkgName, "ebin", [PkgName, ".beam"]]),
@ -220,7 +221,7 @@ upgrade(Config) ->
),
rebar_test_utils:run_and_check(
Config, RConf, ["plugins", "upgrade"],
Config, RConf, ["plugins", "upgrade", "--all"],
{ok, [{app, Name, valid}, {file, PluginBeam}, {plugin, PkgName}]}
).
@ -263,6 +264,13 @@ upgrade_project_plugin(Config) ->
{ok, [{app, Name}, {plugin, PkgName, <<"0.1.3">>}]}
).
upgrade_no_args(Config) ->
try rebar_test_utils:run_and_check(Config, [], ["plugins", "upgrade"], return)
catch {error, {rebar_prv_plugins_upgrade, no_arg}} ->
ok
end,
ok.
sub_app_plugins(Config) ->
AppDir = ?config(apps, Config),

View File

@ -49,7 +49,7 @@ release(Config) ->
config_file(Config) ->
AppDir = ?config(apps, Config),
Name = list_to_atom(?config(name, Config)),
%% Relase build fails if no relx config exists
%% Release build fails if no relx config exists
?assertError({error, {relx, no_releases_in_system}},
rebar_test_utils:run_and_check(Config, [], ["release"], result)),
%% Write relx.config

View File

@ -3,7 +3,7 @@
-include_lib("eunit/include/eunit.hrl").
-compile(export_all).
all() -> [pkgunlock, unlock, unlock_all].
all() -> [pkgunlock, unlock, unlock_all, unlock_no_args].
init_per_testcase(pkgunlock, Config0) ->
Config = rebar_test_utils:init_rebar_state(Config0, "pkgunlock"),
@ -54,11 +54,18 @@ unlock(Config) ->
unlock_all(Config) ->
[_|_] = read_locks(Config),
{ok, State} = rebar_test_utils:run_and_check(Config, [], ["unlock"], return),
{ok, State} = rebar_test_utils:run_and_check(Config, [], ["unlock", "--all"], return),
?assertEqual({error, enoent}, read_locks(Config)),
?assertEqual([], rebar_state:get(State, {locks, default})),
ok.
unlock_no_args(Config) ->
try rebar_test_utils:run_and_check(Config, [], ["unlock"], return)
catch {error, {rebar_prv_unlock, no_arg}} ->
ok
end,
ok.
read_locks(Config) ->
case file:consult(?config(lockfile, Config)) of
{ok, _} ->

View File

@ -3,7 +3,7 @@
-include_lib("eunit/include/eunit.hrl").
-compile(export_all).
all() -> [{group, git}, {group, pkg}, novsn_pkg].
all() -> [{group, git}, {group, pkg}, novsn_pkg, upgrade_no_args].
groups() ->
[{all, [], [top_a, top_b, top_c, top_d1, top_d2, top_e,
@ -53,6 +53,8 @@ init_per_testcase(novsn_pkg, Config0) ->
end},
{expected, {ok, [{dep, "fakeapp", "1.1.0"}, {lock, "fakeapp", "1.1.0"}]}}
| Config];
init_per_testcase(upgrade_no_args, Config0) ->
rebar_test_utils:init_rebar_state(Config0, "upgrade_no_args_");
init_per_testcase(Case, Config) ->
DepsType = ?config(deps_type, Config),
{Deps, UpDeps, ToUp, Expectations} = upgrades(Case),
@ -543,6 +545,9 @@ mock_deps(pkg, OldDeps, Deps, Upgrades) ->
{_, PkgDeps} = rebar_test_utils:flat_deps(Deps++OldDeps),
mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]).
normalize_unlocks({[], Locks}) ->
{"--all",
normalize_unlocks_expect(Locks)};
normalize_unlocks({App, Locks}) ->
{iolist_to_binary(App),
normalize_unlocks_expect(Locks)};
@ -646,7 +651,7 @@ compile_upgrade_parity(Config) ->
Lockfile = filename:join([AppDir, "rebar.lock"]),
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
{ok, CompileLockData1} = file:read_file(Lockfile),
rebar_test_utils:run_and_check(Config, RebarConfig, ["upgrade"], {ok, []}),
rebar_test_utils:run_and_check(Config, RebarConfig, ["upgrade", "--all"], {ok, []}),
{ok, UpgradeLockData} = file:read_file(Lockfile),
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
{ok, CompileLockData2} = file:read_file(Lockfile),
@ -781,7 +786,7 @@ novsn_pkg(Config) ->
Expectation = ?config(expected, Config),
apply(?config(mock_update, Config), []),
rebar_test_utils:run_and_check(
Config, RebarConfig, ["upgrade"], Expectation
Config, RebarConfig, ["upgrade", "--all"], Expectation
),
ok.
@ -808,3 +813,10 @@ rewrite_locks({ok, Expectations}, Config) ->
end, [], Locks),
ct:pal("rewriting locks from ~p to~n~p", [Locks, NewLocks]),
file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])).
upgrade_no_args(Config) ->
try rebar_test_utils:run_and_check(Config, [], ["upgrade"], return)
catch {error, {rebar_prv_upgrade, no_arg}} ->
ok
end,
ok.