diff --git a/apps/rebar/rebar.config b/apps/rebar/rebar.config index c9a4a9344..bda929bb2 100644 --- a/apps/rebar/rebar.config +++ b/apps/rebar/rebar.config @@ -3,8 +3,7 @@ %% Upgrade by calling 'rebar3 experimental vendor' and making sure %% any manual patches (Eg. erlware_commons or relx) are kept. -{deps, [{erlware_commons, "1.8.0"}, - {ssl_verify_fun, "1.1.6"}, +{deps, [{ssl_verify_fun, "1.1.6"}, {certifi, "2.13.0"}, {providers, "1.9.0"}, {getopt, "1.0.2"}, @@ -63,10 +62,6 @@ {prod, [ {erl_opts, [no_debug_info]}, {overrides, [ - {override, erlware_commons, [ - {erl_opts, [no_debug_info, - warnings_as_errors]}, - {deps, []}, {plugins, []}]}, {add, ssl_verify_hostname, [{erl_opts, [no_debug_info]}]}, {add, certifi, [{erl_opts, [no_debug_info]}]}, {add, cf, [{erl_opts, [no_debug_info]}]}, diff --git a/apps/rebar/src/rebar.app.src.script b/apps/rebar/src/rebar.app.src.script index 36ae2dd45..841af4eea 100644 --- a/apps/rebar/src/rebar.app.src.script +++ b/apps/rebar/src/rebar.app.src.script @@ -20,7 +20,6 @@ edoc, snmp, getopt, - erlware_commons, providers, bbmustache, ssl_verify_fun, diff --git a/apps/rebar/src/rebar_agent.erl b/apps/rebar/src/rebar_agent.erl index d89a643e9..48a9515b3 100644 --- a/apps/rebar/src/rebar_agent.erl +++ b/apps/rebar/src/rebar_agent.erl @@ -182,7 +182,7 @@ refresh_paths(RState) -> ShellBlacklist = proplists:get_value(app_reload_blacklist, ShellOpts, []), Blacklist = lists:usort( application:get_env(rebar, refresh_paths_blacklist, ShellBlacklist) - ++ [rebar, erlware_commons, providers, cf, cth_readable]), + ++ [rebar, providers, cf, cth_readable]), %% Similar to rebar_utils:update_code/1, but also forces a reload %% of used modules. Also forces to reload all of ebin/ instead %% of just the modules in the .app file, because 'extra_src_dirs' diff --git a/apps/rebar/src/rebar_app_discover.erl b/apps/rebar/src/rebar_app_discover.erl index 94fb20488..bb0fec460 100644 --- a/apps/rebar/src/rebar_app_discover.erl +++ b/apps/rebar/src/rebar_app_discover.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + %%% @doc utility functions to do the basic discovery of apps %%% and layout for the project. -module(rebar_app_discover). @@ -78,13 +100,13 @@ do(State, LibDirs) -> root | binary(). define_root_app(Apps, State) -> RootDir = rebar_dir:root_dir(State), - case ec_lists:find(fun(X) -> - ec_file:real_dir_path(rebar_app_info:dir(X)) =:= - ec_file:real_dir_path(RootDir) + case lists:search(fun(X) -> + rebar_file_utils:real_dir_path(rebar_app_info:dir(X)) =:= + rebar_file_utils:real_dir_path(RootDir) end, Apps) of - {ok, App} -> + {value, App} -> rebar_app_info:name(App); - error -> + false -> root end. @@ -177,7 +199,7 @@ parse_profile_deps(Profile, Name, Deps, Opts, State) -> maybe_reset_hooks_plugins(AppInfo, State) -> Dir = rebar_app_info:dir(AppInfo), CurrentProfiles = rebar_state:current_profiles(State), - case ec_file:real_dir_path(rebar_dir:root_dir(State)) of + case rebar_file_utils:real_dir_path(rebar_dir:root_dir(State)) of Dir -> Opts = reset_hooks(rebar_state:opts(State), CurrentProfiles), State1 = rebar_state:opts(State, Opts), @@ -329,7 +351,7 @@ find_app(AppInfo, AppDir, Validate, State) -> [file:filename_all()], valid | invalid | all, rebar_state:t()) -> {true, rebar_app_info:t()} | false. find_app(AppInfo, AppDir, SrcDirs, Validate, State) -> - AppInfo1 = case ec_file:real_dir_path(rebar_dir:root_dir(State)) of + AppInfo1 = case rebar_file_utils:real_dir_path(rebar_dir:root_dir(State)) of AppDir -> Opts = rebar_state:opts(State), rebar_app_info:default(rebar_app_info:opts(AppInfo, Opts), Opts); diff --git a/apps/rebar/src/rebar_app_info.erl b/apps/rebar/src/rebar_app_info.erl index bc20ed283..44fe1b5bc 100644 --- a/apps/rebar/src/rebar_app_info.erl +++ b/apps/rebar/src/rebar_app_info.erl @@ -1,3 +1,24 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% -module(rebar_app_info). -export([new/0, @@ -196,7 +217,7 @@ app_to_map(#app_info_t{name=Name, optional_applications=OptionalApplications, out_dir=OutDir, ebin_dir=EbinDir}) -> - #{name => ec_cnv:to_atom(Name), + #{name => rebar_utils:to_atom(Name), vsn => Vsn, applications => Applications, included_applications => IncludedApplications, diff --git a/apps/rebar/src/rebar_app_utils.erl b/apps/rebar/src/rebar_app_utils.erl index 12a125e88..184788bce 100644 --- a/apps/rebar/src/rebar_app_utils.erl +++ b/apps/rebar/src/rebar_app_utils.erl @@ -1,10 +1,15 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et -%% ------------------------------------------------------------------- + +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: MIT +%% +%% SPDX-FileCopyrightText: Copyright 2009 Dave Smith (dizzyd@dizzyd.com) %% -%% rebar: Erlang Build Tools +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors %% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -23,7 +28,9 @@ %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% THE SOFTWARE. -%% ------------------------------------------------------------------- +%% +%% %CopyrightEnd% + -module(rebar_app_utils). -export([find/2, @@ -49,15 +56,15 @@ %% @doc finds the proper app info record for a given app name in a list of %% such records. --spec find(binary(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error. +-spec find(binary(), [rebar_app_info:t()]) -> {value, rebar_app_info:t()} | false. find(Name, Apps) -> - ec_lists:find(fun(App) -> rebar_app_info:name(App) =:= Name end, Apps). + lists:search(fun(App) -> rebar_app_info:name(App) =:= Name end, Apps). %% @doc finds the proper app info record for a given app name at a given version %% in a list of such records. --spec find(binary(), binary(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error. +-spec find(binary(), binary(), [rebar_app_info:t()]) -> {value, rebar_app_info:t()} | false. find(Name, Vsn, Apps) -> - ec_lists:find(fun(App) -> + lists:search(fun(App) -> rebar_app_info:name(App) =:= Name andalso rebar_app_info:original_vsn(App) =:= Vsn end, Apps). diff --git a/apps/rebar/src/rebar_compiler_erl.erl b/apps/rebar/src/rebar_compiler_erl.erl index 98e365c94..8bcbaf28f 100644 --- a/apps/rebar/src/rebar_compiler_erl.erl +++ b/apps/rebar/src/rebar_compiler_erl.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_compiler_erl). -behaviour(rebar_compiler). @@ -19,7 +41,7 @@ context(AppInfo) -> OutDir = rebar_app_info:dir(AppInfo), SrcDirs = rebar_dir:src_dirs(rebar_app_info:opts(AppInfo)), ExistingSrcDirs = lists:filter(fun(D) -> - ec_file:is_dir(filename:join(OutDir, D)) + filelib:is_dir(filename:join(OutDir, D)) end, SrcDirs), RebarOpts = rebar_app_info:opts(AppInfo), diff --git a/apps/rebar/src/rebar_digraph.erl b/apps/rebar/src/rebar_digraph.erl index 776d7b8ba..cbf0f4bb6 100644 --- a/apps/rebar/src/rebar_digraph.erl +++ b/apps/rebar/src/rebar_digraph.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + %%% @doc build a digraph of applications in order to figure out dependency %%% and compile order. -module(rebar_digraph). @@ -93,16 +115,9 @@ subgraph(Graph, Vertices) -> %% @private from a list of app names, fetch the proper app info records %% for them. --spec names_to_apps([atom()], [rebar_app_info:t()]) -> [rebar_app_info:t()]. +-spec names_to_apps([binary()], [rebar_app_info:t()]) -> [rebar_app_info:t()]. names_to_apps(Names, Apps) -> - [element(2, App) || App <- [find_app_by_name(Name, Apps) || Name <- Names], App =/= error]. - -%% @private fetch the proper app info record for a given app name. --spec find_app_by_name(atom(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error. -find_app_by_name(Name, Apps) -> - ec_lists:find(fun(App) -> - rebar_app_info:name(App) =:= Name - end, Apps). + [element(2, App) || App <- [rebar_app_utils:find(Name, Apps) || Name <- Names], App =/= false]. %% @private The union of all entries in the applications list for an app and %% the deps listed in its rebar.config is all deps that may be needed diff --git a/apps/rebar/src/rebar_erlc_compiler.erl b/apps/rebar/src/rebar_erlc_compiler.erl index 0667ebb0b..108199639 100644 --- a/apps/rebar/src/rebar_erlc_compiler.erl +++ b/apps/rebar/src/rebar_erlc_compiler.erl @@ -1,10 +1,14 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et -%% ------------------------------------------------------------------- +%% %CopyrightBegin% %% -%% rebar: Erlang Build Tools +%% SPDX-Licence-Identifier: MIT %% -%% Copyright (c) 2009, 2010 Dave Smith (dizzyd@dizzyd.com) +%% SPDX-FileCopyrightText: Copyright 2009-2010 Dave Smith (dizzyd@dizzyd.com) +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -23,7 +27,8 @@ %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% THE SOFTWARE. -%% ------------------------------------------------------------------- +%% %CopyrightEnd% + -module(rebar_erlc_compiler). -export([compile/1, compile/2, compile/3, @@ -124,7 +129,7 @@ compile(AppInfo, CompileOpts) when element(1, AppInfo) == app_info_t -> ExtraDirs = rebar_dir:extra_src_dirs(RebarOpts), F = fun(D) -> - case ec_file:is_dir(filename:join([Dir, D])) of + case filelib:is_dir(filename:join([Dir, D])) of true -> compile_dirs(RebarOpts, Dir, [D], D, CompileOpts); false -> ok end @@ -156,7 +161,7 @@ compile(RebarOpts, BaseDir, OutDir, CompileOpts) -> ExtraDirs = rebar_dir:extra_src_dirs(RebarOpts), F = fun(D) -> - case ec_file:is_dir(filename:join([BaseDir, D])) of + case filelib:is_dir(filename:join([BaseDir, D])) of true -> compile_dirs(RebarOpts, BaseDir, [D], D, CompileOpts); false -> ok end diff --git a/apps/rebar/src/rebar_fetch.erl b/apps/rebar/src/rebar_fetch.erl index 28753a308..eee70ae5c 100644 --- a/apps/rebar/src/rebar_fetch.erl +++ b/apps/rebar/src/rebar_fetch.erl @@ -1,10 +1,34 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et + +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + %% ------------------------------------------------------------------- %% %% rebar: Erlang Build Tools %% %% ------------------------------------------------------------------- + -module(rebar_fetch). -export([lock_source/2, @@ -59,11 +83,11 @@ download_source_(AppInfo, State) -> download_source_online(AppInfo, State) -> AppDir = rebar_app_info:dir(AppInfo), - TmpDir = ec_file:insecure_mkdtemp(), + TmpDir = rebar_file_utils:insecure_mkdtemp(), AppDir1 = rebar_utils:to_list(AppDir), case rebar_resource_v2:download(TmpDir, AppInfo, State) of ok -> - ec_file:mkdir_p(AppDir1), + filelib:ensure_path(AppDir1), code:del_path(filename:absname(filename:join(AppDir1, "ebin"))), FetchDir = rebar_app_info:fetch_dir(AppInfo), ok = rebar_file_utils:rm_rf(filename:absname(FetchDir)), diff --git a/apps/rebar/src/rebar_file_utils.erl b/apps/rebar/src/rebar_file_utils.erl index f9ebd07e0..da65dda5e 100644 --- a/apps/rebar/src/rebar_file_utils.erl +++ b/apps/rebar/src/rebar_file_utils.erl @@ -1,10 +1,12 @@ -%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- -%% ex: ts=4 sw=4 et -%% ------------------------------------------------------------------- +%% %CopyrightBegin% %% -%% rebar: Erlang Build Tools +%% SPDX-Licence-Identifier: MIT %% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) +%% SPDX-FileCopyrightText: Copyright 2009 Dave Smith (dizzyd@dizzyd.com) +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -23,7 +25,8 @@ %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% THE SOFTWARE. -%% ------------------------------------------------------------------- +%% %CopyrightEnd% + -module(rebar_file_utils). -export([try_consult/1, @@ -32,6 +35,8 @@ consult_any_config/2, consult_config_terms/2, format_error/1, + copy/2, + copy/3, symlink_or_copy/2, rm_rf/1, cp_r/2, @@ -51,13 +56,18 @@ normalize_relative_path/1, resolve_link/1, split_dirname/1, - ensure_dir/1]). + ensure_dir/1, + real_dir_path/1, + insecure_mkdtemp/0]). -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). -include_lib("kernel/include/file.hrl"). +-type copy_file_info() :: mode | time | owner | group. +-type copy_option() :: recursive | {file_info, [copy_file_info()]}. + %% =================================================================== %% Public API @@ -384,7 +394,7 @@ robocopy_mv_and_rename(Source, Dest, SrcDir, SrcName, DestDir, DestName) -> %% - rename srcname destname (to avoid clobbering) %% - robocopy tmp_dir dest_dir destname %% - remove tmp_dir - case ec_file:insecure_mkdtemp() of + case insecure_mkdtemp() of {error, _Reason} -> {error, lists:flatten( io_lib:format("Failed to move ~ts to ~ts (tmpdir failed)~n", @@ -503,7 +513,7 @@ system_tmpdir(PathComponents) -> reset_dir(Path) -> %% delete the directory if it exists - _ = ec_file:remove(Path, [recursive]), + _ = file:del_dir_r(Path), %% recreate the directory ensure_dir(Path). @@ -605,6 +615,159 @@ split_dirname(Path) -> ensure_dir(Path) -> filelib:ensure_dir(filename:join(Path, "fake_file")). +%% SPDX-SnippetBegin +%% SPDX-License-Identifier: MIT +%% SPDX-SnippetCopyrightText: 2011 Erlware, LLC +%% SPDX-FileCopyrightText: 2026 Dipl. Phys. Peer Stritzinger GmbH +%% SPDX-SnippetComment: Functions are adapted from ec_file in erlware_commons. +-spec real_dir_path(file:name()) -> file:name(). + real_dir_path(Path) -> + {ok, CurCwd} = file:get_cwd(), + try + ok = file:set_cwd(Path), + {ok, RealPath} = file:get_cwd(), + filename:absname(RealPath) + after + ok = file:set_cwd(CurCwd) + end. + +%% @doc make a unique temporary directory. Similar function to BSD stdlib +%% function of the same name. +-spec insecure_mkdtemp() -> TmpDirPath::file:name() | {error, term()}. +insecure_mkdtemp() -> + UniqueNumber = erlang:integer_to_list(erlang:trunc(rand:uniform() * 1_000_000_000_000)), + TmpDirPath = + filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]), + + case filelib:ensure_path(TmpDirPath) of + ok -> TmpDirPath; + Error -> Error + end. + +-spec tmp() -> file:name(). +tmp() -> + case os:type() of + {win32, _} -> + case os:getenv("TEMP") of + false -> "./tmp"; + Val -> Val + end; + _ -> + case os:getenv("TMPDIR") of + false -> "/tmp"; + Val -> Val + end + end. +%% +%% @doc copy a file including timestamps, ownership and mode etc. +-spec copy(file:filename(), file:filename()) -> ok | {error, term()}. +copy(From, To) -> + copy_(From, To, [{file_info, [mode, time, owner, group]}]). + +%% @doc copy an entire directory to another location. +-spec copy(file:name(), file:name(), [copy_option()]) -> ok | {error, term()}. +copy(From, To, []) -> + copy_(From, To, []); +copy(From, To, Options) -> + case proplists:get_value(recursive, Options, false) of + true -> + case is_dir(From) of + false -> + copy_(From, To, Options); + true -> + make_dir_if_dir(To), + copy_subfiles(From, To, Options) + end; + false -> + copy_(From, To, Options) + end. + +copy_(From, To, Options) -> + Linked = + case file:read_link(From) of + {ok, Linked0} -> Linked0; + {error, _} -> undefined + end, + case Linked =/= undefined orelse file:copy(From, To) of + true -> + file:make_symlink(Linked, To); + {ok, _} -> + copy_file_info(To, From, proplists:get_value(file_info, Options, [])); + {error, Error} -> + {error, {copy_failed, Error}} + end. + +copy_file_info(To, From, FileInfoToKeep) -> + case file:read_file_info(From) of + {ok, FileInfo} -> + case write_file_info(To, FileInfo, FileInfoToKeep) of + [] -> + ok; + Errors -> + {error, {write_file_info_failed_for, Errors}} + end; + {error, RFError} -> + {error, {read_file_info_failed, RFError}} + end. + +write_file_info(To, FileInfo, FileInfoToKeep) -> + WriteInfoFuns = [{mode, fun try_write_mode/2}, + {time, fun try_write_time/2}, + {group, fun try_write_group/2}, + {owner, fun try_write_owner/2}], + lists:foldl(fun(Info, Acc) -> + case proplists:get_value(Info, WriteInfoFuns, undefined) of + undefined -> + Acc; + F -> + case F(To, FileInfo) of + ok -> + Acc; + {error, Reason} -> + [{Info, Reason} | Acc] + end + end + end, [], FileInfoToKeep). + +try_write_mode(To, #file_info{mode=Mode}) -> + file:write_file_info(To, #file_info{mode=Mode}). + +try_write_time(To, #file_info{atime=Atime, mtime=Mtime}) -> + file:write_file_info(To, #file_info{atime=Atime, mtime=Mtime}). + +try_write_owner(To, #file_info{uid=OwnerId}) -> + file:write_file_info(To, #file_info{uid=OwnerId}). + +try_write_group(To, #file_info{gid=OwnerId}) -> + file:write_file_info(To, #file_info{gid=OwnerId}). + +copy_subfiles(From, To, Options) -> + Fun = + fun(ChildFrom) -> + ChildTo = filename:join([To, filename:basename(ChildFrom)]), + copy(ChildFrom, ChildTo, Options) + end, + lists:foreach(Fun, sub_files(From)). + +make_dir_if_dir(File) -> + case is_dir(File) of + true -> ok; + false -> ensure_dir(File) + end. + +is_dir(Path) -> + case file:read_file_info(Path) of + {ok, #file_info{type = directory}} -> + true; + _ -> + false + end. + +sub_files(From) -> + {ok, SubFiles} = file:list_dir(From), + [filename:join(From, SubFile) || SubFile <- SubFiles]. +%% SPDX-SnippetEnd + %% =================================================================== %% Internal functions %% =================================================================== diff --git a/apps/rebar/src/rebar_hex_repos.erl b/apps/rebar/src/rebar_hex_repos.erl index 04cdf6870..f9acd634c 100644 --- a/apps/rebar/src/rebar_hex_repos.erl +++ b/apps/rebar/src/rebar_hex_repos.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_hex_repos). -export([from_state/2, @@ -44,10 +66,10 @@ from_state(BaseConfig, State) -> -spec get_repo_config(unicode:unicode_binary(), rebar_state:t() | [repo()]) -> {ok, repo()} | error. get_repo_config(RepoName, Repos) when is_list(Repos) -> - case ec_lists:find(fun(#{name := N}) -> N =:= RepoName end, Repos) of - error -> + case lists:search(fun(#{name := N}) -> N =:= RepoName end, Repos) of + false -> throw(?PRV_ERROR({repo_not_found, RepoName})); - {ok, RepoConfig} -> + {value, RepoConfig} -> {ok, RepoConfig} end; get_repo_config(RepoName, State) -> diff --git a/apps/rebar/src/rebar_log.erl b/apps/rebar/src/rebar_log.erl index 4942bf7fb..ba24a21b6 100644 --- a/apps/rebar/src/rebar_log.erl +++ b/apps/rebar/src/rebar_log.erl @@ -1,10 +1,13 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et -%% ------------------------------------------------------------------- + +%% %CopyrightBegin% %% -%% rebar: Erlang Build Tools +%% SPDX-License-Identifier: MIT %% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) +%% SPDX-FileCopyrightText: Copyright 2009 Dave Smith (dizzyd@dizzyd.com) +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -23,7 +26,9 @@ %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% THE SOFTWARE. -%% ------------------------------------------------------------------- +%% +%% %CopyrightEnd% + -module(rebar_log). -export([init/2, @@ -48,6 +53,24 @@ -define(DIAGNOSTIC_LEVEL, 4). -define(DFLT_INTENSITY, high). +-define(PREFIX, "===> "). +-define(RESET, "~!!"). +-define(BOLD, "~!^"). + +%% =================================================================== +%% Types +%% =================================================================== + +-type level() :: ?ERROR_LEVEL + | ?WARN_LEVEL + | ?INFO_LEVEL + | ?DEBUG_LEVEL + | ?DIAGNOSTIC_LEVEL. + +-type level_atom() :: error | warn | info | debug | diagnostic. +-type intensity() :: low | high | none. +-type color() :: $r | $R | $b | $B | $g | $G | $m | $M | $c | $C. + %% =================================================================== %% Public API %% =================================================================== @@ -74,30 +97,25 @@ intensity() -> end. init(Caller, Verbosity) -> - Level = case valid_level(Verbosity) of - ?ERROR_LEVEL -> error; - ?WARN_LEVEL -> warn; - ?INFO_LEVEL -> info; - ?DEBUG_LEVEL -> debug; - ?DIAGNOSTIC_LEVEL -> debug - end, - Intensity = intensity(), application:set_env(rebar, log_caller, Caller), - Log = ec_cmd_log:new(Level, Caller, Intensity), - set_level(valid_level(Verbosity)), - application:set_env(rebar, log, Log). + set_level(Verbosity). -set_level(Level) -> +-spec set_level(level_atom() | level()) -> ok | {error, term()}. +set_level(Level) when is_integer(Level) -> + set_level(level_to_atom(valid_level(Level))); +set_level(Level) when is_atom(Level)-> ok = application:set_env(rebar, log_level, Level). +-spec get_level() -> level(). get_level() -> case application:get_env(rebar, log_level) of undefined -> - default_level(); + ?INFO_LEVEL; {ok, Level} -> - Level + atom_to_level(Level) end. +-spec log(level_atom(), string(), list()) -> ok. log(diagnostic, Str, Args) -> %% The diagnostic level is intended for debug info %% that is useful for rebar3 developers and implementers who @@ -109,19 +127,9 @@ log(diagnostic, Str, Args) -> ?DIAGNOSTIC_LEVEL -> log(debug, Str, Args); _ -> ok end; -log(Level = error, Str, Args) -> - case application:get_env(rebar, log) of - {ok, LogState} -> - NewStr = lists:flatten(cf:format("~!^~ts~n", [Str])), - ec_cmd_log:Level( LogState, NewStr, Args); - undefined -> % fallback - io:format(standard_error, Str++"~n", Args) - end; log(Level, Str, Args) -> - case application:get_env(rebar, log) of - {ok, LogState} -> ec_cmd_log:Level(LogState, Str++"~n", Args); - undefined -> io:format(Str++"~n", Args) - end. + Formatted = format_log(Level, intensity(), Str, Args), + maybe_log(Level, Formatted). crashdump(Str, Args) -> crashdump("rebar3.crashdump", Str, Args). @@ -141,9 +149,11 @@ diagnostic_level() -> ?DIAGNOSTIC_LEVEL. is_verbose(State) -> rebar_state:get(State, is_verbose, false). +-spec valid_level(level()) -> level(). valid_level(Level) -> erlang:max(?ERROR_LEVEL, erlang:min(Level, ?DIAGNOSTIC_LEVEL)). +-spec atom_to_level(level_atom()) -> level(). atom_to_level(Level) -> case Level of error -> ?ERROR_LEVEL; @@ -153,6 +163,16 @@ atom_to_level(Level) -> diagnostic -> ?DIAGNOSTIC_LEVEL end. +-spec level_to_atom(level()) -> level_atom(). +level_to_atom(Level) -> + case Level of + ?ERROR_LEVEL -> error; + ?WARN_LEVEL -> warn; + ?INFO_LEVEL -> info; + ?DEBUG_LEVEL -> debug; + ?DIAGNOSTIC_LEVEL -> diagnostic + end. + %% =================================================================== %% Internal functions %% =================================================================== @@ -174,3 +194,56 @@ take_bytes(N, [H|T]) when is_integer(H) -> take_bytes(N, [H|T]) when is_binary(H); is_list(H) -> Res = take_bytes(N, H), [Res | take_bytes(N-byte_size(Res), T)]. + +-spec level_to_color(level_atom()) -> color(). +level_to_color(error) -> + $R; +level_to_color(warn) -> + $m; +level_to_color(info) -> + $g; +level_to_color(debug) -> + $c; +level_to_color(diagnostic) -> + $c. + +-spec bold(level_atom()) -> boolean(). +bold(error) -> true; +bold(_) -> false. + +-spec message_format(intensity(), boolean()) -> string(). +message_format(high, false) -> + "~ts~ts"; +message_format(high, true) -> + "~ts" ++ ?BOLD ++ "~ts"; +message_format(low, false) -> + "~ts" ++ ?RESET ++ "~ts"; +message_format(low, true) -> + "~ts" ++ ?RESET ++ ?BOLD ++ "~ts". + +-spec colorize(intensity(), level_atom(), list()) -> list(). +colorize(none, Level, Text) -> + case bold(Level) of + false -> Text; + true -> lists:flatten(cf:format(?BOLD ++ "~ts", [Text])) + end; +colorize(Intensity, Level, Text) -> + Color = case Intensity of + none -> ""; + _ -> "~!" ++ [level_to_color(Level)] + end, + FmtMsg = message_format(Intensity, bold(Level)), + lists:flatten(cf:format(Color ++ FmtMsg, [?PREFIX, Text])). + +format_log(Level, Intensity, Str, Args) -> + Msg = [io_lib:format(Str, Args), "\n"], + colorize(Intensity, Level, Msg). + +maybe_log(AtomLevel, LogMsg) -> + CurrentLevel = get_level(), + case atom_to_level(AtomLevel) of + Level when Level =< CurrentLevel -> + io:put_chars(LogMsg); + _ -> + ok + end. diff --git a/apps/rebar/src/rebar_packages.erl b/apps/rebar/src/rebar_packages.erl index 9f47911f6..4b719f8c0 100644 --- a/apps/rebar/src/rebar_packages.erl +++ b/apps/rebar/src/rebar_packages.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_packages). -export([get/2 @@ -95,7 +117,7 @@ get_package(Dep, Vsn, Hash, Repos, Table, State) -> [] -> not_found end; - + _ -> not_found end. @@ -197,7 +219,7 @@ find_highest_matching_(Dep, DepVsn, #{name := Repo}, Table, State) when is_binar case rebar_semver:parse_version(DepVsn) of {ok, _} -> resolve_version_(Dep, <<"~> "/utf8, DepVsn/binary>>, Repo, Table, State); - + {error, _} -> resolve_version_(Dep, DepVsn, Repo, Table, State) end. @@ -311,7 +333,7 @@ resolve_version(Dep, DepVsn, _OldHash, Hash, HexRegistry, State) -> resolve_version_no_package(Dep, DepVsn, Hash, HexRegistry, State) -> case rebar_semver:parse_constraint(DepVsn) of {ok, _} -> - Fun = fun(Repo) -> + Fun = fun(#{name := Repo}) -> case resolve_version_(Dep, DepVsn, Repo, HexRegistry, State) of none -> not_found; @@ -320,16 +342,20 @@ resolve_version_no_package(Dep, DepVsn, Hash, HexRegistry, State) -> end end, handle_missing_no_exception(Fun, Dep, State); - Error -> Error end. - -check_all_repos(Fun, RepoConfigs) -> - ec_lists:search(fun(#{name := R}) -> - Fun(R) - end, RepoConfigs). + +check_all_repos(_, []) -> + not_found; +check_all_repos(Fun, [Config | OtherConfigs]) -> + case Fun(Config) of + {ok, Value} -> + {ok, Value, Config}; + not_found -> + check_all_repos(Fun, OtherConfigs) + end. handle_missing_no_exception(Fun, Dep, State) -> Resources = rebar_state:resources(State), @@ -339,14 +365,14 @@ handle_missing_no_exception(Fun, Dep, State) -> %% if none is found then we step through checking after updating the repo registry case check_all_repos(Fun, RepoConfigs) of not_found -> - ec_lists:search(fun(Config=#{name := R}) -> + check_all_repos(fun(Config) -> case ?MODULE:update_package(Dep, Config, State) of ok -> - Fun(R); + Fun(Config); _ -> not_found end - end, RepoConfigs); + end, RepoConfigs); Result -> Result end. @@ -357,11 +383,10 @@ resolve_version_(Dep, Constraint, Repo, HexRegistry, State) -> AllowPreRelease = rebar_semver:is_prerelease_or_build(Constraint), AllVersions = get_package_versions(Dep, AllowPreRelease, Repo, HexRegistry, State), resolve_version_loop(Match, AllVersions, none); - Error -> Error end. - + resolve_version_loop(_Constraint, [], none) -> none; resolve_version_loop(_Constraint, [], BestMatch) -> {ok, BestMatch}; resolve_version_loop(Constraint, [Vsn|R], none) -> diff --git a/apps/rebar/src/rebar_paths.erl b/apps/rebar/src/rebar_paths.erl index ed3f13cef..0615f940b 100644 --- a/apps/rebar/src/rebar_paths.erl +++ b/apps/rebar/src/rebar_paths.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_paths). -include("rebar.hrl"). @@ -234,8 +256,8 @@ get_runtime_apps([App|Rest0], AppsAcc0, AppsList) -> fun(AppName, {Rest, Acc}) -> %% We only care about those apps we ccould find in the state. case rebar_app_utils:find(AppName, AppsList) of - {ok, AppInfo} -> {[AppInfo|Rest], sets:add_element(AppInfo, Acc)}; - error -> {Rest, Acc} + {value, AppInfo} -> {[AppInfo|Rest], sets:add_element(AppInfo, Acc)}; + false -> {Rest, Acc} end end, {Rest0, sets:add_element(App, AppsAcc0)}, TotalApps), get_runtime_apps(Rest1 ++ TotalApps, AppsAcc1, AppsList). diff --git a/apps/rebar/src/rebar_plugins.erl b/apps/rebar/src/rebar_plugins.erl index ad8211a94..a56e6ff13 100644 --- a/apps/rebar/src/rebar_plugins.erl +++ b/apps/rebar/src/rebar_plugins.erl @@ -1,6 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_plugins). -export([project_plugins_install/1 @@ -80,7 +102,7 @@ filter_existing_plugins(Plugins, State) -> AllPlugins = rebar_state:all_plugin_deps(State), rebar_utils:filtermap(fun({Plugin, PluginName}) -> case rebar_app_utils:find(PluginName, AllPlugins) of - {ok, _} -> + {value, _} -> false; _ -> {true, Plugin} diff --git a/apps/rebar/src/rebar_prv_compile.erl b/apps/rebar/src/rebar_prv_compile.erl index bd774edfc..c4f8f5fc9 100644 --- a/apps/rebar/src/rebar_prv_compile.erl +++ b/apps/rebar/src/rebar_prv_compile.erl @@ -9,6 +9,7 @@ -export([compile/2, compile/3, compile/4]). -export([copy_app_dirs/3]). +-include_lib("kernel/include/file.hrl"). -include_lib("providers/include/providers.hrl"). -include("rebar.hrl"). @@ -299,7 +300,7 @@ extra_virtual_apps(_, _, []) -> []; extra_virtual_apps(State, VApp0, [Dir|Dirs]) -> SrcDir = filename:join([rebar_state:dir(State), Dir]), - case ec_file:is_dir(SrcDir) of + case filelib:is_dir(SrcDir) of false -> extra_virtual_apps(State, VApp0, Dirs); true -> @@ -401,7 +402,7 @@ paths_for_apps([], Acc) -> Acc; paths_for_apps([App|Rest], Acc) -> {_SrcDirs, ExtraDirs} = resolve_src_dirs(rebar_app_info:opts(App)), Paths = [filename:join([rebar_app_info:out_dir(App), Dir]) || Dir <- ["ebin"|ExtraDirs]], - FilteredPaths = lists:filter(fun ec_file:is_dir/1, Paths), + FilteredPaths = lists:filter(fun filelib:is_dir/1, Paths), paths_for_apps(Rest, Acc ++ FilteredPaths). paths_for_extras(State, Apps) -> @@ -415,7 +416,7 @@ paths_for_extras(State, Apps) -> paths_for_extras(State) -> {_SrcDirs, ExtraDirs} = resolve_src_dirs(rebar_state:opts(State)), Paths = [filename:join([rebar_dir:base_dir(State), "extras", Dir]) || Dir <- ExtraDirs], - lists:filter(fun ec_file:is_dir/1, Paths). + lists:filter(fun filelib:is_dir/1, Paths). has_all_artifacts(AppInfo1) -> case rebar_app_info:has_all_artifacts(AppInfo1) of @@ -476,7 +477,7 @@ symlink_or_copy(OldAppDir, AppDir, Dir) -> symlink_or_copy_existing(OldAppDir, AppDir, Dir) -> Source = filename:join([OldAppDir, Dir]), Target = filename:join([AppDir, Dir]), - case ec_file:is_dir(Source) of + case filelib:is_dir(Source) of true -> rebar_file_utils:symlink_or_copy(Source, Target); false -> ok end. @@ -484,7 +485,7 @@ symlink_or_copy_existing(OldAppDir, AppDir, Dir) -> copy(OldAppDir, AppDir, Dir) -> Source = filename:join([OldAppDir, Dir]), Target = filename:join([AppDir, Dir]), - case ec_file:is_dir(Source) of + case filelib:is_dir(Source) of true -> copy(Source, Target); false -> ok end. @@ -507,9 +508,9 @@ copy(Source, Target) -> end. delete_if_symlink(Path) -> - case ec_file:is_symlink(Path) of - true -> file:delete(Path); - false -> ok + case file:read_link_info(Path) of + {ok, #file_info{type = symlink}} -> file:delete(Path); + _ -> ok end. resolve_src_dirs(Opts) -> diff --git a/apps/rebar/src/rebar_prv_cover.erl b/apps/rebar/src/rebar_prv_cover.erl index 9022571bc..ac8052e72 100644 --- a/apps/rebar/src/rebar_prv_cover.erl +++ b/apps/rebar/src/rebar_prv_cover.erl @@ -1,6 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_prv_cover). -behaviour(provider). @@ -322,7 +344,7 @@ cover_compile(State, apps) -> ExclApps = [rebar_utils:to_binary(A) || A <- rebar_state:get(State, cover_excl_apps, [])], Apps = filter_checkouts_and_excluded(rebar_state:project_apps(State), ExclApps), AppDirs = app_dirs(Apps), - cover_compile(State, lists:filter(fun(D) -> ec_file:is_dir(D) end, AppDirs)); + cover_compile(State, lists:filter(fun(D) -> filelib:is_dir(D) end, AppDirs)); cover_compile(State, Dirs) -> rebar_paths:set_paths([deps], State), %% start the cover server if necessary diff --git a/apps/rebar/src/rebar_prv_dialyzer.erl b/apps/rebar/src/rebar_prv_dialyzer.erl index ca71e3d11..28407adfa 100644 --- a/apps/rebar/src/rebar_prv_dialyzer.erl +++ b/apps/rebar/src/rebar_prv_dialyzer.erl @@ -244,7 +244,7 @@ proj_plt_files(State) -> get_files(State, "project", DepApps, [], PltMods, [], []). proj_apps(State) -> - [ec_cnv:to_atom(rebar_app_info:name(App)) || + [rebar_utils:to_atom(rebar_app_info:name(App)) || App <- rebar_state:project_apps(State)]. proj_plt_apps(State) -> @@ -587,8 +587,8 @@ succ_typing_apps(undefined, ProjApps) -> ProjApps; succ_typing_apps(App, ProjApps) -> try - true = lists:member(ec_cnv:to_atom(App), ProjApps), - [ec_cnv:to_atom(App)] + true = lists:member(rebar_utils:to_atom(App), ProjApps), + [rebar_utils:to_atom(App)] catch error:_ -> throw({unknown_application, App}) diff --git a/apps/rebar/src/rebar_prv_escriptize.erl b/apps/rebar/src/rebar_prv_escriptize.erl index 49487c6a6..9ed4c65d9 100644 --- a/apps/rebar/src/rebar_prv_escriptize.erl +++ b/apps/rebar/src/rebar_prv_escriptize.erl @@ -81,7 +81,7 @@ do(State) -> Name -> AllApps = rebar_state:all_deps(State)++rebar_state:project_apps(State), case rebar_app_utils:find(rebar_utils:to_binary(Name), AllApps) of - {ok, AppInfo} -> + {value, AppInfo} -> AppInfo; _ -> ?PRV_ERROR({bad_name, Name}) @@ -116,7 +116,7 @@ escriptize(State0, App) -> %% Look for a list of other applications (dependencies) to include %% in the output file. We then use the .app files for each of these %% to pull in all the .beam files. - TopInclApps = lists:usort([ec_cnv:to_atom(AppName) | rebar_state:get(State, escript_incl_apps, [])]), + TopInclApps = lists:usort([rebar_utils:to_atom(AppName) | rebar_state:get(State, escript_incl_apps, [])]), AllApps = rebar_state:all_deps(State)++rebar_state:project_apps(State), InclApps = find_deps(TopInclApps, AllApps, State), ?DEBUG("bundled applications:~n\t~p", [InclApps]), @@ -186,7 +186,7 @@ get_apps_beams([], _, Acc) -> Acc; get_apps_beams([App | Rest], AllApps, Acc) -> case rebar_app_utils:find(rebar_utils:to_binary(App), AllApps) of - {ok, App1} -> + {value, App1} -> OutDir = filename:absname(rebar_app_info:ebin_dir(App1)), Beams = get_app_beams(App, OutDir), get_apps_beams(Rest, AllApps, Beams ++ Acc); @@ -222,7 +222,7 @@ get_extra(State) -> % Converts a wildcard path relative to an app (e.g., `priv/*`) into a wildcard % path with with the app name included (e.g., `relx/priv/*`). resolve_incl_priv({AppName, PrivWildcard}, AllApps) when is_atom(AppName) -> - {ok, AppInfo} = + {value, AppInfo} = rebar_app_utils:find(rebar_utils:to_binary(AppName), AllApps), AppOutDir = rebar_app_info:out_dir(AppInfo), Wildcard = filename:join([atom_to_list(AppName), "priv", PrivWildcard]), @@ -283,7 +283,7 @@ get_nonempty(Files) -> find_deps(AppNames, AllApps, State) -> BinAppNames = [rebar_utils:to_binary(Name) || Name <- AppNames], - [ec_cnv:to_atom(Name) || + [rebar_utils:to_atom(Name) || Name <- find_deps_of_deps(BinAppNames, AllApps, State, BinAppNames)]. %% Should look at the app files to find direct dependencies @@ -291,9 +291,9 @@ find_deps_of_deps([], _, _, Acc) -> Acc; find_deps_of_deps([Name|Names], Apps, State, Acc) -> ?DIAGNOSTIC("processing ~p", [Name]), App = case rebar_app_utils:find(Name, Apps) of - {ok, Found} -> + {value, Found} -> Found; - error -> + false -> case find_external_app(Name, State) of error -> throw(?PRV_ERROR({bad_app, binary_to_atom(Name, utf8)})); App0 -> App0 diff --git a/apps/rebar/src/rebar_prv_eunit.erl b/apps/rebar/src/rebar_prv_eunit.erl index 16b39f40d..4e2f3e24e 100644 --- a/apps/rebar/src/rebar_prv_eunit.erl +++ b/apps/rebar/src/rebar_prv_eunit.erl @@ -1,6 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_prv_eunit). -behaviour(provider). @@ -395,7 +417,7 @@ validate(State, {generator, Module, Function}) -> validate(State, Module) when is_atom(Module) -> validate_module(State, Module); validate(State, Path) when is_list(Path) -> - case ec_file:is_dir(Path) of + case filelib:is_dir(Path) of true -> validate(State, {dir, Path}); false -> validate(State, {file, Path}) end; @@ -417,13 +439,13 @@ validate_app(State, [App|Rest], AppName) -> end. validate_dir(State, Dir) -> - case ec_file:is_dir(filename:join([rebar_state:dir(State), Dir])) of + case filelib:is_dir(filename:join([rebar_state:dir(State), Dir])) of true -> ok; false -> {error, lists:concat(["Directory `", Dir, "' not found."])} end. validate_file(State, File) -> - case ec_file:exists(filename:join([rebar_state:dir(State), File])) of + case filelib:is_file(filename:join([rebar_state:dir(State), File])) of true -> ok; false -> {error, lists:concat(["File `", File, "' not found."])} end. diff --git a/apps/rebar/src/rebar_prv_install_deps.erl b/apps/rebar/src/rebar_prv_install_deps.erl index 5331c4cbc..b80602910 100644 --- a/apps/rebar/src/rebar_prv_install_deps.erl +++ b/apps/rebar/src/rebar_prv_install_deps.erl @@ -275,7 +275,7 @@ update_seen_dep(AppInfo, _Profile, _Level, Deps, Apps, State, Upgrade, Seen, Loc false when Upgrade -> ok; false when not Upgrade -> - {ok, SeenApp} = rebar_app_utils:find(Name, Apps), + {value, SeenApp} = rebar_app_utils:find(Name, Apps), Source = rebar_app_info:source(AppInfo), case rebar_app_info:source(SeenApp) of Source -> diff --git a/apps/rebar/src/rebar_prv_local_upgrade.erl b/apps/rebar/src/rebar_prv_local_upgrade.erl index 74d198da6..5ad2d0ada 100644 --- a/apps/rebar/src/rebar_prv_local_upgrade.erl +++ b/apps/rebar/src/rebar_prv_local_upgrade.erl @@ -1,6 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_prv_local_upgrade). -behaviour(provider). @@ -88,7 +110,7 @@ get_md5(Rebar3Path) -> rebar_string:lowercase(DigestHex). maybe_fetch_rebar3(Rebar3Md5) -> - TmpDir = ec_file:insecure_mkdtemp(), + TmpDir = rebar_file_utils:insecure_mkdtemp(), TmpFile = filename:join(TmpDir, "rebar3"), case request("https://s3.amazonaws.com/rebar3/rebar3", Rebar3Md5) of {ok, Binary, ETag} -> diff --git a/apps/rebar/src/rebar_prv_path.erl b/apps/rebar/src/rebar_prv_path.erl index dd0608c1a..ba4be1e4c 100644 --- a/apps/rebar/src/rebar_prv_path.erl +++ b/apps/rebar/src/rebar_prv_path.erl @@ -1,6 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_prv_path). -behaviour(provider). @@ -96,7 +118,7 @@ src_dirs(Apps, State) -> print_paths_if_exist(Paths, State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), Sep = proplists:get_value(separator, RawOpts, " "), - RealPaths = lists:filter(fun(P) -> ec_file:is_dir(P) end, Paths), + RealPaths = lists:filter(fun(P) -> filelib:is_dir(P) end, Paths), io:format("~ts", [rebar_string:join(RealPaths, Sep)]). project_deps(State) -> diff --git a/apps/rebar/src/rebar_prv_plugins.erl b/apps/rebar/src/rebar_prv_plugins.erl index 6fd10b262..b89aff0e7 100644 --- a/apps/rebar/src/rebar_prv_plugins.erl +++ b/apps/rebar/src/rebar_prv_plugins.erl @@ -84,9 +84,9 @@ display_plugins(Apps, Plugins) -> is_tuple(Plugin) -> rebar_utils:to_binary(element(1, Plugin)) end, case rebar_app_utils:find(Name, Apps) of - {ok, App} -> + {value, App} -> ?CONSOLE("~ts (~s)", [Name, rebar_app_info:original_vsn(App)]); - error -> + false -> ?DEBUG("Unable to find plugin ~ts", [Name]) end end, Plugins). diff --git a/apps/rebar/src/rebar_prv_plugins_upgrade.erl b/apps/rebar/src/rebar_prv_plugins_upgrade.erl index e525e3822..00b9b2b26 100644 --- a/apps/rebar/src/rebar_prv_plugins_upgrade.erl +++ b/apps/rebar/src/rebar_prv_plugins_upgrade.erl @@ -34,9 +34,9 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> - case handle_args(State) of + case handle_args(State) of {false, undefined} -> throw(?PRV_ERROR(no_arg)); - {true, _} -> + {true, _} -> {_, LocalPluginsNames} = rebar_prv_plugins:list_local_plugins(State), lists:foldl( fun (LocalPluginName, {ok, StateAcc}) -> @@ -50,12 +50,12 @@ do(State) -> -spec format_error(any()) -> iolist(). format_error({not_found, Plugin}) -> io_lib:format("Plugin to upgrade not found: ~ts", [Plugin]); -format_error(no_arg) -> +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) -> +handle_args(State) -> {Args, _} = rebar_state:command_parsed_args(State), All = proplists:get_value(all, Args, false), Plugin = proplists:get_value(plugin, Args), @@ -101,17 +101,16 @@ do_upgrade(State, P, Profile) -> {ok, State}. -find_plugin(Plugin, Profiles, State) -> - ec_lists:search(fun(Profile) -> - Plugins = rebar_state:get(State, {plugins, Profile}, []) ++ - rebar_state:get(State, {project_plugins, Profile}, []), - case rebar_utils:tup_find(list_to_atom(Plugin), Plugins) of - false -> - not_found; - P -> - {ok, P} - end - end, Profiles). +find_plugin(_, [], _) -> + not_found; +find_plugin(Plugin, [Profile | OtherProfiles], State) -> + Plugins = rebar_state:get(State, {plugins, Profile}, []) ++ rebar_state:get(State, {project_plugins, Profile}, []), + case rebar_utils:tup_find(list_to_atom(Plugin), Plugins) of + false -> + find_plugin(Plugin, OtherProfiles, State); + P -> + {ok, P, Profile} + end. build_plugin(ToBuild, State) -> Providers = rebar_state:providers(State), diff --git a/apps/rebar/src/rebar_prv_upgrade.erl b/apps/rebar/src/rebar_prv_upgrade.erl index 63ad951e3..84fdc7fae 100644 --- a/apps/rebar/src/rebar_prv_upgrade.erl +++ b/apps/rebar/src/rebar_prv_upgrade.erl @@ -1,6 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_prv_upgrade). -behaviour(provider). @@ -130,12 +152,12 @@ 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) -> +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) -> +handle_args(State) -> {Args, _} = rebar_state:command_parsed_args(State), All = proplists:get_value(all, Args, false), Package = proplists:get_value(package, Args), @@ -146,7 +168,7 @@ update_pkg_deps([], _, _) -> ok; update_pkg_deps([{Name, _, _} | Rest], AppInfos, State) -> case rebar_app_utils:find(Name, AppInfos) of - {ok, AppInfo} -> + {value, AppInfo} -> Source = rebar_app_info:source(AppInfo), case element(1, Source) of pkg -> diff --git a/apps/rebar/src/rebar_prv_vendor.erl b/apps/rebar/src/rebar_prv_vendor.erl index 7e1cafb27..67ee0f36f 100644 --- a/apps/rebar/src/rebar_prv_vendor.erl +++ b/apps/rebar/src/rebar_prv_vendor.erl @@ -125,12 +125,12 @@ check_project_layout(State) -> %% Code duplicated from rebar_prv_lock:define_root_app/2 RootDir = rebar_dir:root_dir(TmpState), case ec_lists:find(fun(X) -> - ec_file:real_dir_path(rebar_app_info:dir(X)) =:= - ec_file:real_dir_path(RootDir) + rebar_file_utils:real_dir_path(rebar_app_info:dir(X)) =:= + rebar_file_utils:real_dir_path(RootDir) end, Apps) of - {ok, _App} -> + {value, _App} -> non_umbrella; - error -> + false -> umbrella end end. diff --git a/apps/rebar/src/rebar_resource_v2.erl b/apps/rebar/src/rebar_resource_v2.erl index f783856f6..270126d71 100644 --- a/apps/rebar/src/rebar_resource_v2.erl +++ b/apps/rebar/src/rebar_resource_v2.erl @@ -1,5 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et + +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_resource_v2). -export([new/3, @@ -46,17 +69,17 @@ new(Type, Module, State) -> -spec find_resource(type(), [resource()]) -> {ok, resource()} | {error, not_found}. find_resource(Type, Resources) -> - case ec_lists:find(fun(#resource{type=T}) -> T =:= Type end, Resources) of - error when is_atom(Type) -> + case lists:search(fun(#resource{type=T}) -> T =:= Type end, Resources) of + false when is_atom(Type) -> case code:which(Type) of non_existing -> {error, not_found}; _ -> {ok, rebar_resource:new(Type, Type, #{})} end; - error -> + false -> {error, not_found}; - {ok, Resource} -> + {value, Resource} -> {ok, Resource} end. diff --git a/apps/rebar/src/rebar_semver.erl b/apps/rebar/src/rebar_semver.erl index 5404fb489..3096576bc 100644 --- a/apps/rebar/src/rebar_semver.erl +++ b/apps/rebar/src/rebar_semver.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_semver). -export([ parse_version/1, @@ -11,12 +33,61 @@ -export_type([version/0, constraint/0]). --type version() :: ec_semver:semver(). --type constraint() :: fun((ec_semver:semver()) -> boolean()). +%% SPDX-SnippetBegin +%% SPDX-License-Identifier: MIT +%% +%% SPDX-SnippetCopyrightText: 2011 Erlware, LLC +%% +%% SPDX-FileCopyrightText: 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Permission is hereby granted, free of charge, to any person obtaining a copy +%% of this software and associated documentation files (the "Software"), to deal +%% in the Software without restriction, including without limitation the rights +%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +%% copies of the Software, and to permit persons to whom the Software is +%% furnished to do so, subject to the following conditions: +%% +%% The above copyright notice and this permission notice shall be included in +%% all copies or substantial portions of the Software. +%% +%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +%% THE SOFTWARE. +%% +%% SPDX-SnippetComment: Types derived from ec_semver.erl in erlware_commons. + +-type version_element() :: non_neg_integer() | binary(). + +-type major_minor_patch_minpatch() :: + version_element() + | {version_element(), version_element()} + | {version_element(), version_element(), version_element()} + | {version_element(), version_element(), + version_element(), version_element()}. + +-type alpha_part() :: integer() | binary() | string(). +-type alpha_info() :: {PreRelease::[alpha_part()], + BuildVersion::[alpha_part()]}. + +-type version() :: {major_minor_patch_minpatch(), alpha_info()}. +-type constraint() :: fun((any_version()) -> boolean()). + +-type version_string() :: string() | binary(). --spec parse_version(binary()) -> {ok, version()} | {error, {invalid_vsn, binary()}}. +-type any_version() :: version_string() | version(). + +%% SPDX-SnippetEnd + +-spec parse_version(Version) -> {ok, Parsed} | Error when + Version :: any_version(), + Parsed :: version(), + Error :: {error, {invalid_vsn, Version}}. parse_version(Version) -> - case ec_semver:parse(Version) of + case parse(Version) of {C, _} when is_binary(C) -> {error, {invalid_vsn, Version}}; {{A, B}, _} when is_binary(A); is_binary(B) -> @@ -38,6 +109,10 @@ parse_constraint(Constraint) -> Match -> {ok, Match} end. +-spec parse_constraint_ors(Patterns, Constraints) -> Result when + Patterns :: [binary()], + Constraints :: [constraint()], + Result :: nomatch | constraint(). parse_constraint_ors([], []) -> nomatch; parse_constraint_ors([], [Match]) -> Match; parse_constraint_ors([], Matchers) -> @@ -48,6 +123,10 @@ parse_constraint_ors([And|Ors], Matchers) -> Match -> parse_constraint_ors(Ors, [Match|Matchers]) end. +-spec parse_constraint_ands(Patterns, Constraints) -> Result when + Patterns :: [binary()], + Constraints :: [constraint()], + Result :: nomatch | constraint(). parse_constraint_ands([], []) -> nomatch; parse_constraint_ands([], [Match]) -> Match; parse_constraint_ands([], Matchers) -> @@ -58,23 +137,28 @@ parse_constraint_ands([Pattern|Ands], Matchers) -> Match -> parse_constraint_ands(Ands, [Match|Matchers]) end. +-spec parse_constraint_pattern(binary()) -> nomatch | constraint(). parse_constraint_pattern(<<" ", Vsn/binary>>) -> parse_constraint_pattern(Vsn); parse_constraint_pattern(<<"==", Vsn/binary>>) -> - parse_version_constraint(Vsn, fun ec_semver:eql/2); + parse_version_constraint(Vsn, fun eql/2); parse_constraint_pattern(<<">=", Vsn/binary>>) -> - parse_version_constraint(Vsn, fun ec_semver:gte/2); + parse_version_constraint(Vsn, fun gte/2); parse_constraint_pattern(<<"<=", Vsn/binary>>) -> - parse_version_constraint(Vsn, fun ec_semver:lte/2); + parse_version_constraint(Vsn, fun lte/2); parse_constraint_pattern(<<">", Vsn/binary>>) -> - parse_version_constraint(Vsn, fun ec_semver:gt/2); + parse_version_constraint(Vsn, fun gt/2); parse_constraint_pattern(<<"<", Vsn/binary>>) -> - parse_version_constraint(Vsn, fun ec_semver:lt/2); + parse_version_constraint(Vsn, fun lt/2); parse_constraint_pattern(<<"~>", Vsn/binary>>) -> - parse_version_constraint(Vsn, fun ec_semver:pes/2); + parse_version_constraint(Vsn, fun pes/2); parse_constraint_pattern(Vsn) -> - parse_version_constraint(Vsn, fun ec_semver:eql/2). + parse_version_constraint(Vsn, fun eql/2). +-spec parse_version_constraint(Vsn, Match) -> Result when + Vsn :: any_version(), + Match :: fun((any_version(), any_version()) -> boolean()), + Result :: nomatch | constraint(). parse_version_constraint(Vsn, Match) -> case parse_version(string:trim(Vsn)) of {ok, Bound} -> fun (V) -> Match(V, Bound) end; @@ -93,21 +177,214 @@ is_prerelease_or_build(undefined) -> false; is_prerelease_or_build(Vsn) -> binary:match(Vsn, [<<"-">>, <<"+">>]) =/= nomatch. --spec match(version(), constraint()) -> boolean(). +-spec match(any_version(), constraint()) -> boolean(). match(Version, Constraint) -> Constraint(Version). --spec cmp(version(), version()) -> gt | lt | eq. +-spec cmp(any_version(), any_version()) -> gt | lt | eq. cmp(Vsn1, Vsn2) -> - case ec_semver:gt(Vsn1, Vsn2) of + case gt(Vsn1, Vsn2) of true -> gt; false -> - case ec_semver:lt(Vsn1, Vsn2) of + case lt(Vsn1, Vsn2) of true -> lt; false -> eq end end. +%% SPDX-SnippetBegin +%% SPDX-License-Identifier: MIT +%% SPDX-SnippetCopyrightText: 2011 Erlware, LLC +%% SPDX-FileCopyrightText: 2026 Dipl. Phys. Peer Stritzinger GmbH +%% SPDX-SnippetComment: Functions derived from ec_semver.erl in erlware_commons. + -spec format(version()) -> binary(). -format(Vsn) -> - iolist_to_binary(ec_semver:format(Vsn)). +format({Maj, {AlphaPart, BuildPart}}) + when erlang:is_integer(Maj); + erlang:is_binary(Maj) -> + iolist_to_binary([format_version_part(Maj), + format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]); +format({{Maj, Min}, {AlphaPart, BuildPart}}) -> + iolist_to_binary([format_version_part(Maj), ".", + format_version_part(Min), + format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]); +format({{Maj, Min, Patch}, {AlphaPart, BuildPart}}) -> + iolist_to_binary([format_version_part(Maj), ".", + format_version_part(Min), ".", + format_version_part(Patch), + format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]); +format({{Maj, Min, Patch, MinPatch}, {AlphaPart, BuildPart}}) -> + iolist_to_binary([format_version_part(Maj), ".", + format_version_part(Min), ".", + format_version_part(Patch), ".", + format_version_part(MinPatch), + format_vsn_rest(<<"-">>, AlphaPart), + format_vsn_rest(<<"+">>, BuildPart)]). + +-spec format_version_part(integer() | binary()) -> iolist(). +format_version_part(Vsn) + when erlang:is_integer(Vsn) -> + erlang:integer_to_list(Vsn); +format_version_part(Vsn) + when erlang:is_binary(Vsn) -> + Vsn. + +%% @doc parse a string or binary into a valid semver representation +-spec parse(any_version()) -> version(). +parse(Version) when erlang:is_list(Version) -> + case rebar_semver_parser:parse(Version) of + {fail, _} -> + {erlang:iolist_to_binary(Version), {[],[]}}; + Good -> + Good + end; +parse(Version) when erlang:is_binary(Version) -> + case rebar_semver_parser:parse(Version) of + {fail, _} -> + {Version, {[],[]}}; + Good -> + Good + end; +parse(Version) -> + Version. + +%% @doc test for quality between semver versions +-spec eql(any_version(), any_version()) -> boolean(). +eql(VsnA, VsnB) -> + NVsnA = normalize(parse(VsnA)), + NVsnB = normalize(parse(VsnB)), + NVsnA =:= NVsnB. + +%% @doc Test that VsnA is greater than VsnB +-spec gt(any_version(), any_version()) -> boolean(). +gt(VsnA, VsnB) -> + {MMPA, {AlphaA, PatchA}} = normalize(parse(VsnA)), + {MMPB, {AlphaB, PatchB}} = normalize(parse(VsnB)), + ((MMPA > MMPB) + orelse + ((MMPA =:= MMPB) + andalso + ((AlphaA =:= [] andalso AlphaB =/= []) + orelse + ((not (AlphaB =:= [] andalso AlphaA =/= [])) + andalso + (AlphaA > AlphaB)))) + orelse + ((MMPA =:= MMPB) + andalso + (AlphaA =:= AlphaB) + andalso + ((PatchB =:= [] andalso PatchA =/= []) + orelse + PatchA > PatchB))). + +%% @doc Test that VsnA is greater than or equal to VsnB +-spec gte(any_version(), any_version()) -> boolean(). +gte(VsnA, VsnB) -> + NVsnA = normalize(parse(VsnA)), + NVsnB = normalize(parse(VsnB)), + gt(NVsnA, NVsnB) orelse eql(NVsnA, NVsnB). + +%% @doc Test that VsnA is less than VsnB +-spec lt(any_version(), any_version()) -> boolean(). +lt(VsnA, VsnB) -> + {MMPA, {AlphaA, PatchA}} = normalize(parse(VsnA)), + {MMPB, {AlphaB, PatchB}} = normalize(parse(VsnB)), + ((MMPA < MMPB) + orelse + ((MMPA =:= MMPB) + andalso + ((AlphaB =:= [] andalso AlphaA =/= []) + orelse + ((not (AlphaA =:= [] andalso AlphaB =/= [])) + andalso + (AlphaA < AlphaB)))) + orelse + ((MMPA =:= MMPB) + andalso + (AlphaA =:= AlphaB) + andalso + ((PatchA =:= [] andalso PatchB =/= []) + orelse + PatchA < PatchB))). + +%% @doc Test that VsnA is less than or equal to VsnB +-spec lte(any_version(), any_version()) -> boolean(). +lte(VsnA, VsnB) -> + NVsnA = normalize(parse(VsnA)), + NVsnB = normalize(parse(VsnB)), + lt(NVsnA, NVsnB) orelse eql(NVsnA, NVsnB). + +%% @doc check that VsnA is Approximately greater than VsnB +%% +%% Specifying ">= 2.6.5" is an optimistic version constraint. All +%% versions greater than the one specified, including major releases +%% (e.g. 3.0.0) are allowed. +%% +%% Conversely, specifying "~> 2.6" is pessimistic about future major +%% revisions and "~> 2.6.5" is pessimistic about future minor +%% revisions. +%% +%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0 +%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0 +-spec pes(any_version(), any_version()) -> boolean(). +pes(VsnA, VsnB) -> + internal_pes(parse(VsnA), parse(VsnB)). + +-spec to_list(integer() | binary() | string()) -> string() | binary(). +to_list(Detail) when erlang:is_integer(Detail) -> + erlang:integer_to_list(Detail); +to_list(Detail) when erlang:is_list(Detail); erlang:is_binary(Detail) -> + Detail. + +-spec format_vsn_rest(binary() | string(), [integer() | binary() | string()]) -> iolist(). +format_vsn_rest(_TypeMark, []) -> + []; +format_vsn_rest(TypeMark, [Head | Rest]) -> + [TypeMark, Head | + [[".", to_list(Detail)] || Detail <- Rest]]. + +%% @doc normalize the semver so they can be compared +-spec normalize(version()) -> version(). +normalize({Vsn, Rest}) + when erlang:is_binary(Vsn); + erlang:is_integer(Vsn) -> + {{Vsn, 0, 0, 0}, Rest}; +normalize({{Maj, Min}, Rest}) -> + {{Maj, Min, 0, 0}, Rest}; +normalize({{Maj, Min, Patch}, Rest}) -> + {{Maj, Min, Patch, 0}, Rest}; +normalize(Other = {{_, _, _, _}, {_,_}}) -> + Other. + +%% @doc to do the pessimistic compare we need a parsed semver. This is +%% the internal implementation of the of the pessimistic run. The +%% external just ensures that versions are parsed. +-spec internal_pes(version(), version()) -> boolean(). +internal_pes(VsnA, {{LM, LMI}, Alpha}) + when erlang:is_integer(LM), + erlang:is_integer(LMI) -> + gte(VsnA, {{LM, LMI, 0}, Alpha}) andalso + lt(VsnA, {{LM + 1, 0, 0, 0}, {[], []}}); +internal_pes(VsnA, {{LM, LMI, LP}, Alpha}) + when erlang:is_integer(LM), + erlang:is_integer(LMI), + erlang:is_integer(LP) -> + gte(VsnA, {{LM, LMI, LP}, Alpha}) + andalso + lt(VsnA, {{LM, LMI + 1, 0, 0}, {[], []}}); +internal_pes(VsnA, {{LM, LMI, LP, LMP}, Alpha}) + when erlang:is_integer(LM), + erlang:is_integer(LMI), + erlang:is_integer(LP), + erlang:is_integer(LMP) -> + gte(VsnA, {{LM, LMI, LP, LMP}, Alpha}) + andalso + lt(VsnA, {{LM, LMI, LP + 1, 0}, {[], []}}); +internal_pes(Vsn, LVsn) -> + gte(Vsn, LVsn). + +%% SPDX-SnippetEnd diff --git a/vendor/erlware_commons/src/ec_semver_parser.erl b/apps/rebar/src/rebar_semver_parser.erl similarity index 77% rename from vendor/erlware_commons/src/ec_semver_parser.erl rename to apps/rebar/src/rebar_semver_parser.erl index c2fe18635..018de5998 100644 --- a/vendor/erlware_commons/src/ec_semver_parser.erl +++ b/apps/rebar/src/rebar_semver_parser.erl @@ -1,5 +1,38 @@ --module(ec_semver_parser). --export([parse/1,file/1]). +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: MIT +%% +%% SPDX-FileCopyrightText: Copyright 2011 Erlware, LLC +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Permission is hereby granted, free of charge, to any person obtaining a copy +%% of this software and associated documentation files (the "Software"), to deal +%% in the Software without restriction, including without limitation the rights +%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +%% copies of the Software, and to permit persons to whom the Software is +%% furnished to do so, subject to the following conditions: +%% +%% The above copyright notice and this permission notice shall be included in +%% all copies or substantial portions of the Software. +%% +%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +%% THE SOFTWARE. +%% +%% SPDX-FileComment: This file is derived from ec_semver_parser.erl and ec_semver.erl in erlware_commons (https://github.com/erlware/erlware_commons). +%% +%% %CopyrightEnd% + +-module(rebar_semver_parser). + +-export([parse/1]). +-export([file/1]). + -define(p_anything,true). -define(p_charclass,true). -define(p_choose,true). @@ -28,7 +61,7 @@ parse(Input) when is_binary(Input) -> -spec 'semver'(input(), index()) -> parse_result(). 'semver'(Input, Index) -> - p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). + p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> internal_parse_version(Node) end). -spec 'major_minor_patch_min_patch'(input(), index()) -> parse_result(). 'major_minor_patch_min_patch'(Input, Index) -> @@ -47,6 +80,46 @@ parse(Input) when is_binary(Input) -> p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9-]">>)))(I,D) end, fun(Node, _Idx) ->erlang:iolist_to_binary(Node) end). +internal_parse_version([MMP, AlphaPart, BuildPart, _]) -> + {parse_major_minor_patch_minpatch(MMP), {parse_alpha_part(AlphaPart), + parse_alpha_part(BuildPart)}}. + +parse_major_minor_patch_minpatch([MajVsn, [], [], []]) -> + strip_maj_version(MajVsn); +parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [], []]) -> + {strip_maj_version(MajVsn), MinVsn}; +parse_major_minor_patch_minpatch([MajVsn, + [<<".">>, MinVsn], + [<<".">>, PatchVsn], []]) -> + {strip_maj_version(MajVsn), MinVsn, PatchVsn}; +parse_major_minor_patch_minpatch([MajVsn, + [<<".">>, MinVsn], + [<<".">>, PatchVsn], + [<<".">>, MinPatch]]) -> + {strip_maj_version(MajVsn), MinVsn, PatchVsn, MinPatch}. + +parse_alpha_part([]) -> + []; +parse_alpha_part([_, AV1, Rest]) -> + [erlang:iolist_to_binary(AV1) | + [format_alpha_part(Part) || Part <- Rest]]. + +format_alpha_part([<<".">>, AlphaPart]) -> + Bin = erlang:iolist_to_binary(AlphaPart), + try + erlang:list_to_integer(erlang:binary_to_list(Bin)) + catch + error:badarg -> + Bin + end. + +strip_maj_version([<<"v">>, MajVsn]) -> + MajVsn; +strip_maj_version([[], MajVsn]) -> + MajVsn; +strip_maj_version(MajVsn) -> + MajVsn. + transform(_,Node,_Index) -> Node. -type index() :: {{line, pos_integer()}, {column, pos_integer()}}. -type input() :: binary(). diff --git a/apps/rebar/src/rebar_templater.erl b/apps/rebar/src/rebar_templater.erl index ce1959397..241746c08 100644 --- a/apps/rebar/src/rebar_templater.erl +++ b/apps/rebar/src/rebar_templater.erl @@ -1,10 +1,14 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et -%% ------------------------------------------------------------------- +%% %CopyrightBegin% %% -%% rebar: Erlang Build Tools +%% SPDX-Licence-Identifier: MIT %% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) +%% SPDX-FileCopyrightText: Copyright 2009 Dave Smith (dizzyd@dizzyd.com) +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -23,7 +27,8 @@ %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% THE SOFTWARE. -%% ------------------------------------------------------------------- +%% %CopyrightEnd% + -module(rebar_templater). -export([new/4, @@ -238,7 +243,7 @@ execute_template([{message, _} | Terms], Files, Template, Vars, Force) -> %% Create a directory execute_template([{dir, Path} | Terms], Files, Template, Vars, Force) -> ?DEBUG("Creating directory ~p", [Path]), - case ec_file:mkdir_p(expand_path(Path, Vars)) of + case filelib:ensure_path(expand_path(Path, Vars)) of ok -> ok; {error, Reason} -> diff --git a/apps/rebar/src/rebar_utils.erl b/apps/rebar/src/rebar_utils.erl index ecb568dff..7d7eddd8c 100644 --- a/apps/rebar/src/rebar_utils.erl +++ b/apps/rebar/src/rebar_utils.erl @@ -263,9 +263,10 @@ to_list(B) when is_binary(B) -> unicode:characters_to_list(B); to_list(I) when is_integer(I) -> integer_to_list(I); to_list(Str) -> unicode:characters_to_list(Str). -to_atom(B) when is_binary(B) -> binary_to_atom(B, utf8); -to_atom(Str) when is_list(Str) -> list_to_atom(Str); -to_atom(A) when is_atom(A) -> A. +to_atom(B) when is_binary(B) -> binary_to_existing_atom(B, utf8); +to_atom(Str) when is_list(Str) -> list_to_existing_atom(Str); +to_atom(A) when is_atom(A) -> A; +to_atom(X) -> to_atom(to_list(X)). tup_dedup(List) -> tup_dedup_(tup_sort(List)). @@ -1169,10 +1170,10 @@ partial_chain(Certs) -> Certs1 = [{Cert, public_key:pkix_decode_cert(Cert, otp)} || Cert <- Certs], CACerts = certifi:cacerts(), CACerts1 = [public_key:pkix_decode_cert(Cert, otp) || Cert <- CACerts], - case ec_lists:find(fun({_, Cert}) -> + case lists:search(fun({_, Cert}) -> check_cert(CACerts1, Cert) - end, Certs1) of - {ok, Trusted} -> + end, Certs1) of + {value, Trusted} -> {trusted_ca, element(1, Trusted)}; _ -> unknown_ca diff --git a/apps/rebar/test/mock_pkg_resource.erl b/apps/rebar/test/mock_pkg_resource.erl index f609b5f36..cc5993f3c 100644 --- a/apps/rebar/test/mock_pkg_resource.erl +++ b/apps/rebar/test/mock_pkg_resource.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + %%% Mock a package resource and create an app magically for each URL submitted. -module(mock_pkg_resource). -export([mock/0, mock/1, unmock/0]). @@ -170,8 +192,8 @@ to_index(AllDeps, Dict, Repos) -> requirement => DVB, source => {pkg, DKB, DVB, undefined, undefined}} || {DK, DV} <- Deps, - DKB <- [ec_cnv:to_binary(DK)], - DVB <- [ec_cnv:to_binary(DV)]], + DKB <- [rebar_utils:to_binary(DK)], + DVB <- [rebar_utils:to_binary(DV)]], Repo = rebar_test_utils:random_element(Repos), {ok, Parsed} = rebar_semver:parse_version(V), ets:insert(?PACKAGE_TABLE, #package{key={N, Parsed, Repo}, @@ -184,11 +206,11 @@ to_index(AllDeps, Dict, Repos) -> lists:foreach(fun({{Name, Vsn}, _}) -> {ok, Parsed} = rebar_semver:parse_version(Vsn), case lists:any(fun(R) -> - ets:member(?PACKAGE_TABLE, {ec_cnv:to_binary(Name), Parsed, R}) + ets:member(?PACKAGE_TABLE, {rebar_utils:to_binary(Name), Parsed, R}) end, Repos) of false -> Repo = rebar_test_utils:random_element(Repos), - ets:insert(?PACKAGE_TABLE, #package{key={ec_cnv:to_binary(Name), Parsed, Repo}, + ets:insert(?PACKAGE_TABLE, #package{key={rebar_utils:to_binary(Name), Parsed, Repo}, dependencies=[], retired=false, inner_checksum = <<"inner_checksum">>, diff --git a/apps/rebar/test/rebar_compile_SUITE.erl b/apps/rebar/test/rebar_compile_SUITE.erl index 0a9ddfa5a..c5b139069 100644 --- a/apps/rebar/test/rebar_compile_SUITE.erl +++ b/apps/rebar/test/rebar_compile_SUITE.erl @@ -617,7 +617,7 @@ clean_basic_extra_dirs(Config) -> rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name, invalid}]}), Beam = lists:flatten(io_lib:format("~ts_extra", [Name])), - false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name, "extras", Beam])). + false = filelib:is_file(filename:join([AppDir, "_build", "default", "lib", Name, "extras", Beam])). clean_release_extra_dirs(Config) -> AppDir = ?config(apps, Config), @@ -627,9 +627,9 @@ clean_release_extra_dirs(Config) -> {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}), Beam1 = lists:flatten(io_lib:format("~ts_extra", [Name1])), - false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name1, "extras", Beam1])), + false = filelib:is_file(filename:join([AppDir, "_build", "default", "lib", Name1, "extras", Beam1])), Beam2 = lists:flatten(io_lib:format("~ts_extra", [Name2])), - false = ec_file:exists(filename:join([AppDir, "_build", "default", "lib", Name2, "extras", Beam2])). + false = filelib:is_file(filename:join([AppDir, "_build", "default", "lib", Name2, "extras", Beam2])). clean_extra_dirs_in_project_root(Config) -> AppDir = ?config(apps, Config), @@ -638,7 +638,7 @@ clean_extra_dirs_in_project_root(Config) -> rebar_test_utils:run_and_check(Config, [], ["clean"], {ok, [{app, Name1, invalid}, {app, Name2, invalid}]}), - false = ec_file:exists(filename:join([AppDir, "_build", "default", "extras"])). + false = filelib:is_file(filename:join([AppDir, "_build", "default", "extras"])). recompile_when_hrl_changes(Config) -> AppDir = ?config(apps, Config), @@ -1146,7 +1146,7 @@ dont_recompile_yrl_or_xrl(Config) -> " {token,{float,TokenLine,list_to_float(TokenChars)}}." "\n\n" "Erlang code.", - ok = ec_file:write(Xrl, XrlBody), + ok = file:write_file(Xrl, XrlBody), Yrl = filename:join([AppDir, "src", "not_a_real_yrl_" ++ Name ++ ".yrl"]), ok = filelib:ensure_dir(Yrl), @@ -1159,7 +1159,7 @@ dont_recompile_yrl_or_xrl(Config) -> "T -> F : '$1'.\n" "F -> '(' E ')' : '$2'.\n" "F -> number : '$1'.\n"], - ok = ec_file:write(Yrl, YrlBody), + ok = file:write_file(Yrl, YrlBody), XrlErl = filename:join([AppDir, "src", filename:basename(Xrl, ".xrl") ++ ".erl"]), YrlErl = filename:join([AppDir, "src", filename:basename(Yrl, ".yrl") ++ ".erl"]), @@ -1171,7 +1171,7 @@ dont_recompile_yrl_or_xrl(Config) -> Hrl = filename:join([AppDir, "include", "some_header.hrl"]), ok = filelib:ensure_dir(Hrl), HrlBody = yeccpre_hrl(), - ok = ec_file:write(Hrl, HrlBody), + ok = file:write_file(Hrl, HrlBody), RebarConfig = [{yrl_opts, [{includefile, "include/some_header.hrl"}]}], rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name}]}), @@ -1257,7 +1257,7 @@ deps_in_path(Config) -> ?assertNotEqual([], [Path || Path <- code:get_path(), {match, _} <- [re:run(Path, PkgName)]]), - true = code:set_path(lists:filter(fun(P) -> ec_file:exists(P) end, StartPaths)), + true = code:set_path(lists:filter(fun(P) -> filelib:is_file(P) end, StartPaths)), %% Make sure apps we look for are not visible again %% Hope not to find src name ?assertEqual([], [Path || Path <- code:get_path(), diff --git a/apps/rebar/test/rebar_dialyzer_SUITE.erl b/apps/rebar/test/rebar_dialyzer_SUITE.erl index 1548a2259..36627fd35 100644 --- a/apps/rebar/test/rebar_dialyzer_SUITE.erl +++ b/apps/rebar/test/rebar_dialyzer_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_dialyzer_SUITE). -export([suite/0, @@ -46,7 +68,7 @@ end_per_group(_Group, _Config) -> init_per_testcase(Testcase, Config) -> PrivDir = ?config(priv_dir, Config), - Prefix = ec_cnv:to_list(Testcase), + Prefix = rebar_utils:to_list(Testcase), BasePrefix = Prefix ++ "_base", Opts = [{plt_prefix, Prefix}, {plt_location, PrivDir}, @@ -248,7 +270,7 @@ build_release_plt(Config) -> Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, - [erts, ec_cnv:to_atom(Name1)]), + [erts, rebar_utils:to_atom(Name1)]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer"], {ok, [{app, Name1}, {app, Name2}]}), @@ -272,13 +294,13 @@ plt_apps_option(Config) -> Vsn1 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"deps",Name1]), Name1, Vsn1, []), - App1 = ec_cnv:to_atom(Name1), + App1 = rebar_utils:to_atom(Name1), Name2 = rebar_test_utils:create_random_name("app2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"deps",Name2]), Name2, Vsn2, [App1]), % App2 depends on App1 - App2 = ec_cnv:to_atom(Name2), + App2 = rebar_utils:to_atom(Name2), Name3 = rebar_test_utils:create_random_name("app3_"), % the project application Vsn3 = rebar_test_utils:create_random_vsn(), @@ -365,7 +387,7 @@ cli_args(Config) -> Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, - [erts, ec_cnv:to_atom(Name1)]), + [erts, rebar_utils:to_atom(Name1)]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer", "--plt-location=" ++ Location, @@ -397,13 +419,13 @@ single_app_succ_typing(Config) -> %% contains warnings in tests rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, []), %% second app, depending on first, should not produce warnings - App1 = ec_cnv:to_atom(Name), + App1 = rebar_utils:to_atom(Name), %%% second app depends on first Name2 = rebar_test_utils:create_random_name("app2_"), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, [App1]), % App2 depends on App1 - App2 = ec_cnv:to_atom(Name2), + App2 = rebar_utils:to_atom(Name2), %% start with building all apps into PLT RebarConfig2 = merge_config([{dialyzer, [{plt_apps, all_apps}]}], @@ -549,7 +571,7 @@ incremental_cli_args(Config) -> Name2 = rebar_test_utils:create_random_name("relapp2_"), Vsn2 = rebar_test_utils:create_random_vsn(), {ok, App2} = rebar_test_utils:create_app(filename:join([AppDir,"apps",Name2]), Name2, Vsn2, - [erts, ec_cnv:to_atom(Name1)]), + [erts, rebar_utils:to_atom(Name1)]), rebar_test_utils:run_and_check(Config, RebarConfig, ["dialyzer", "--incremental", @@ -669,7 +691,7 @@ get_apps_from_beam_files(BeamFiles) -> [begin AppNameVsn = filename:basename(filename:dirname(filename:dirname(File))), [AppName | _] = rebar_string:lexemes(AppNameVsn ++ "-", "-"), - ec_cnv:to_atom(AppName) + rebar_utils:to_atom(AppName) end || File <- BeamFiles]). -spec is_incremental_available() -> boolean(). diff --git a/apps/rebar/test/rebar_dir_SUITE.erl b/apps/rebar/test/rebar_dir_SUITE.erl index f88232038..5e97b2ce3 100644 --- a/apps/rebar/test/rebar_dir_SUITE.erl +++ b/apps/rebar/test/rebar_dir_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_dir_SUITE). -export([all/0, init_per_testcase/2, end_per_testcase/2]). @@ -99,7 +121,7 @@ alt_src_dir_nested(Config) -> ModDir = filename:join([AppsDir, "apps", Name1, "alt", "nested"]), Mod = "-module(altmod). -export([main/0]). main() -> ok.", - ec_file:mkdir_path(ModDir), + filelib:ensure_path(ModDir), ok = file:write_file(filename:join([ModDir, "altmod.erl"]), Mod), Ebin = filename:join([AppsDir, "_build", "default", "lib", Name1, "ebin", "altmod.beam"]), diff --git a/apps/rebar/test/rebar_disable_app_SUITE.erl b/apps/rebar/test/rebar_disable_app_SUITE.erl index dd71ffbe6..058399534 100644 --- a/apps/rebar/test/rebar_disable_app_SUITE.erl +++ b/apps/rebar/test/rebar_disable_app_SUITE.erl @@ -1,9 +1,31 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_disable_app_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). --define(MOD(Name), +-define(MOD(Name), io_lib:format("-module(~s).~n-export([x/0]).~nx() -> ok.~n", [Name])). all() -> [disable_app]. @@ -45,5 +67,5 @@ create_random_app(AppDir, Prefix) -> Mod = filename:join([AppDir, "apps", Name, "src", ModName ++ ".erl"]), ok = filelib:ensure_dir(Mod), Src = ?MOD(ModName), - ok = ec_file:write(Mod, Src), + ok = file:write_file(Mod, Src), Name. diff --git a/apps/rebar/test/rebar_edoc_SUITE.erl b/apps/rebar/test/rebar_edoc_SUITE.erl index 5f8cad63e..d84adc76e 100644 --- a/apps/rebar/test/rebar_edoc_SUITE.erl +++ b/apps/rebar/test/rebar_edoc_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_edoc_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -11,7 +33,7 @@ init_per_testcase(multiapp, Config) -> PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("multiapp"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), - ec_file:copy(filename:join([DataDir, "foo"]), AppsDir, [recursive]), + rebar_file_utils:copy(filename:join([DataDir, "foo"]), AppsDir, [recursive]), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} @@ -23,8 +45,8 @@ init_per_testcase(multiapp_macros, Config) -> PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("multiapp_macros"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), - ec_file:copy(filename:join([DataDir, "foo"]), AppsDir, [recursive]), - ok = ec_file:remove(filename:join([AppsDir, "apps", "foo"]), [recursive]), + rebar_file_utils:copy(filename:join([DataDir, "foo"]), AppsDir, [recursive]), + ok = file:del_dir_r(filename:join([AppsDir, "apps", "foo"])), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} @@ -36,7 +58,7 @@ init_per_testcase(error_survival, Config) -> PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("error_survival"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), - ec_file:copy(filename:join([DataDir, "bad"]), AppsDir, [recursive]), + rebar_file_utils:copy(filename:join([DataDir, "bad"]), AppsDir, [recursive]), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])} diff --git a/apps/rebar/test/rebar_eunit_SUITE.erl b/apps/rebar/test/rebar_eunit_SUITE.erl index 662ded27a..6d9ca16e7 100644 --- a/apps/rebar/test/rebar_eunit_SUITE.erl +++ b/apps/rebar/test/rebar_eunit_SUITE.erl @@ -60,11 +60,11 @@ groups() -> init_per_suite(Config) -> PrivDir = ?config(priv_dir, Config), DataDir = ?config(data_dir, Config), - ok = ec_file:copy(filename:join([DataDir, "basic_app.zip"]), filename:join([PrivDir, "basic_app.zip"])), + ok = rebar_file_utils:copy(filename:join([DataDir, "basic_app.zip"]), filename:join([PrivDir, "basic_app.zip"])), {ok, _} = zip:extract(filename:join([PrivDir, "basic_app.zip"]), [{cwd, PrivDir}]), - ok = ec_file:copy(filename:join([DataDir, "multi_app.zip"]), filename:join([PrivDir, "multi_app.zip"])), + ok = rebar_file_utils:copy(filename:join([DataDir, "multi_app.zip"]), filename:join([PrivDir, "multi_app.zip"])), {ok, _} = zip:extract(filename:join([PrivDir, "multi_app.zip"]), [{cwd, PrivDir}]), - ok = ec_file:copy(filename:join([DataDir, "syscfg_app.zip"]), filename:join([PrivDir, "syscfg_app.zip"])), + ok = rebar_file_utils:copy(filename:join([DataDir, "syscfg_app.zip"]), filename:join([PrivDir, "syscfg_app.zip"])), {ok, _} = zip:extract(filename:join([PrivDir, "syscfg_app.zip"]), [{cwd, PrivDir}]), Config. @@ -78,7 +78,7 @@ init_per_group(basic_app, Config) -> AppDirs = ["src", "include", "test"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), @@ -95,7 +95,7 @@ init_per_group(multi_app, Config) -> AppDirs = ["apps", "test"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "multi_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "multi_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), @@ -112,7 +112,7 @@ init_per_group(cmd_line_args, Config) -> AppDirs = ["apps", "test"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "multi_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "multi_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), @@ -149,9 +149,9 @@ basic_app_compiles(Config) -> basic_app_files(Config) -> AppDir = ?config(apps, Config), - lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "ebin", F])) end, + lists:foreach(fun(F) -> true = filelib:is_file(filename:join([AppDir, "_build", "test", "lib", "basic_app", "ebin", F])) end, ["basic_app.app", "basic_app.beam"]), - lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "test", F])) end, + lists:foreach(fun(F) -> true = filelib:is_file(filename:join([AppDir, "_build", "test", "lib", "basic_app", "test", F])) end, ["basic_app_tests.beam", "basic_app_tests_helper.beam"]). %% check that the correct tests are exported from modules for project @@ -208,15 +208,15 @@ multi_app_compiles(Config) -> multi_app_files(Config) -> AppDir = ?config(apps, Config), - lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", F])) end, + lists:foreach(fun(F) -> true = filelib:is_file(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", F])) end, ["multi_app_bar.app", "multi_app_bar.beam"]), - lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", F])) end, + lists:foreach(fun(F) -> true = filelib:is_file(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", F])) end, ["multi_app_baz.app", "multi_app_baz.beam"]), - lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "test", F])) end, + lists:foreach(fun(F) -> true = filelib:is_file(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "test", F])) end, ["multi_app_bar_tests.beam", "multi_app_bar_tests_helper.beam"]), - lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "test", F])) end, + lists:foreach(fun(F) -> true = filelib:is_file(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "test", F])) end, ["multi_app_baz_tests.beam", "multi_app_baz_tests_helper.beam"]), - lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "extras", "test", F])) end, + lists:foreach(fun(F) -> true = filelib:is_file(filename:join([AppDir, "_build", "test", "extras", "test", F])) end, ["multi_app_tests.beam", "multi_app_tests_helper.beam"]). %% check that the correct tests are exported from modules for project @@ -604,7 +604,7 @@ misspecified_eunit_tests(Config) -> AppDirs = ["src", "include", "test"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), @@ -624,7 +624,7 @@ misspecified_eunit_compile_opts(Config) -> AppDirs = ["src", "include", "test"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), @@ -642,7 +642,7 @@ misspecified_eunit_first_files(Config) -> AppDirs = ["src", "include", "test"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), @@ -662,7 +662,7 @@ alternate_test_regex(Config) -> AppDirs = ["src", "include", "test"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "basic_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), @@ -685,7 +685,7 @@ syscfg_app_opts(Config) -> AppDirs = ["src", "test", "config"], - lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "syscfg_app", F]), + lists:foreach(fun(F) -> rebar_file_utils:copy(filename:join([PrivDir, "syscfg_app", F]), filename:join([AppDir, F]), [recursive]) end, AppDirs), diff --git a/apps/rebar/test/rebar_file_utils_SUITE.erl b/apps/rebar/test/rebar_file_utils_SUITE.erl index 06eed81f5..b1a8139e2 100644 --- a/apps/rebar/test/rebar_file_utils_SUITE.erl +++ b/apps/rebar/test/rebar_file_utils_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_file_utils_SUITE). -export([all/0, @@ -113,7 +135,7 @@ multi_tmpdir(_Config) -> reset_nonexistent_dir(Config) -> TmpDir = ?config(tmpdir, Config), - _ = ec_file:remove(TmpDir, [recursive]), + _ = file:del_dir_r(TmpDir), ?assertNot(filelib:is_dir(TmpDir)), ok = rebar_file_utils:reset_dir(TmpDir), ?assert(filelib:is_dir(TmpDir)), @@ -121,7 +143,7 @@ reset_nonexistent_dir(Config) -> reset_empty_dir(Config) -> TmpDir = ?config(tmpdir, Config), - _ = ec_file:remove(TmpDir, [recursive]), + _ = file:del_dir_r(TmpDir), _ = filelib:ensure_dir(filename:join([TmpDir, "dummy.beam"])), ?assert(filelib:is_dir(TmpDir)), ok = rebar_file_utils:reset_dir(TmpDir), @@ -130,7 +152,7 @@ reset_empty_dir(Config) -> reset_dir(Config) -> TmpDir = ?config(tmpdir, Config), - _ = ec_file:remove(TmpDir, [recursive]), + _ = file:del_dir_r(TmpDir), _ = filelib:ensure_dir(filename:join([TmpDir, "dummy.beam"])), ?assert(filelib:is_dir(TmpDir)), lists:foreach(fun(Name) -> file:write_file(filename:join([TmpDir, Name]), <<>>) end, @@ -205,7 +227,7 @@ resolve_link(_Config) -> ["rebar_file_utils_SUITE", "resolve_link"]), Link = filename:join(TmpDir, "link"), Target = filename:join(TmpDir, "link-target"), - ec_file:remove(TmpDir, [recursive]), + file:del_dir_r(TmpDir), ok = filelib:ensure_dir(Target), ok = file:write_file(Target, <<>>), ok = file:make_symlink(Target, Link), @@ -232,7 +254,7 @@ mv_dir(Config) -> PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_dir), SrcDir = filename:join(BaseDir, "src/"), - ec_file:mkdir_p(SrcDir), + filelib:ensure_path(SrcDir), ?assert(filelib:is_dir(SrcDir)), %% empty dir movement DstDir1 = filename:join(BaseDir, "dst1/"), @@ -262,7 +284,7 @@ mv_dir(Config) -> DstDir3 = filename:join(BaseDir, "dst3/"), D3F1 = filename:join(DstDir3, "src/file1"), D3F2 = filename:join(DstDir3, "src/subdir/file2"), - ec_file:mkdir_p(DstDir3), + filelib:ensure_path(DstDir3), ?assert(filelib:is_dir(DstDir3)), ?assertEqual(ok, rebar_file_utils:mv(SrcDir, DstDir3)), ?assertNot(filelib:is_file(F1)), @@ -277,12 +299,12 @@ mv_file_same(Config) -> PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_same), SrcDir = filename:join(BaseDir, "src/"), - ec_file:mkdir_p(SrcDir), + filelib:ensure_path(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), - ec_file:mkdir_p(DstDir), + filelib:ensure_path(DstDir), Dst = filename:join(DstDir, "file"), ?assertEqual(ok, rebar_file_utils:mv(F, Dst)), ?assert(filelib:is_file(Dst)), @@ -295,12 +317,12 @@ mv_file_diff(Config) -> PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_diff), SrcDir = filename:join(BaseDir, "src/"), - ec_file:mkdir_p(SrcDir), + filelib:ensure_path(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), - ec_file:mkdir_p(DstDir), + filelib:ensure_path(DstDir), Dst = filename:join(DstDir, "file-rename"), file:write_file(Dst, "not-the-right-content"), ?assert(filelib:is_file(Dst)), @@ -315,12 +337,12 @@ mv_file_dir_same(Config) -> PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_dir_same), SrcDir = filename:join(BaseDir, "src/"), - ec_file:mkdir_p(SrcDir), + filelib:ensure_path(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), - ec_file:mkdir_p(DstDir), + filelib:ensure_path(DstDir), Dst = filename:join(DstDir, "file"), ?assert(filelib:is_dir(DstDir)), ?assertEqual(ok, rebar_file_utils:mv(F, DstDir)), @@ -333,12 +355,12 @@ mv_file_dir_diff(Config) -> PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_file_dir_diff), SrcDir = filename:join(BaseDir, "src/"), - ec_file:mkdir_p(SrcDir), + filelib:ensure_path(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), DstDir = filename:join(BaseDir, "dst/"), - ec_file:mkdir_p(DstDir), + filelib:ensure_path(DstDir), Dst = filename:join(DstDir, "file-rename"), ?assert(filelib:is_dir(DstDir)), ?assertNot(filelib:is_file(Dst)), @@ -352,14 +374,14 @@ mv_no_clobber(Config) -> PrivDir = ?config(priv_dir, Config), BaseDir = mk_base_dir(PrivDir, mv_no_clobber), SrcDir = filename:join(BaseDir, "src/"), - ec_file:mkdir_p(SrcDir), + filelib:ensure_path(SrcDir), ?assert(filelib:is_dir(SrcDir)), F = filename:join(SrcDir, "file"), file:write_file(F, "hello"), FBad = filename:join(SrcDir, "file-alt"), file:write_file(FBad, "wrong-data"), DstDir = filename:join(BaseDir, "dst/"), - ec_file:mkdir_p(DstDir), + filelib:ensure_path(DstDir), Dst = filename:join(DstDir, "file-alt"), DstBad = filename:join(DstDir, "file"), file:write_file(DstBad, "wrong-data"), @@ -383,7 +405,7 @@ mk_base_dir(BasePath, Name) -> {_,_,Micro} = os:timestamp(), Index = integer_to_list(Micro), Path = filename:join(BasePath, atom_to_list(Name) ++ Index), - ec_file:mkdir_p(Path), + filelib:ensure_path(Path), Path. cp_r_copies_files(Config) -> @@ -393,7 +415,7 @@ cp_r_copies_files(Config) -> {SrcList, DestDir} = create_dir_tree_helper(BaseDir), rebar_file_utils:cp_r(SrcList, DestDir, []), - + % dest/file DestFile = filename:join(DestDir, "file"), ?assert(filelib:is_file(DestFile)), @@ -420,7 +442,7 @@ cp_r_dereferences_symbolic_links(Config) -> {SrcList, DestDir} = create_dir_tree_helper(BaseDir), rebar_file_utils:cp_r(SrcList, DestDir, [{dereference, true}]), - + % dest/file DestFile = filename:join(DestDir, "file"), ?assert(filelib:is_file(DestFile)), @@ -447,7 +469,7 @@ create_dir_tree_helper(BaseDir) -> % Give a directory path, it creates the tree directory below and returns a map % with the expected paths in dest/ aftercopying them. % - % sub_dir is it needed so try all the win32 copy options + % sub_dir is it needed so try all the win32 copy options % % |-- src % |-- file @@ -476,7 +498,7 @@ create_dir_tree_helper(BaseDir) -> create_by_type([], _) -> ok; create_by_type([{folder, Path} |Rest], BaseDir) -> - ok = ec_file:mkdir_p(filename:join([BaseDir | Path])), + ok = filelib:ensure_path(filename:join([BaseDir | Path])), create_by_type(Rest, BaseDir); create_by_type([{file, Path, Content} |Rest], BaseDir) -> ok = file:write_file(filename:join([BaseDir | Path]), Content), diff --git a/apps/rebar/test/rebar_new_SUITE.erl b/apps/rebar/test/rebar_new_SUITE.erl index 5cee8fc57..f794d4bb5 100644 --- a/apps/rebar/test/rebar_new_SUITE.erl +++ b/apps/rebar/test/rebar_new_SUITE.erl @@ -16,7 +16,7 @@ init_per_testcase(plugin_tpl, Config) -> PrivDir = ?config(priv_dir, Config), Name = rebar_test_utils:create_random_name("plugin_tpl"), AppsDir = filename:join([PrivDir, rebar_test_utils:create_random_name(Name)]), - ec_file:copy(filename:join([DataDir, "plugin_tpl"]), AppsDir, [recursive]), + rebar_file_utils:copy(filename:join([DataDir, "plugin_tpl"]), AppsDir, [recursive]), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), GlobalDir = filename:join([DataDir, "cache"]), diff --git a/apps/rebar/test/rebar_pkg_SUITE.erl b/apps/rebar/test/rebar_pkg_SUITE.erl index 6a74fcb96..a65f99fc8 100644 --- a/apps/rebar/test/rebar_pkg_SUITE.erl +++ b/apps/rebar/test/rebar_pkg_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + %% Test suite for the rebar pkg index caching and decompression %% mechanisms. -module(rebar_pkg_SUITE). @@ -79,7 +101,7 @@ init_per_testcase(bad_to_good=Name, Config0) -> Config = mock_config(Name, Config1), Source = filename:join(?config(data_dir, Config), <<"badpkg-1.0.0.tar">>), Dest = filename:join(?config(cache_dir, Config), <<"goodpkg-1.0.0.tar">>), - ec_file:copy(Source, Dest), + rebar_file_utils:copy(Source, Dest), Config; init_per_testcase(good_disconnect=Name, Config0) -> Pkg = {<<"goodpkg">>, <<"1.0.0">>}, @@ -293,10 +315,10 @@ mock_config(Name, Config) -> catch ets:delete(?PACKAGE_TABLE), rebar_packages:new_package_table(), lists:foreach(fun({{N, Vsn}, [Deps, InnerChecksum, OuterChecksum, _]}) -> - case ets:member(?PACKAGE_TABLE, {ec_cnv:to_binary(N), Vsn, <<"hexpm">>}) of + case ets:member(?PACKAGE_TABLE, {rebar_utils:to_binary(N), Vsn, <<"hexpm">>}) of false -> {ok, Parsed} = rebar_semver:parse_version(Vsn), - ets:insert(?PACKAGE_TABLE, #package{key={ec_cnv:to_binary(N), Parsed, <<"hexpm">>}, + ets:insert(?PACKAGE_TABLE, #package{key={rebar_utils:to_binary(N), Parsed, <<"hexpm">>}, dependencies=Deps, retired=false, inner_checksum=InnerChecksum, @@ -371,4 +393,4 @@ copy_to_cache({Pkg,Vsn}, Config) -> Name = <>, Source = filename:join(?config(data_dir, Config), Name), Dest = filename:join(?config(cache_dir, Config), Name), - ec_file:copy(Source, Dest). + rebar_file_utils:copy(Source, Dest). diff --git a/apps/rebar/test/rebar_pkg_alias_SUITE.erl b/apps/rebar/test/rebar_pkg_alias_SUITE.erl index 6aaea9c6f..eba2f9423 100644 --- a/apps/rebar/test/rebar_pkg_alias_SUITE.erl +++ b/apps/rebar/test/rebar_pkg_alias_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_pkg_alias_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). @@ -165,7 +187,7 @@ transitive_hash_mismatch(Config) -> [io:format(Io, "~p.~n", [Attr]) || Attr <- NewLock], file:close(Io), ct:pal("lock: ~p", [file:consult(Lockfile)]), - ec_file:remove(filename:join([AppDir, "_build"]), [recursive]), + file:del_dir_r(filename:join([AppDir, "_build"])), ?assertMatch( {error, {rebar_fetch, {unexpected_hash, _, _, _}}}, rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], return) @@ -227,10 +249,10 @@ mock_config(Name, Config) -> rebar_packages:new_package_table(), lists:foreach(fun({{N, Vsn}, [Deps, Checksum, _]}) -> - case ets:member(?PACKAGE_TABLE, {ec_cnv:to_binary(N), Vsn, <<"hexpm">>}) of + case ets:member(?PACKAGE_TABLE, {rebar_utils:to_binary(N), Vsn, <<"hexpm">>}) of false -> {ok, Parsed} = rebar_semver:parse_version(Vsn), - ets:insert(?PACKAGE_TABLE, #package{key={ec_cnv:to_binary(N), Parsed, <<"hexpm">>}, + ets:insert(?PACKAGE_TABLE, #package{key={rebar_utils:to_binary(N), Parsed, <<"hexpm">>}, dependencies=[{DAppName, {pkg, DN, DV, undefined}} || {DN, DV, _, DAppName} <- Deps], retired=false, outer_checksum=Checksum}); diff --git a/apps/rebar/test/rebar_pkg_repos_SUITE.erl b/apps/rebar/test/rebar_pkg_repos_SUITE.erl index 4cb5ee26a..7369bf2ce 100644 --- a/apps/rebar/test/rebar_pkg_repos_SUITE.erl +++ b/apps/rebar/test/rebar_pkg_repos_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + %% Test suite for the handling hexpm repo configurations -module(rebar_pkg_repos_SUITE). @@ -15,7 +37,8 @@ all() -> groups() -> [{resolve_version, [use_first_repo_match, use_exact_with_hash, fail_repo_update, ignore_match_in_excluded_repo, optional_prereleases, - or_in_prerelease + or_in_prerelease, check_all_repos_finds_local, + fallback_to_update_on_missing ]}]. init_per_group(resolve_version, Config) -> @@ -107,6 +130,44 @@ init_per_testcase(ignore_match_in_excluded_repo, Config) -> meck:expect(rebar_packages, verify_table, fun(_State) -> true end), + [{state, State} | Config]; +init_per_testcase(check_all_repos_finds_local, Config) -> + Deps = ?config(deps, Config), + Repos = ?config(repos, Config), + State = setup_deps_and_repos(Deps, Repos), + + meck:new(rebar_packages, [passthrough, no_link]), + + meck:expect(rebar_packages, update_package, + fun(_, _, _State) -> fail end), + meck:expect(rebar_packages, verify_table, + fun(_State) -> true end), + + [{state, State} | Config]; +init_per_testcase(fallback_to_update_on_missing, Config) -> + Repos = ?config(repos, Config), + %% Only insert deps that do NOT include D — D will be "fetched" by update_package + State = setup_deps_and_repos([], Repos), + + meck:new(rebar_packages, [passthrough, no_link]), + + %% Simulate update_package fetching D-1.0.0 into the ETS table on the first repo + [Repo1 | _] = Repos, + meck:expect(rebar_packages, update_package, + fun(<<"D">>, #{name := Repo}, _State) when Repo =:= Repo1 -> + {ok, Parsed} = rebar_semver:parse_version("1.0.0"), + ets:insert(?PACKAGE_TABLE, + #package{key={<<"D">>, Parsed, Repo}, + dependencies=[], + retired=false, + inner_checksum = <<"inner checksum">>, + outer_checksum = <<"outer checksum">>}), + ok; + (_, _, _State) -> fail + end), + meck:expect(rebar_packages, verify_table, + fun(_State) -> true end), + [{state, State} | Config]; init_per_testcase(Case, Config) when Case =:= optional_prereleases; Case =:= or_in_prerelease -> Deps = ?config(deps, Config), @@ -148,7 +209,9 @@ end_per_testcase(Case, _Config) when Case =:= use_first_repo_match ; Case =:= fail_repo_update ; Case =:= ignore_match_in_excluded_repo ; Case =:= optional_prereleases ; - Case =:= or_in_prerelease -> + Case =:= or_in_prerelease ; + Case =:= check_all_repos_finds_local ; + Case =:= fallback_to_update_on_missing -> meck:unload(rebar_packages); end_per_testcase(_, _) -> ok. @@ -391,7 +454,7 @@ use_first_repo_match(Config) -> ?assertMatch({ok,{package,{<<"B">>, {{1,4,0}, {[],[]}}, Repo3}, <<"inner checksum">>,<<"outer checksum">>, false, []}, - #{name := Repo3, + #{name := Repo3, http_adapter := {rebar_httpc_adapter, #{profile := rebar}}}}, rebar_packages:resolve_version(<<"B">>, <<"~> 1.4.0">>, undefined, undefined, ?PACKAGE_TABLE, State)). @@ -480,6 +543,20 @@ or_in_prerelease(Config) -> rebar_packages:resolve_version(<<"B">>, <<"~> 1.5.5-a-or-b.0">>, <<"inner checksum">>, <<"outer checksum">>, ?PACKAGE_TABLE, State1)). +check_all_repos_finds_local(Config) -> + State = ?config(state, Config), + + ?assertMatch({ok, {package, {<<"B">>, {{2,0,0}, {[],[]}}, _}, _, _, _, _}, _}, + rebar_packages:resolve_version(<<"B">>, <<"> 1.4.0">>, undefined, undefined, + ?PACKAGE_TABLE, State)). + +fallback_to_update_on_missing(Config) -> + State = ?config(state, Config), + + ?assertMatch({ok, {package, {<<"D">>, {{1,0,0}, {[],[]}}, _}, _, _, _, _}, _}, + rebar_packages:resolve_version(<<"D">>, <<"1.0.0">>, undefined, undefined, + ?PACKAGE_TABLE, State)). + %% setup_deps_and_repos(Deps, Repos) -> diff --git a/apps/rebar/test/rebar_release_SUITE.erl b/apps/rebar/test/rebar_release_SUITE.erl index dd6c33b1c..12fd30284 100644 --- a/apps/rebar/test/rebar_release_SUITE.erl +++ b/apps/rebar/test/rebar_release_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_release_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). @@ -22,7 +44,7 @@ init_per_testcase(Case, Config0) -> AppDir = ?config(apps, Config), application:load(rebar), - ok = ec_file:mkdir_p(AppDir), + ok = filelib:ensure_path(AppDir), State = rebar_state:new([{base_dir, filename:join([AppDir, "_build"])}]), rebar_test_utils:create_app(AppDir, Name, "1.0.0", [kernel, stdlib]), diff --git a/apps/rebar/test/rebar_resource_SUITE.erl b/apps/rebar/test/rebar_resource_SUITE.erl index ddacb91bb..4f4750c9e 100644 --- a/apps/rebar/test/rebar_resource_SUITE.erl +++ b/apps/rebar/test/rebar_resource_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_resource_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). @@ -28,7 +50,7 @@ init_per_testcase(change_type_upgrade, Config) -> Type = ?config(type, Config), TypeStr = atom_to_list(Type), DirName = filename:join([?config(priv_dir, Config), "resource_"++TypeStr]), - ec_file:mkdir_path(DirName), + filelib:ensure_path(DirName), {ok, AppInfo} = rebar_app_info:new(test_app, "0.0.1", DirName), AppInfo1 = rebar_app_info:source(AppInfo, ?config(resource, Config)), diff --git a/apps/rebar/test/rebar_src_dirs_SUITE.erl b/apps/rebar/test/rebar_src_dirs_SUITE.erl index bc221605e..5c7b8d7cb 100644 --- a/apps/rebar/test/rebar_src_dirs_SUITE.erl +++ b/apps/rebar/test/rebar_src_dirs_SUITE.erl @@ -1,3 +1,25 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_src_dirs_SUITE). -export([suite/0, @@ -165,7 +187,7 @@ build_basic_app(Config) -> Extra = filename:join([AppDir, "extra", "extra.erl"]), ok = filelib:ensure_dir(Extra), Src = io_lib:format("-module(extra).~n-export([x/0]).~nx() -> ok.", []), - ok = ec_file:write(Extra, Src), + ok = file:write_file(Extra, Src), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], @@ -200,12 +222,12 @@ build_multi_apps(Config) -> Extra1 = filename:join([AppDir, "apps", Name1, "extra", "extra1.erl"]), ok = filelib:ensure_dir(Extra1), Src1 = io_lib:format("-module(extra1).~n-export([x/0]).~nx() -> ok.", []), - ok = ec_file:write(Extra1, Src1), + ok = file:write_file(Extra1, Src1), Extra2 = filename:join([AppDir, "apps", Name2, "extra", "extra2.erl"]), ok = filelib:ensure_dir(Extra2), Src2 = io_lib:format("-module(extra2).~n-export([x/0]).~nx() -> ok.", []), - ok = ec_file:write(Extra2, Src2), + ok = file:write_file(Extra2, Src2), RebarConfig = [{erl_opts, [{extra_src_dirs, ["extra"]}]}], @@ -254,7 +276,7 @@ src_dir_takes_precedence_over_extra(Config) -> Extra = filename:join([AppDir, "extra", "extra.erl"]), ok = filelib:ensure_dir(Extra), Src = io_lib:format("-module(extra).~n-export([x/0]).~nx() -> ok.", []), - ok = ec_file:write(Extra, Src), + ok = file:write_file(Extra, Src), RebarConfig = [{erl_opts, [{src_dirs, ["src", "extra"]}, {extra_src_dirs, ["extra"]}]}], diff --git a/apps/rebar/test/rebar_test_utils.erl b/apps/rebar/test/rebar_test_utils.erl index 395698c99..afbcf5876 100644 --- a/apps/rebar/test/rebar_test_utils.erl +++ b/apps/rebar/test/rebar_test_utils.erl @@ -1,4 +1,27 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_test_utils). +-include_lib("kernel/include/file.hrl"). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -export([init_rebar_state/1, init_rebar_state/2, run_and_check/3, run_and_check/4, @@ -24,8 +47,8 @@ init_rebar_state(Config, Name) -> DataDir = ?config(priv_dir, Config), AppsDir = filename:join([DataDir, create_random_name(Name)]), CheckoutsDir = filename:join([AppsDir, "_checkouts"]), - ok = ec_file:mkdir_p(AppsDir), - ok = ec_file:mkdir_p(CheckoutsDir), + ok = filelib:ensure_path(AppsDir), + ok = filelib:ensure_path(CheckoutsDir), Verbosity = rebar3:log_level(), rebar_log:init(command_line, Verbosity), GlobalDir = filename:join([DataDir, "cache"]), @@ -162,7 +185,7 @@ create_config(AppDir, Contents) -> create_config(_AppDir, ConfFilename, Contents) -> ok = filelib:ensure_dir(ConfFilename), Config = lists:flatten([io_lib:fwrite("~p.~n", [Term]) || Term <- Contents]), - ok = ec_file:write(ConfFilename, Config), + ok = file:write_file(ConfFilename, Config), ConfFilename. %% @doc Util to create a random variation of a given name. @@ -268,19 +291,19 @@ check_results(AppDir, Expected, ProfileRun, State) -> InvalidApps = rebar_app_discover:find_apps(BuildDirs, invalid, State), ValidApps = rebar_app_discover:find_apps(BuildDirs, valid, State), - InvalidDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- InvalidApps], - ValidDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- ValidApps], + InvalidDepsNames = [{rebar_utils:to_list(rebar_app_info:name(App)), App} || App <- InvalidApps], + ValidDepsNames = [{rebar_utils:to_list(rebar_app_info:name(App)), App} || App <- ValidApps], Deps = rebar_app_discover:find_apps(BuildDirs, all, State), SubDeps = rebar_app_discover:find_apps(BuildSubDirs, all, State), - DepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Deps], - SubDirDepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- SubDeps], + DepsNames = [{rebar_utils:to_list(rebar_app_info:name(App)), App} || App <- Deps], + SubDirDepsNames = [{rebar_utils:to_list(rebar_app_info:name(App)), App} || App <- SubDeps], Checkouts = rebar_app_discover:find_apps(CheckoutsDirs, all, State), - CheckoutsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Checkouts], + CheckoutsNames = [{rebar_utils:to_list(rebar_app_info:name(App)), App} || App <- Checkouts], Plugins = rebar_app_discover:find_apps(PluginDirs, all, State), - PluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Plugins], + PluginsNames = [{rebar_utils:to_list(rebar_app_info:name(App)), App} || App <- Plugins], GlobalPlugins = rebar_app_discover:find_apps(GlobalPluginDirs, all, State), - GlobalPluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- GlobalPlugins], + GlobalPluginsNames = [{rebar_utils:to_list(rebar_app_info:name(App)), App} || App <- GlobalPlugins], lists:foreach( fun({app, Name}) -> @@ -432,11 +455,14 @@ check_results(AppDir, Expected, ProfileRun, State) -> {ok, RelLibs} = rebar_utils:list_dir(LibDir), IsSymLinkFun = fun(X) -> - ec_file:is_symlink(filename:join(LibDir, X)) + case file:read_link_info(filename:join(LibDir, X)) of + {ok, #file_info{type = symlink}} -> true; + _ -> false + end end, DevMode = lists:all(IsSymLinkFun, RelLibs), ?assertEqual(ExpectedDevMode, DevMode), - ?assert(ec_file:exists(filename:join([ReleaseDir, Name, "releases", Vsn]))), + ?assert(filelib:is_file(filename:join([ReleaseDir, Name, "releases", Vsn]))), %% throws not_found if it doesn't exist ok @@ -461,32 +487,34 @@ check_results(AppDir, Expected, ProfileRun, State) -> write_plugin_file(Dir, Name) -> Erl = filename:join([Dir, "src", Name]), ok = filelib:ensure_dir(Erl), - ok = ec_file:write(Erl, plugin_src_file(Name)). + ok = file:write_file(Erl, plugin_src_file(Name)). write_src_file(Dir, Name) -> Erl = filename:join([Dir, "src", Name]), ok = filelib:ensure_dir(Erl), - ok = ec_file:write(Erl, erl_src_file(Name)). + ok = file:write_file(Erl, erl_src_file(Name)). write_eunitized_src_file(Dir, Name) -> Erl = filename:join([Dir, "src", "not_a_real_src_" ++ Name ++ ".erl"]), ok = filelib:ensure_dir(Erl), - ok = ec_file:write(Erl, erl_eunitized_src_file("not_a_real_src_" ++ Name ++ ".erl")). + ok = file:write_file(Erl, erl_eunitized_src_file("not_a_real_src_" ++ Name ++ ".erl")). write_eunit_suite_file(Dir, Name) -> Erl = filename:join([Dir, "test", "not_a_real_src_" ++ Name ++ "_tests.erl"]), ok = filelib:ensure_dir(Erl), - ok = ec_file:write(Erl, erl_eunit_suite_file("not_a_real_src_" ++ Name ++ ".erl")). + ok = file:write_file(Erl, erl_eunit_suite_file("not_a_real_src_" ++ Name ++ ".erl")). write_app_file(Dir, Name, Version, Deps) -> Filename = filename:join([Dir, "ebin", Name ++ ".app"]), ok = filelib:ensure_dir(Filename), - ok = ec_file:write_term(Filename, get_app_metadata(ec_cnv:to_list(Name), Version, Deps)). + Term = get_app_metadata(rebar_utils:to_list(Name), Version, Deps), + ok = file:write_file(Filename, lists:flatten(io_lib:fwrite("~p. ", [Term]))). write_app_src_file(Dir, Name, Version, Deps) -> Filename = filename:join([Dir, "src", Name ++ ".app.src"]), ok = filelib:ensure_dir(Filename), - ok = ec_file:write_term(Filename, get_app_metadata(ec_cnv:to_list(Name), Version, Deps)). + Term = get_app_metadata(rebar_utils:to_list(Name), Version, Deps), + ok = file:write_file(Filename, lists:flatten(io_lib:fwrite("~p. ", [Term]))). erl_src_file(Name) -> io_lib:format("-module('~s').\n" diff --git a/apps/rebar/test/rebar_unlock_SUITE.erl b/apps/rebar/test/rebar_unlock_SUITE.erl index 67692d249..a2e3473ee 100644 --- a/apps/rebar/test/rebar_unlock_SUITE.erl +++ b/apps/rebar/test/rebar_unlock_SUITE.erl @@ -8,13 +8,13 @@ all() -> [pkgunlock, unlock, unlock_all, unlock_no_args]. init_per_testcase(pkgunlock, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0, "pkgunlock"), Lockfile = filename:join(?config(apps, Config), "rebar.lock"), - ec_file:copy(filename:join(?config(data_dir, Config), "pkg.rebar.lock"), + rebar_file_utils:copy(filename:join(?config(data_dir, Config), "pkg.rebar.lock"), Lockfile), [{lockfile, Lockfile} | Config]; init_per_testcase(Case, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0, atom_to_list(Case)), Lockfile = filename:join(?config(apps, Config), "rebar.lock"), - ec_file:copy(filename:join(?config(data_dir, Config), "rebar.lock"), + rebar_file_utils:copy(filename:join(?config(data_dir, Config), "rebar.lock"), Lockfile), [{lockfile, Lockfile} | Config]. diff --git a/apps/rebar/test/rebar_xref_SUITE.erl b/apps/rebar/test/rebar_xref_SUITE.erl index 42d9eedcd..225974729 100644 --- a/apps/rebar/test/rebar_xref_SUITE.erl +++ b/apps/rebar/test/rebar_xref_SUITE.erl @@ -1,5 +1,28 @@ %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 et + +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2015-2026 Rebar3 and its contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% + -module(rebar_xref_SUITE). -export([suite/0, @@ -199,7 +222,7 @@ verify_test_results(xref_ignore_test, AppName, XrefResults, _QueryResults) -> write_src_file(Dir, AppName, Module, IgnoreXref) -> Erl = filename:join([Dir, "src", module_name(AppName, Module)]), ok = filelib:ensure_dir(Erl), - ok = ec_file:write(Erl, get_module_body(Module, AppName, IgnoreXref)). + ok = file:write_file(Erl, get_module_body(Module, AppName, IgnoreXref)). delete_src_file(Dir, AppName, Module) -> Erl = filename:join([Dir, "src", module_name(AppName, Module)]), diff --git a/bootstrap b/bootstrap index 73e086900..829fba5f6 100755 --- a/bootstrap +++ b/bootstrap @@ -44,7 +44,6 @@ main(Args) -> BaseDeps = [{providers, []} ,{getopt, []} ,{cf, []} - ,{erlware_commons, ["ec_dictionary.erl", "ec_vsn.erl"]} ,{certifi, ["certifi_pt.erl"]}], Deps = get_deps(), [fetch_and_compile(Dep, Deps) || Dep <- BaseDeps], @@ -94,11 +93,6 @@ fetch_and_compile({Name, ErlFirstFiles}, Deps) -> [cp_r([DepDir], "_build/default/lib/") || {Dep, DepDir} <- Deps, atom_to_list(Name) =:= Dep], - %% Hack: erlware_commons depends on a .script file to check if it is being built with - %% rebar2 or rebar3. But since rebar3 isn't built yet it can't get the vsn with get_key. - %% So we simply make sure that file is deleted before compiling - file:delete("_build/default/lib/erlware_commons/rebar.config.script"), - compile(Name, ErlFirstFiles). get_rebar_config() -> diff --git a/rebar.config b/rebar.config index 16645f71c..57660f2d4 100644 --- a/rebar.config +++ b/rebar.config @@ -20,8 +20,7 @@ {escript_incl_priv, [{relx, "templates/*"}, {rebar, "templates/*"}]}. -{overrides, [{override, erlware_commons, [{erl_opts, [nowarn_deprecated_catch]}]}, - {add, relx, [{erl_opts, [{d, 'RLX_LOG', rebar_log}]}]}]}. +{overrides, [{add, relx, [{erl_opts, [{d, 'RLX_LOG', rebar_log}]}]}]}. {profiles, [ %% Only works at the top-level @@ -35,7 +34,7 @@ %% Ignore deps known to generate warnings {dialyzer, [{warnings, [no_unknown]}, {plt_extra_apps, [parsetools, public_key]}, - {exclude_apps, [cth_readable, erlware_commons, relx]}]} + {exclude_apps, [cth_readable, relx]}]} ]}, %% Duplicated from apps/rebar3: %% - we don't want the test profile applied to our vendored deps. @@ -48,10 +47,6 @@ {prod, [ {erl_opts, [no_debug_info]}, {overrides, [ - {override, erlware_commons, [ - {erl_opts, [no_debug_info, - warnings_as_errors]}, - {deps, []}, {plugins, []}]}, {add, ssl_verify_hostname, [{erl_opts, [no_debug_info]}]}, {add, certifi, [{erl_opts, [no_debug_info]}]}, {add, cf, [{erl_opts, [no_debug_info]}]}, diff --git a/vendor/cf/hex_metadata.config b/vendor/cf/hex_metadata.config index f12ec2d4d..00efa27d0 100644 --- a/vendor/cf/hex_metadata.config +++ b/vendor/cf/hex_metadata.config @@ -1,3 +1,13 @@ +%% %CopyrightBegin% +%% +%% SPDX-License-Identifier: Apache-2.0 +%% +%% SPDX-FileCopyrightText: Copyright 2014-2021 Tristan Sloughter and Contributors +%% +%% SPDX-FileCopyrightText: Copyright 2026 Dipl. Phys. Peer Stritzinger GmbH +%% +%% %CopyrightEnd% + {<<"name">>,<<"cf">>}. {<<"version">>,<<"0.3.1">>}. {<<"requirements">>,#{}}. diff --git a/vendor/erlware_commons/README.md b/vendor/erlware_commons/README.md deleted file mode 100644 index 3e9f19346..000000000 --- a/vendor/erlware_commons/README.md +++ /dev/null @@ -1,143 +0,0 @@ -Erlware Commons -=============== - -Current Status --------------- - -[![Hex.pm](https://img.shields.io/hexpm/v/erlware_commons)](https://hex.pm/packages/erlware_commons) -[![Tests](https://github.com/erlware/erlware_commons/workflows/EUnit/badge.svg)](https://github.com/erlware/erlware_commons/actions) - -Introduction ------------- - -Erlware commons can best be described as an extension to the stdlib -application that is distributed with Erlang. These are things that we -at Erlware have found useful for production applications but are not -included with the distribution. We hope that as things in this library -prove themselves useful, they will make their way into the main Erlang -distribution. However, whether they do or not, we hope that this -application will prove generally useful. - -Goals for the project ---------------------- - -* Generally Useful Code -* High Quality -* Well Documented -* Well Tested - -Licenses --------- - -This project contains elements licensed with Apache License, Version 2.0, -as well as elements licensed with The MIT License. - -You'll find license-related information in the header of specific files, -where warranted. - -In cases where no such information is present refer to -[COPYING](COPYING). - -Currently Available Modules/Systems ------------------------------------- - -### [ec_date](https://github.com/erlware/erlware_commons/blob/master/src/ec_date.erl) - -This module formats erlang dates in the form {{Year, Month, Day}, -{Hour, Minute, Second}} to printable strings, using (almost) -equivalent formatting rules as http://uk.php.net/date, US vs European -dates are disambiguated in the same way as -http://uk.php.net/manual/en/function.strtotime.php That is, Dates in -the m/d/y or d-m-y formats are disambiguated by looking at the -separator between the various components: if the separator is a slash -(/), then the American m/d/y is assumed; whereas if the separator is a -dash (-) or a dot (.), then the European d-m-y format is assumed. To -avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) -dates. - -erlang has no concept of timezone so the following formats are not -implemented: B e I O P T Z formats c and r will also differ slightly - -### [ec_file](https://github.com/erlware/erlware_commons/blob/master/src/ec_file.erl) - -A set of commonly defined helper functions for files that are not -included in stdlib. - -### [ec_plists](https://github.com/erlware/erlware_commons/blob/master/src/ec_plists.erl) - -plists is a drop-in replacement for module lists, making most -list operations parallel. It can operate on each element in parallel, -for IO-bound operations, on sublists in parallel, for taking advantage -of multi-core machines with CPU-bound operations, and across erlang -nodes, for parallelizing inside a cluster. It handles errors and node -failures. It can be configured, tuned, and tweaked to get optimal -performance while minimizing overhead. - -Almost all the functions are identical to equivalent functions in -lists, returning exactly the same result, and having both a form with -an identical syntax that operates on each element in parallel and a -form which takes an optional "malt", a specification for how to -parallelize the operation. - -fold is the one exception, parallel fold is different from linear -fold. This module also include a simple mapreduce implementation, and -the function runmany. All the other functions are implemented with -runmany, which is as a generalization of parallel list operations. - -### [ec_semver](https://github.com/erlware/erlware_commons/blob/master/src/ec_semver.erl) - -A complete parser for the [semver](http://semver.org/) -standard. Including a complete set of conforming comparison functions. - -### [ec_lists](https://github.com/erlware/erlware_commons/blob/master/src/ec_lists.erl) - -A set of additional list manipulation functions designed to supliment -the `lists` module in stdlib. - -### [ec_talk](https://github.com/erlware/erlware_commons/blob/master/src/ec_talk.erl) - -A set of simple utility functions to facilitate command line -communication with a user. - -Signatures ------------ - -Other languages, have built in support for **Interface** or -**signature** functionality. Java has Interfaces, SML has -Signatures. Erlang, though, doesn't currently support this model, at -least not directly. There are a few ways you can approximate it. We -have defined a mechanism called *signatures* and several modules that -to serve as examples and provide a good set of *dictionary* -signatures. More information about signatures can be found at -[signature](https://github.com/erlware/erlware_commons/blob/master/doc/signatures.md). - - -### [ec_dictionary](https://github.com/erlware/erlware_commons/blob/master/src/ec_dictionary.erl) - -A signature that supports association of keys to values. A map cannot -contain duplicate keys; each key can map to at most one value. - -### [ec_dict](https://github.com/erlware/erlware_commons/blob/master/src/ec_dict.erl) - -This provides an implementation of the ec_dictionary signature using -erlang's dicts as a base. The function documentation for ec_dictionary -applies here as well. - -### [ec_gb_trees](https://github.com/erlware/erlware_commons/blob/master/src/ec_gb_trees.erl) - -This provides an implementation of the ec_dictionary signature using -erlang's gb_trees as a base. The function documentation for -ec_dictionary applies here as well. - -### [ec_orddict](https://github.com/erlware/erlware_commons/blob/master/src/ec_orddict.erl) - -This provides an implementation of the ec_dictionary signature using -erlang's orddict as a base. The function documentation for -ec_dictionary applies here as well. - -### [ec_rbdict](https://github.com/erlware/erlware_commons/blob/master/src/ec_rbdict.erl) - -This provides an implementation of the ec_dictionary signature using -Robert Virding's rbdict module as a base. The function documentation -for ec_dictionary applies here as well. diff --git a/vendor/erlware_commons/hex_metadata.config b/vendor/erlware_commons/hex_metadata.config deleted file mode 100644 index 29084e45d..000000000 --- a/vendor/erlware_commons/hex_metadata.config +++ /dev/null @@ -1,25 +0,0 @@ -{<<"app">>,<<"erlware_commons">>}. -{<<"build_tools">>,[<<"rebar3">>]}. -{<<"description">>,<<"Additional standard library for Erlang">>}. -{<<"files">>, - [<<"README.md">>,<<"include">>,<<"include/ec_cmd_log.hrl">>,<<"priv">>, - <<"priv/ec_semver_parser.peg">>,<<"rebar.config">>, - <<"rebar.config.script">>,<<"rebar.lock">>,<<"src">>, - <<"src/ec_assoc_list.erl">>,<<"src/ec_cmd_log.erl">>, - <<"src/ec_cmd_log.hrl">>,<<"src/ec_cnv.erl">>,<<"src/ec_compile.erl">>, - <<"src/ec_date.erl">>,<<"src/ec_dict.erl">>,<<"src/ec_dictionary.erl">>, - <<"src/ec_file.erl">>,<<"src/ec_gb_trees.erl">>,<<"src/ec_git_vsn.erl">>, - <<"src/ec_lists.erl">>,<<"src/ec_orddict.erl">>,<<"src/ec_plists.erl">>, - <<"src/ec_rbdict.erl">>,<<"src/ec_semver.erl">>, - <<"src/ec_semver_parser.erl">>,<<"src/ec_talk.erl">>,<<"src/ec_vsn.erl">>, - <<"src/erlware_commons.app.src">>]}. -{<<"licenses">>,[<<"Apache">>,<<"MIT">>]}. -{<<"links">>, - [{<<"Github">>,<<"https://github.com/erlware/erlware_commons">>}]}. -{<<"name">>,<<"erlware_commons">>}. -{<<"requirements">>, - [{<<"cf">>, - [{<<"app">>,<<"cf">>}, - {<<"optional">>,false}, - {<<"requirement">>,<<"~>0.3">>}]}]}. -{<<"version">>,<<"1.8.0">>}. diff --git a/vendor/erlware_commons/include/ec_cmd_log.hrl b/vendor/erlware_commons/include/ec_cmd_log.hrl deleted file mode 100644 index 170d399c8..000000000 --- a/vendor/erlware_commons/include/ec_cmd_log.hrl +++ /dev/null @@ -1,24 +0,0 @@ -%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- -%%% Copyright 2012 Erlware, LLC. All Rights Reserved. -%%% -%%% This file is provided to you under the Apache License, -%%% Version 2.0 (the "License"); you may not use this file -%%% except in compliance with the License. You may obtain -%%% a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, -%%% software distributed under the License is distributed on an -%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -%%% KIND, either express or implied. See the License for the -%%% specific language governing permissions and limitations -%%% under the License. -%%%--------------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright (C) 2012 Erlware, LLC. - --define(EC_ERROR, 0). --define(EC_WARN, 1). --define(EC_INFO, 2). --define(EC_DEBUG, 3). diff --git a/vendor/erlware_commons/priv/ec_semver_parser.peg b/vendor/erlware_commons/priv/ec_semver_parser.peg deleted file mode 100644 index d0444a667..000000000 --- a/vendor/erlware_commons/priv/ec_semver_parser.peg +++ /dev/null @@ -1,9 +0,0 @@ -semver <- major_minor_patch_min_patch ("-" alpha_part ("." alpha_part)*)? ("+" alpha_part ("." alpha_part)*)? !. - ` ec_semver:internal_parse_version(Node) ` ; - -major_minor_patch_min_patch <- ("v"? numeric_part / alpha_part) ("." version_part)? ("." version_part)? ("." version_part)? ; - -version_part <- numeric_part / alpha_part ; - -numeric_part <- [0-9]+ `erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node)))` ; -alpha_part <- [A-Za-z0-9]+ `erlang:iolist_to_binary(Node)` ; diff --git a/vendor/erlware_commons/rebar.config b/vendor/erlware_commons/rebar.config deleted file mode 100644 index 017e3fec8..000000000 --- a/vendor/erlware_commons/rebar.config +++ /dev/null @@ -1,24 +0,0 @@ -%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- - -%% Dependencies ================================================================ -{deps, [ - {cf, "~>0.3"} -]}. - -{erl_first_files, ["ec_dictionary", "ec_vsn"]}. - -%% Compiler Options ============================================================ -{erl_opts, [debug_info, warnings_as_errors]}. - -%% EUnit ======================================================================= -{eunit_opts, [verbose, - {report, {eunit_surefire, [{dir, "."}]}}]}. - -{cover_enabled, true}. -{cover_print_enabled, true}. - -%% Profiles ==================================================================== -{profiles, [{dev, [{deps, - [{neotoma, "", - {git, "https://github.com/seancribbs/neotoma.git", {branch, master}}}]}]} - ]}. diff --git a/vendor/erlware_commons/rebar.config.script b/vendor/erlware_commons/rebar.config.script deleted file mode 100644 index cc054a80a..000000000 --- a/vendor/erlware_commons/rebar.config.script +++ /dev/null @@ -1,7 +0,0 @@ -NoDialWarns = {dialyzer, [{warnings, [no_unknown]}]}, -OTPRelease = erlang:list_to_integer(erlang:system_info(otp_release)), - -case OTPRelease<26 of - true -> CONFIG; - false -> lists:keystore(dialyzer, 1, CONFIG, NoDialWarns) -end. diff --git a/vendor/erlware_commons/rebar.lock b/vendor/erlware_commons/rebar.lock deleted file mode 100644 index 7873d25f1..000000000 --- a/vendor/erlware_commons/rebar.lock +++ /dev/null @@ -1,8 +0,0 @@ -{"1.2.0", -[{<<"cf">>,{pkg,<<"cf">>,<<"0.3.1">>},0}]}. -[ -{pkg_hash,[ - {<<"cf">>, <<"5CB902239476E141EA70A740340233782D363A31EEA8AD37049561542E6CD641">>}]}, -{pkg_hash_ext,[ - {<<"cf">>, <<"315E8D447D3A4B02BCDBFA397AD03BBB988A6E0AA6F44D3ADD0F4E3C3BF97672">>}]} -]. diff --git a/vendor/erlware_commons/src/ec_assoc_list.erl b/vendor/erlware_commons/src/ec_assoc_list.erl deleted file mode 100644 index 9921f5556..000000000 --- a/vendor/erlware_commons/src/ec_assoc_list.erl +++ /dev/null @@ -1,106 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright 2011 Erlware, LLC. -%%% @doc -%%% provides an implementation of ec_dictionary using an association -%%% list as a basy -%%% see ec_dictionary -%%% @end -%%%------------------------------------------------------------------- --module(ec_assoc_list). - --behaviour(ec_dictionary). - -%% API --export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). - --export_type([dictionary/2]). - -%%%=================================================================== -%%% Types -%%%=================================================================== -%% This should be opaque, but that kills dialyzer so for now we export it -%% however you should not rely on the internal representation here --type dictionary(K, V) :: {ec_assoc_list, - [{ec_dictionary:key(K), ec_dictionary:value(V)}]}. - -%%%=================================================================== -%%% API -%%%=================================================================== - --spec new() -> dictionary(_K, _V). -new() -> - {ec_assoc_list, []}. - --spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). -has_key(Key, {ec_assoc_list, Data}) -> - lists:keymember(Key, 1, Data). - --spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> - ec_dictionary:value(V). -get(Key, {ec_assoc_list, Data}) -> - case lists:keyfind(Key, 1, Data) of - {Key, Value} -> - Value; - false -> - throw(not_found) - end. - --spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - Object::dictionary(K, V)) -> - ec_dictionary:value(V). -get(Key, Default, {ec_assoc_list, Data}) -> - case lists:keyfind(Key, 1, Data) of - {Key, Value} -> - Value; - false -> - Default - end. - --spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::dictionary(K, V)) -> - dictionary(K, V). -add(Key, Value, {ec_assoc_list, _Data}=Dict) -> - {ec_assoc_list, Rest} = remove(Key,Dict), - {ec_assoc_list, [{Key, Value} | Rest ]}. - --spec remove(ec_dictionary:key(K), Object::dictionary(K, _V)) -> - dictionary(K, _V). -remove(Key, {ec_assoc_list, Data}) -> - {ec_assoc_list, lists:keydelete(Key, 1, Data)}. - --spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). -has_value(Value, {ec_assoc_list, Data}) -> - lists:keymember(Value, 2, Data). - --spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). -size({ec_assoc_list, Data}) -> - length(Data). - --spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), - ec_dictionary:value(V)}]. -to_list({ec_assoc_list, Data}) -> - Data. - --spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - dictionary(K, V). -from_list(List) when is_list(List) -> - {ec_assoc_list, List}. - --spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. -keys({ec_assoc_list, Data}) -> - lists:map(fun({Key, _Value}) -> - Key - end, Data). diff --git a/vendor/erlware_commons/src/ec_cmd_log.erl b/vendor/erlware_commons/src/ec_cmd_log.erl deleted file mode 100644 index 15267a7a3..000000000 --- a/vendor/erlware_commons/src/ec_cmd_log.erl +++ /dev/null @@ -1,257 +0,0 @@ -%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- -%%% Copyright 2012 Erlware, LLC. All Rights Reserved. -%%% -%%% This file is provided to you under the Apache License, -%%% Version 2.0 (the "License"); you may not use this file -%%% except in compliance with the License. You may obtain -%%% a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, -%%% software distributed under the License is distributed on an -%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -%%% KIND, either express or implied. See the License for the -%%% specific language governing permissions and limitations -%%% under the License. -%%%--------------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright (C) 2012 Erlware, LLC. -%%% -%%% @doc This provides simple output functions for command line apps. You should -%%% use this to talk to the users if you are writing code for the system --module(ec_cmd_log). - -%% Avoid clashing with `error/3` BIF added in Erlang/OTP 24 --compile({no_auto_import,[error/3]}). - --export([new/1, - new/2, - new/3, - log/4, - should/2, - debug/2, - debug/3, - info/2, - info/3, - error/2, - error/3, - warn/2, - warn/3, - log_level/1, - atom_log_level/1, - colorize/4, - format/1]). - --include_lib("erlware_commons/include/ec_cmd_log.hrl"). --include("ec_cmd_log.hrl"). - --define(PREFIX, "===> "). - --record(state_t, {log_level=0 :: int_log_level(), - caller=api :: caller(), - intensity=low :: intensity()}). - -%%============================================================================ -%% types -%%============================================================================ --export_type([t/0, - int_log_level/0, - atom_log_level/0, - log_level/0, - caller/0, - log_fun/0]). - --type caller() :: api | command_line. - --type log_level() :: int_log_level() | atom_log_level(). - --type int_log_level() :: 0..3. - --type atom_log_level() :: error | warn | info | debug. - --type intensity() :: none | low | high. - --type log_fun() :: fun(() -> iolist()). - --type color() :: char(). - --opaque t() :: #state_t{}. - -%%============================================================================ -%% API -%%============================================================================ -%% @doc Create a new 'log level' for the system --spec new(log_level()) -> t(). -new(LogLevel) -> - new(LogLevel, api). - --spec new(log_level(), caller()) -> t(). -new(LogLevel, Caller) -> - new(LogLevel, Caller, high). - - --spec new(log_level(), caller(), intensity()) -> t(). -new(LogLevel, Caller, Intensity) when (Intensity =:= none orelse - Intensity =:= low orelse - Intensity =:= high), - LogLevel >= 0, LogLevel =< 3 -> - #state_t{log_level=LogLevel, caller=Caller, - intensity=Intensity}; -new(AtomLogLevel, Caller, Intensity) - when AtomLogLevel =:= error; - AtomLogLevel =:= warn; - AtomLogLevel =:= info; - AtomLogLevel =:= debug -> - LogLevel = case AtomLogLevel of - error -> 0; - warn -> 1; - info -> 2; - debug -> 3 - end, - new(LogLevel, Caller, Intensity). - - -%% @doc log at the debug level given the current log state with a string or -%% function that returns a string --spec debug(t(), string() | log_fun()) -> ok. -debug(LogState, Fun) - when erlang:is_function(Fun) -> - log(LogState, ?EC_DEBUG, fun() -> - colorize(LogState, ?CYAN, false, Fun()) - end); -debug(LogState, String) -> - debug(LogState, "~ts~n", [String]). - -%% @doc log at the debug level given the current log state with a format string -%% and arguments @see io:format/2 --spec debug(t(), string(), [any()]) -> ok. -debug(LogState, FormatString, Args) -> - log(LogState, ?EC_DEBUG, colorize(LogState, ?CYAN, false, FormatString), Args). - -%% @doc log at the info level given the current log state with a string or -%% function that returns a string --spec info(t(), string() | log_fun()) -> ok. -info(LogState, Fun) - when erlang:is_function(Fun) -> - log(LogState, ?EC_INFO, fun() -> - colorize(LogState, ?GREEN, false, Fun()) - end); -info(LogState, String) -> - info(LogState, "~ts~n", [String]). - -%% @doc log at the info level given the current log state with a format string -%% and arguments @see io:format/2 --spec info(t(), string(), [any()]) -> ok. -info(LogState, FormatString, Args) -> - log(LogState, ?EC_INFO, colorize(LogState, ?GREEN, false, FormatString), Args). - -%% @doc log at the error level given the current log state with a string or -%% format string that returns a function --spec error(t(), string() | log_fun()) -> ok. -error(LogState, Fun) - when erlang:is_function(Fun) -> - log(LogState, ?EC_ERROR, fun() -> - colorize(LogState, ?RED, false, Fun()) - end); -error(LogState, String) -> - error(LogState, "~ts~n", [String]). - -%% @doc log at the error level given the current log state with a format string -%% and arguments @see io:format/2 --spec error(t(), string(), [any()]) -> ok. -error(LogState, FormatString, Args) -> - log(LogState, ?EC_ERROR, colorize(LogState, ?RED, false, FormatString), Args). - -%% @doc log at the warn level given the current log state with a string or -%% format string that returns a function --spec warn(t(), string() | log_fun()) -> ok. -warn(LogState, Fun) - when erlang:is_function(Fun) -> - log(LogState, ?EC_WARN, fun() -> colorize(LogState, ?MAGENTA, false, Fun()) end); -warn(LogState, String) -> - warn(LogState, "~ts~n", [String]). - -%% @doc log at the warn level given the current log state with a format string -%% and arguments @see io:format/2 --spec warn(t(), string(), [any()]) -> ok. -warn(LogState, FormatString, Args) -> - log(LogState, ?EC_WARN, colorize(LogState, ?MAGENTA, false, FormatString), Args). - -%% @doc Execute the fun passed in if log level is as expected. --spec log(t(), int_log_level(), log_fun()) -> ok. -log(#state_t{log_level=DetailLogLevel}, LogLevel, Fun) - when DetailLogLevel >= LogLevel -> - io:format("~ts~n", [Fun()]); -log(_, _, _) -> - ok. - -%% @doc when the module log level is less then or equal to the log level for the -%% call then write the log info out. When its not then ignore the call. --spec log(t(), int_log_level(), string(), [any()]) -> ok. -log(#state_t{log_level=DetailLogLevel}, LogLevel, FormatString, Args) - when DetailLogLevel >= LogLevel, - erlang:is_list(Args) -> - io:format(FormatString, Args); -log(_, _, _, _) -> - ok. - -%% @doc return a boolean indicating if the system should log for the specified -%% levelg --spec should(t(), int_log_level() | any()) -> boolean(). -should(#state_t{log_level=DetailLogLevel}, LogLevel) - when DetailLogLevel >= LogLevel -> - true; -should(_, _) -> - false. - -%% @doc get the current log level as an integer --spec log_level(t()) -> int_log_level(). -log_level(#state_t{log_level=DetailLogLevel}) -> - DetailLogLevel. - -%% @doc get the current log level as an atom --spec atom_log_level(t()) -> atom_log_level(). -atom_log_level(#state_t{log_level=?EC_ERROR}) -> - error; -atom_log_level(#state_t{log_level=?EC_WARN}) -> - warn; -atom_log_level(#state_t{log_level=?EC_INFO}) -> - info; -atom_log_level(#state_t{log_level=?EC_DEBUG}) -> - debug. - --spec format(t()) -> iolist(). -format(Log) -> - [<<"(">>, - ec_cnv:to_binary(log_level(Log)), <<":">>, - ec_cnv:to_binary(atom_log_level(Log)), - <<")">>]. - --spec colorize(t(), color(), boolean(), string()) -> string(). - --define(VALID_COLOR(C), - C =:= $r orelse C =:= $g orelse C =:= $y orelse - C =:= $b orelse C =:= $m orelse C =:= $c orelse - C =:= $R orelse C =:= $G orelse C =:= $Y orelse - C =:= $B orelse C =:= $M orelse C =:= $C). - -colorize(#state_t{intensity=none}, _, _, Msg) -> - Msg; -%% When it is supposed to be bold and we already have a uppercase -%% (bold color) we don't need to modify the color -colorize(State, Color, true, Msg) when ?VALID_COLOR(Color), - Color >= $A, Color =< $Z -> - colorize(State, Color, false, Msg); -%% We're sneaky we can subtract 32 to get the uppercase character if we want -%% bold but have a non bold color. -colorize(State, Color, true, Msg) when ?VALID_COLOR(Color) -> - colorize(State, Color - 32, false, Msg); -colorize(#state_t{caller=command_line, intensity = high}, - Color, false, Msg) when ?VALID_COLOR(Color) -> - lists:flatten(cf:format("~!" ++ [Color] ++"~ts~ts", [?PREFIX, Msg])); -colorize(#state_t{caller=command_line, intensity = low}, - Color, false, Msg) when ?VALID_COLOR(Color) -> - lists:flatten(cf:format("~!" ++ [Color] ++"~ts~!!~ts", [?PREFIX, Msg])); -colorize(_LogState, _Color, _Bold, Msg) -> - Msg. diff --git a/vendor/erlware_commons/src/ec_cmd_log.hrl b/vendor/erlware_commons/src/ec_cmd_log.hrl deleted file mode 100644 index 428fd7491..000000000 --- a/vendor/erlware_commons/src/ec_cmd_log.hrl +++ /dev/null @@ -1,7 +0,0 @@ -%%% @copyright 2024 Erlware, LLC. --define(RED, $r). --define(GREEN, $g). --define(YELLOW, $y). --define(BLUE, $b). --define(MAGENTA, $m). --define(CYAN, $c). diff --git a/vendor/erlware_commons/src/ec_cnv.erl b/vendor/erlware_commons/src/ec_cnv.erl deleted file mode 100644 index bc3b3f35b..000000000 --- a/vendor/erlware_commons/src/ec_cnv.erl +++ /dev/null @@ -1,214 +0,0 @@ -%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 80 -*- -%%% Copyright 2012 Erlware, LLC. All Rights Reserved. -%%% -%%% This file is provided to you under the Apache License, -%%% Version 2.0 (the "License"); you may not use this file -%%% except in compliance with the License. You may obtain -%%% a copy of the License at -%%% -%%% http://www.apache.org/licenses/LICENSE-2.0 -%%% -%%% Unless required by applicable law or agreed to in writing, -%%% software distributed under the License is distributed on an -%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -%%% KIND, either express or implied. See the License for the -%%% specific language governing permissions and limitations -%%% under the License. -%%%--------------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright (C) 2012 Erlware, LLC. -%%% --module(ec_cnv). - -%% API --export([to_integer/1, - to_integer/2, - to_float/1, - to_float/2, - to_number/1, - to_list/1, - to_binary/1, - to_atom/1, - to_boolean/1, - is_true/1, - is_false/1]). - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc -%% Automatic conversion of a term into integer type. The conversion -%% will round a float value if nonstrict is specified otherwise badarg --spec to_integer(string() | binary() | integer() | float()) -> - integer(). -to_integer(X)-> - to_integer(X, nonstrict). - --spec to_integer(string() | binary() | integer() | float(), - strict | nonstrict) -> - integer(). -to_integer(X, strict) - when erlang:is_float(X) -> - erlang:error(badarg); -to_integer(X, nonstrict) - when erlang:is_float(X) -> - erlang:round(X); -to_integer(X, S) - when erlang:is_binary(X) -> - to_integer(erlang:binary_to_list(X), S); -to_integer(X, S) - when erlang:is_list(X) -> - try erlang:list_to_integer(X) of - Result -> - Result - catch - error:badarg when S =:= nonstrict -> - erlang:round(erlang:list_to_float(X)) - end; -to_integer(X, _) - when erlang:is_integer(X) -> - X. - -%% @doc -%% Automatic conversion of a term into float type. badarg if strict -%% is defined and an integer value is passed. --spec to_float(string() | binary() | integer() | float()) -> - float(). -to_float(X) -> - to_float(X, nonstrict). - --spec to_float(string() | binary() | integer() | float(), - strict | nonstrict) -> - float(). -to_float(X, S) when is_binary(X) -> - to_float(erlang:binary_to_list(X), S); -to_float(X, S) - when erlang:is_list(X) -> - try erlang:list_to_float(X) of - Result -> - Result - catch - error:badarg when S =:= nonstrict -> - erlang:list_to_integer(X) * 1.0 - end; -to_float(X, strict) when - erlang:is_integer(X) -> - erlang:error(badarg); -to_float(X, nonstrict) - when erlang:is_integer(X) -> - X * 1.0; -to_float(X, _) when erlang:is_float(X) -> - X. - -%% @doc -%% Automatic conversion of a term into number type. --spec to_number(binary() | string() | number()) -> - number(). -to_number(X) - when erlang:is_number(X) -> - X; -to_number(X) - when erlang:is_binary(X) -> - to_number(to_list(X)); -to_number(X) - when erlang:is_list(X) -> - try list_to_integer(X) of - Int -> Int - catch - error:badarg -> - list_to_float(X) - end. - -%% @doc -%% Automatic conversion of a term into Erlang list --spec to_list(atom() | list() | binary() | integer() | float()) -> - list(). -to_list(X) - when erlang:is_float(X) -> - erlang:float_to_list(X); -to_list(X) - when erlang:is_integer(X) -> - erlang:integer_to_list(X); -to_list(X) - when erlang:is_binary(X) -> - erlang:binary_to_list(X); -to_list(X) - when erlang:is_atom(X) -> - erlang:atom_to_list(X); -to_list(X) - when erlang:is_list(X) -> - X. - -%% @doc -%% Known limitations: -%% Converting [256 | _], lists with integers > 255 --spec to_binary(atom() | string() | binary() | integer() | float()) -> - binary(). -to_binary(X) - when erlang:is_float(X) -> - to_binary(to_list(X)); -to_binary(X) - when erlang:is_integer(X) -> - erlang:iolist_to_binary(integer_to_list(X)); -to_binary(X) - when erlang:is_atom(X) -> - erlang:list_to_binary(erlang:atom_to_list(X)); -to_binary(X) - when erlang:is_list(X) -> - erlang:iolist_to_binary(X); -to_binary(X) - when erlang:is_binary(X) -> - X. - --spec to_boolean(binary() | string() | atom()) -> - boolean(). -to_boolean(<<"true">>) -> - true; -to_boolean("true") -> - true; -to_boolean(true) -> - true; -to_boolean(<<"false">>) -> - false; -to_boolean("false") -> - false; -to_boolean(false) -> - false. - --spec is_true(binary() | string() | atom()) -> - boolean(). -is_true(<<"true">>) -> - true; -is_true("true") -> - true; -is_true(true) -> - true; -is_true(_) -> - false. - --spec is_false(binary() | string() | atom()) -> - boolean(). -is_false(<<"false">>) -> - true; -is_false("false") -> - true; -is_false(false) -> - true; -is_false(_) -> - false. - -%% @doc -%% Automation conversion a term to an existing atom. badarg is -%% returned if the atom doesn't exist. the safer version, won't let -%% you leak atoms --spec to_atom(atom() | list() | binary() | integer() | float()) -> - atom(). -to_atom(X) - when erlang:is_atom(X) -> - X; -to_atom(X) - when erlang:is_list(X) -> - erlang:list_to_existing_atom(X); -to_atom(X) -> - to_atom(to_list(X)). diff --git a/vendor/erlware_commons/src/ec_compile.erl b/vendor/erlware_commons/src/ec_compile.erl deleted file mode 100644 index 7199610f6..000000000 --- a/vendor/erlware_commons/src/ec_compile.erl +++ /dev/null @@ -1,131 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author Eric Merritt <> -%%% @copyright (C) 2011, Erlware, LLC. -%%% @doc -%%% These are various utility functions to help with compiling and -%%% decompiling erlang source. They are mostly useful to the -%%% language/parse transform implementor. -%%% @end -%%%------------------------------------------------------------------- --module(ec_compile). - --export([beam_to_erl_source/2, - erl_source_to_core_ast/1, - erl_source_to_erl_ast/1, - erl_source_to_asm/1, - erl_source_to_erl_syntax/1, - erl_string_to_core_ast/1, - erl_string_to_erl_ast/1, - erl_string_to_asm/1, - erl_string_to_erl_syntax/1]). - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc decompile a beam file that has been compiled with +debug_info -%% into a erlang source file -%% -%% @param BeamFName the name of the beamfile -%% @param ErlFName the name of the erlang file where the generated -%% source file will be output. This should *not* be the same as the -%% source file that created the beamfile unless you want to overwrite -%% it. --spec beam_to_erl_source(string(), string()) -> ok | term(). -beam_to_erl_source(BeamFName, ErlFName) -> - case beam_lib:chunks(BeamFName, [abstract_code]) of - {ok, {_, [{abstract_code, {raw_abstract_v1,Forms}}]}} -> - Src = - erl_prettypr:format(erl_syntax:form_list(tl(Forms))), - {ok, Fd} = file:open(ErlFName, [write]), - io:fwrite(Fd, "~ts~n", [Src]), - file:close(Fd); - Error -> - Error - end. - -%% @doc compile an erlang source file into a Core Erlang AST -%% -%% @param Path - The path to the erlang source file --spec erl_source_to_core_ast(file:filename()) -> CoreAst::term(). -erl_source_to_core_ast(Path) -> - {ok, Contents} = file:read_file(Path), - erl_string_to_core_ast(binary_to_list(Contents)). - -%% @doc compile an erlang source file into an Erlang AST -%% -%% @param Path - The path to the erlang source file --spec erl_source_to_erl_ast(file:filename()) -> ErlangAst::term(). -erl_source_to_erl_ast(Path) -> - {ok, Contents} = file:read_file(Path), - erl_string_to_erl_ast(binary_to_list(Contents)). - -%% @doc compile an erlang source file into erlang terms that represent -%% the relevant ASM -%% -%% @param Path - The path to the erlang source file --spec erl_source_to_asm(file:filename()) -> ErlangAsm::term(). -erl_source_to_asm(Path) -> - {ok, Contents} = file:read_file(Path), - erl_string_to_asm(binary_to_list(Contents)). - -%% @doc compile an erlang source file to a string that displays the -%% 'erl_syntax1 calls needed to reproduce those terms. -%% -%% @param Path - The path to the erlang source file --spec erl_source_to_erl_syntax(file:filename()) -> string(). -erl_source_to_erl_syntax(Path) -> - {ok, Contents} = file:read_file(Path), - erl_string_to_erl_syntax(Contents). - -%% @doc compile a string representing an erlang expression into an -%% Erlang AST -%% -%% @param StringExpr - The path to the erlang source file --spec erl_string_to_erl_ast(string()) -> ErlangAst::term(). -erl_string_to_erl_ast(StringExpr) -> - Forms0 = - lists:foldl(fun(<<>>, Acc) -> - Acc; - (<<"\n\n">>, Acc) -> - Acc; - (El, Acc) -> - {ok, Tokens, _} = - erl_scan:string(binary_to_list(El) - ++ "."), - [Tokens | Acc] - end, [], re:split(StringExpr, "\\.\n")), - %% No need to reverse. This will rereverse for us - lists:foldl(fun(Form, Forms) -> - {ok, ErlAST} = erl_parse:parse_form(Form), - [ErlAST | Forms] - end, [], Forms0). - -%% @doc compile a string representing an erlang expression into a -%% Core Erlang AST -%% -%% @param StringExpr - The path to the erlang source file --spec erl_string_to_core_ast(string()) -> CoreAst::term(). -erl_string_to_core_ast(StringExpr) -> - compile:forms(erl_string_to_erl_ast(StringExpr), [to_core]). - -%% @doc compile a string representing an erlang expression into a term -%% that represents the ASM -%% -%% @param StringExpr - The path to the erlang source file --spec erl_string_to_asm(string()) -> ErlangAsm::term(). -erl_string_to_asm(StringExpr) -> - compile:forms(erl_string_to_erl_ast(StringExpr), ['S']). - -%% @doc compile an erlang source file to a string that displays the -%% 'erl_syntax1 calls needed to reproduce those terms. -%% -%% @param StringExpr - The string representing the erlang code. --spec erl_string_to_erl_syntax(string() | binary()) -> string(). -erl_string_to_erl_syntax(BinaryExpr) - when erlang:is_binary(BinaryExpr) -> - erlang:binary_to_list(BinaryExpr); -erl_string_to_erl_syntax(StringExpr) -> - {ok, Tokens, _} = erl_scan:string(StringExpr), - {ok, ErlAST} = erl_parse:parse_form(Tokens), - io:format(erl_prettypr:format(erl_syntax:meta(ErlAST))). diff --git a/vendor/erlware_commons/src/ec_date.erl b/vendor/erlware_commons/src/ec_date.erl deleted file mode 100644 index 747b24646..000000000 --- a/vendor/erlware_commons/src/ec_date.erl +++ /dev/null @@ -1,1082 +0,0 @@ -%% vi:ts=4 sw=4 et -%% @copyright Dale Harvey -%% @doc Format dates in erlang -%% -%% Licensed under the MIT license -%% -%% This module formats erlang dates in the form {{Year, Month, Day}, -%% {Hour, Minute, Second}} to printable strings, using (almost) -%% equivalent formatting rules as http://uk.php.net/date, US vs -%% European dates are disambiguated in the same way as -%% http://uk.php.net/manual/en/function.strtotime.php That is, Dates -%% in the m/d/y or d-m-y formats are disambiguated by looking at the -%% separator between the various components: if the separator is a -%% slash (/), then the American m/d/y is assumed; whereas if the -%% separator is a dash (-) or a dot (.), then the European d-m-y -%% format is assumed. To avoid potential ambiguity, it's best to use -%% ISO 8601 (YYYY-MM-DD) dates. -%% -%% erlang has no concept of timezone so the following -%% formats are not implemented: B e I O P T Z -%% formats c and r will also differ slightly -%% -%% See tests at bottom for examples --module(ec_date). --author("Dale Harvey "). - --export([format/1, format/2]). --export([format_iso8601/1]). --export([parse/1, parse/2]). --export([nparse/1]). --export([tokenise/2]). - -%% These are used exclusively as guards and so the function like -%% defines make sense --define( is_num(X), (X >= $0 andalso X =< $9) ). --define( is_meridian(X), (X==[] orelse X==[am] orelse X==[pm]) ). --define( is_us_sep(X), ( X==$/) ). --define( is_world_sep(X), ( X==$-) ). - --define( MONTH_TAG, month ). --define( is_year(X), (is_integer(X) andalso X > 31) ). --define( is_day(X), (is_integer(X) andalso X =< 31) ). --define( is_hinted_month(X), (is_tuple(X) andalso size(X)=:=2 andalso element(1,X)=:=?MONTH_TAG) ). --define( is_month(X), ( (is_integer(X) andalso X =< 12) orelse ?is_hinted_month(X) ) ). --define( is_tz_offset(H1,H2,M1,M2), (?is_num(H1) andalso ?is_num(H2) andalso ?is_num(M1) andalso ?is_num(M2)) ). - --define(GREGORIAN_SECONDS_1970, 62_167_219_200). --define(ISO_8601_DATETIME_FORMAT, "Y-m-dTH:i:sZ"). --define(ISO_8601_DATETIME_WITH_MS_FORMAT, "Y-m-dTH:i:s.fZ"). - --type year() :: non_neg_integer(). --type month() :: 1..12 | {?MONTH_TAG, 1..12}. --type day() :: 1..31. --type hour() :: 0..23. --type minute() :: 0..59. --type second() :: 0..59. --type microsecond() :: 0..999_999. - --type daynum() :: 1..7. --type date() :: {year(),month(),day()}. --type time() :: {hour(),minute(),second()} | {hour(),minute(),second(),microsecond()}. --type datetime() :: {date(),time()}. --type now() :: {integer(),integer(),integer()}. - -%% -%% EXPORTS -%% - --spec format(string()) -> string(). -%% @doc format current local time as Format -format(Format) -> - format(Format, calendar:universal_time(),[]). - --spec format(string(),datetime() | now()) -> string(). -%% @doc format Date as Format -format(Format, {_,_,Ms}=Now) -> - {Date,{H,M,S}} = calendar:now_to_datetime(Now), - format(Format, {Date, {H,M,S,Ms}}, []); -format(Format, Date) -> - format(Format, Date, []). - --spec format_iso8601(datetime()) -> string(). -%% @doc format date in the ISO8601 format -%% This always puts 'Z' as time zone, since we have no notion of timezone -format_iso8601({{_, _, _}, {_, _, _}} = Date) -> - format(?ISO_8601_DATETIME_FORMAT, Date); -format_iso8601({{_, _, _}, {_, _, _, _}} = Date) -> - format(?ISO_8601_DATETIME_WITH_MS_FORMAT, Date). - --spec parse(string()) -> datetime(). -%% @doc parses the datetime from a string -parse(Date) -> - do_parse(Date, calendar:universal_time(),[]). - --spec parse(string(),datetime() | now()) -> datetime(). - -%% @doc parses the datetime from a string -parse(Date, {_,_,_}=Now) -> - do_parse(Date, calendar:now_to_datetime(Now), []); -parse(Date, Now) -> - do_parse(Date, Now, []). - -do_parse(Date, Now, Opts) -> - case filter_hints(parse(tokenise(string:uppercase(Date), []), Now, Opts)) of - {error, bad_date} -> - erlang:throw({?MODULE, {bad_date, Date}}); - {D1, T1} = {{Y, M, D}, {H, M1, S}} - when is_number(Y), is_number(M), - is_number(D), is_number(H), - is_number(M1), is_number(S) -> - case calendar:valid_date(D1) of - true -> {D1, T1}; - false -> erlang:throw({?MODULE, {bad_date, Date}}) - end; - {D1, _T1, {Ms}} = {{Y, M, D}, {H, M1, S}, {Ms}} - when is_number(Y), is_number(M), - is_number(D), is_number(H), - is_number(M1), is_number(S), - is_number(Ms) -> - case calendar:valid_date(D1) of - true -> {D1, {H,M1,S,Ms}}; - false -> erlang:throw({?MODULE, {bad_date, Date}}) - end; - Unknown -> erlang:throw({?MODULE, {bad_date, Date, Unknown }}) - end. - -filter_hints({{Y, {?MONTH_TAG, M}, D}, {H, M1, S}}) -> - filter_hints({{Y, M, D}, {H, M1, S}}); -filter_hints({{Y, {?MONTH_TAG, M}, D}, {H, M1, S}, {Ms}}) -> - filter_hints({{Y, M, D}, {H, M1, S}, {Ms}}); -filter_hints(Other) -> - Other. - --spec nparse(string()) -> now(). -%% @doc parses the datetime from a string into 'now' format -nparse(Date) -> - case parse(Date) of - {DateS, {H, M, S, Ms} } -> - GSeconds = calendar:datetime_to_gregorian_seconds({DateS, {H, M, S} }), - ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, - {ESeconds div 1_000_000, ESeconds rem 1_000_000, Ms}; - DateTime -> - GSeconds = calendar:datetime_to_gregorian_seconds(DateTime), - ESeconds = GSeconds - ?GREGORIAN_SECONDS_1970, - {ESeconds div 1_000_000, ESeconds rem 1_000_000, 0} - end. - -%% -%% LOCAL FUNCTIONS -%% - -parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $., Micros, $Z ], _Now, _Opts) - when ?is_world_sep(X) - andalso (Micros >= 0 andalso Micros < 1_000_000) - andalso Year > 31 -> - {{Year, Month, Day}, {hour(Hour, []), Min, Sec}, {Micros}}; - -parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $Z ], _Now, _Opts) - when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> - {{Year, Month, Day}, {hour(Hour, []), Min, Sec}}; - -parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $., Micros, $+, Off | _Rest ], _Now, _Opts) - when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso (Micros >= 0 andalso Micros < 1_000_000) - andalso Year > 31 -> - {{Year, Month, Day}, {hour(Hour, []) - Off, Min, Sec}, {Micros}}; - -parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $+, Off | _Rest ], _Now, _Opts) - when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> - {{Year, Month, Day}, {hour(Hour, []) - Off, Min, Sec}, {0}}; - -parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $., Micros, $-, Off | _Rest ], _Now, _Opts) - when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso (Micros >= 0 andalso Micros < 1_000_000) - andalso Year > 31 -> - {{Year, Month, Day}, {hour(Hour, []) + Off, Min, Sec}, {Micros}}; - -parse([Year, X, Month, X, Day, Hour, $:, Min, $:, Sec, $-, Off | _Rest ], _Now, _Opts) - when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso Year > 31 -> - {{Year, Month, Day}, {hour(Hour, []) + Off, Min, Sec}, {0}}; - -%% Date/Times 22 Aug 2008 6:35.0001 PM -parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso - (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso ?is_year(Year) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; -parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_us_sep(X) - andalso ?is_year(Year) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; -parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec,$., Ms | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_world_sep(X) - andalso ?is_year(Year) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}, {Ms}}; - -%% Date/Times Dec 1st, 2012 6:25 PM -parse([Month,Day,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; -parse([Month,Day,Year,Hour,$:,Min | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; -parse([Month,Day,Year,Hour | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_hinted_month(Month) andalso ?is_day(Day) -> - {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; - -%% Date/Times Fri Nov 21 14:55:26 +0000 2014 (Twitter format) -parse([Month, Day, Hour,$:,Min,$:,Sec, Year], _Now, _Opts) - when ?is_hinted_month(Month), ?is_day(Day), ?is_year(Year) -> - {{Year, Month, Day}, {hour(Hour, []), Min, Sec}}; - -%% Times - 21:45, 13:45:54, 13:15PM etc -parse([Hour,$:,Min,$:,Sec | PAM], {Date, _Time}, _O) when ?is_meridian(PAM) -> - {Date, {hour(Hour, PAM), Min, Sec}}; -parse([Hour,$:,Min | PAM], {Date, _Time}, _Opts) when ?is_meridian(PAM) -> - {Date, {hour(Hour, PAM), Min, 0}}; -parse([Hour | PAM],{Date,_Time}, _Opts) when ?is_meridian(PAM) -> - {Date, {hour(Hour,PAM), 0, 0}}; - -%% Dates (Any combination with word month "aug 8th, 2008", "8 aug 2008", "2008 aug 21" "2008 5 aug" ) -%% Will work because of the "Hinted month" -parse([Day,Month,Year], {_Date, Time}, _Opts) - when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> - {{Year, Month, Day}, Time}; -parse([Month,Day,Year], {_Date, Time}, _Opts) - when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> - {{Year, Month, Day}, Time}; -parse([Year,Day,Month], {_Date, Time}, _Opts) - when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> - {{Year, Month, Day}, Time}; -parse([Year,Month,Day], {_Date, Time}, _Opts) - when ?is_day(Day) andalso ?is_hinted_month(Month) andalso ?is_year(Year) -> - {{Year, Month, Day}, Time}; - -%% Dates 23/april/1963 -parse([Day,Month,Year], {_Date, Time}, _Opts) -> - {{Year, Month, Day}, Time}; -parse([Year,X,Month,X,Day], {_Date, Time}, _Opts) - when (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso ?is_year(Year) -> - {{Year, Month, Day}, Time}; -parse([Month,X,Day,X,Year], {_Date, Time}, _Opts) when ?is_us_sep(X) -> - {{Year, Month, Day}, Time}; -parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_world_sep(X) -> - {{Year, Month, Day}, Time}; - -%% Date/Times 22 Aug 2008 6:35 PM -%% Time is "7 PM" -parse([Year,X,Month,X,Day,Hour | PAM], _Date, _Opts) - when ?is_meridian(PAM) andalso - (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso ?is_year(Year) -> - {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; -parse([Day,X,Month,X,Year,Hour | PAM], _Date, _Opts) - when ?is_meridian(PAM) andalso ?is_world_sep(X) -> - {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; -parse([Month,X,Day,X,Year,Hour | PAM], _Date, _Opts) - when ?is_meridian(PAM) andalso ?is_us_sep(X) -> - {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; - - -%% Time is "6:35 PM" ms return -parse([Year,X,Month,X,Day,Hour,$:,Min | PAM], _Date, _Opts) - when ?is_meridian(PAM) andalso - (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso ?is_year(Year) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; -parse([Day,X,Month,X,Year,Hour,$:,Min | PAM], _Date, _Opts) - when ?is_meridian(PAM) andalso ?is_world_sep(X) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; -parse([Month,X,Day,X,Year,Hour,$:,Min | PAM], _Date, _Opts) - when ?is_meridian(PAM) andalso ?is_us_sep(X) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; - -%% Time is "6:35:15 PM" -parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso - (?is_us_sep(X) orelse ?is_world_sep(X)) - andalso ?is_year(Year) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; -parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_us_sep(X) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; -parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) - when ?is_meridian(PAM) andalso ?is_world_sep(X) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; - -parse([Day,Month,Year,Hour | PAM], _Now, _Opts) - when ?is_meridian(PAM) -> - {{Year, Month, Day}, {hour(Hour, PAM), 0, 0}}; -parse([Day,Month,Year,Hour,$:,Min | PAM], _Now, _Opts) - when ?is_meridian(PAM) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}}; -parse([Day,Month,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts) - when ?is_meridian(PAM) -> - {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}}; - -parse(_Tokens, _Now, _Opts) -> - {error, bad_date}. - -tokenise([], Acc) -> - lists:reverse(Acc); - -%% ISO 8601 fractions of a second -tokenise([$., N1, N2, N3, N4, N5, N6 | Rest], Acc) - when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4), ?is_num(N5), ?is_num(N6) -> - tokenise(Rest, [ ltoi([N1, N2, N3, N4, N5, N6]), $. | Acc]); -tokenise([$., N1, N2, N3, N4, N5 | Rest], Acc) - when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4), ?is_num(N5) -> - tokenise(Rest, [ ltoi([N1, N2, N3, N4, N5]) * 10, $. | Acc]); -tokenise([$., N1, N2, N3, N4 | Rest], Acc) - when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4) -> - tokenise(Rest, [ ltoi([N1, N2, N3, N4]) * 100, $. | Acc]); -tokenise([$., N1, N2, N3 | Rest], Acc) when ?is_num(N1), ?is_num(N2), ?is_num(N3) -> - tokenise(Rest, [ ltoi([N1, N2, N3]) * 1_000, $. | Acc]); -tokenise([$., N1, N2 | Rest], Acc) when ?is_num(N1), ?is_num(N2) -> - tokenise(Rest, [ ltoi([N1, N2]) * 10_000, $. | Acc]); -tokenise([$., N1 | Rest], Acc) when ?is_num(N1) -> - tokenise(Rest, [ ltoi([N1]) * 100_000, $. | Acc]); - -tokenise([N1, N2, N3, N4, N5, N6 | Rest], Acc) - when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4), ?is_num(N5), ?is_num(N6) -> - tokenise(Rest, [ ltoi([N1, N2, N3, N4, N5, N6]) | Acc]); -tokenise([N1, N2, N3, N4, N5 | Rest], Acc) - when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4), ?is_num(N5) -> - tokenise(Rest, [ ltoi([N1, N2, N3, N4, N5]) | Acc]); -tokenise([N1, N2, N3, N4 | Rest], Acc) - when ?is_num(N1), ?is_num(N2), ?is_num(N3), ?is_num(N4) -> - tokenise(Rest, [ ltoi([N1, N2, N3, N4]) | Acc]); -tokenise([N1, N2, N3 | Rest], Acc) - when ?is_num(N1), ?is_num(N2), ?is_num(N3) -> - tokenise(Rest, [ ltoi([N1, N2, N3]) | Acc]); -tokenise([N1, N2 | Rest], Acc) - when ?is_num(N1), ?is_num(N2) -> - tokenise(Rest, [ ltoi([N1, N2]) | Acc]); -tokenise([N1 | Rest], Acc) - when ?is_num(N1) -> - tokenise(Rest, [ ltoi([N1]) | Acc]); - - -%% Worded Months get tagged with ?MONTH_TAG to let the parser know that these -%% are unambiguously declared to be months. This was there's no confusion -%% between, for example: "Aug 12" and "12 Aug" -%% These hint tags are filtered in filter_hints/1 above. -tokenise("JANUARY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,1} | Acc]); -tokenise("JAN"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,1} | Acc]); -tokenise("FEBRUARY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,2} | Acc]); -tokenise("FEB"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,2} | Acc]); -tokenise("MARCH"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,3} | Acc]); -tokenise("MAR"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,3} | Acc]); -tokenise("APRIL"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,4} | Acc]); -tokenise("APR"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,4} | Acc]); -tokenise("MAY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,5} | Acc]); -tokenise("JUNE"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,6} | Acc]); -tokenise("JUN"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,6} | Acc]); -tokenise("JULY"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,7} | Acc]); -tokenise("JUL"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,7} | Acc]); -tokenise("AUGUST"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,8} | Acc]); -tokenise("AUG"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,8} | Acc]); -tokenise("SEPTEMBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,9} | Acc]); -tokenise("SEPT"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,9} | Acc]); -tokenise("SEP"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,9} | Acc]); -tokenise("OCTOBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,10} | Acc]); -tokenise("OCT"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,10} | Acc]); -tokenise("NOVEMBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,11} | Acc]); -tokenise("NOVEM"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,11} | Acc]); -tokenise("NOV"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,11} | Acc]); -tokenise("DECEMBER"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,12} | Acc]); -tokenise("DECEM"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,12} | Acc]); -tokenise("DEC"++Rest, Acc) -> tokenise(Rest, [{?MONTH_TAG,12} | Acc]); - -tokenise([$: | Rest], Acc) -> tokenise(Rest, [ $: | Acc]); -tokenise([$/ | Rest], Acc) -> tokenise(Rest, [ $/ | Acc]); -tokenise([$- | Rest], Acc) -> tokenise(Rest, [ $- | Acc]); -tokenise("AM"++Rest, Acc) -> tokenise(Rest, [am | Acc]); -tokenise("PM"++Rest, Acc) -> tokenise(Rest, [pm | Acc]); -tokenise("A"++Rest, Acc) -> tokenise(Rest, [am | Acc]); -tokenise("P"++Rest, Acc) -> tokenise(Rest, [pm | Acc]); - -%% Postel's Law -%% -%% be conservative in what you do, -%% be liberal in what you accept from others. -%% -%% See RFC 793 Section 2.10 http://tools.ietf.org/html/rfc793 -%% -%% Mebbies folk want to include Saturday etc in a date, nae borra -tokenise("MONDAY"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("MON"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("TUESDAY"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("TUES"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("TUE"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("WEDNESDAY"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("WEDS"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("WED"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("THURSDAY"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("THURS"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("THUR"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("THU"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("FRIDAY"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("FRI"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("SATURDAY"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("SAT"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("SUNDAY"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("SUN"++Rest, Acc) -> tokenise(Rest, Acc); - -%% Hmm Excel reports GMT in times so nuke that too -tokenise("GMT"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("UTC"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("DST"++Rest, Acc) -> tokenise(Rest, Acc); % daylight saving time - -tokenise([$, | Rest], Acc) -> tokenise(Rest, Acc); -tokenise([32 | Rest], Acc) -> tokenise(Rest, Acc); % Spaces -tokenise("TH"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("ND"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("ST"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("OF"++Rest, Acc) -> tokenise(Rest, Acc); -tokenise("T"++Rest, Acc) -> tokenise(Rest, Acc); % 2012-12-12T12:12:12 ISO formatting. -tokenise([$Z | Rest], Acc) -> tokenise(Rest, [$Z | Acc]); % 2012-12-12T12:12:12Zulu -tokenise([$+, H1,H2,M1,M2| Rest], Acc) when ?is_tz_offset(H1,H2,M1,M2) -> tokenise(Rest, Acc); % Tue Nov 11 15:03:18 +0000 2014 Twitter format -tokenise([$+| Rest], Acc) -> tokenise(Rest, [$+ | Acc]); % 2012-12-12T12:12:12.xxxx+ ISO formatting. - -tokenise([Else | Rest], Acc) -> - tokenise(Rest, [{bad_token, Else} | Acc]). - -hour(Hour, []) -> Hour; -hour(12, [am]) -> 0; -hour(Hour, [am]) -> Hour; -hour(12, [pm]) -> 12; -hour(Hour, [pm]) -> Hour+12. - --spec format(string(),datetime(),list()) -> string(). -%% Finished, return -format([], _Date, Acc) -> - lists:flatten(lists:reverse(Acc)); - -%% Escape backslashes -format([$\\,H|T], Dt, Acc) -> - format(T,Dt,[H|Acc]); - -%% Year Formats -format([$Y|T], {{Y,_,_},_}=Dt, Acc) -> - format(T, Dt, [itol(Y)|Acc]); -format([$y|T], {{Y,_,_},_}=Dt, Acc) -> - [_, _, Y3, Y4] = itol(Y), - format(T, Dt, [[Y3,Y4]|Acc]); -format([$L|T], {{Y,_,_},_}=Dt, Acc) -> - format(T, Dt, [itol(is_leap(Y))|Acc]); -format([$o|T], {Date,_}=Dt, Acc) -> - format(T, Dt, [itol(iso_year(Date))|Acc]); - -%% Month Formats -format([$n|T], {{_,M,_},_}=Dt, Acc) -> - format(T, Dt, [itol(M)|Acc]); -format([$m|T], {{_,M,_},_}=Dt, Acc) -> - format(T, Dt, [pad2(M)|Acc]); -format([$M|T], {{_,M,_},_}=Dt, Acc) -> - format(T, Dt, [smonth(M)|Acc]); -format([$F|T], {{_,M,_},_}=Dt, Acc) -> - format(T, Dt, [month(M)|Acc]); -format([$t|T], {{Y,M,_},_}=Dt, Acc) -> - format(T, Dt, [itol(calendar:last_day_of_the_month(Y,M))|Acc]); - -%% Week Formats -format([$W|T], {Date,_}=Dt, Acc) -> - format(T, Dt, [pad2(iso_week(Date))|Acc]); - -%% Day Formats -format([$j|T], {{_,_,D},_}=Dt, Acc) -> - format(T, Dt, [itol(D)|Acc]); -format([$S|T], {{_,_,D},_}=Dt, Acc) -> - format(T, Dt,[suffix(D)| Acc]); -format([$d|T], {{_,_,D},_}=Dt, Acc) -> - format(T, Dt, [pad2(D)|Acc]); -format([$D|T], {Date,_}=Dt, Acc) -> - format(T, Dt, [sdayd(Date)|Acc]); -format([$l|T], {Date,_}=Dt, Acc) -> - format(T, Dt, [day(calendar:day_of_the_week(Date))|Acc]); -format([$N|T], {Date,_}=Dt, Acc) -> - format(T, Dt, [itol(calendar:day_of_the_week(Date))|Acc]); -format([$w|T], {Date,_}=Dt, Acc) -> - format(T, Dt, [itol(to_w(calendar:day_of_the_week(Date)))|Acc]); -format([$z|T], {Date,_}=Dt, Acc) -> - format(T, Dt, [itol(days_in_year(Date))|Acc]); - -%% Time Formats -format([$a|T], Dt={_,{H,_,_}}, Acc) when H >= 12 -> - format(T, Dt, ["pm"|Acc]); -format([$a|T], Dt={_,{_,_,_}}, Acc) -> - format(T, Dt, ["am"|Acc]); -format([$A|T], {_,{H,_,_}}=Dt, Acc) when H >= 12 -> - format(T, Dt, ["PM"|Acc]); -format([$A|T], Dt={_,{_,_,_}}, Acc) -> - format(T, Dt, ["AM"|Acc]); -format([$g|T], {_,{H,_,_}}=Dt, Acc) when H == 12; H == 0 -> - format(T, Dt, ["12"|Acc]); -format([$g|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> - format(T, Dt, [itol(H-12)|Acc]); -format([$g|T], {_,{H,_,_}}=Dt, Acc) -> - format(T, Dt, [itol(H)|Acc]); -format([$G|T], {_,{H,_,_}}=Dt, Acc) -> - format(T, Dt, [itol(H)|Acc]); -format([$h|T], {_,{H,_,_}}=Dt, Acc) when H > 12 -> - format(T, Dt, [pad2(H-12)|Acc]); -format([$h|T], {_,{H,_,_}}=Dt, Acc) -> - format(T, Dt, [pad2(H)|Acc]); -format([$H|T], {_,{H,_,_}}=Dt, Acc) -> - format(T, Dt, [pad2(H)|Acc]); -format([$i|T], {_,{_,M,_}}=Dt, Acc) -> - format(T, Dt, [pad2(M)|Acc]); -format([$s|T], {_,{_,_,S}}=Dt, Acc) -> - format(T, Dt, [pad2(S)|Acc]); -format([$f|T], {_,{_,_,_}}=Dt, Acc) -> - format(T, Dt, [itol(0)|Acc]); - -%% Time Formats ms -format([$a|T], Dt={_,{H,_,_,_}}, Acc) when H > 12 -> - format(T, Dt, ["pm"|Acc]); -format([$a|T], Dt={_,{_,_,_,_}}, Acc) -> - format(T, Dt, ["am"|Acc]); -format([$A|T], {_,{H,_,_,_}}=Dt, Acc) when H > 12 -> - format(T, Dt, ["PM"|Acc]); -format([$A|T], Dt={_,{_,_,_,_}}, Acc) -> - format(T, Dt, ["AM"|Acc]); -format([$g|T], {_,{H,_,_,_}}=Dt, Acc) when H == 12; H == 0 -> - format(T, Dt, ["12"|Acc]); -format([$g|T], {_,{H,_,_,_}}=Dt, Acc) when H > 12 -> - format(T, Dt, [itol(H-12)|Acc]); -format([$g|T], {_,{H,_,_,_}}=Dt, Acc) -> - format(T, Dt, [itol(H)|Acc]); -format([$G|T], {_,{H,_,_,_}}=Dt, Acc) -> - format(T, Dt, [pad2(H)|Acc]); -format([$h|T], {_,{H,_,_,_}}=Dt, Acc) when H > 12 -> - format(T, Dt, [pad2(H-12)|Acc]); -format([$h|T], {_,{H,_,_,_}}=Dt, Acc) -> - format(T, Dt, [pad2(H)|Acc]); -format([$H|T], {_,{H,_,_,_}}=Dt, Acc) -> - format(T, Dt, [pad2(H)|Acc]); -format([$i|T], {_,{_,M,_,_}}=Dt, Acc) -> - format(T, Dt, [pad2(M)|Acc]); -format([$s|T], {_,{_,_,S,_}}=Dt, Acc) -> - format(T, Dt, [pad2(S)|Acc]); -format([$f|T], {_,{_,_,_,Ms}}=Dt, Acc) -> - format(T, Dt, [pad6(Ms)|Acc]); - -%% Whole Dates -format([$c|T], {{Y,M,D},{H,Min,S}}=Dt, Acc) -> - Format = "~4.10.0B-~2.10.0B-~2.10.0B" - ++" ~2.10.0B:~2.10.0B:~2.10.0B", - Date = io_lib:format(Format, [Y, M, D, H, Min, S]), - format(T, Dt, [Date|Acc]); -format([$r|T], {{Y,M,D},{H,Min,S}}=Dt, Acc) -> - Format = "~s, ~p ~s ~p ~2.10.0B:~2.10.0B:~2.10.0B", - Args = [sdayd({Y,M,D}), D, smonth(M), Y, H, Min, S], - format(T, Dt, [io_lib:format(Format, Args)|Acc]); -format([$U|T], Dt, Acc) -> - Epoch = {{1970,1,1},{0,0,0}}, - Time = calendar:datetime_to_gregorian_seconds(Dt) - - calendar:datetime_to_gregorian_seconds(Epoch), - format(T, Dt, [itol(Time)|Acc]); - -%% Unrecognised, print as is -format([H|T], Date, Acc) -> - format(T, Date, [H|Acc]). - - -%% @doc days in year --spec days_in_year(date()) -> integer(). -days_in_year({Y,_,_}=Date) -> - calendar:date_to_gregorian_days(Date) - - calendar:date_to_gregorian_days({Y,1,1}). - -%% @doc is a leap year --spec is_leap(year()) -> 1|0. -is_leap(Y) -> - case calendar:is_leap_year(Y) of - true -> 1; - false -> 0 - end. - -%% @doc Made up numeric day of the week -%% (0 Sunday -> 6 Saturday) --spec to_w(daynum()) -> integer(). -to_w(7) -> 0; -to_w(X) -> X. - --spec suffix(day()) -> string(). -%% @doc English ordinal suffix for the day of the -%% month, 2 characters -suffix(1) -> "st"; -suffix(2) -> "nd"; -suffix(3) -> "rd"; -suffix(21) -> "st"; -suffix(22) -> "nd"; -suffix(23) -> "rd"; -suffix(31) -> "st"; -suffix(_) -> "th". - --spec sdayd(date()) -> string(). -%% @doc A textual representation of a day, three letters -sdayd({Y,M,D}) -> - sday(calendar:day_of_the_week({Y,M,D})). - --spec sday(daynum()) -> string(). -%% @doc A textual representation of a day, three letters -sday(1) -> "Mon"; -sday(2) -> "Tue"; -sday(3) -> "Wed"; -sday(4) -> "Thu"; -sday(5) -> "Fri"; -sday(6) -> "Sat"; -sday(7) -> "Sun". - --spec day(daynum()) -> string(). -%% @doc A full textual representation of a day -day(1) -> "Monday"; -day(2) -> "Tuesday"; -day(3) -> "Wednesday"; -day(4) -> "Thursday"; -day(5) -> "Friday"; -day(6) -> "Saturday"; -day(7) -> "Sunday". - --spec smonth(month()) -> string(). -%% @doc A short textual representation of a -%% month, three letters -smonth(1) -> "Jan"; -smonth(2) -> "Feb"; -smonth(3) -> "Mar"; -smonth(4) -> "Apr"; -smonth(5) -> "May"; -smonth(6) -> "Jun"; -smonth(7) -> "Jul"; -smonth(8) -> "Aug"; -smonth(9) -> "Sep"; -smonth(10) -> "Oct"; -smonth(11) -> "Nov"; -smonth(12) -> "Dec". - --spec month(month()) -> string(). -%% @doc A full textual representation of a month -month(1) -> "January"; -month(2) -> "February"; -month(3) -> "March"; -month(4) -> "April"; -month(5) -> "May"; -month(6) -> "June"; -month(7) -> "July"; -month(8) -> "August"; -month(9) -> "September"; -month(10) -> "October"; -month(11) -> "November"; -month(12) -> "December". - --spec iso_week(date()) -> integer(). -%% @doc The week of the years as defined in ISO 8601 -%% http://en.wikipedia.org/wiki/ISO_week_date -iso_week(Date) -> - Week = iso_week_one(iso_year(Date)), - Days = calendar:date_to_gregorian_days(Date) - - calendar:date_to_gregorian_days(Week), - trunc((Days / 7) + 1). - --spec iso_year(date()) -> integer(). -%% @doc The year number as defined in ISO 8601 -%% http://en.wikipedia.org/wiki/ISO_week_date -iso_year({Y, _M, _D}=Dt) -> - case Dt >= {Y, 12, 29} of - true -> - case Dt < iso_week_one(Y+1) of - true -> Y; - false -> Y+1 - end; - false -> - case Dt < iso_week_one(Y) of - true -> Y-1; - false -> Y - end - end. - --spec iso_week_one(year()) -> date(). -%% @doc The date of the the first day of the first week -%% in the ISO calendar -iso_week_one(Y) -> - Day1 = calendar:day_of_the_week({Y,1,4}), - Days = calendar:date_to_gregorian_days({Y,1,4}) + (1-Day1), - calendar:gregorian_days_to_date(Days). - --spec itol(integer()) -> list(). -%% @doc short hand -itol(X) -> - integer_to_list(X). - --spec pad2(integer() | float()) -> list(). -%% @doc int padded with 0 to make sure its 2 chars -pad2(X) when is_integer(X) -> - io_lib:format("~2.10.0B",[X]); -pad2(X) when is_float(X) -> - io_lib:format("~2.10.0B",[trunc(X)]). - --spec pad6(integer()) -> list(). -pad6(X) when is_integer(X) -> - io_lib:format("~6.10.0B",[X]). - -ltoi(X) -> - list_to_integer(X). - -%%%=================================================================== -%%% Tests -%%%=================================================================== - --ifdef(TEST). --include_lib("eunit/include/eunit.hrl"). - - --define(DATE, {{2001,3,10},{17,16,17}}). --define(DATEMS, {{2001,3,10},{17,16,17,123_456}}). --define(DATE_NOON, {{2001,3,10},{12,0,0}}). --define(DATE_MIDNIGHT, {{2001,3,10},{0,0,0}}). --define(ISO, "o \\WW"). - -basic_format_test_() -> - [ - ?_assertEqual(format("F j, Y, g:i a",?DATE), "March 10, 2001, 5:16 pm"), - ?_assertEqual(format("F jS, Y, g:i a",?DATE), "March 10th, 2001, 5:16 pm"), - ?_assertEqual(format("F jS",{{2011,3,21},{0,0,0}}), "March 21st"), - ?_assertEqual(format("F jS",{{2011,3,22},{0,0,0}}), "March 22nd"), - ?_assertEqual(format("F jS",{{2011,3,23},{0,0,0}}), "March 23rd"), - ?_assertEqual(format("F jS",{{2011,3,31},{0,0,0}}), "March 31st"), - ?_assertEqual(format("m.d.y",?DATE), "03.10.01"), - ?_assertEqual(format("j, n, Y",?DATE), "10, 3, 2001"), - ?_assertEqual(format("Ymd",?DATE), "20010310"), - ?_assertEqual(format("H:i:s",?DATE), "17:16:17"), - ?_assertEqual(format("z",?DATE), "68"), - ?_assertEqual(format("D M j G:i:s Y",?DATE), "Sat Mar 10 17:16:17 2001"), - ?_assertEqual(format("D M j G:i:s Y", {{2001,3,10},{5,16,17}}), "Sat Mar 10 5:16:17 2001"), - ?_assertEqual(format("D M j H:i:s Y", {{2001,3,10},{5,16,17}}), "Sat Mar 10 05:16:17 2001"), - ?_assertEqual(format("ga",?DATE_NOON), "12pm"), - ?_assertEqual(format("gA",?DATE_NOON), "12PM"), - ?_assertEqual(format("ga",?DATE_MIDNIGHT), "12am"), - ?_assertEqual(format("gA",?DATE_MIDNIGHT), "12AM"), - - ?_assertEqual(format("h-i-s, j-m-y, it is w Day",?DATE), - "05-16-17, 10-03-01, 1631 1617 6 Satpm01"), - ?_assertEqual(format("\\i\\t \\i\\s \\t\\h\\e\\ jS \\d\\a\\y.",?DATE), - "it is the 10th day."), - ?_assertEqual(format("H:m:s \\m \\i\\s \\m\\o\\n\\t\\h",?DATE), - "17:03:17 m is month") - ]. - -basic_parse_test_() -> - [ - ?_assertEqual({{2008,8,22}, {17,16,17}}, - parse("22nd of August 2008", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,0,0}}, - parse("22-Aug-2008 6 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("22-Aug-2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,12}}, - parse("22-Aug-2008 6:35:12 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,0,0}}, - parse("August/22/2008 6 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("August/22/2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("22 August 2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,0,0}}, - parse("22 Aug 2008 6AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("22 Aug 2008 6:35AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("22 Aug 2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,0,0}}, - parse("22 Aug 2008 6", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("22 Aug 2008 6:35", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,35,0}}, - parse("22 Aug 2008 6:35 PM", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,0,0}}, - parse("22 Aug 2008 6 PM", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,0,0}}, - parse("Aug 22, 2008 6 PM", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,0,0}}, - parse("August 22nd, 2008 6:00 PM", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,15,15}}, - parse("August 22nd 2008, 6:15:15pm", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,15,15}}, - parse("August 22nd, 2008, 6:15:15pm", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,15,0}}, - parse("Aug 22nd 2008, 18:15", ?DATE)), - ?_assertEqual({{2008,8,2}, {17,16,17}}, - parse("2nd of August 2008", ?DATE)), - ?_assertEqual({{2008,8,2}, {17,16,17}}, - parse("August 2nd, 2008", ?DATE)), - ?_assertEqual({{2008,8,2}, {17,16,17}}, - parse("2nd August, 2008", ?DATE)), - ?_assertEqual({{2008,8,2}, {17,16,17}}, - parse("2008 August 2nd", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,0,0}}, - parse("2-Aug-2008 6 AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,35,0}}, - parse("2-Aug-2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,35,12}}, - parse("2-Aug-2008 6:35:12 AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,0,0}}, - parse("August/2/2008 6 AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,35,0}}, - parse("August/2/2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,35,0}}, - parse("2 August 2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,0,0}}, - parse("2 Aug 2008 6AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,35,0}}, - parse("2 Aug 2008 6:35AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,35,0}}, - parse("2 Aug 2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,0,0}}, - parse("2 Aug 2008 6", ?DATE)), - ?_assertEqual({{2008,8,2}, {6,35,0}}, - parse("2 Aug 2008 6:35", ?DATE)), - ?_assertEqual({{2008,8,2}, {18,35,0}}, - parse("2 Aug 2008 6:35 PM", ?DATE)), - ?_assertEqual({{2008,8,2}, {18,0,0}}, - parse("2 Aug 2008 6 PM", ?DATE)), - ?_assertEqual({{2008,8,2}, {18,0,0}}, - parse("Aug 2, 2008 6 PM", ?DATE)), - ?_assertEqual({{2008,8,2}, {18,0,0}}, - parse("August 2nd, 2008 6:00 PM", ?DATE)), - ?_assertEqual({{2008,8,2}, {18,15,15}}, - parse("August 2nd 2008, 6:15:15pm", ?DATE)), - ?_assertEqual({{2008,8,2}, {18,15,15}}, - parse("August 2nd, 2008, 6:15:15pm", ?DATE)), - ?_assertEqual({{2008,8,2}, {18,15,0}}, - parse("Aug 2nd 2008, 18:15", ?DATE)), - ?_assertEqual({{2012,12,10}, {0,0,0}}, - parse("Dec 10th, 2012, 12:00 AM", ?DATE)), - ?_assertEqual({{2012,12,10}, {0,0,0}}, - parse("10 Dec 2012 12:00 AM", ?DATE)), - ?_assertEqual({{2001,3,10}, {11,15,0}}, - parse("11:15", ?DATE)), - ?_assertEqual({{2001,3,10}, {1,15,0}}, - parse("1:15", ?DATE)), - ?_assertEqual({{2001,3,10}, {1,15,0}}, - parse("1:15 am", ?DATE)), - ?_assertEqual({{2001,3,10}, {0,15,0}}, - parse("12:15 am", ?DATE)), - ?_assertEqual({{2001,3,10}, {12,15,0}}, - parse("12:15 pm", ?DATE)), - ?_assertEqual({{2001,3,10}, {3,45,39}}, - parse("3:45:39", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("23-4-1963", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("23-april-1963", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("23-apr-1963", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("4/23/1963", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("april/23/1963", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("apr/23/1963", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("1963/4/23", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("1963/april/23", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("1963/apr/23", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("1963-4-23", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("1963-4-23", ?DATE)), - ?_assertEqual({{1963,4,23}, {17,16,17}}, - parse("1963-apr-23", ?DATE)), - ?_assertThrow({?MODULE, {bad_date, "23/ap/195"}}, - parse("23/ap/195", ?DATE)), - ?_assertEqual({{2001,3,10}, {6,45,0}}, - parse("6:45 am", ?DATE)), - ?_assertEqual({{2001,3,10}, {18,45,0}}, - parse("6:45 PM", ?DATE)), - ?_assertEqual({{2001,3,10}, {18,45,0}}, - parse("6:45 PM ", ?DATE)) - ]. - -parse_with_days_test_() -> - [ - ?_assertEqual({{2008,8,22}, {17,16,17}}, - parse("Sat 22nd of August 2008", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("Sat, 22-Aug-2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,12}}, - parse("Sunday 22-Aug-2008 6:35:12 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("Sun 22-Aug-2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("THURSDAY, 22-August-2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,0,0}}, - parse("THURSDAY, 22-August-2008 6 pM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("THU 22 August 2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("FRi 22 Aug 2008 6:35AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,0,0}}, - parse("FRi 22 Aug 2008 6AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("Wednesday 22 Aug 2008 6:35 AM", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,35,0}}, - parse("Monday 22 Aug 2008 6:35", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,0,0}}, - parse("Monday 22 Aug 2008 6", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,0,0}}, - parse("Monday 22 Aug 2008 6p", ?DATE)), - ?_assertEqual({{2008,8,22}, {6,0,0}}, - parse("Monday 22 Aug 2008 6a", ?DATE)), - ?_assertEqual({{2008,8,22}, {18,35,0}}, - parse("Mon, 22 Aug 2008 6:35 PM", ?DATE)), - % Twitter style - ?_assertEqual({{2008,8,22}, {06,35,04}}, - parse("Mon Aug 22 06:35:04 +0000 2008", ?DATE)), - ?_assertEqual({{2008,8,22}, {06,35,04}}, - parse("Mon Aug 22 06:35:04 +0500 2008", ?DATE)) - ]. - -parse_with_TZ_test_() -> - [ - ?_assertEqual({{2008,8,22}, {17,16,17}}, - parse("Sat 22nd of August 2008 GMT", ?DATE)), - ?_assertEqual({{2008,8,22}, {17,16,17}}, - parse("Sat 22nd of August 2008 UTC", ?DATE)), - ?_assertEqual({{2008,8,22}, {17,16,17}}, - parse("Sat 22nd of August 2008 DST", ?DATE)) - ]. - -iso_test_() -> - [ - ?_assertEqual("2004 W53",format(?ISO,{{2005,1,1}, {1,1,1}})), - ?_assertEqual("2004 W53",format(?ISO,{{2005,1,2}, {1,1,1}})), - ?_assertEqual("2005 W52",format(?ISO,{{2005,12,31},{1,1,1}})), - ?_assertEqual("2007 W01",format(?ISO,{{2007,1,1}, {1,1,1}})), - ?_assertEqual("2007 W52",format(?ISO,{{2007,12,30},{1,1,1}})), - ?_assertEqual("2008 W01",format(?ISO,{{2007,12,31},{1,1,1}})), - ?_assertEqual("2008 W01",format(?ISO,{{2008,1,1}, {1,1,1}})), - ?_assertEqual("2009 W01",format(?ISO,{{2008,12,29},{1,1,1}})), - ?_assertEqual("2009 W01",format(?ISO,{{2008,12,31},{1,1,1}})), - ?_assertEqual("2009 W01",format(?ISO,{{2009,1,1}, {1,1,1}})), - ?_assertEqual("2009 W53",format(?ISO,{{2009,12,31},{1,1,1}})), - ?_assertEqual("2009 W53",format(?ISO,{{2010,1,3}, {1,1,1}})) - ]. - -ms_test_() -> - Now=os:timestamp(), - [ - ?_assertEqual({{2012,12,12}, {12,12,12,1234}}, parse("2012-12-12T12:12:12.001234")), - ?_assertEqual({{2012,12,12}, {12,12,12,123_000}}, parse("2012-12-12T12:12:12.123")), - ?_assertEqual(format("H:m:s.f \\m \\i\\s \\m\\o\\n\\t\\h",?DATEMS), - "17:03:17.123456 m is month"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",?DATEMS), - "2001-03-10T17:16:17.123456"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), - "2001-03-10T05:16:17.123456"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T05:16:17.123456")), - "2001-03-10T05:16:17.123456"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T15:16:17.123456")), - "2001-03-10T15:16:17.123456"), - ?_assertEqual(format("Y-m-d\\TH:i:s.f",nparse("2001-03-10T15:16:17.000123")), - "2001-03-10T15:16:17.000123"), - ?_assertEqual(Now, nparse(format("Y-m-d\\TH:i:s.f", Now))) - ]. - -zulu_test_() -> - [ - ?_assertEqual(format("Y-m-d\\TH:i:sZ",nparse("2001-03-10T15:16:17.123456")), - "2001-03-10T15:16:17Z"), - ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17Z")), - "2001-03-10T15:16:17"), - ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17+04")), - "2001-03-10T11:16:17"), - ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17+04:00")), - "2001-03-10T11:16:17"), - ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17-04")), - "2001-03-10T19:16:17"), - ?_assertEqual(format("Y-m-d\\TH:i:s",nparse("2001-03-10T15:16:17-04:00")), - "2001-03-10T19:16:17") - ]. - -format_iso8601_test_() -> - [ - ?_assertEqual("2001-03-10T17:16:17Z", - format_iso8601({{2001,3,10},{17,16,17}})), - ?_assertEqual("2001-03-10T17:16:17.000000Z", - format_iso8601({{2001,3,10},{17,16,17,0}})), - ?_assertEqual("2001-03-10T17:16:17.100000Z", - format_iso8601({{2001,3,10},{17,16,17,100_000}})), - ?_assertEqual("2001-03-10T17:16:17.120000Z", - format_iso8601({{2001,3,10},{17,16,17,120_000}})), - ?_assertEqual("2001-03-10T17:16:17.123000Z", - format_iso8601({{2001,3,10},{17,16,17,123_000}})), - ?_assertEqual("2001-03-10T17:16:17.123400Z", - format_iso8601({{2001,3,10},{17,16,17,123_400}})), - ?_assertEqual("2001-03-10T17:16:17.123450Z", - format_iso8601({{2001,3,10},{17,16,17,123_450}})), - ?_assertEqual("2001-03-10T17:16:17.123456Z", - format_iso8601({{2001,3,10},{17,16,17,123_456}})), - ?_assertEqual("2001-03-10T17:16:17.023456Z", - format_iso8601({{2001,3,10},{17,16,17,23_456}})), - ?_assertEqual("2001-03-10T17:16:17.003456Z", - format_iso8601({{2001,3,10},{17,16,17,3_456}})), - ?_assertEqual("2001-03-10T17:16:17.000456Z", - format_iso8601({{2001,3,10},{17,16,17,456}})), - ?_assertEqual("2001-03-10T17:16:17.000056Z", - format_iso8601({{2001,3,10},{17,16,17,56}})), - ?_assertEqual("2001-03-10T17:16:17.000006Z", - format_iso8601({{2001,3,10},{17,16,17,6}})), - ?_assertEqual("2001-03-10T07:16:17Z", - format_iso8601({{2001,3,10},{07,16,17}})), - ?_assertEqual("2001-03-10T07:16:17.000000Z", - format_iso8601({{2001,3,10},{07,16,17,0}})), - ?_assertEqual("2001-03-10T07:16:17.100000Z", - format_iso8601({{2001,3,10},{07,16,17,100_000}})), - ?_assertEqual("2001-03-10T07:16:17.120000Z", - format_iso8601({{2001,3,10},{07,16,17,120_000}})), - ?_assertEqual("2001-03-10T07:16:17.123000Z", - format_iso8601({{2001,3,10},{07,16,17,123_000}})), - ?_assertEqual("2001-03-10T07:16:17.123400Z", - format_iso8601({{2001,3,10},{07,16,17,123_400}})), - ?_assertEqual("2001-03-10T07:16:17.123450Z", - format_iso8601({{2001,3,10},{07,16,17,123_450}})), - ?_assertEqual("2001-03-10T07:16:17.123456Z", - format_iso8601({{2001,3,10},{07,16,17,123_456}})), - ?_assertEqual("2001-03-10T07:16:17.023456Z", - format_iso8601({{2001,3,10},{07,16,17,23_456}})), - ?_assertEqual("2001-03-10T07:16:17.003456Z", - format_iso8601({{2001,3,10},{07,16,17,3_456}})), - ?_assertEqual("2001-03-10T07:16:17.000456Z", - format_iso8601({{2001,3,10},{07,16,17,456}})), - ?_assertEqual("2001-03-10T07:16:17.000056Z", - format_iso8601({{2001,3,10},{07,16,17,56}})), - ?_assertEqual("2001-03-10T07:16:17.000006Z", - format_iso8601({{2001,3,10},{07,16,17,6}})) - ]. - -parse_iso8601_test_() -> - [ - ?_assertEqual({{2001,3,10},{17,16,17}}, - parse("2001-03-10T17:16:17Z")), - ?_assertEqual({{2001,3,10},{17,16,17,0}}, - parse("2001-03-10T17:16:17.000Z")), - ?_assertEqual({{2001,3,10},{17,16,17,0}}, - parse("2001-03-10T17:16:17.000000Z")), - ?_assertEqual({{2001,3,10},{17,16,17,100_000}}, - parse("2001-03-10T17:16:17.1Z")), - ?_assertEqual({{2001,3,10},{17,16,17,120_000}}, - parse("2001-03-10T17:16:17.12Z")), - ?_assertEqual({{2001,3,10},{17,16,17,123_000}}, - parse("2001-03-10T17:16:17.123Z")), - ?_assertEqual({{2001,3,10},{17,16,17,123_400}}, - parse("2001-03-10T17:16:17.1234Z")), - ?_assertEqual({{2001,3,10},{17,16,17,123_450}}, - parse("2001-03-10T17:16:17.12345Z")), - ?_assertEqual({{2001,3,10},{17,16,17,123_456}}, - parse("2001-03-10T17:16:17.123456Z")), - - ?_assertEqual({{2001,3,10},{15,16,17,100_000}}, - parse("2001-03-10T16:16:17.1+01:00")), - ?_assertEqual({{2001,3,10},{15,16,17,123_456}}, - parse("2001-03-10T16:16:17.123456+01:00")), - ?_assertEqual({{2001,3,10},{17,16,17,100_000}}, - parse("2001-03-10T16:16:17.1-01:00")), - ?_assertEqual({{2001,3,10},{17,16,17,123_456}}, - parse("2001-03-10T16:16:17.123456-01:00")), - - ?_assertEqual({{2001,3,10},{17,16,17,456}}, - parse("2001-03-10T17:16:17.000456Z")), - ?_assertEqual({{2001,3,10},{17,16,17,123_000}}, - parse("2001-03-10T17:16:17.123000Z")) - ]. - --endif. diff --git a/vendor/erlware_commons/src/ec_dict.erl b/vendor/erlware_commons/src/ec_dict.erl deleted file mode 100644 index 3e9418e68..000000000 --- a/vendor/erlware_commons/src/ec_dict.erl +++ /dev/null @@ -1,110 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright 2011 Erlware, LLC. -%%% @doc -%%% This provides an implementation of the ec_dictionary type using -%%% erlang dicts as a base. The function documentation for -%%% ec_dictionary applies here as well. -%%% see ec_dictionary -%%% see dict -%%% @end -%%%------------------------------------------------------------------- --module(ec_dict). - --behaviour(ec_dictionary). - -%% API --export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). - --export_type([dictionary/2]). - -%%%=================================================================== -%%% Types -%%%=================================================================== -%% This should be opaque, but that kills dialyzer so for now we export it -%% however you should not rely on the internal representation here --type dictionary(_K, _V) :: dict:dict(). - -%%%=================================================================== -%%% API -%%%=================================================================== - --spec new() -> dictionary(_K, _V). -new() -> - dict:new(). - --spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). -has_key(Key, Data) -> - dict:is_key(Key, Data). - --spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> - ec_dictionary:value(V). -get(Key, Data) -> - case dict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - throw(not_found) - end. - --spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - Object::dictionary(K, V)) -> - ec_dictionary:value(V). -get(Key, Default, Data) -> - case dict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - Default - end. - --spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::dictionary(K, V)) -> - dictionary(K, V). -add(Key, Value, Data) -> - dict:store(Key, Value, Data). - --spec remove(ec_dictionary:key(K), Object::dictionary(K, V)) -> - dictionary(K, V). -remove(Key, Data) -> - dict:erase(Key, Data). - --spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). -has_value(Value, Data) -> - dict:fold(fun(_, NValue, _) when NValue == Value -> - true; - (_, _, Acc) -> - Acc - end, - false, - Data). - --spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). -size(Data) -> - dict:size(Data). - --spec to_list(dictionary(K, V)) -> [{ec_dictionary:key(K), - ec_dictionary:value(V)}]. -to_list(Data) -> - dict:to_list(Data). - --spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - dictionary(K, V). -from_list(List) when is_list(List) -> - dict:from_list(List). - --spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. -keys(Dict) -> - dict:fetch_keys(Dict). diff --git a/vendor/erlware_commons/src/ec_dictionary.erl b/vendor/erlware_commons/src/ec_dictionary.erl deleted file mode 100644 index ea7fdc921..000000000 --- a/vendor/erlware_commons/src/ec_dictionary.erl +++ /dev/null @@ -1,153 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright 2011 Erlware, LLC. -%%% @doc -%%% A module that supports association of keys to values. A map cannot -%%% contain duplicate keys; each key can map to at most one value. -%%% -%%% This interface is a member of the Erlware Commons Library. -%%% @end -%%%------------------------------------------------------------------- --module(ec_dictionary). - -%% API --export([new/1, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/2, - keys/1]). - --export_type([dictionary/2, - key/1, - value/1]). - -%%%=================================================================== -%%% Types -%%%=================================================================== - --record(dict_t, - {callback, - data}). - -%% This should be opaque, but that kills dialyzer so for now we export it -%% however you should not rely on the internal representation here --type dictionary(_K, _V) :: #dict_t{}. --type key(T) :: T. --type value(T) :: T. - --callback new() -> any(). --callback has_key(key(any()), any()) -> boolean(). --callback get(key(any()), any()) -> any(). --callback add(key(any()), value(any()), T) -> T. --callback remove(key(any()), T) -> T. --callback has_value(value(any()), any()) -> boolean(). --callback size(any()) -> non_neg_integer(). --callback to_list(any()) -> [{key(any()), value(any())}]. --callback from_list([{key(any()), value(any())}]) -> any(). --callback keys(any()) -> [key(any())]. - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc create a new dictionary object from the specified module. The -%% module should implement the dictionary behaviour. -%% -%% @param ModuleName The module name. --spec new(module()) -> dictionary(_K, _V). -new(ModuleName) when is_atom(ModuleName) -> - #dict_t{callback = ModuleName, data = ModuleName:new()}. - -%% @doc check to see if the dictionary provided has the specified key. -%% -%% @param Dict The dictory object to check -%% @param Key The key to check the dictionary for --spec has_key(key(K), dictionary(K, _V)) -> boolean(). -has_key(Key, #dict_t{callback = Mod, data = Data}) -> - Mod:has_key(Key, Data). - -%% @doc given a key return that key from the dictionary. If the key is -%% not found throw a 'not_found' exception. -%% -%% @param Dict The dictionary object to return the value from -%% @param Key The key requested -%% when the key does not exist @throws not_found --spec get(key(K), dictionary(K, V)) -> value(V). -get(Key, #dict_t{callback = Mod, data = Data}) -> - Mod:get(Key, Data). - -%% @doc given a key return that key from the dictionary. If the key is -%% not found then the default value is returned. -%% -%% @param Dict The dictionary object to return the value from -%% @param Key The key requested -%% @param Default The value that will be returned if no value is found -%% in the database. --spec get(key(K), value(V), dictionary(K, V)) -> value(V). -get(Key, Default, #dict_t{callback = Mod, data = Data}) -> - Mod:get(Key, Default, Data). - -%% @doc add a new value to the existing dictionary. Return a new -%% dictionary containing the value. -%% -%% @param Dict the dictionary object to add too -%% @param Key the key to add -%% @param Value the value to add --spec add(key(K), value(V), dictionary(K, V)) -> dictionary(K, V). -add(Key, Value, #dict_t{callback = Mod, data = Data} = Dict) -> - Dict#dict_t{data = Mod:add(Key, Value, Data)}. - -%% @doc Remove a value from the dictionary returning a new dictionary -%% with the value removed. -%% -%% @param Dict the dictionary object to remove the value from -%% @param Key the key of the key/value pair to remove --spec remove(key(K), dictionary(K, V)) -> dictionary(K, V). -remove(Key, #dict_t{callback = Mod, data = Data} = Dict) -> - Dict#dict_t{data = Mod:remove(Key, Data)}. - -%% @doc Check to see if the value exists in the dictionary -%% -%% @param Dict the dictionary object to check -%% @param Value The value to check if exists --spec has_value(value(V), dictionary(_K, V)) -> boolean(). -has_value(Value, #dict_t{callback = Mod, data = Data}) -> - Mod:has_value(Value, Data). - -%% @doc return the current number of key value pairs in the dictionary -%% -%% @param Dict the object return the size for. --spec size(dictionary(_K, _V)) -> integer(). -size(#dict_t{callback = Mod, data = Data}) -> - Mod:size(Data). - -%% @doc Return the contents of this dictionary as a list of key value -%% pairs. -%% -%% @param Dict the base dictionary to make use of. --spec to_list(Dict::dictionary(K, V)) -> [{key(K), value(V)}]. -to_list(#dict_t{callback = Mod, data = Data}) -> - Mod:to_list(Data). - -%% @doc Create a new dictionary, of the specified implementation using -%% the list provided as the starting contents. -%% -%% @param ModuleName the type to create the dictionary from -%% @param List The list of key value pairs to start with --spec from_list(module(), [{key(K), value(V)}]) -> dictionary(K, V). -from_list(ModuleName, List) when is_list(List) -> - #dict_t{callback = ModuleName, data = ModuleName:from_list(List)}. - -%% @doc Return the keys of this dictionary as a list -%% -%% @param Dict the base dictionary to make use of. --spec keys(Dict::dictionary(K, _V)) -> [key(K)]. -keys(#dict_t{callback = Mod, data = Data}) -> - Mod:keys(Data). diff --git a/vendor/erlware_commons/src/ec_file.erl b/vendor/erlware_commons/src/ec_file.erl deleted file mode 100644 index 1feab58cf..000000000 --- a/vendor/erlware_commons/src/ec_file.erl +++ /dev/null @@ -1,377 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @copyright (C) 2011, Erlware LLC -%%% @doc -%%% Helper functions for working with files. -%%% @end -%%%------------------------------------------------------------------- --module(ec_file). - --export([ - exists/1, - copy/2, - copy/3, - copy_file_info/3, - insecure_mkdtemp/0, - mkdir_path/1, - mkdir_p/1, - find/2, - is_symlink/1, - is_dir/1, - type/1, - real_dir_path/1, - remove/1, - remove/2, - md5sum/1, - sha1sum/1, - read/1, - write/2, - write_term/2 - ]). - --export_type([ - option/0 - ]). - --include_lib("kernel/include/file.hrl"). - --define(CHECK_PERMS_MSG, - "Try checking that you have the correct permissions and try again~n"). - -%%============================================================================ -%% Types -%%============================================================================ --type file_info() :: mode | time | owner | group. --type option() :: recursive | {file_info, [file_info()]}. - -%%%=================================================================== -%%% API -%%%=================================================================== --spec exists(file:filename()) -> boolean(). -exists(Filename) -> - case file:read_file_info(Filename) of - {ok, _} -> - true; - {error, _Reason} -> - false - end. - -%% @doc copy an entire directory to another location. --spec copy(file:name(), file:name(), Options::[option()]) -> ok | {error, Reason::term()}. -copy(From, To, []) -> - copy_(From, To, []); -copy(From, To, Options) -> - case proplists:get_value(recursive, Options, false) of - true -> - case is_dir(From) of - false -> - copy_(From, To, Options); - true -> - make_dir_if_dir(To), - copy_subfiles(From, To, Options) - end; - false -> - copy_(From, To, Options) - end. - -%% @doc copy a file including timestamps,ownership and mode etc. --spec copy(From::file:filename(), To::file:filename()) -> ok | {error, Reason::term()}. -copy(From, To) -> - copy_(From, To, [{file_info, [mode, time, owner, group]}]). - -copy_(From, To, Options) -> - Linked - = case file:read_link(From) of - {ok, Linked0} -> Linked0; - {error, _} -> undefined - end, - case Linked =/= undefined orelse file:copy(From, To) of - true -> - file:make_symlink(Linked, To); - {ok, _} -> - copy_file_info(To, From, proplists:get_value(file_info, Options, [])); - {error, Error} -> - {error, {copy_failed, Error}} - end. - -copy_file_info(To, From, FileInfoToKeep) -> - case file:read_file_info(From) of - {ok, FileInfo} -> - case write_file_info(To, FileInfo, FileInfoToKeep) of - [] -> - ok; - Errors -> - {error, {write_file_info_failed_for, Errors}} - end; - {error, RFError} -> - {error, {read_file_info_failed, RFError}} - end. - -write_file_info(To, FileInfo, FileInfoToKeep) -> - WriteInfoFuns = [{mode, fun try_write_mode/2}, - {time, fun try_write_time/2}, - {group, fun try_write_group/2}, - {owner, fun try_write_owner/2}], - lists:foldl(fun(Info, Acc) -> - case proplists:get_value(Info, WriteInfoFuns, undefined) of - undefined -> - Acc; - F -> - case F(To, FileInfo) of - ok -> - Acc; - {error, Reason} -> - [{Info, Reason} | Acc] - end - end - end, [], FileInfoToKeep). - - -try_write_mode(To, #file_info{mode=Mode}) -> - file:write_file_info(To, #file_info{mode=Mode}). - -try_write_time(To, #file_info{atime=Atime, mtime=Mtime}) -> - file:write_file_info(To, #file_info{atime=Atime, mtime=Mtime}). - -try_write_owner(To, #file_info{uid=OwnerId}) -> - file:write_file_info(To, #file_info{uid=OwnerId}). - -try_write_group(To, #file_info{gid=OwnerId}) -> - file:write_file_info(To, #file_info{gid=OwnerId}). - -%% @doc return the MD5 digest of a string or a binary, -%% named after the UNIX utility. --spec md5sum(string() | binary()) -> string(). -md5sum(Value) -> - bin_to_hex(crypto:hash(md5, Value)). - -%% @doc return the SHA-1 digest of a string or a binary, -%% named after the UNIX utility. --spec sha1sum(string() | binary()) -> string(). -sha1sum(Value) -> - bin_to_hex(crypto:hash(sha, Value)). - -bin_to_hex(Bin) -> - hex(binary_to_list(Bin)). - -%% @doc delete a file. Use the recursive option for directories. -%%
-%% Example: remove("./tmp_dir", [recursive]).
-%% 
--spec remove(file:name(), Options::[option()]) -> ok | {error, Reason::term()}. -remove(Path, Options) -> - case lists:member(recursive, Options) of - false -> file:delete(Path); - true -> remove_recursive(Path, Options) - end. - - -%% @doc delete a file. --spec remove(file:name()) -> ok | {error, Reason::term()}. -remove(Path) -> - remove(Path, []). - -%% @doc indicates with a boolean if the path supplied refers to symlink. --spec is_symlink(file:name()) -> boolean(). -is_symlink(Path) -> - case file:read_link_info(Path) of - {ok, #file_info{type = symlink}} -> - true; - _ -> - false - end. - -is_dir(Path) -> - case file:read_file_info(Path) of - {ok, #file_info{type = directory}} -> - true; - _ -> - false - end. - -%% @doc returns the type of the file. --spec type(file:name()) -> file | symlink | directory | undefined. -type(Path) -> - case filelib:is_regular(Path) of - true -> - file; - false -> - case is_symlink(Path) of - true -> - symlink; - false -> - case is_dir(Path) of - true -> directory; - false -> undefined - end - end - - end. -%% @doc gets the real path of a directory. This is mostly useful for -%% resolving symlinks. Be aware that this temporarily changes the -%% current working directory to figure out what the actual path -%% is. That means that it can be quite slow. --spec real_dir_path(file:name()) -> file:name(). -real_dir_path(Path) -> - {ok, CurCwd} = file:get_cwd(), - ok = file:set_cwd(Path), - {ok, RealPath} = file:get_cwd(), - ok = file:set_cwd(CurCwd), - filename:absname(RealPath). - -%% @doc make a unique temporary directory. Similar function to BSD stdlib -%% function of the same name. --spec insecure_mkdtemp() -> TmpDirPath::file:name() | {error, term()}. -insecure_mkdtemp() -> - UniqueNumber = erlang:integer_to_list(erlang:trunc(rand:uniform() * 1_000_000_000_000)), - TmpDirPath = - filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]), - - case mkdir_path(TmpDirPath) of - ok -> TmpDirPath; - Error -> Error - end. - -%% @doc Makes a directory including parent dirs if they are missing. --spec mkdir_p(file:name()) -> ok | {error, Reason::term()}. -mkdir_p(Path) -> - %% We are exploiting a feature of ensuredir that that creates all - %% directories up to the last element in the filename, then ignores - %% that last element. This way we ensure that the dir is created - %% and not have any worries about path names - DirName = filename:join([filename:absname(Path), "tmp"]), - filelib:ensure_dir(DirName). - - -%% @doc Makes a directory including parent dirs if they are missing. --spec mkdir_path(file:name()) -> ok | {error, Reason::term()}. -mkdir_path(Path) -> - mkdir_p(Path). - - -%% @doc read a file from the file system. Provide UEX exception on failure. --spec read(FilePath::file:filename()) -> {ok, binary()} | {error, Reason::term()}. -read(FilePath) -> - %% Now that we are moving away from exceptions again this becomes - %% a bit redundant but we want to be backwards compatible as much - %% as possible in the api. - file:read_file(FilePath). - - -%% @doc write a file to the file system. Provide UEX exception on failure. --spec write(FileName::file:filename(), Contents::string()) -> ok | {error, Reason::term()}. -write(FileName, Contents) -> - %% Now that we are moving away from exceptions again this becomes - %% a bit redundant but we want to be backwards compatible as much - %% as possible in the api. - file:write_file(FileName, Contents). - -%% @doc write a term out to a file so that it can be consulted later. --spec write_term(file:filename(), term()) -> ok | {error, Reason::term()}. -write_term(FileName, Term) -> - write(FileName, lists:flatten(io_lib:fwrite("~p. ", [Term]))). - -%% @doc Finds files and directories that match the regexp supplied in -%% the TargetPattern regexp. --spec find(FromDir::file:name(), TargetPattern::string()) -> [file:name()]. -find([], _) -> - []; -find(FromDir, TargetPattern) -> - case is_dir(FromDir) of - false -> - case re:run(FromDir, TargetPattern) of - {match, _} -> [FromDir]; - _ -> [] - end; - true -> - FoundDir = case re:run(FromDir, TargetPattern) of - {match, _} -> [FromDir]; - _ -> [] - end, - List = find_in_subdirs(FromDir, TargetPattern), - FoundDir ++ List - end. -%%%=================================================================== -%%% Internal Functions -%%%=================================================================== --spec find_in_subdirs(file:name(), string()) -> [file:name()]. -find_in_subdirs(FromDir, TargetPattern) -> - lists:foldl(fun(CheckFromDir, Acc) - when CheckFromDir == FromDir -> - Acc; - (ChildFromDir, Acc) -> - case find(ChildFromDir, TargetPattern) of - [] -> Acc; - Res -> Res ++ Acc - end - end, - [], - sub_files(FromDir)). - - - --spec remove_recursive(file:name(), Options::list()) -> ok | {error, Reason::term()}. -remove_recursive(Path, Options) -> - case is_dir(Path) of - false -> - file:delete(Path); - true -> - lists:foreach(fun(ChildPath) -> - remove_recursive(ChildPath, Options) - end, sub_files(Path)), - file:del_dir(Path) - end. - --spec tmp() -> file:name(). -tmp() -> - case os:type() of - {win32, _} -> - case os:getenv("TEMP") of - false -> "./tmp"; - Val -> Val - end; - _ -> - case os:getenv("TMPDIR") of - false -> "/tmp"; - Val -> Val - end - end. - -%% Copy the subfiles of the From directory to the to directory. --spec copy_subfiles(file:name(), file:name(), [option()]) -> {error, Reason::term()} | ok. -copy_subfiles(From, To, Options) -> - Fun = - fun(ChildFrom) -> - ChildTo = filename:join([To, filename:basename(ChildFrom)]), - copy(ChildFrom, ChildTo, Options) - end, - lists:foreach(Fun, sub_files(From)). - --spec make_dir_if_dir(file:name()) -> ok | {error, Reason::term()}. -make_dir_if_dir(File) -> - case is_dir(File) of - true -> ok; - false -> mkdir_path(File) - end. - -%% @doc convert a list of integers into hex. --spec hex(string() | non_neg_integer()) -> string(). -hex(L) when is_list (L) -> - lists:flatten([hex(I) || I <- L]); -hex(I) when I > 16#f -> - [hex0((I band 16#f0) bsr 4), hex0((I band 16#0f))]; -hex(I) -> - [$0, hex0(I)]. - -hex0(10) -> $a; -hex0(11) -> $b; -hex0(12) -> $c; -hex0(13) -> $d; -hex0(14) -> $e; -hex0(15) -> $f; -hex0(I) -> $0 + I. - - -sub_files(From) -> - {ok, SubFiles} = file:list_dir(From), - [filename:join(From, SubFile) || SubFile <- SubFiles]. diff --git a/vendor/erlware_commons/src/ec_gb_trees.erl b/vendor/erlware_commons/src/ec_gb_trees.erl deleted file mode 100644 index cde3f1b9c..000000000 --- a/vendor/erlware_commons/src/ec_gb_trees.erl +++ /dev/null @@ -1,137 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright 2011 Erlware, LLC. -%%% @doc -%%% This provides an implementation of the type ec_dictionary using -%%% gb_trees as a backin -%%% see ec_dictionary -%%% see gb_trees -%%% @end -%%%------------------------------------------------------------------- --module(ec_gb_trees). - --behaviour(ec_dictionary). - -%% API --export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc create a new dictionary object from the specified module. The -%% module should implement the dictionary behaviour. In the clause -%% where an existing object is passed in new empty dictionary of the -%% same implementation is created and returned. -%% -%% @param ModuleName|Object The module name or existing dictionary object. --spec new() -> gb_trees:tree(_K, _V). -new() -> - gb_trees:empty(). - -%% @doc check to see if the dictionary provided has the specified key. -%% -%% @param Object The dictory object to check -%% @param Key The key to check the dictionary for --spec has_key(ec_dictionary:key(K), Object::gb_trees:tree(K, _V)) -> boolean(). -has_key(Key, Data) -> - case gb_trees:lookup(Key, Data) of - {value, _Val} -> - true; - none -> - false - end. - -%% @doc given a key return that key from the dictionary. If the key is -%% not found throw a 'not_found' exception. -%% -%% @param Object The dictionary object to return the value from -%% @param Key The key requested -%% when the key does not exist @throws not_found --spec get(ec_dictionary:key(K), Object::gb_trees:tree(K, V)) -> - ec_dictionary:value(V). -get(Key, Data) -> - case gb_trees:lookup(Key, Data) of - {value, Value} -> - Value; - none -> - throw(not_found) - end. - --spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - Object::gb_trees:tree(K, V)) -> - ec_dictionary:value(V). -get(Key, Default, Data) -> - case gb_trees:lookup(Key, Data) of - {value, Value} -> - Value; - none -> - Default - end. - -%% @doc add a new value to the existing dictionary. Return a new -%% dictionary containing the value. -%% -%% @param Object the dictionary object to add too -%% @param Key the key to add -%% @param Value the value to add --spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::gb_trees:tree(K, V)) -> - gb_trees:tree(K, V). -add(Key, Value, Data) -> - gb_trees:enter(Key, Value, Data). - -%% @doc Remove a value from the dictionary returning a new dictionary -%% with the value removed. -%% -%% @param Object the dictionary object to remove the value from -%% @param Key the key of the key/value pair to remove --spec remove(ec_dictionary:key(K), Object::gb_trees:tree(K, V)) -> - gb_trees:tree(K, V). -remove(Key, Data) -> - gb_trees:delete_any(Key, Data). - -%% @doc Check to see if the value exists in the dictionary -%% -%% @param Object the dictionary object to check -%% @param Value The value to check if exists --spec has_value(ec_dictionary:value(V), Object::gb_trees:tree(_K, V)) -> boolean(). -has_value(Value, Data) -> - lists:member(Value, gb_trees:values(Data)). - -%% @doc return the current number of key value pairs in the dictionary -%% -%% @param Object the object return the size for. --spec size(Object::gb_trees:tree(_K, _V)) -> non_neg_integer(). -size(Data) -> - gb_trees:size(Data). - --spec to_list(gb_trees:tree(K, V)) -> [{ec_dictionary:key(K), - ec_dictionary:value(V)}]. -to_list(Data) -> - gb_trees:to_list(Data). - --spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - gb_trees:tree(K, V). -from_list(List) when is_list(List) -> - lists:foldl(fun({Key, Value}, Dict) -> - gb_trees:enter(Key, Value, Dict) - end, - gb_trees:empty(), - List). - --spec keys(gb_trees:tree(K,_V)) -> [ec_dictionary:key(K)]. -keys(Data) -> - gb_trees:keys(Data). diff --git a/vendor/erlware_commons/src/ec_git_vsn.erl b/vendor/erlware_commons/src/ec_git_vsn.erl deleted file mode 100644 index e67d8e4c0..000000000 --- a/vendor/erlware_commons/src/ec_git_vsn.erl +++ /dev/null @@ -1,107 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright 2011 Erlware, LLC. -%%% @doc -%%% This provides an implementation of the ec_vsn for git. That is -%%% it is capable of returning a semver for a git repository -%%% see ec_vsn -%%% see ec_semver -%%% @end -%%%------------------------------------------------------------------- --module(ec_git_vsn). - --behaviour(ec_vsn). - -%% API --export([new/0, - vsn/1]). - --ifdef(TEST). --export([parse_tags/1, - get_patch_count/1, - collect_default_refcount/1 - ]). --endif. - --export_type([t/0]). - -%%%=================================================================== -%%% Types -%%%=================================================================== -%% This should be opaque, but that kills dialyzer so for now we export it -%% however you should not rely on the internal representation here --type t() :: {}. - -%%%=================================================================== -%%% API -%%%=================================================================== - --spec new() -> t(). -new() -> - {}. - --spec vsn(t()|string()) -> {ok, string()} | {error, Reason::any()}. -vsn(Data) -> - {Vsn, RawRef, RawCount} = collect_default_refcount(Data), - {ok, build_vsn_string(Vsn, RawRef, RawCount)}. - -%%%=================================================================== -%%% Internal Functions -%%%=================================================================== - -collect_default_refcount(Data) -> - %% Get the tag timestamp and minimal ref from the system. The - %% timestamp is really important from an ordering perspective. - RawRef = os:cmd("git log -n 1 --pretty=format:'%h\n' "), - - {Tag, TagVsn} = parse_tags(Data), - RawCount = - case Tag of - undefined -> - os:cmd("git rev-list --count HEAD"); - _ -> - get_patch_count(Tag) - end, - {TagVsn, RawRef, RawCount}. - -build_vsn_string(Vsn, RawRef, RawCount) -> - %% Cleanup the tag and the Ref information. Basically leading 'v's and - %% whitespace needs to go away. - RefTag = [".ref", re:replace(RawRef, "\\s", "", [global])], - Count = erlang:iolist_to_binary(re:replace(RawCount, "\\s", "", [global])), - - %% Create the valid [semver](http://semver.org) version from the tag - case Count of - <<"0">> -> - erlang:binary_to_list(erlang:iolist_to_binary(Vsn)); - _ -> - erlang:binary_to_list(erlang:iolist_to_binary([Vsn, "+build.", - Count, RefTag])) - end. - -get_patch_count(RawRef) -> - Ref = re:replace(RawRef, "\\s", "", [global]), - Cmd = io_lib:format("git rev-list --count ~ts..HEAD", - [Ref]), - case os:cmd(Cmd) of - "fatal: " ++ _ -> - 0; - Count -> - Count - end. - --spec parse_tags(t()|string()) -> {string()|undefined, ec_semver:version_string()}. -parse_tags({}) -> - parse_tags(""); -parse_tags(Pattern) -> - Cmd = io_lib:format("git describe --abbrev=0 --tags --match \"~ts*\"", [Pattern]), - Tag = os:cmd(Cmd), - case Tag of - "fatal: " ++ _ -> - {undefined, ""}; - _ -> - Vsn = string:slice(Tag, string:length(Pattern)), - Vsn1 = string:trim(string:trim(Vsn, leading, "v"), trailing, "\n"), - {Tag, Vsn1} - end. diff --git a/vendor/erlware_commons/src/ec_lists.erl b/vendor/erlware_commons/src/ec_lists.erl deleted file mode 100644 index fed76d096..000000000 --- a/vendor/erlware_commons/src/ec_lists.erl +++ /dev/null @@ -1,65 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @copyright (C) 2011, Erlware LLC -%%% @doc -%%% Provides useful functionionality on standard lists that are -%%% not provided in the standard library. -%%% @end -%%%------------------------------------------------------------------- --module(ec_lists). - -%% API --export([find/2, - fetch/2, - search/2]). - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc Search each value in the list with the specified -%% function. When the function returns a value of {ok, term()} the -%% search function stops and returns a tuple of {ok, term(), term()}, -%% where the second value is the term returned from the function and -%% the third value is the element passed to the function. The purpose -%% of this is to allow a list to be searched where some internal state -%% is important while the input element is not. --spec search(fun(), list()) -> {ok, Result::term(), Element::term()} | not_found. -search(Fun, [H|T]) -> - case Fun(H) of - {ok, Value} -> - {ok, Value, H}; - not_found -> - search(Fun, T) - end; -search(_, []) -> - not_found. - -%% @doc Find a value in the list with the specified function. If the -%% function returns the atom true, the value is returned as {ok, -%% term()} and processing is aborted, if the function returns false, -%% processing continues until the end of the list. If the end is found -%% and the function never returns true the atom error is returned. --spec find(fun(), list()) -> {ok, term()} | error. -find(Fun, [Head|Tail]) when is_function(Fun) -> - case Fun(Head) of - true -> - {ok, Head}; - false -> - find(Fun, Tail) - end; -find(_Fun, []) -> - error. - -%% @doc Fetch a value from the list. If the function returns true the -%% value is returned. If processing reaches the end of the list and -%% the function has never returned true an exception not_found is -%% thrown. --spec fetch(fun(), list()) -> term(). -fetch(Fun, List) when is_list(List), is_function(Fun) -> - case find(Fun, List) of - {ok, Head} -> - Head; - error -> - throw(not_found) - end. diff --git a/vendor/erlware_commons/src/ec_orddict.erl b/vendor/erlware_commons/src/ec_orddict.erl deleted file mode 100644 index 90418f5ea..000000000 --- a/vendor/erlware_commons/src/ec_orddict.erl +++ /dev/null @@ -1,110 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright 2011 Erlware, LLC. -%%% @doc -%%% This provides an implementation of the ec_dictionary type using -%%% erlang orddicts as a base. The function documentation for -%%% ec_dictionary applies here as well. -%%% see ec_dictionary -%%% see orddict -%%% @end -%%%------------------------------------------------------------------- --module(ec_orddict). - --behaviour(ec_dictionary). - -%% API --export([new/0, - has_key/2, - get/2, - get/3, - add/3, - remove/2, - has_value/2, - size/1, - to_list/1, - from_list/1, - keys/1]). - --export_type([dictionary/2]). - -%%%=================================================================== -%%% Types -%%%=================================================================== -%% This should be opaque, but that kills dialyzer so for now we export it -%% however you should not rely on the internal representation here --type dictionary(K, V) :: [{K, V}]. - -%%%=================================================================== -%%% API -%%%=================================================================== - --spec new() -> dictionary(_K, _V). -new() -> - orddict:new(). - --spec has_key(ec_dictionary:key(K), Object::dictionary(K, _V)) -> boolean(). -has_key(Key, Data) -> - orddict:is_key(Key, Data). - --spec get(ec_dictionary:key(K), Object::dictionary(K, V)) -> - ec_dictionary:value(V). -get(Key, Data) -> - case orddict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - throw(not_found) - end. - --spec get(ec_dictionary:key(K), - Default::ec_dictionary:value(V), - Object::dictionary(K, V)) -> - ec_dictionary:value(V). -get(Key, Default, Data) -> - case orddict:find(Key, Data) of - {ok, Value} -> - Value; - error -> - Default - end. - --spec add(ec_dictionary:key(K), ec_dictionary:value(V), - Object::dictionary(K, V)) -> - dictionary(K, V). -add(Key, Value, Data) -> - orddict:store(Key, Value, Data). - --spec remove(ec_dictionary:key(K), Object::dictionary(K, V)) -> - dictionary(K, V). -remove(Key, Data) -> - orddict:erase(Key, Data). - --spec has_value(ec_dictionary:value(V), Object::dictionary(_K, V)) -> boolean(). -has_value(Value, Data) -> - orddict:fold(fun(_, NValue, _) when NValue == Value -> - true; - (_, _, Acc) -> - Acc - end, - false, - Data). - --spec size(Object::dictionary(_K, _V)) -> non_neg_integer(). -size(Data) -> - orddict:size(Data). - --spec to_list(dictionary(K, V)) -> - [{ec_dictionary:key(K), ec_dictionary:value(V)}]. -to_list(Data) -> - orddict:to_list(Data). - --spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - dictionary(K, V). -from_list(List) when is_list(List) -> - orddict:from_list(List). - --spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. -keys(Dict) -> - orddict:fetch_keys(Dict). diff --git a/vendor/erlware_commons/src/ec_plists.erl b/vendor/erlware_commons/src/ec_plists.erl deleted file mode 100644 index 221075bcc..000000000 --- a/vendor/erlware_commons/src/ec_plists.erl +++ /dev/null @@ -1,945 +0,0 @@ -%%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- -%%% vi:ts=4 sw=4 et -%%% The MIT License -%%% -%%% Copyright (c) 2007 Stephen Marsh -%%% -%%% Permission is hereby granted, free of charge, to any person obtaining a copy -%%% of this software and associated documentation files (the "Software"), to deal -%%% in the Software without restriction, including without limitation the rights -%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -%%% copies of the Software, and to permit persons to whom the Software is -%%% furnished to do so, subject to the following conditions: -%%% -%%% The above copyright notice and this permission notice shall be included in -%%% all copies or substantial portions of the Software. -%%% -%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -%%% THE SOFTWARE. -%%%--------------------------------------------------------------------------- -%%% @author Stephen Marsh -%%% @copyright 2007 Stephen Marsh freeyourmind ++ [$@|gmail.com] -%%% @doc -%%% plists is a drop-in replacement for module lists, making -%%% most list operations parallel. It can operate on each element in -%%% parallel, for IO-bound operations, on sublists in parallel, for -%%% taking advantage of multi-core machines with CPU-bound operations, -%%% and across erlang nodes, for parallelizing inside a cluster. It -%%% handles errors and node failures. It can be configured, tuned, and -%%% tweaked to get optimal performance while minimizing overhead. -%%% -%%% Almost all the functions are identical to equivalent functions in -%%% lists, returning exactly the same result, and having both a form -%%% with an identical syntax that operates on each element in parallel -%%% and a form which takes an optional "malt", a specification for how -%%% to parallelize the operation. -%%% -%%% fold is the one exception, parallel fold is different from linear -%%% fold. This module also include a simple mapreduce implementation, -%%% and the function runmany. All the other functions are implemented -%%% with runmany, which is as a generalization of parallel list -%%% operations. -%%% -%%% Malts -%%% ===== -%%% -%%% A malt specifies how to break a list into sublists, and can optionally -%%% specify a timeout, which nodes to run on, and how many processes to start -%%% per node. -%%% -%%% Malt = MaltComponent | [MaltComponent] -%%% MaltComponent = SubListSize::integer() | {processes, integer()} | -%%% {processes, schedulers} | -%%% {timeout, Milliseconds::integer()} | {nodes, [NodeSpec]}
-%%% -%%% NodeSpec = Node::atom() | {Node::atom(), NumProcesses::integer()} | -%%% {Node::atom(), schedulers} -%%% -%%% An integer can be given to specify the exact size for sublists. 1 -%%% is a good choice for IO-bound operations and when the operation on -%%% each list element is expensive. Larger numbers minimize overhead -%%% and are faster for cheap operations. -%%% -%%% If the integer is omitted, and you have specified a `{processes, -%%% X}`, the list is split into X sublists. This is only useful when -%%% the time to process each element is close to identical and you -%%% know exactly how many lines of execution are available to you. -%%% -%%% If neither of the above applies, the sublist size defaults to 1. -%%% -%%% You can use `{processes, X}` to have the list processed by `X` -%%% processes on the local machine. A good choice for `X` is the -%%% number of lines of execution (cores) the machine provides. This -%%% can be done automatically with {processes, schedulers}, which sets -%%% the number of processes to the number of schedulers in the erlang -%%% virtual machine (probably equal to the number of cores). -%%% -%%% `{timeout, Milliseconds}` specifies a timeout. This is a timeout -%%% for the entire operation, both operating on the sublists and -%%% combining the results. exit(timeout) is evaluated if the timeout -%%% is exceeded. -%%% -%%% `{nodes, NodeList}` specifies that the operation should be done -%%% across nodes. Every element of NodeList is of the form -%%% `{NodeName, NumProcesses}` or NodeName, which means the same as -%%% `{NodeName, 1}`. plists runs NumProcesses processes on NodeName -%%% concurrently. A good choice for NumProcesses is the number of -%%% lines of execution (cores) a node provides plus one. This ensures -%%% the node is completely busy even when fetching a new sublist. This -%%% can be done automatically with `{NodeName, schedulers}`, in which -%%% case plists uses a cached value if it has one, and otherwise finds -%%% the number of schedulers in the remote node and adds one. This -%%% will ensure at least one busy process per core (assuming the node -%%% has a scheduler for each core). -%%% -%%% plists is able to recover if a node goes down. If all nodes go -%%% down, exit(allnodescrashed) is evaluated. -%%% -%%% Any of the above may be used as a malt, or may be combined into a -%%% list. `{nodes, NodeList}` and {processes, X} may not be combined. -%%% -%%% Examples -%%% ======== -%%% -%%% %%start a process for each element (1-element sublists)< -%%% 1 -%%% -%%% %% start a process for each ten elements (10-element sublists) -%%% 10 -%%% -%%% %% split the list into two sublists and process in two processes -%%% {processes, 2} -%%% -%%% %% split the list into X sublists and process in X processes, -%%% %% where X is the number of cores in the machine -%%% {processes, schedulers} -%%% -%%% %% split the list into 10-element sublists and process in two processes -%%% [10, {processes, 2}] -%%% -%%% %% timeout after one second. Assumes that a process should be started -%%% %% for each element.
-%%% {timeout, 1000} -%%% -%%% %% Runs 3 processes at a time on apple@desktop, and 2 on orange@laptop -%%% %% This is the best way to utilize all the CPU-power of a dual-core
-%%% %% desktop and a single-core laptop. Assumes that the list should be
-%%% %% split into 1-element sublists.
-%%% {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]} -%%% -%%% %% Like above, but makes plists figure out how many processes to use. -%%% {nodes, [{apple@desktop, schedulers}, {orange@laptop, schedulers}]} -%%% -%%% %% Gives apple and orange three seconds to process the list as
-%%% %% 100-element sublists.
-%%% [100, {timeout, 3000}, {nodes, [{apple@desktop, 3}, {orange@laptop, 2}]}] -%%% -%%% Aside: Why Malt? -%%% ================ -%%% -%%% I needed a word for this concept, so maybe my subconsciousness -%%% gave me one by making me misspell multiply. Maybe it is an acronym -%%% for Malt is A List Tearing Specification. Maybe it is a beer -%%% metaphor, suggesting that code only runs in parallel if bribed -%%% with spirits. It's jargon, learn it or you can't be part of the -%%% in-group. -%%% -%%% Messages and Errors -%%% =================== -%%% -%%% plists assures that no extraneous messages are left in or will -%%% later enter the message queue. This is guaranteed even in the -%%% event of an error. -%%% -%%% Errors in spawned processes are caught and propagated to the -%%% calling process. If you invoke -%%% -%%% plists:map(fun (X) -> 1/X end, [1, 2, 3, 0]). -%%% -%%% you get a badarith error, exactly like when you use lists:map. -%%% -%%% plists uses monitors to watch the processes it spawns. It is not a -%%% good idea to invoke plists when you are already monitoring -%%% processes. If one of them does a non-normal exit, plists receives -%%% the 'DOWN' message believing it to be from one of its own -%%% processes. The error propagation system goes into effect, which -%%% results in the error occurring in the calling process. -%%% --module(ec_plists). - --export([all/2, all/3, - any/2, any/3, - filter/2, filter/3, - fold/3, fold/4, fold/5, - foreach/2, foreach/3, - map/2, map/3, - ftmap/2, ftmap/3, - partition/2, partition/3, - sort/1, sort/2, sort/3, - usort/1, usort/2, usort/3, - mapreduce/2, mapreduce/3, mapreduce/5, - runmany/3, runmany/4]). - --export_type([malt/0, malt_component/0, node_spec/0, fuse/0, fuse_fun/0]). - -%%============================================================================ -%% types -%%============================================================================ - --type malt() :: malt_component() | [malt_component()]. - --type malt_component() :: SubListSize::integer() - | {processes, integer()} - | {processes, schedulers} - | {timeout, Milliseconds::integer()} - | {nodes, [node_spec()]}. - --type node_spec() :: Node::atom() - | {Node::atom(), NumProcesses::integer()} - | {Node::atom(), schedulers}. - --type fuse_fun() :: fun((term(), term()) -> term()). --type fuse() :: fuse_fun() | {recursive, fuse_fun()} | {reverse, fuse_fun()}. --type el_fun() :: fun((term()) -> term()). - -%%============================================================================ -%% API -%%============================================================================ - -%% Everything here is defined in terms of runmany. -%% The following methods are convient interfaces to runmany. - -%% @doc Same semantics as in module -%% lists. --spec all(el_fun(), list()) -> boolean(). -all(Fun, List) -> - all(Fun, List, 1). - -%% @doc Same semantics as in module -%% lists. --spec all(el_fun(), list(), malt()) -> boolean(). -all(Fun, List, Malt) -> - try - runmany(fun (L) -> - B = lists:all(Fun, L), - if - B -> - nil; - true -> - erlang:throw(notall) - end - end, - fun (_A1, _A2) -> - nil - end, - List, Malt), - true - catch - throw:notall -> - false - end. - -%% @doc Same semantics as in module -%% lists. --spec any(fun(), list()) -> boolean(). -any(Fun, List) -> - any(Fun, List, 1). - -%% @doc Same semantics as in module -%% lists. --spec any(fun(), list(), malt()) -> boolean(). -any(Fun, List, Malt) -> - try - runmany(fun (L) -> - B = lists:any(Fun, L), - if B -> - erlang:throw(any); - true -> - nil - end - end, - fun (_A1, _A2) -> - nil - end, - List, Malt) of - _ -> - false - catch throw:any -> - true - end. - -%% @doc Same semantics as in module -%% lists. --spec filter(fun(), list()) -> list(). -filter(Fun, List) -> - filter(Fun, List, 1). - -%% @doc Same semantics as in module -%% lists. --spec filter(fun(), list(), malt()) -> list(). -filter(Fun, List, Malt) -> - runmany(fun (L) -> - lists:filter(Fun, L) - end, - {reverse, fun (A1, A2) -> - A1 ++ A2 - end}, - List, Malt). - -%% Note that with parallel fold there is not foldl and foldr, -%% instead just one fold that can fuse Accumlators. - -%% @doc Like below, but assumes 1 as the Malt. This function is almost useless, -%% and is intended only to aid converting code from using lists to plists. --spec fold(fun(), InitAcc::term(), list()) -> term(). -fold(Fun, InitAcc, List) -> - fold(Fun, Fun, InitAcc, List, 1). - -%% @doc Like below, but uses the Fun as the Fuse by default. --spec fold(fun(), InitAcc::term(), list(), malt()) -> term(). -fold(Fun, InitAcc, List, Malt) -> - fold(Fun, Fun, InitAcc, List, Malt). - -%% @doc fold is more complex when made parallel. There is no foldl and -%% foldr, accumulators aren't passed in any defined order. The list -%% is split into sublists which are folded together. Fun is identical -%% to the function passed to lists:fold[lr], it takes (an element, and -%% the accumulator) and returns -> a new accumulator. It is used for -%% the initial stage of folding sublists. Fuse fuses together the -%% results, it takes (Results1, Result2) and returns -> a new result. -%% By default sublists are fused left to right, each result of a fuse -%% being fed into the first element of the next fuse. The result of -%% the last fuse is the result. -%% -%% Fusing may also run in parallel using a recursive algorithm, -%% by specifying the fuse as {recursive, Fuse}. See -%% the discussion in {@link runmany/4}. -%% -%% Malt is the malt for the initial folding of sublists, and for the -%% possible recursive fuse. --spec fold(fun(), fuse(), InitAcc::term(), list(), malt()) -> term(). -fold(Fun, Fuse, InitAcc, List, Malt) -> - Fun2 = fun (L) -> - lists:foldl(Fun, InitAcc, L) - end, - runmany(Fun2, Fuse, List, Malt). - -%% @doc Similar to foreach in module -%% lists -%% except it makes no guarantee about the order it processes list elements. --spec foreach(fun(), list()) -> ok. -foreach(Fun, List) -> - foreach(Fun, List, 1). - -%% @doc Similar to foreach in module -%% lists -%% except it makes no guarantee about the order it processes list elements. --spec foreach(fun(), list(), malt()) -> ok. -foreach(Fun, List, Malt) -> - runmany(fun (L) -> - lists:foreach(Fun, L) - end, - fun (_A1, _A2) -> - ok - end, - List, Malt). - -%% @doc Same semantics as in module -%% lists. --spec map(fun(), list()) -> list(). -map(Fun, List) -> - map(Fun, List, 1). - -%% @doc Same semantics as in module -%% lists. --spec map(fun(), list(), malt()) -> list(). -map(Fun, List, Malt) -> - runmany(fun (L) -> - lists:map(Fun, L) - end, - {reverse, fun (A1, A2) -> - A1 ++ A2 - end}, - List, Malt). - -%% @doc values are returned as {value, term()}. --spec ftmap(fun(), list()) -> list(). -ftmap(Fun, List) -> - map(fun(L) -> - try - {value, Fun(L)} - catch - Class:Type -> - {error, {Class, Type}} - end - end, List). - -%% @doc values are returned as {value, term()}. --spec ftmap(fun(), list(), malt()) -> list(). -ftmap(Fun, List, Malt) -> - map(fun(L) -> - try - {value, Fun(L)} - catch - Class:Type -> - {error, {Class, Type}} - end - end, List, Malt). - -%% @doc Same semantics as in module -%% lists. --spec partition(fun(), list()) -> {list(), list()}. -partition(Fun, List) -> - partition(Fun, List, 1). - -%% @doc Same semantics as in module -%% lists. --spec partition(fun(), list(), malt()) -> {list(), list()}. -partition(Fun, List, Malt) -> - runmany(fun (L) -> - lists:partition(Fun, L) - end, - {reverse, fun ({True1, False1}, {True2, False2}) -> - {True1 ++ True2, False1 ++ False2} - end}, - List, Malt). - -%% SORTMALT needs to be tuned --define(SORTMALT, 100). - -%% @doc Same semantics as in module -%% lists. --spec sort(list()) -> list(). -sort(List) -> - sort(fun (A, B) -> - A =< B - end, - List). - -%% @doc Same semantics as in module -%% lists. --spec sort(fun(), list()) -> list(). -sort(Fun, List) -> - sort(Fun, List, ?SORTMALT). - -%% @doc This version lets you specify your own malt for sort. -%% -%% sort splits the list into sublists and sorts them, and it merges the -%% sorted lists together. These are done in parallel. Each sublist is -%% sorted in a separate process, and each merging of results is done in a -%% separate process. Malt defaults to 100, causing the list to be split into -%% 100-element sublists. --spec sort(fun(), list(), malt()) -> list(). -sort(Fun, List, Malt) -> - Fun2 = fun (L) -> - lists:sort(Fun, L) - end, - Fuse = fun (A1, A2) -> - lists:merge(Fun, A1, A2) - end, - runmany(Fun2, {recursive, Fuse}, List, Malt). - -%% @doc Same semantics as in module -%% lists. --spec usort(list()) -> list(). -usort(List) -> - usort(fun (A, B) -> - A =< B - end, - List). - -%% @doc Same semantics as in module -%% lists. --spec usort(fun(), list()) -> list(). -usort(Fun, List) -> - usort(Fun, List, ?SORTMALT). - -%% @doc This version lets you specify your own malt for usort. -%% -%% usort splits the list into sublists and sorts them, and it merges the -%% sorted lists together. These are done in parallel. Each sublist is -%% sorted in a separate process, and each merging of results is done in a -%% separate process. Malt defaults to 100, causing the list to be split into -%% 100-element sublists. -%% -%% usort removes duplicate elements while it sorts. --spec usort(fun(), list(), malt()) -> list(). -usort(Fun, List, Malt) -> - Fun2 = fun (L) -> - lists:usort(Fun, L) - end, - Fuse = fun (A1, A2) -> - lists:umerge(Fun, A1, A2) - end, - runmany(Fun2, {recursive, Fuse}, List, Malt). - -%% @doc Like below, assumes default MapMalt of 1. --spec mapreduce(MapFunc, list()) -> dict:dict() when - MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), - DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}. - -mapreduce(MapFunc, List) -> - mapreduce(MapFunc, List, 1). - -%% Like below, but uses a default reducer that collects all -%% {Key, Value} pairs into a -%% dict, -%% with values {Key, [Value1, Value2...]}. -%% This dict is returned as the result. -mapreduce(MapFunc, List, MapMalt) -> - mapreduce(MapFunc, List, dict:new(), fun add_key/3, MapMalt). - -%% @doc This is a very basic mapreduce. You won't write a -%% Google-rivaling search engine with it. It has no equivalent in -%% lists. Each element in the list is run through the MapFunc, which -%% produces either a {Key, Value} pair, or a lists of key value pairs, -%% or a list of lists of key value pairs...etc. A reducer process runs -%% in parallel with the mapping processes, collecting the key value -%% pairs. It starts with a state given by InitState, and for each -%% {Key, Value} pair that it receives it invokes ReduceFunc(OldState, -%% Key, Value) to compute its new state. mapreduce returns the -%% reducer's final state. -%% -%% MapMalt is the malt for the mapping operation, with a default value of 1, -%% meaning each element of the list is mapped by a separate process. -%% -%% mapreduce requires OTP R11B, or it may leave monitoring messages in the -%% message queue. --spec mapreduce(MapFunc, list(), InitState::term(), ReduceFunc, malt()) -> dict:dict() when - MapFunc :: fun((term()) -> DeepListOfKeyValuePairs), - DeepListOfKeyValuePairs :: [DeepListOfKeyValuePairs] | {Key::term(), Value::term()}, - ReduceFunc :: fun((OldState::term(), Key::term(), Value::term()) -> NewState::term()). -mapreduce(MapFunc, List, InitState, ReduceFunc, MapMalt) -> - Parent = self(), - {Reducer, ReducerRef} = - erlang:spawn_monitor(fun () -> - reducer(Parent, 0, InitState, ReduceFunc) - end), - MapFunc2 = fun (L) -> - Reducer ! lists:map(MapFunc, L), - 1 - end, - SentMessages = try - runmany(MapFunc2, fun (A, B) -> A+B end, List, MapMalt) - catch - exit:Reason -> - erlang:demonitor(ReducerRef, [flush]), - Reducer ! die, - exit(Reason) - end, - Reducer ! {mappers, done, SentMessages}, - Results = receive - {Reducer, Results2} -> - Results2; - {'DOWN', _, _, Reducer, Reason2} -> - exit(Reason2) - end, - receive - {'DOWN', _, _, Reducer, normal} -> - nil - end, - Results. - -reducer(Parent, NumReceived, State, Func) -> - receive - die -> - nil; - {mappers, done, NumReceived} -> - Parent ! {self (), State}; - Keys -> - reducer(Parent, NumReceived + 1, each_key(State, Func, Keys), Func) - end. - -each_key(State, Func, {Key, Value}) -> - Func(State, Key, Value); -each_key(State, Func, [List|Keys]) -> - each_key(each_key(State, Func, List), Func, Keys); -each_key(State, _, []) -> - State. - -add_key(Dict, Key, Value) -> - case dict:is_key(Key, Dict) of - true -> - dict:append(Key, Value, Dict); - false -> - dict:store(Key, [Value], Dict) - end. - -%% @doc Like below, but assumes a Malt of 1, -%% meaning each element of the list is processed by a separate process. --spec runmany(fun(), fuse(), list()) -> term(). -runmany(Fun, Fuse, List) -> - runmany(Fun, Fuse, List, 1). - -%% Begin internal stuff (though runmany/4 is exported). - -%% @doc All of the other functions are implemented with runmany. runmany -%% takes a List, splits it into sublists, and starts processes to operate on -%% each sublist, all done according to Malt. Each process passes its sublist -%% into Fun and sends the result back. -%% -%% The results are then fused together to get the final result. There are two -%% ways this can operate, lineraly and recursively. If Fuse is a function, -%% a fuse is done linearly left-to-right on the sublists, the results -%% of processing the first and second sublists being passed to Fuse, then -%% the result of the first fuse and processing the third sublits, and so on. If -%% Fuse is {reverse, FuseFunc}, then a fuse is done right-to-left, the results -%% of processing the second-to-last and last sublists being passed to FuseFunc, -%% then the results of processing the third-to-last sublist and -%% the results of the first fuse, and and so forth. -%% Both methods preserve the original order of the lists elements. -%% -%% To do a recursive fuse, pass Fuse as {recursive, FuseFunc}. -%% The recursive fuse makes no guarantee about the order the results of -%% sublists, or the results of fuses are passed to FuseFunc. It -%% continues fusing pairs of results until it is down to one. -%% -%% Recursive fuse is down in parallel with processing the sublists, and a -%% process is spawned to fuse each pair of results. It is a parallelized -%% algorithm. Linear fuse is done after all results of processing sublists -%% have been collected, and can only run in a single process. -%% -%% Even if you pass {recursive, FuseFunc}, a recursive fuse is only done if -%% the malt contains {nodes, NodeList} or {processes, X}. If this is not the -%% case, a linear fuse is done. --spec runmany(fun(([term()]) -> term()), fuse(), list(), malt()) -> term(). -runmany(Fun, Fuse, List, Malt) - when erlang:is_list(Malt) -> - runmany(Fun, Fuse, List, local, no_split, Malt); -runmany(Fun, Fuse, List, Malt) -> - runmany(Fun, Fuse, List, [Malt]). - -runmany(Fun, Fuse, List, Nodes, no_split, [MaltTerm|Malt]) - when erlang:is_integer(MaltTerm) -> - runmany(Fun, Fuse, List, Nodes, MaltTerm, Malt); -runmany(Fun, Fuse, List, local, Split, [{processes, schedulers}|Malt]) -> - %% run a process for each scheduler - S = erlang:system_info(schedulers), - runmany(Fun, Fuse, List, local, Split, [{processes, S}|Malt]); -runmany(Fun, Fuse, List, local, no_split, [{processes, X}|_]=Malt) -> - %% Split the list into X sublists, where X is the number of processes - L = erlang:length(List), - case (L rem X) of - 0 -> - runmany(Fun, Fuse, List, local, (L / X), Malt); - _ -> - runmany(Fun, Fuse, List, local, (L / X) + 1, Malt) - end; -runmany(Fun, Fuse, List, local, Split, [{processes, X}|Malt]) -> - %% run X process on local machine - Nodes = lists:duplicate(X, node()), - runmany(Fun, Fuse, List, Nodes, Split, Malt); -runmany(Fun, Fuse, List, Nodes, Split, [{timeout, X}|Malt]) -> - Parent = erlang:self(), - Timer = proc_lib:spawn(fun () -> - receive - stoptimer -> - Parent ! {timerstopped, erlang:self()} - after X -> - Parent ! {timerrang, erlang:self()}, - receive - stoptimer -> - Parent ! {timerstopped, erlang:self()} - end - end - end), - Ans = try - runmany(Fun, Fuse, List, Nodes, Split, Malt) - catch - %% we really just want the after block, the syntax - %% makes this catch necessary. - willneverhappen -> - nil - after - Timer ! stoptimer, - cleanup_timer(Timer) - end, - Ans; -runmany(Fun, Fuse, List, local, Split, [{nodes, NodeList}|Malt]) -> - Nodes = lists:foldl(fun ({Node, schedulers}, A) -> - X = schedulers_on_node(Node) + 1, - lists:reverse(lists:duplicate(X, Node), A); - ({Node, X}, A) -> - lists:reverse(lists:duplicate(X, Node), A); - (Node, A) -> - [Node|A] - end, - [], NodeList), - runmany(Fun, Fuse, List, Nodes, Split, Malt); -runmany(Fun, {recursive, Fuse}, List, local, Split, []) -> - %% local recursive fuse, for when we weren't invoked with {processes, X} - %% or {nodes, NodeList}. Degenerates recursive fuse into linear fuse. - runmany(Fun, Fuse, List, local, Split, []); -runmany(Fun, Fuse, List, Nodes, no_split, []) -> - %% by default, operate on each element separately - runmany(Fun, Fuse, List, Nodes, 1, []); -runmany(Fun, Fuse, List, local, Split, []) -> - List2 = splitmany(List, Split), - local_runmany(Fun, Fuse, List2); -runmany(Fun, Fuse, List, Nodes, Split, []) -> - List2 = splitmany(List, Split), - cluster_runmany(Fun, Fuse, List2, Nodes). - -cleanup_timer(Timer) -> - receive - {timerrang, Timer} -> - cleanup_timer(Timer); - {timerstopped, Timer} -> - nil - end. - -schedulers_on_node(Node) -> - case erlang:get(ec_plists_schedulers_on_nodes) of - undefined -> - X = determine_schedulers(Node), - erlang:put(ec_plists_schedulers_on_nodes, - dict:store(Node, X, dict:new())), - X; - Dict -> - case dict:is_key(Node, Dict) of - true -> - dict:fetch(Node, Dict); - false -> - X = determine_schedulers(Node), - erlang:put(ec_plists_schedulers_on_nodes, - dict:store(Node, X, Dict)), - X - end - end. - -determine_schedulers(Node) -> - Parent = erlang:self(), - Child = proc_lib:spawn(Node, fun () -> - Parent ! {self(), erlang:system_info(schedulers)} - end), - erlang:monitor(process, Child), - receive - {Child, X} -> - receive - {'DOWN', _, _, Child, _Reason} -> - nil - end, - X; - {'DOWN', _, _, Child, Reason} when Reason =/= normal -> - 0 - end. - -%% @doc local runmany, for when we weren't invoked with {processes, X} -%% or {nodes, NodeList}. Every sublist is processed in parallel. -local_runmany(Fun, Fuse, List) -> - Parent = self (), - Pids = lists:map(fun (L) -> - F = fun () -> - Parent ! {self (), Fun(L)} - end, - {Pid, _} = erlang:spawn_monitor(F), - Pid - end, - List), - Answers = try - lists:map(fun receivefrom/1, Pids) - catch - throw:Message -> - {BadPid, Reason} = Message, - handle_error(BadPid, Reason, Pids) - end, - lists:foreach(fun (Pid) -> - normal_cleanup(Pid) - end, Pids), - fuse(Fuse, Answers). - -receivefrom(Pid) -> - receive - {Pid, R} -> - R; - {'DOWN', _, _, Pid, Reason} when Reason =/= normal -> - erlang:throw({Pid, Reason}); - {timerrang, _} -> - erlang:throw({nil, timeout}) - end. - -%% Convert List into [{Number, Sublist}] -cluster_runmany(Fun, Fuse, List, Nodes) -> - {List2, _} = lists:foldl(fun (X, {L, Count}) -> - {[{Count, X}|L], Count+1} - end, - {[], 0}, List), - cluster_runmany(Fun, Fuse, List2, Nodes, [], []). - -%% @doc Add a pair of results into the TaskList as a fusing task -cluster_runmany(Fun, {recursive, Fuse}, [], Nodes, Running, - [{_, R1}, {_, R2}|Results]) -> - cluster_runmany(Fun, {recursive, Fuse}, [{fuse, R1, R2}], Nodes, - Running, Results); -cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], [{_, Result}]) -> - %% recursive fuse done, return result - Result; -cluster_runmany(_, {recursive, _Fuse}, [], _Nodes, [], []) -> - %% edge case where we are asked to do nothing - []; -cluster_runmany(_, Fuse, [], _Nodes, [], Results) -> - %% We're done, now we just have to [linear] fuse the results - fuse(Fuse, lists:map(fun ({_, R}) -> - R - end, - lists:sort(fun ({A, _}, {B, _}) -> - A =< B - end, - lists:reverse(Results)))); -cluster_runmany(Fun, Fuse, [Task|TaskList], [N|Nodes], Running, Results) -> -%% We have a ready node and a sublist or fuse to be processed, so we start -%% a new process - - Parent = erlang:self(), - case Task of - {Num, L2} -> - Fun2 = fun () -> - Parent ! {erlang:self(), Num, Fun(L2)} - end; - {fuse, R1, R2} -> - {recursive, FuseFunc} = Fuse, - Fun2 = fun () -> - Parent ! {erlang:self(), fuse, FuseFunc(R1, R2)} - end - end, - Fun3 = fun() -> runmany_wrap(Fun2, Parent) end, - Pid = proc_lib:spawn(N, Fun3), - erlang:monitor(process, Pid), - cluster_runmany(Fun, Fuse, TaskList, Nodes, [{Pid, N, Task}|Running], Results); -cluster_runmany(Fun, Fuse, TaskList, Nodes, Running, Results) when length(Running) > 0 -> - %% We can't start a new process, but can watch over already running ones - receive - {_Pid, error, Reason} -> - RunningPids = lists:map(fun ({Pid, _, _}) -> - Pid - end, - Running), - handle_error(junkvalue, Reason, RunningPids); - {Pid, Num, Result} -> - %% throw out the exit message, Reason should be - %% normal, noproc, or noconnection - receive - {'DOWN', _, _, Pid, _Reason} -> - nil - end, - {Running2, FinishedNode, _} = delete_running(Pid, Running, []), - cluster_runmany(Fun, Fuse, TaskList, - [FinishedNode|Nodes], Running2, [{Num, Result}|Results]); - {timerrang, _} -> - RunningPids = lists:map(fun ({Pid, _, _}) -> - Pid - end, - Running), - handle_error(nil, timeout, RunningPids); - %% node failure - {'DOWN', _, _, Pid, noconnection} -> - {Running2, _DeadNode, Task} = delete_running(Pid, Running, []), - cluster_runmany(Fun, Fuse, [Task|TaskList], Nodes, - Running2, Results); - %% could a noproc exit message come before the message from - %% the process? we are assuming it can't. - %% this clause is unlikely to get invoked due to cluster_runmany's - %% spawned processes. It will still catch errors in mapreduce's - %% reduce process, however. - {'DOWN', _, _, BadPid, Reason} when Reason =/= normal -> - RunningPids = lists:map(fun ({Pid, _, _}) -> - Pid - end, - Running), - handle_error(BadPid, Reason, RunningPids) - end; -cluster_runmany(_, _, [_Non|_Empty], []=_Nodes, []=_Running, _) -> -%% We have data, but no nodes either available or occupied - erlang:exit(allnodescrashed). - -runmany_wrap(Fun, Parent) -> - try - Fun() - catch - exit:siblingdied -> - ok; - exit:Reason -> - Parent ! {erlang:self(), error, Reason}; - error:R:Stacktrace -> - Parent ! {erlang:self(), error, {R, Stacktrace}}; - throw:R:Stacktrace -> - Parent ! {erlang:self(), error, {{nocatch, R}, Stacktrace}} - end. - -delete_running(Pid, [{Pid, Node, List}|Running], Acc) -> - {Running ++ Acc, Node, List}; -delete_running(Pid, [R|Running], Acc) -> - delete_running(Pid, Running, [R|Acc]). - -handle_error(BadPid, Reason, Pids) -> - lists:foreach(fun (Pid) -> - erlang:exit(Pid, siblingdied) - end, Pids), - lists:foreach(fun (Pid) -> - error_cleanup(Pid, BadPid) - end, Pids), - erlang:exit(Reason). - -error_cleanup(BadPid, BadPid) -> - ok; -error_cleanup(Pid, BadPid) -> - receive - {Pid, _} -> - error_cleanup(Pid, BadPid); - {Pid, _, _} -> - error_cleanup(Pid, BadPid); - {'DOWN', _, _, Pid, _Reason} -> - ok - end. - -normal_cleanup(Pid) -> - receive - {'DOWN', _, _, Pid, _Reason} -> - ok - end. - -%% edge case -fuse(_, []) -> - []; -fuse({reverse, _}=Fuse, Results) -> - [RL|ResultsR] = lists:reverse(Results), - fuse(Fuse, ResultsR, RL); -fuse(Fuse, [R1|Results]) -> - fuse(Fuse, Results, R1). - -fuse({reverse, FuseFunc}=Fuse, [R2|Results], R1) -> - fuse(Fuse, Results, FuseFunc(R2, R1)); -fuse(Fuse, [R2|Results], R1) -> - fuse(Fuse, Results, Fuse(R1, R2)); -fuse(_, [], R) -> - R. - -%% @doc Splits a list into a list of sublists, each of size Size, -%% except for the last element which is less if the original list -%% could not be evenly divided into Size-sized lists. -splitmany(List, Size) -> - splitmany(List, [], Size). - -splitmany([], Acc, _) -> - lists:reverse(Acc); -splitmany(List, Acc, Size) -> - {Top, NList} = split(Size, List), - splitmany(NList, [Top|Acc], Size). - -%% @doc Like lists:split, except it splits a list smaller than its first -%% parameter -split(Size, List) -> - split(Size, List, []). - -split(0, List, Acc) -> - {lists:reverse(Acc), List}; -split(Size, [H|List], Acc) -> - split(Size - 1, List, [H|Acc]); -split(_, [], Acc) -> - {lists:reverse(Acc), []}. diff --git a/vendor/erlware_commons/src/ec_rbdict.erl b/vendor/erlware_commons/src/ec_rbdict.erl deleted file mode 100644 index 9f3b61745..000000000 --- a/vendor/erlware_commons/src/ec_rbdict.erl +++ /dev/null @@ -1,322 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%% Copyright (c) 2008 Robert Virding. All rights reserved. -%%% -%%% Redistribution and use in source and binary forms, with or without -%%% modification, are permitted provided that the following conditions -%%% are met: -%%% -%%% 1. Redistributions of source code must retain the above copyright -%%% notice, this list of conditions and the following disclaimer. -%%% 2. Redistributions in binary form must reproduce the above copyright -%%% notice, this list of conditions and the following disclaimer in the -%%% documentation and/or other materials provided with the distribution. -%%% -%%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -%%% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -%%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -%%% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -%%% COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -%%% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -%%% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -%%% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -%%% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -%%% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -%%% POSSIBILITY OF SUCH DAMAGE. -%%%------------------------------------------------------------------- -%%% @copyright 2008 Robert Verding -%%% -%%% @doc -%%% -%%% Rbdict implements a Key - Value dictionary. An rbdict is a -%%% representation of a dictionary, where a red-black tree is used to -%%% store the keys and values. -%%% -%%% This module implements exactly the same interface as the module -%%% ec_dictionary but with a defined representation. One difference is -%%% that while dict considers two keys as different if they do not -%%% match (=:=), this module considers two keys as different if and -%%% only if they do not compare equal (==). -%%% -%%% The algorithms here are taken directly from Okasaki and Rbset -%%% in ML/Scheme. The interface is compatible with the standard dict -%%% interface. -%%% -%%% The following structures are used to build the the RB-dict: -%%% -%%% {r,Left,Key,Val,Right} -%%% {b,Left,Key,Val,Right} -%%% empty -%%% -%%% It is interesting to note that expanding out the first argument of -%%% l/rbalance, the colour, in store etc. is actually slower than not -%%% doing it. Measured. -%%% -%%% see ec_dictionary -%%% @end -%%%------------------------------------------------------------------- --module(ec_rbdict). - --behaviour(ec_dictionary). - -%% Standard interface. --export([add/3, from_list/1, get/2, get/3, has_key/2, - has_value/2, new/0, remove/2, size/1, to_list/1, - keys/1]). - --export_type([dictionary/2]). - -%%%=================================================================== -%%% Types -%%%=================================================================== -%% This should be opaque, but that kills dialyzer so for now we export it -%% however you should not rely on the internal representation here --type dictionary(K, V) :: empty | {color(), - dictionary(K, V), - ec_dictionary:key(K), - ec_dictionary:value(V), - dictionary(K, V)}. - --type color() :: r | b. - -%%%=================================================================== -%%% API -%%%=================================================================== - --spec new() -> dictionary(_K, _V). -new() -> empty. - --spec has_key(ec_dictionary:key(K), dictionary(K, _V)) -> boolean(). -has_key(_, empty) -> - false; -has_key(K, {_, Left, K1, _, _}) when K < K1 -> - has_key(K, Left); -has_key(K, {_, _, K1, _, Right}) when K > K1 -> - has_key(K, Right); -has_key(_, {_, _, _, _, _}) -> - true. - --spec get(ec_dictionary:key(K), dictionary(K, V)) -> ec_dictionary:value(V). -get(_, empty) -> - throw(not_found); -get(K, {_, Left, K1, _, _}) when K < K1 -> - get(K, Left); -get(K, {_, _, K1, _, Right}) when K > K1 -> - get(K, Right); -get(_, {_, _, _, Val, _}) -> - Val. - --spec get(ec_dictionary:key(K), - ec_dictionary:value(V), - dictionary(K, V)) -> ec_dictionary:value(V). -get(_, Default, empty) -> - Default; -get(K, Default, {_, Left, K1, _, _}) when K < K1 -> - get(K, Default, Left); -get(K, Default, {_, _, K1, _, Right}) when K > K1 -> - get(K, Default, Right); -get(_, _, {_, _, _, Val, _}) -> - Val. - --spec add(ec_dictionary:key(K), ec_dictionary:value(V), - dictionary(K, V)) -> dictionary(K, V). -add(Key, Value, Dict) -> - {_, L, K1, V1, R} = add1(Key, Value, Dict), - {b, L, K1, V1, R}. - --spec remove(ec_dictionary:key(K), dictionary(K, V)) -> dictionary(K, V). -remove(Key, Dictionary) -> - {Dict1, _} = erase_aux(Key, Dictionary), Dict1. - --spec has_value(ec_dictionary:value(V), dictionary(_K, V)) -> boolean(). -has_value(Value, Dict) -> - fold(fun (_, NValue, _) when NValue == Value -> true; - (_, _, Acc) -> Acc - end, - false, Dict). - --spec size(dictionary(_K, _V)) -> non_neg_integer(). -size(T) -> - size1(T). - --spec to_list(dictionary(K, V)) -> - [{ec_dictionary:key(K), ec_dictionary:value(V)}]. -to_list(T) -> - to_list(T, []). - --spec from_list([{ec_dictionary:key(K), ec_dictionary:value(V)}]) -> - dictionary(K, V). -from_list(L) -> - lists:foldl(fun ({K, V}, D) -> - add(K, V, D) - end, new(), - L). - --spec keys(dictionary(K, _V)) -> [ec_dictionary:key(K)]. -keys(Dict) -> - keys(Dict, []). - -%%%=================================================================== -%%% Enternal functions -%%%=================================================================== --spec keys(dictionary(K, _V), [ec_dictionary:key(K)]) -> - [ec_dictionary:key(K)]. -keys(empty, Tail) -> - Tail; -keys({_, L, K, _, R}, Tail) -> - keys(L, [K | keys(R, Tail)]). - - --spec erase_aux(ec_dictionary:key(K), dictionary(K, V)) -> - {dictionary(K, V), boolean()}. -erase_aux(_, empty) -> - {empty, false}; -erase_aux(K, {b, A, Xk, Xv, B}) -> - if K < Xk -> - {A1, Dec} = erase_aux(K, A), - if Dec -> - unbalright(b, A1, Xk, Xv, B); - true -> - {{b, A1, Xk, Xv, B}, false} - end; - K > Xk -> - {B1, Dec} = erase_aux(K, B), - if Dec -> - unballeft(b, A, Xk, Xv, B1); - true -> - {{b, A, Xk, Xv, B1}, false} - end; - true -> - case B of - empty -> - blackify(A); - _ -> - {B1, {Mk, Mv}, Dec} = erase_min(B), - if Dec -> - unballeft(b, A, Mk, Mv, B1); - true -> - {{b, A, Mk, Mv, B1}, false} - end - end - end; -erase_aux(K, {r, A, Xk, Xv, B}) -> - if K < Xk -> - {A1, Dec} = erase_aux(K, A), - if Dec -> - unbalright(r, A1, Xk, Xv, B); - true -> - {{r, A1, Xk, Xv, B}, false} - end; - K > Xk -> - {B1, Dec} = erase_aux(K, B), - if Dec -> - unballeft(r, A, Xk, Xv, B1); - true -> - {{r, A, Xk, Xv, B1}, false} - end; - true -> - case B of - empty -> - {A, false}; - _ -> - {B1, {Mk, Mv}, Dec} = erase_min(B), - if Dec -> - unballeft(r, A, Mk, Mv, B1); - true -> - {{r, A, Mk, Mv, B1}, false} - end - end - end. - --spec erase_min(dictionary(K, V)) -> - {dictionary(K, V), {ec_dictionary:key(K), ec_dictionary:value(V)}, boolean()}. -erase_min({b, empty, Xk, Xv, empty}) -> - {empty, {Xk, Xv}, true}; -erase_min({b, empty, Xk, Xv, {r, A, Yk, Yv, B}}) -> - {{b, A, Yk, Yv, B}, {Xk, Xv}, false}; -erase_min({b, empty, _, _, {b, _, _, _, _}}) -> - exit(boom); -erase_min({r, empty, Xk, Xv, A}) -> - {A, {Xk, Xv}, false}; -erase_min({b, A, Xk, Xv, B}) -> - {A1, Min, Dec} = erase_min(A), - if Dec -> - {T, Dec1} = unbalright(b, A1, Xk, Xv, B), - {T, Min, Dec1}; - true -> {{b, A1, Xk, Xv, B}, Min, false} - end; -erase_min({r, A, Xk, Xv, B}) -> - {A1, Min, Dec} = erase_min(A), - if Dec -> - {T, Dec1} = unbalright(r, A1, Xk, Xv, B), - {T, Min, Dec1}; - true -> {{r, A1, Xk, Xv, B}, Min, false} - end. - -blackify({r, A, K, V, B}) -> {{b, A, K, V, B}, false}; -blackify(Node) -> {Node, true}. - -unballeft(r, {b, A, Xk, Xv, B}, Yk, Yv, C) -> - {lbalance(b, {r, A, Xk, Xv, B}, Yk, Yv, C), false}; -unballeft(b, {b, A, Xk, Xv, B}, Yk, Yv, C) -> - {lbalance(b, {r, A, Xk, Xv, B}, Yk, Yv, C), true}; -unballeft(b, {r, A, Xk, Xv, {b, B, Yk, Yv, C}}, Zk, Zv, - D) -> - {{b, A, Xk, Xv, - lbalance(b, {r, B, Yk, Yv, C}, Zk, Zv, D)}, - false}. - -unbalright(r, A, Xk, Xv, {b, B, Yk, Yv, C}) -> - {rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), false}; -unbalright(b, A, Xk, Xv, {b, B, Yk, Yv, C}) -> - {rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), true}; -unbalright(b, A, Xk, Xv, - {r, {b, B, Yk, Yv, C}, Zk, Zv, D}) -> - {{b, rbalance(b, A, Xk, Xv, {r, B, Yk, Yv, C}), Zk, Zv, - D}, - false}. - --spec fold(fun((ec_dictionary:key(K), ec_dictionary:value(V), any()) -> any()), - any(), dictionary(K, V)) -> any(). -fold(_, Acc, empty) -> Acc; -fold(F, Acc, {_, A, Xk, Xv, B}) -> - fold(F, F(Xk, Xv, fold(F, Acc, B)), A). - -add1(K, V, empty) -> {r, empty, K, V, empty}; -add1(K, V, {C, Left, K1, V1, Right}) when K < K1 -> - lbalance(C, add1(K, V, Left), K1, V1, Right); -add1(K, V, {C, Left, K1, V1, Right}) when K > K1 -> - rbalance(C, Left, K1, V1, add1(K, V, Right)); -add1(K, V, {C, L, _, _, R}) -> {C, L, K, V, R}. - -size1(empty) -> 0; -size1({_, L, _, _, R}) -> size1(L) + size1(R) + 1. - -to_list(empty, List) -> List; -to_list({_, A, Xk, Xv, B}, List) -> - to_list(A, [{Xk, Xv} | to_list(B, List)]). - -%% Balance a tree after (possibly) adding a node to the left/right. --spec lbalance(color(), dictionary(K, V), - ec_dictionary:key(K), ec_dictionary:value(V), - dictionary(K, V)) -> - dictionary(K, V). -lbalance(b, {r, {r, A, Xk, Xv, B}, Yk, Yv, C}, Zk, Zv, - D) -> - {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; -lbalance(b, {r, A, Xk, Xv, {r, B, Yk, Yv, C}}, Zk, Zv, - D) -> - {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; -lbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. - --spec rbalance(color(), dictionary(K, V), - ec_dictionary:key(K), ec_dictionary:value(V), - dictionary(K, V)) -> - dictionary(K, V). -rbalance(b, A, Xk, Xv, - {r, {r, B, Yk, Yv, C}, Zk, Zv, D}) -> - {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; -rbalance(b, A, Xk, Xv, - {r, B, Yk, Yv, {r, C, Zk, Zv, D}}) -> - {r, {b, A, Xk, Xv, B}, Yk, Yv, {b, C, Zk, Zv, D}}; -rbalance(C, A, Xk, Xv, B) -> {C, A, Xk, Xv, B}. diff --git a/vendor/erlware_commons/src/ec_semver.erl b/vendor/erlware_commons/src/ec_semver.erl deleted file mode 100644 index 3ffd591da..000000000 --- a/vendor/erlware_commons/src/ec_semver.erl +++ /dev/null @@ -1,311 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @copyright (C) 2011, Erlware LLC -%%% @doc -%%% Helper functions for working with semver versioning strings. -%%% See http://semver.org/ for the spec. -%%% @end -%%%------------------------------------------------------------------- --module(ec_semver). - --export([parse/1, - format/1, - eql/2, - gt/2, - gte/2, - lt/2, - lte/2, - pes/2, - between/3]). - -%% For internal use by the ec_semver_parser peg --export([internal_parse_version/1]). - --export_type([semver/0, - version_string/0, - any_version/0]). - -%%%=================================================================== -%%% Public Types -%%%=================================================================== - --type version_element() :: non_neg_integer() | binary(). - --type major_minor_patch_minpatch() :: - version_element() - | {version_element(), version_element()} - | {version_element(), version_element(), version_element()} - | {version_element(), version_element(), - version_element(), version_element()}. - --type alpha_part() :: integer() | binary() | string(). --type alpha_info() :: {PreRelease::[alpha_part()], - BuildVersion::[alpha_part()]}. - --type semver() :: {major_minor_patch_minpatch(), alpha_info()}. - --type version_string() :: string() | binary(). - --type any_version() :: version_string() | semver(). - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc parse a string or binary into a valid semver representation --spec parse(any_version()) -> semver(). -parse(Version) when erlang:is_list(Version) -> - case ec_semver_parser:parse(Version) of - {fail, _} -> - {erlang:iolist_to_binary(Version), {[],[]}}; - Good -> - Good - end; -parse(Version) when erlang:is_binary(Version) -> - case ec_semver_parser:parse(Version) of - {fail, _} -> - {Version, {[],[]}}; - Good -> - Good - end; -parse(Version) -> - Version. - --spec format(semver()) -> iolist(). -format({Maj, {AlphaPart, BuildPart}}) - when erlang:is_integer(Maj); - erlang:is_binary(Maj) -> - [format_version_part(Maj), - format_vsn_rest(<<"-">>, AlphaPart), - format_vsn_rest(<<"+">>, BuildPart)]; -format({{Maj, Min}, {AlphaPart, BuildPart}}) -> - [format_version_part(Maj), ".", - format_version_part(Min), - format_vsn_rest(<<"-">>, AlphaPart), - format_vsn_rest(<<"+">>, BuildPart)]; -format({{Maj, Min, Patch}, {AlphaPart, BuildPart}}) -> - [format_version_part(Maj), ".", - format_version_part(Min), ".", - format_version_part(Patch), - format_vsn_rest(<<"-">>, AlphaPart), - format_vsn_rest(<<"+">>, BuildPart)]; -format({{Maj, Min, Patch, MinPatch}, {AlphaPart, BuildPart}}) -> - [format_version_part(Maj), ".", - format_version_part(Min), ".", - format_version_part(Patch), ".", - format_version_part(MinPatch), - format_vsn_rest(<<"-">>, AlphaPart), - format_vsn_rest(<<"+">>, BuildPart)]. - --spec format_version_part(integer() | binary()) -> iolist(). -format_version_part(Vsn) - when erlang:is_integer(Vsn) -> - erlang:integer_to_list(Vsn); -format_version_part(Vsn) - when erlang:is_binary(Vsn) -> - Vsn. - - - -%% @doc test for quality between semver versions --spec eql(any_version(), any_version()) -> boolean(). -eql(VsnA, VsnB) -> - NVsnA = normalize(parse(VsnA)), - NVsnB = normalize(parse(VsnB)), - NVsnA =:= NVsnB. - -%% @doc Test that VsnA is greater than VsnB --spec gt(any_version(), any_version()) -> boolean(). -gt(VsnA, VsnB) -> - {MMPA, {AlphaA, PatchA}} = normalize(parse(VsnA)), - {MMPB, {AlphaB, PatchB}} = normalize(parse(VsnB)), - ((MMPA > MMPB) - orelse - ((MMPA =:= MMPB) - andalso - ((AlphaA =:= [] andalso AlphaB =/= []) - orelse - ((not (AlphaB =:= [] andalso AlphaA =/= [])) - andalso - (AlphaA > AlphaB)))) - orelse - ((MMPA =:= MMPB) - andalso - (AlphaA =:= AlphaB) - andalso - ((PatchB =:= [] andalso PatchA =/= []) - orelse - PatchA > PatchB))). - -%% @doc Test that VsnA is greater than or equal to VsnB --spec gte(any_version(), any_version()) -> boolean(). -gte(VsnA, VsnB) -> - NVsnA = normalize(parse(VsnA)), - NVsnB = normalize(parse(VsnB)), - gt(NVsnA, NVsnB) orelse eql(NVsnA, NVsnB). - -%% @doc Test that VsnA is less than VsnB --spec lt(any_version(), any_version()) -> boolean(). -lt(VsnA, VsnB) -> - {MMPA, {AlphaA, PatchA}} = normalize(parse(VsnA)), - {MMPB, {AlphaB, PatchB}} = normalize(parse(VsnB)), - ((MMPA < MMPB) - orelse - ((MMPA =:= MMPB) - andalso - ((AlphaB =:= [] andalso AlphaA =/= []) - orelse - ((not (AlphaA =:= [] andalso AlphaB =/= [])) - andalso - (AlphaA < AlphaB)))) - orelse - ((MMPA =:= MMPB) - andalso - (AlphaA =:= AlphaB) - andalso - ((PatchA =:= [] andalso PatchB =/= []) - orelse - PatchA < PatchB))). - -%% @doc Test that VsnA is less than or equal to VsnB --spec lte(any_version(), any_version()) -> boolean(). -lte(VsnA, VsnB) -> - NVsnA = normalize(parse(VsnA)), - NVsnB = normalize(parse(VsnB)), - lt(NVsnA, NVsnB) orelse eql(NVsnA, NVsnB). - -%% @doc Test that VsnMatch is greater than or equal to Vsn1 and -%% less than or equal to Vsn2 --spec between(any_version(), any_version(), any_version()) -> boolean(). -between(Vsn1, Vsn2, VsnMatch) -> - NVsnA = normalize(parse(Vsn1)), - NVsnB = normalize(parse(Vsn2)), - NVsnMatch = normalize(parse(VsnMatch)), - gte(NVsnMatch, NVsnA) andalso - lte(NVsnMatch, NVsnB). - -%% @doc check that VsnA is Approximately greater than VsnB -%% -%% Specifying ">= 2.6.5" is an optimistic version constraint. All -%% versions greater than the one specified, including major releases -%% (e.g. 3.0.0) are allowed. -%% -%% Conversely, specifying "~> 2.6" is pessimistic about future major -%% revisions and "~> 2.6.5" is pessimistic about future minor -%% revisions. -%% -%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0 -%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0 -pes(VsnA, VsnB) -> - internal_pes(parse(VsnA), parse(VsnB)). - -%%%=================================================================== -%%% Friend Functions -%%%=================================================================== -%% @doc helper function for the peg grammar to parse the iolist into a semver --spec internal_parse_version(iolist()) -> semver(). -internal_parse_version([MMP, AlphaPart, BuildPart, _]) -> - {parse_major_minor_patch_minpatch(MMP), {parse_alpha_part(AlphaPart), - parse_alpha_part(BuildPart)}}. - -%% @doc helper function for the peg grammar to parse the iolist into a major_minor_patch --spec parse_major_minor_patch_minpatch(iolist()) -> major_minor_patch_minpatch(). -parse_major_minor_patch_minpatch([MajVsn, [], [], []]) -> - strip_maj_version(MajVsn); -parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [], []]) -> - {strip_maj_version(MajVsn), MinVsn}; -parse_major_minor_patch_minpatch([MajVsn, - [<<".">>, MinVsn], - [<<".">>, PatchVsn], []]) -> - {strip_maj_version(MajVsn), MinVsn, PatchVsn}; -parse_major_minor_patch_minpatch([MajVsn, - [<<".">>, MinVsn], - [<<".">>, PatchVsn], - [<<".">>, MinPatch]]) -> - {strip_maj_version(MajVsn), MinVsn, PatchVsn, MinPatch}. - -%% @doc helper function for the peg grammar to parse the iolist into an alpha part --spec parse_alpha_part(iolist()) -> [alpha_part()]. -parse_alpha_part([]) -> - []; -parse_alpha_part([_, AV1, Rest]) -> - [erlang:iolist_to_binary(AV1) | - [format_alpha_part(Part) || Part <- Rest]]. - -%% @doc according to semver alpha parts that can be treated like -%% numbers must be. We implement that here by taking the alpha part -%% and trying to convert it to a number, if it succeeds we use -%% it. Otherwise we do not. --spec format_alpha_part(iolist()) -> integer() | binary(). -format_alpha_part([<<".">>, AlphaPart]) -> - Bin = erlang:iolist_to_binary(AlphaPart), - try - erlang:list_to_integer(erlang:binary_to_list(Bin)) - catch - error:badarg -> - Bin - end. - -%%%=================================================================== -%%% Internal Functions -%%%=================================================================== --spec strip_maj_version(iolist()) -> version_element(). -strip_maj_version([<<"v">>, MajVsn]) -> - MajVsn; -strip_maj_version([[], MajVsn]) -> - MajVsn; -strip_maj_version(MajVsn) -> - MajVsn. - --spec to_list(integer() | binary() | string()) -> string() | binary(). -to_list(Detail) when erlang:is_integer(Detail) -> - erlang:integer_to_list(Detail); -to_list(Detail) when erlang:is_list(Detail); erlang:is_binary(Detail) -> - Detail. - --spec format_vsn_rest(binary() | string(), [integer() | binary()]) -> iolist(). -format_vsn_rest(_TypeMark, []) -> - []; -format_vsn_rest(TypeMark, [Head | Rest]) -> - [TypeMark, Head | - [[".", to_list(Detail)] || Detail <- Rest]]. - -%% @doc normalize the semver so they can be compared --spec normalize(semver()) -> semver(). -normalize({Vsn, Rest}) - when erlang:is_binary(Vsn); - erlang:is_integer(Vsn) -> - {{Vsn, 0, 0, 0}, Rest}; -normalize({{Maj, Min}, Rest}) -> - {{Maj, Min, 0, 0}, Rest}; -normalize({{Maj, Min, Patch}, Rest}) -> - {{Maj, Min, Patch, 0}, Rest}; -normalize(Other = {{_, _, _, _}, {_,_}}) -> - Other. - -%% @doc to do the pessimistic compare we need a parsed semver. This is -%% the internal implementation of the of the pessimistic run. The -%% external just ensures that versions are parsed. --spec internal_pes(semver(), semver()) -> boolean(). -internal_pes(VsnA, {{LM, LMI}, Alpha}) - when erlang:is_integer(LM), - erlang:is_integer(LMI) -> - gte(VsnA, {{LM, LMI, 0}, Alpha}) andalso - lt(VsnA, {{LM + 1, 0, 0, 0}, {[], []}}); -internal_pes(VsnA, {{LM, LMI, LP}, Alpha}) - when erlang:is_integer(LM), - erlang:is_integer(LMI), - erlang:is_integer(LP) -> - gte(VsnA, {{LM, LMI, LP}, Alpha}) - andalso - lt(VsnA, {{LM, LMI + 1, 0, 0}, {[], []}}); -internal_pes(VsnA, {{LM, LMI, LP, LMP}, Alpha}) - when erlang:is_integer(LM), - erlang:is_integer(LMI), - erlang:is_integer(LP), - erlang:is_integer(LMP) -> - gte(VsnA, {{LM, LMI, LP, LMP}, Alpha}) - andalso - lt(VsnA, {{LM, LMI, LP + 1, 0}, {[], []}}); -internal_pes(Vsn, LVsn) -> - gte(Vsn, LVsn). diff --git a/vendor/erlware_commons/src/ec_talk.erl b/vendor/erlware_commons/src/ec_talk.erl deleted file mode 100644 index 8c3a105fd..000000000 --- a/vendor/erlware_commons/src/ec_talk.erl +++ /dev/null @@ -1,203 +0,0 @@ -%% -*- mode: Erlang; fill-column: 79; comment-column: 70; -*- -%% vi:ts=4 sw=4 et -%%%--------------------------------------------------------------------------- -%%% Permission is hereby granted, free of charge, to any person -%%% obtaining a copy of this software and associated documentation -%%% files (the "Software"), to deal in the Software without -%%% restriction, including without limitation the rights to use, copy, -%%% modify, merge, publish, distribute, sublicense, and/or sell copies -%%% of the Software, and to permit persons to whom the Software is -%%% furnished to do so, subject to the following conditions: -%%% -%%% The above copyright notice and this permission notice shall be -%%% included in all copies or substantial portions of the Software. -%%% -%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -%%% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -%%% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -%%% DEALINGS IN THE SOFTWARE. -%%%--------------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @doc -%%% Provides the ability to ask questions of the user and -%%% get a response. -%%% @end -%%% @copyright Erlware 2006-2011 -%%%--------------------------------------------------------------------------- --module(ec_talk). - -%% API --export([ask/1, - ask/2, - ask_default/2, - ask_default/3, - ask/3, - say/1, - say/2]). - --ifdef(TEST). --export([get_boolean/1, - get_integer/1]). --endif. - --export_type([prompt/0, - type/0, - supported/0]). - -%%============================================================================ -%% Types -%%============================================================================ --type prompt() :: string(). --type type() :: boolean | number | string. --type supported() :: boolean() | number() | string(). - -%%============================================================================ -%% API -%%============================================================================ - -%% @doc Outputs the line to the screen --spec say(string()) -> ok. -say(Say) -> - io:format(lists:flatten([Say, "~n"])). - --spec say(string(), [term()] | term()) -> ok. -say(Say, Args) when is_list(Args) -> - io:format(lists:flatten([Say, "~n"]), Args); -say(Say, Args) -> - io:format(lists:flatten([Say, "~n"]), [Args]). - -%% @doc Asks the user for a response to the specified prompt. --spec ask(prompt()) -> string(). -ask(Prompt) -> - ask_convert(Prompt, fun get_string/1, string, none). - -%% @doc Asks the user for a response to the specified prompt. --spec ask_default(prompt(), string()) -> string(). -ask_default(Prompt, Default) -> - ask_convert(Prompt, fun get_string/1, string, Default). - -%% @doc Asks the user to respond to the prompt. Tries to return the -%% value in the format specified by 'Type'. --spec ask(prompt(), type()) -> supported(). -ask(Prompt, boolean) -> - ask_convert(Prompt, fun get_boolean/1, boolean, none); -ask(Prompt, number) -> - ask_convert(Prompt, fun get_integer/1, number, none); -ask(Prompt, string) -> - ask_convert(Prompt, fun get_string/1, string, none). - -%% @doc Asks the user to respond to the prompt. Tries to return the -%% value in the format specified by 'Type'. --spec ask_default(prompt(), type(), supported()) -> supported(). -ask_default(Prompt, boolean, Default) -> - ask_convert(Prompt, fun get_boolean/1, boolean, Default); -ask_default(Prompt, number, Default) -> - ask_convert(Prompt, fun get_integer/1, number, Default); -ask_default(Prompt, string, Default) -> - ask_convert(Prompt, fun get_string/1, string, Default). - -%% @doc Asks the user to respond to the number prompt with a value -%% between min and max. --spec ask(prompt(), number(), number()) -> number(). -ask(Prompt, Min, Max) - when erlang:is_list(Prompt), - erlang:is_number(Min), - erlang:is_number(Max), - Min =< Max -> - Res = ask_convert(Prompt, fun get_integer/1, number, none), - case (Res >= Min andalso Res =< Max) of - true -> - Res; - false -> - say("Your answer must be between ~w and ~w!", [Min, Max]), - ask(Prompt, Min, Max) - end. - -%%============================================================================ -%% Internal functions -%% ============================================================================ -%% @doc Actually does the work of asking, checking result and -%% translating result into the requested format. --spec ask_convert(prompt(), fun((any()) -> any()), type(), supported() | none) -> supported(). -ask_convert(Prompt, TransFun, Type, Default) -> - NewPrompt = - erlang:binary_to_list(erlang:iolist_to_binary([Prompt, - case Default of - none -> - []; - Default -> - [" (", io_lib:format("~p", [Default]) , ")"] - end, "> "])), - Data = string:trim(string:trim(io:get_line(NewPrompt)), both, [$\n]), - Ret = TransFun(Data), - case Ret of - no_data -> - case Default of - none -> - say("I didn't get that. This ~p kind of question.~n", [Type]), - ask_convert(Prompt, TransFun, Type, Default); - Default -> - TransFun(Default) - end; - no_clue -> - say("I didn't get that. This ~p kind of question.~n", [Type]), - ask_convert(Prompt, TransFun, Type, Default); - _ -> - Ret - end. - -%% @doc Tries to translate the result into a boolean --spec get_boolean(string()) -> boolean(). -get_boolean([]) -> - no_data; -get_boolean([$T | _]) -> - true; -get_boolean([$t | _]) -> - true; -get_boolean("ok") -> - true; -get_boolean("OK") -> - true; -get_boolean([$Y | _]) -> - true; -get_boolean([$y | _]) -> - true; -get_boolean([$f | _]) -> - false; -get_boolean([$F | _]) -> - false; -get_boolean([$n | _]) -> - false; -get_boolean([$N | _]) -> - false; -get_boolean(_) -> - no_clue. - -%% @doc Tries to translate the result into an integer --spec get_integer(string()) -> integer(). -get_integer([]) -> - no_data; -get_integer(String) -> - case (catch list_to_integer(String)) of - {'Exit', _} -> - no_clue; - Integer -> - Integer - end. - -%% @doc Solely returns a string give the string. This is so the same -%% translate function can be used across the board --spec get_string(string()) -> string(). -get_string([]) -> - no_data; -get_string(String) -> - case is_list(String) of - true -> - String; - false -> - no_clue - end. diff --git a/vendor/erlware_commons/src/ec_vsn.erl b/vendor/erlware_commons/src/ec_vsn.erl deleted file mode 100644 index e407b9fc8..000000000 --- a/vendor/erlware_commons/src/ec_vsn.erl +++ /dev/null @@ -1,51 +0,0 @@ -%%% vi:ts=4 sw=4 et -%%%------------------------------------------------------------------- -%%% @author Eric Merritt -%%% @copyright 2014 Erlware, LLC. -%%% @doc -%%% Provides a signature to manage returning semver formatted versions -%%% from various version control repositories. -%%% -%%% This interface is a member of the Erlware Commons Library. -%%% @end -%%%------------------------------------------------------------------- --module(ec_vsn). - -%% API --export([new/1, - vsn/1]). - --export_type([t/0]). - -%%%=================================================================== -%%% Types -%%%=================================================================== - --record(t, {callback, data}). - -%% This should be opaque, but that kills dialyzer so for now we export it -%% however you should not rely on the internal representation here --type t() :: #t{}. - --callback new() -> any(). --callback vsn(any()) -> {ok, string()} | {error, Reason::any()}. - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc create a new dictionary object from the specified module. The -%% module should implement the dictionary behaviour. -%% -%% @param ModuleName The module name. --spec new(module()) -> t(). -new(ModuleName) when erlang:is_atom(ModuleName) -> - #t{callback = ModuleName, data = ModuleName:new()}. - -%% @doc Return the semver or an error depending on what is possible -%% with this implementation in this directory. -%% -%% @param The dictionary object --spec vsn(t()) -> {ok, string()} | {error, Reason::any()}. -vsn(#t{callback = Mod, data = Data}) -> - Mod:vsn(Data). diff --git a/vendor/erlware_commons/src/erlware_commons.app.src b/vendor/erlware_commons/src/erlware_commons.app.src deleted file mode 100644 index 5cb0a169d..000000000 --- a/vendor/erlware_commons/src/erlware_commons.app.src +++ /dev/null @@ -1,11 +0,0 @@ -{application,erlware_commons, - [{description,"Additional standard library for Erlang"}, - {vsn,"1.8.0"}, - {modules,[]}, - {registered,[]}, - {applications,[kernel,stdlib,cf]}, - {maintainers,["Eric Merritt","Tristan Sloughter", - "Jordan Wilberding","Martin Logan"]}, - {licenses,["Apache","MIT"]}, - {links,[{"Github", - "https://github.com/erlware/erlware_commons"}]}]}. diff --git a/vendor/providers/hex_metadata.config b/vendor/providers/hex_metadata.config index db1fa4cb2..b8cabebbd 100644 --- a/vendor/providers/hex_metadata.config +++ b/vendor/providers/hex_metadata.config @@ -10,11 +10,7 @@ {<<"links">>,[{<<"Github">>,<<"https://github.com/tsloughter/providers">>}]}. {<<"name">>,<<"providers">>}. {<<"requirements">>, - [{<<"erlware_commons">>, - [{<<"app">>,<<"erlware_commons">>}, - {<<"optional">>,false}, - {<<"requirement">>,<<"1.4.0">>}]}, - {<<"getopt">>, + [{<<"getopt">>, [{<<"app">>,<<"getopt">>}, {<<"optional">>,false}, {<<"requirement">>,<<"1.0.1">>}]}]}. diff --git a/vendor/providers/rebar.config b/vendor/providers/rebar.config index 113a56697..b8f31f042 100644 --- a/vendor/providers/rebar.config +++ b/vendor/providers/rebar.config @@ -1,5 +1,5 @@ {erl_opts, [{platform_define, "R14", no_callback_support} ,debug_info]}. -{deps, [{getopt, "1.0.1"}, {erlware_commons, "1.4.0"}]}. +{deps, [{getopt, "1.0.1"}]}. diff --git a/vendor/providers/rebar.lock b/vendor/providers/rebar.lock index 2ada5feca..2b3ab53eb 100644 --- a/vendor/providers/rebar.lock +++ b/vendor/providers/rebar.lock @@ -1,14 +1,11 @@ {"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,[ {<<"cf">>, <<"5CB902239476E141EA70A740340233782D363A31EEA8AD37049561542E6CD641">>}, - {<<"erlware_commons">>, <<"F9EE38412E1413944BE78736DDB9BDB4C0664ABA5133563F4F3B359A8ED0AD52">>}, {<<"getopt">>, <<"C73A9FA687B217F2FF79F68A3B637711BB1936E712B521D8CE466B29CBF7808A">>}]}, {pkg_hash_ext,[ {<<"cf">>, <<"315E8D447D3A4B02BCDBFA397AD03BBB988A6E0AA6F44D3ADD0F4E3C3BF97672">>}, - {<<"erlware_commons">>, <<"185ECF5CF43BAB3A013DDB3614CE7BBA7F6C7A827904E64E57DA54FCDFDCE2E6">>}, {<<"getopt">>, <<"53E1AB83B9CEB65C9672D3E7A35B8092E9BDC9B3EE80721471A161C10C59959C">>}]} ].