diff options
-rw-r--r-- | include/relx.hrl (renamed from include/relcool.hrl) | 0 | ||||
-rw-r--r-- | relx.config (renamed from relcool.config) | 0 | ||||
-rw-r--r-- | src/relx.app.src (renamed from src/relcool.app.src) | 0 | ||||
-rw-r--r-- | src/relx.erl (renamed from src/relcool.erl) | 0 | ||||
-rw-r--r-- | src/rlx_app_discovery.erl (renamed from src/rcl_app_discovery.erl) | 0 | ||||
-rw-r--r-- | src/rlx_app_info.erl (renamed from src/rcl_app_info.erl) | 0 | ||||
-rw-r--r-- | src/rlx_cmd_args.erl (renamed from src/rcl_cmd_args.erl) | 0 | ||||
-rw-r--r-- | src/rlx_depsolver.erl (renamed from src/rcl_depsolver.erl) | 0 | ||||
-rw-r--r-- | src/rlx_depsolver_culprit.erl (renamed from src/rcl_depsolver_culprit.erl) | 0 | ||||
-rw-r--r-- | src/rlx_dscv_util.erl (renamed from src/rcl_dscv_util.erl) | 0 | ||||
-rw-r--r-- | src/rlx_goal.erl | 263 | ||||
-rw-r--r-- | src/rlx_goal.peg (renamed from src/rcl_goal.peg) | 0 | ||||
-rw-r--r-- | src/rlx_goal_utils.erl (renamed from src/rcl_goal_utils.erl) | 0 | ||||
-rw-r--r-- | src/rlx_log.erl (renamed from src/rcl_log.erl) | 0 | ||||
-rw-r--r-- | src/rlx_provider.erl (renamed from src/rcl_provider.erl) | 0 | ||||
-rw-r--r-- | src/rlx_prv_assembler.erl (renamed from src/rcl_prv_assembler.erl) | 0 | ||||
-rw-r--r-- | src/rlx_prv_config.erl (renamed from src/rcl_prv_config.erl) | 0 | ||||
-rw-r--r-- | src/rlx_prv_discover.erl (renamed from src/rcl_prv_discover.erl) | 0 | ||||
-rw-r--r-- | src/rlx_prv_overlay.erl (renamed from src/rcl_prv_overlay.erl) | 0 | ||||
-rw-r--r-- | src/rlx_prv_release.erl (renamed from src/rcl_prv_release.erl) | 0 | ||||
-rw-r--r-- | src/rlx_rel_discovery.erl (renamed from src/rcl_rel_discovery.erl) | 0 | ||||
-rw-r--r-- | src/rlx_release.erl (renamed from src/rcl_release.erl) | 0 | ||||
-rw-r--r-- | src/rlx_state.erl (renamed from src/rcl_state.erl) | 0 | ||||
-rw-r--r-- | src/rlx_topo.erl (renamed from src/rcl_topo.erl) | 0 | ||||
-rw-r--r-- | src/rlx_util.erl (renamed from src/rcl_util.erl) | 0 | ||||
-rw-r--r-- | test/rlx_command_SUITE.erl (renamed from test/rclt_command_SUITE.erl) | 0 | ||||
-rw-r--r-- | test/rlx_depsolver_tester.erl (renamed from test/rcl_depsolver_tester.erl) | 0 | ||||
-rw-r--r-- | test/rlx_depsolver_tests.erl (renamed from test/rcl_depsolver_tests.erl) | 0 | ||||
-rw-r--r-- | test/rlx_discover_SUITE.erl (renamed from test/rclt_discover_SUITE.erl) | 0 | ||||
-rw-r--r-- | test/rlx_goal_tests.erl (renamed from test/rclt_goal.erl) | 0 | ||||
-rw-r--r-- | test/rlx_release_SUITE.erl (renamed from test/rclt_release_SUITE.erl) | 0 |
31 files changed, 263 insertions, 0 deletions
diff --git a/include/relcool.hrl b/include/relx.hrl index 11a0dec..11a0dec 100644 --- a/include/relcool.hrl +++ b/include/relx.hrl diff --git a/relcool.config b/relx.config index a86ab3f..a86ab3f 100644 --- a/relcool.config +++ b/relx.config diff --git a/src/relcool.app.src b/src/relx.app.src index 0c1c45a..0c1c45a 100644 --- a/src/relcool.app.src +++ b/src/relx.app.src diff --git a/src/relcool.erl b/src/relx.erl index c404e6f..c404e6f 100644 --- a/src/relcool.erl +++ b/src/relx.erl diff --git a/src/rcl_app_discovery.erl b/src/rlx_app_discovery.erl index 7b04b19..7b04b19 100644 --- a/src/rcl_app_discovery.erl +++ b/src/rlx_app_discovery.erl diff --git a/src/rcl_app_info.erl b/src/rlx_app_info.erl index dadc579..dadc579 100644 --- a/src/rcl_app_info.erl +++ b/src/rlx_app_info.erl diff --git a/src/rcl_cmd_args.erl b/src/rlx_cmd_args.erl index fee4449..fee4449 100644 --- a/src/rcl_cmd_args.erl +++ b/src/rlx_cmd_args.erl diff --git a/src/rcl_depsolver.erl b/src/rlx_depsolver.erl index 0cf8c88..0cf8c88 100644 --- a/src/rcl_depsolver.erl +++ b/src/rlx_depsolver.erl diff --git a/src/rcl_depsolver_culprit.erl b/src/rlx_depsolver_culprit.erl index f2115c7..f2115c7 100644 --- a/src/rcl_depsolver_culprit.erl +++ b/src/rlx_depsolver_culprit.erl diff --git a/src/rcl_dscv_util.erl b/src/rlx_dscv_util.erl index 68dcb68..68dcb68 100644 --- a/src/rcl_dscv_util.erl +++ b/src/rlx_dscv_util.erl diff --git a/src/rlx_goal.erl b/src/rlx_goal.erl new file mode 100644 index 0000000..bd3f265 --- /dev/null +++ b/src/rlx_goal.erl @@ -0,0 +1,263 @@ +-module(rlx_goal). +-export([parse/1,file/1]). +-compile({nowarn_unused_function,[p/4, p/5, p_eof/0, p_optional/1, p_not/1, p_assert/1, p_seq/1, p_and/1, p_choose/1, p_zero_or_more/1, p_one_or_more/1, p_label/2, p_string/1, p_anything/0, p_charclass/1, p_regexp/1, p_attempt/4, line/1, column/1]}). + + +-compile(export_all). +-spec file(file:name()) -> any(). +file(Filename) -> {ok, Bin} = file:read_file(Filename), parse(Bin). + +-spec parse(binary() | list()) -> any(). +parse(List) when is_list(List) -> parse(list_to_binary(List)); +parse(Input) when is_binary(Input) -> + setup_memo(), + Result = case 'constraint'(Input,{{line,1},{column,1}}) of + {AST, <<>>, _Index} -> AST; + Any -> Any + end, + release_memo(), Result. + +'constraint'(Input, Index) -> + p(Input, Index, 'constraint', fun(I,D) -> (p_choose([p_seq([p_optional(fun 'ws'/2), fun 'app_name'/2, p_optional(fun 'ws'/2), fun 'between_op'/2, p_optional(fun 'ws'/2), fun 'version'/2, p_optional(fun 'ws'/2), p_string(<<",">>), p_optional(fun 'ws'/2), fun 'version'/2, p_optional(fun 'ws'/2), p_not(p_anything())]), p_seq([p_optional(fun 'ws'/2), fun 'app_name'/2, p_optional(fun 'ws'/2), fun 'constraint_op'/2, p_optional(fun 'ws'/2), fun 'version'/2, p_optional(fun 'ws'/2), p_not(p_anything())]), p_seq([p_optional(fun 'ws'/2), fun 'app_name'/2, p_optional(fun 'ws'/2), p_not(p_anything())])]))(I,D) end, fun(Node, _Idx) -> + case Node of + [_,AppName,_, _] -> + {ok, AppName}; + [_,AppName,_,Op,_,Vsn,_, _] -> + {ok, + {AppName, + rcl_goal_utils:to_vsn(Vsn), + rcl_goal_utils:to_op(Op)}}; + [_,AppName,_,Op,_,Vsn1,_,_,_,Vsn2,_,_] -> + {ok, + {AppName, + rcl_goal_utils:to_vsn(Vsn1), + rcl_goal_utils:to_vsn(Vsn2), + rcl_goal_utils:to_op(Op)}}; + _ -> + io:format("~p~n", [Node]) + end + end). + +'ws'(Input, Index) -> + p(Input, Index, 'ws', fun(I,D) -> (p_charclass(<<"[\s\t\n\s\r]">>))(I,D) end, fun(Node, Idx) -> transform('ws', Node, Idx) end). + +'app_name'(Input, Index) -> + p(Input, Index, 'app_name', fun(I,D) -> (p_one_or_more(p_charclass(<<"[a-zA-Z0-9_]">>)))(I,D) end, fun(Node, _Idx) -> erlang:list_to_atom(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). + +'between_op'(Input, Index) -> + p(Input, Index, 'between_op', fun(I,D) -> (p_seq([p_string(<<":">>), p_optional(fun 'ws'/2), p_choose([p_string(<<"btwn">>), p_string(<<"between">>)]), p_optional(fun 'ws'/2), p_string(<<":">>)]))(I,D) end, fun(Node, _Idx) -> case Node of + [C,_,Op,_,C] -> erlang:iolist_to_binary([C,Op,C]); + _ -> Node + end + end). + +'constraint_op'(Input, Index) -> + p(Input, Index, 'constraint_op', fun(I,D) -> (p_choose([p_string(<<"=">>), p_string(<<"-">>), p_string(<<"<=">>), p_string(<<"<">>), p_string(<<"~>">>), p_string(<<">=">>), p_string(<<">">>), fun 'word_constraint_op'/2, p_string(<<":">>)]))(I,D) end, fun(Node, Idx) -> transform('constraint_op', Node, Idx) end). + +'word_constraint_op'(Input, Index) -> + p(Input, Index, 'word_constraint_op', fun(I,D) -> (p_seq([p_string(<<":">>), p_optional(fun 'ws'/2), p_choose([p_string(<<"gte">>), p_string(<<"lte">>), p_string(<<"gt">>), p_string(<<"lt">>), p_string(<<"pes">>)]), p_optional(fun 'ws'/2), p_string(<<":">>)]))(I,D) end, fun(Node, _Idx) -> case Node of + [C,_,Op,_,C] -> erlang:iolist_to_binary([C,Op,C]); + _ -> Node + end + end). + +'version'(Input, Index) -> + p(Input, Index, 'version', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9a-zA-Z-+.]">>)))(I,D) end, fun(Node, Idx) -> transform('version', Node, Idx) end). + + +transform(_,Node,_Index) -> Node. + +p(Inp, Index, Name, ParseFun) -> + p(Inp, Index, Name, ParseFun, fun(N, _Idx) -> N end). + +p(Inp, StartIndex, Name, ParseFun, TransformFun) -> + case get_memo(StartIndex, Name) of % See if the current reduction is memoized + {ok, Memo} -> %Memo; % If it is, return the stored result + Memo; + _ -> % If not, attempt to parse + Result = case ParseFun(Inp, StartIndex) of + {fail,_} = Failure -> % If it fails, memoize the failure + Failure; + {Match, InpRem, NewIndex} -> % If it passes, transform and memoize the result. + Transformed = TransformFun(Match, StartIndex), + {Transformed, InpRem, NewIndex} + end, + memoize(StartIndex, Name, Result), + Result + end. + +setup_memo() -> + put({parse_memo_table, ?MODULE}, ets:new(?MODULE, [set])). + +release_memo() -> + ets:delete(memo_table_name()). + +memoize(Index, Name, Result) -> + Memo = case ets:lookup(memo_table_name(), Index) of + [] -> []; + [{Index, Plist}] -> Plist + end, + ets:insert(memo_table_name(), {Index, [{Name, Result}|Memo]}). + +get_memo(Index, Name) -> + case ets:lookup(memo_table_name(), Index) of + [] -> {error, not_found}; + [{Index, Plist}] -> + case proplists:lookup(Name, Plist) of + {Name, Result} -> {ok, Result}; + _ -> {error, not_found} + end + end. + +memo_table_name() -> + get({parse_memo_table, ?MODULE}). + +p_eof() -> + fun(<<>>, Index) -> {eof, [], Index}; + (_, Index) -> {fail, {expected, eof, Index}} end. + +p_optional(P) -> + fun(Input, Index) -> + case P(Input, Index) of + {fail,_} -> {[], Input, Index}; + {_, _, _} = Success -> Success + end + end. + +p_not(P) -> + fun(Input, Index)-> + case P(Input,Index) of + {fail,_} -> + {[], Input, Index}; + {Result, _, _} -> {fail, {expected, {no_match, Result},Index}} + end + end. + +p_assert(P) -> + fun(Input,Index) -> + case P(Input,Index) of + {fail,_} = Failure-> Failure; + _ -> {[], Input, Index} + end + end. + +p_and(P) -> + p_seq(P). + +p_seq(P) -> + fun(Input, Index) -> + p_all(P, Input, Index, []) + end. + +p_all([], Inp, Index, Accum ) -> {lists:reverse( Accum ), Inp, Index}; +p_all([P|Parsers], Inp, Index, Accum) -> + case P(Inp, Index) of + {fail, _} = Failure -> Failure; + {Result, InpRem, NewIndex} -> p_all(Parsers, InpRem, NewIndex, [Result|Accum]) + end. + +p_choose(Parsers) -> + fun(Input, Index) -> + p_attempt(Parsers, Input, Index, none) + end. + +p_attempt([], _Input, _Index, Failure) -> Failure; +p_attempt([P|Parsers], Input, Index, FirstFailure)-> + case P(Input, Index) of + {fail, _} = Failure -> + case FirstFailure of + none -> p_attempt(Parsers, Input, Index, Failure); + _ -> p_attempt(Parsers, Input, Index, FirstFailure) + end; + Result -> Result + end. + +p_zero_or_more(P) -> + fun(Input, Index) -> + p_scan(P, Input, Index, []) + end. + +p_one_or_more(P) -> + fun(Input, Index)-> + Result = p_scan(P, Input, Index, []), + case Result of + {[_|_], _, _} -> + Result; + _ -> + {fail, {expected, Failure, _}} = P(Input,Index), + {fail, {expected, {at_least_one, Failure}, Index}} + end + end. + +p_label(Tag, P) -> + fun(Input, Index) -> + case P(Input, Index) of + {fail,_} = Failure -> + Failure; + {Result, InpRem, NewIndex} -> + {{Tag, Result}, InpRem, NewIndex} + end + end. + +p_scan(_, [], Index, Accum) -> {lists:reverse( Accum ), [], Index}; +p_scan(P, Inp, Index, Accum) -> + case P(Inp, Index) of + {fail,_} -> {lists:reverse(Accum), Inp, Index}; + {Result, InpRem, NewIndex} -> p_scan(P, InpRem, NewIndex, [Result | Accum]) + end. + +p_string(S) when is_list(S) -> p_string(list_to_binary(S)); +p_string(S) -> + Length = erlang:byte_size(S), + fun(Input, Index) -> + try + <<S:Length/binary, Rest/binary>> = Input, + {S, Rest, p_advance_index(S, Index)} + catch + error:{badmatch,_} -> {fail, {expected, {string, S}, Index}} + end + end. + +p_anything() -> + fun(<<>>, Index) -> {fail, {expected, any_character, Index}}; + (Input, Index) when is_binary(Input) -> + <<C/utf8, Rest/binary>> = Input, + {<<C/utf8>>, Rest, p_advance_index(<<C/utf8>>, Index)} + end. + +p_charclass(Class) -> + {ok, RE} = re:compile(Class, [unicode, dotall]), + fun(Inp, Index) -> + case re:run(Inp, RE, [anchored]) of + {match, [{0, Length}|_]} -> + {Head, Tail} = erlang:split_binary(Inp, Length), + {Head, Tail, p_advance_index(Head, Index)}; + _ -> {fail, {expected, {character_class, binary_to_list(Class)}, Index}} + end + end. + +p_regexp(Regexp) -> + {ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]), + fun(Inp, Index) -> + case re:run(Inp, RE) of + {match, [{0, Length}|_]} -> + {Head, Tail} = erlang:split_binary(Inp, Length), + {Head, Tail, p_advance_index(Head, Index)}; + _ -> {fail, {expected, {regexp, binary_to_list(Regexp)}, Index}} + end + end. + +line({{line,L},_}) -> L; +line(_) -> undefined. + +column({_,{column,C}}) -> C; +column(_) -> undefined. + +p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput)-> % strings + lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput)); +p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters + {{line, Line}, {column, Col}} = Index, + case MatchedInput of + $\n -> {{line, Line+1}, {column, 1}}; + _ -> {{line, Line}, {column, Col+1}} + end. diff --git a/src/rcl_goal.peg b/src/rlx_goal.peg index bfac607..bfac607 100644 --- a/src/rcl_goal.peg +++ b/src/rlx_goal.peg diff --git a/src/rcl_goal_utils.erl b/src/rlx_goal_utils.erl index 6065e5c..6065e5c 100644 --- a/src/rcl_goal_utils.erl +++ b/src/rlx_goal_utils.erl diff --git a/src/rcl_log.erl b/src/rlx_log.erl index 71c0b5d..71c0b5d 100644 --- a/src/rcl_log.erl +++ b/src/rlx_log.erl diff --git a/src/rcl_provider.erl b/src/rlx_provider.erl index 4d8f044..4d8f044 100644 --- a/src/rcl_provider.erl +++ b/src/rlx_provider.erl diff --git a/src/rcl_prv_assembler.erl b/src/rlx_prv_assembler.erl index aca783d..aca783d 100644 --- a/src/rcl_prv_assembler.erl +++ b/src/rlx_prv_assembler.erl diff --git a/src/rcl_prv_config.erl b/src/rlx_prv_config.erl index 2bc9851..2bc9851 100644 --- a/src/rcl_prv_config.erl +++ b/src/rlx_prv_config.erl diff --git a/src/rcl_prv_discover.erl b/src/rlx_prv_discover.erl index 56085ac..56085ac 100644 --- a/src/rcl_prv_discover.erl +++ b/src/rlx_prv_discover.erl diff --git a/src/rcl_prv_overlay.erl b/src/rlx_prv_overlay.erl index 35e37bf..35e37bf 100644 --- a/src/rcl_prv_overlay.erl +++ b/src/rlx_prv_overlay.erl diff --git a/src/rcl_prv_release.erl b/src/rlx_prv_release.erl index d90b492..d90b492 100644 --- a/src/rcl_prv_release.erl +++ b/src/rlx_prv_release.erl diff --git a/src/rcl_rel_discovery.erl b/src/rlx_rel_discovery.erl index 6cd84f0..6cd84f0 100644 --- a/src/rcl_rel_discovery.erl +++ b/src/rlx_rel_discovery.erl diff --git a/src/rcl_release.erl b/src/rlx_release.erl index 9ed741e..9ed741e 100644 --- a/src/rcl_release.erl +++ b/src/rlx_release.erl diff --git a/src/rcl_state.erl b/src/rlx_state.erl index ca6ec8c..ca6ec8c 100644 --- a/src/rcl_state.erl +++ b/src/rlx_state.erl diff --git a/src/rcl_topo.erl b/src/rlx_topo.erl index 462b7c5..462b7c5 100644 --- a/src/rcl_topo.erl +++ b/src/rlx_topo.erl diff --git a/src/rcl_util.erl b/src/rlx_util.erl index 4afb26d..4afb26d 100644 --- a/src/rcl_util.erl +++ b/src/rlx_util.erl diff --git a/test/rclt_command_SUITE.erl b/test/rlx_command_SUITE.erl index 05da548..05da548 100644 --- a/test/rclt_command_SUITE.erl +++ b/test/rlx_command_SUITE.erl diff --git a/test/rcl_depsolver_tester.erl b/test/rlx_depsolver_tester.erl index 53f5ac0..53f5ac0 100644 --- a/test/rcl_depsolver_tester.erl +++ b/test/rlx_depsolver_tester.erl diff --git a/test/rcl_depsolver_tests.erl b/test/rlx_depsolver_tests.erl index eae31a4..eae31a4 100644 --- a/test/rcl_depsolver_tests.erl +++ b/test/rlx_depsolver_tests.erl diff --git a/test/rclt_discover_SUITE.erl b/test/rlx_discover_SUITE.erl index e3a2861..e3a2861 100644 --- a/test/rclt_discover_SUITE.erl +++ b/test/rlx_discover_SUITE.erl diff --git a/test/rclt_goal.erl b/test/rlx_goal_tests.erl index 20fb5e5..20fb5e5 100644 --- a/test/rclt_goal.erl +++ b/test/rlx_goal_tests.erl diff --git a/test/rclt_release_SUITE.erl b/test/rlx_release_SUITE.erl index 90d99c9..90d99c9 100644 --- a/test/rclt_release_SUITE.erl +++ b/test/rlx_release_SUITE.erl |