Minor reformatting/whitespace removal
Signed-off-by: Jordan Wilberding <jwilberding@gmail.com>
This commit is contained in:
parent
284ada2bd9
commit
694e805012
5 changed files with 279 additions and 279 deletions
246
src/ec_file.erl
246
src/ec_file.erl
|
@ -7,38 +7,38 @@
|
||||||
-module(ec_file).
|
-module(ec_file).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
copy/2,
|
copy/2,
|
||||||
copy/3,
|
copy/3,
|
||||||
mkdtemp/0,
|
mkdtemp/0,
|
||||||
mkdir_path/1,
|
mkdir_path/1,
|
||||||
find/2,
|
find/2,
|
||||||
is_symlink/1,
|
is_symlink/1,
|
||||||
remove/1,
|
remove/1,
|
||||||
remove/2,
|
remove/2,
|
||||||
md5sum/1,
|
md5sum/1,
|
||||||
read/1,
|
read/1,
|
||||||
write/2,
|
write/2,
|
||||||
write_term/2,
|
write_term/2,
|
||||||
consult/1
|
consult/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export_type([
|
-export_type([
|
||||||
path/0,
|
path/0,
|
||||||
option/0
|
option/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include_lib("kernel/include/file.hrl").
|
-include_lib("kernel/include/file.hrl").
|
||||||
|
|
||||||
%% User friendly exception message (remove line and module info once we
|
%% User friendly exception message (remove line and module info once we
|
||||||
%% get them in stack traces)
|
%% get them in stack traces)
|
||||||
-define(UEX(Exception, UMSG, UVARS),
|
-define(UEX(Exception, UMSG, UVARS),
|
||||||
{uex, {?MODULE,
|
{uex, {?MODULE,
|
||||||
?LINE,
|
?LINE,
|
||||||
Exception,
|
Exception,
|
||||||
lists:flatten(io_lib:fwrite(UMSG, UVARS))}}).
|
lists:flatten(io_lib:fwrite(UMSG, UVARS))}}).
|
||||||
|
|
||||||
-define(CHECK_PERMS_MSG,
|
-define(CHECK_PERMS_MSG,
|
||||||
"Try checking that you have the correct permissions and try again~n").
|
"Try checking that you have the correct permissions and try again~n").
|
||||||
|
|
||||||
%%============================================================================
|
%%============================================================================
|
||||||
%% Types
|
%% Types
|
||||||
|
@ -55,20 +55,20 @@ copy(From, To, []) ->
|
||||||
copy(From, To);
|
copy(From, To);
|
||||||
copy(From, To, [recursive] = Options) ->
|
copy(From, To, [recursive] = Options) ->
|
||||||
case filelib:is_dir(From) of
|
case filelib:is_dir(From) of
|
||||||
false ->
|
false ->
|
||||||
copy(From, To);
|
copy(From, To);
|
||||||
true ->
|
true ->
|
||||||
make_dir_if_dir(To),
|
make_dir_if_dir(To),
|
||||||
copy_subfiles(From, To, Options)
|
copy_subfiles(From, To, Options)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc copy a file including timestamps,ownership and mode etc.
|
%% @doc copy a file including timestamps,ownership and mode etc.
|
||||||
-spec copy(From::string(), To::string()) -> ok.
|
-spec copy(From::string(), To::string()) -> ok.
|
||||||
copy(From, To) ->
|
copy(From, To) ->
|
||||||
try
|
try
|
||||||
ec_file_copy(From, To)
|
ec_file_copy(From, To)
|
||||||
catch
|
catch
|
||||||
_C:E -> throw(?UEX({copy_failed, E}, ?CHECK_PERMS_MSG, []))
|
_C:E -> throw(?UEX({copy_failed, E}, ?CHECK_PERMS_MSG, []))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc return an md5 checksum string or a binary. Same as unix utility of
|
%% @doc return an md5 checksum string or a binary. Same as unix utility of
|
||||||
|
@ -84,9 +84,9 @@ md5sum(Value) ->
|
||||||
-spec remove(path(), Options::[option()]) -> ok | {error, Reason::term()}.
|
-spec remove(path(), Options::[option()]) -> ok | {error, Reason::term()}.
|
||||||
remove(Path, Options) ->
|
remove(Path, Options) ->
|
||||||
try
|
try
|
||||||
ok = ec_file_remove(Path, Options)
|
ok = ec_file_remove(Path, Options)
|
||||||
catch
|
catch
|
||||||
_C:E -> throw(?UEX({remove_failed, E}, ?CHECK_PERMS_MSG, []))
|
_C:E -> throw(?UEX({remove_failed, E}, ?CHECK_PERMS_MSG, []))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc delete a file.
|
%% @doc delete a file.
|
||||||
|
@ -98,10 +98,10 @@ remove(Path) ->
|
||||||
-spec is_symlink(path()) -> boolean().
|
-spec is_symlink(path()) -> boolean().
|
||||||
is_symlink(Path) ->
|
is_symlink(Path) ->
|
||||||
case file:read_link_info(Path) of
|
case file:read_link_info(Path) of
|
||||||
{ok, #file_info{type = symlink}} ->
|
{ok, #file_info{type = symlink}} ->
|
||||||
true;
|
true;
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,27 +111,27 @@ is_symlink(Path) ->
|
||||||
mkdtemp() ->
|
mkdtemp() ->
|
||||||
UniqueNumber = integer_to_list(element(3, now())),
|
UniqueNumber = integer_to_list(element(3, now())),
|
||||||
TmpDirPath =
|
TmpDirPath =
|
||||||
filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]),
|
filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]),
|
||||||
try
|
try
|
||||||
ok = mkdir_path(TmpDirPath),
|
ok = mkdir_path(TmpDirPath),
|
||||||
TmpDirPath
|
TmpDirPath
|
||||||
catch
|
catch
|
||||||
_C:E -> throw(?UEX({mkdtemp_failed, E}, ?CHECK_PERMS_MSG, []))
|
_C:E -> throw(?UEX({mkdtemp_failed, E}, ?CHECK_PERMS_MSG, []))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
%% @doc Makes a directory including parent dirs if they are missing.
|
%% @doc Makes a directory including parent dirs if they are missing.
|
||||||
-spec mkdir_path(path()) -> ok.
|
-spec mkdir_path(path()) -> ok.
|
||||||
mkdir_path(Path) ->
|
mkdir_path(Path) ->
|
||||||
% We are exploiting a feature of ensuredir that that creates all
|
% We are exploiting a feature of ensuredir that that creates all
|
||||||
% directories up to the last element in the filename, then ignores
|
% directories up to the last element in the filename, then ignores
|
||||||
% that last element. This way we ensure that the dir is created
|
% that last element. This way we ensure that the dir is created
|
||||||
% and not have any worries about path names
|
% and not have any worries about path names
|
||||||
DirName = filename:join([filename:absname(Path), "tmp"]),
|
DirName = filename:join([filename:absname(Path), "tmp"]),
|
||||||
try
|
try
|
||||||
ok = filelib:ensure_dir(DirName)
|
ok = filelib:ensure_dir(DirName)
|
||||||
catch
|
catch
|
||||||
_C:E -> throw(?UEX({mkdir_path_failed, E}, ?CHECK_PERMS_MSG, []))
|
_C:E -> throw(?UEX({mkdir_path_failed, E}, ?CHECK_PERMS_MSG, []))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,43 +140,43 @@ mkdir_path(Path) ->
|
||||||
-spec consult(FilePath::path()) -> term().
|
-spec consult(FilePath::path()) -> term().
|
||||||
consult(FilePath) ->
|
consult(FilePath) ->
|
||||||
case file:consult(FilePath) of
|
case file:consult(FilePath) of
|
||||||
{ok, [Term]} ->
|
{ok, [Term]} ->
|
||||||
Term;
|
Term;
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
Msg = "The file at ~p~n" ++
|
Msg = "The file at ~p~n" ++
|
||||||
"is either not a valid Erlang term, does not to exist~n" ++
|
"is either not a valid Erlang term, does not to exist~n" ++
|
||||||
"or you lack the permissions to read it. Please check~n" ++
|
"or you lack the permissions to read it. Please check~n" ++
|
||||||
"to see if the file exists and that it has the correct~n" ++
|
"to see if the file exists and that it has the correct~n" ++
|
||||||
"permissions~n",
|
"permissions~n",
|
||||||
throw(?UEX({failed_to_consult_file, {FilePath, Error}},
|
throw(?UEX({failed_to_consult_file, {FilePath, Error}},
|
||||||
Msg, [FilePath]))
|
Msg, [FilePath]))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc read a file from the file system. Provide UEX exeption on failure.
|
%% @doc read a file from the file system. Provide UEX exeption on failure.
|
||||||
-spec read(FilePath::string()) -> binary().
|
-spec read(FilePath::string()) -> binary().
|
||||||
read(FilePath) ->
|
read(FilePath) ->
|
||||||
try
|
try
|
||||||
{ok, FileBin} = file:read_file(FilePath),
|
{ok, FileBin} = file:read_file(FilePath),
|
||||||
FileBin
|
FileBin
|
||||||
catch
|
catch
|
||||||
_C:E -> throw(?UEX({read_failed, {FilePath, E}},
|
_C:E -> throw(?UEX({read_failed, {FilePath, E}},
|
||||||
"Read failed for the file ~p with ~p~n" ++
|
"Read failed for the file ~p with ~p~n" ++
|
||||||
?CHECK_PERMS_MSG,
|
?CHECK_PERMS_MSG,
|
||||||
[FilePath, E]))
|
[FilePath, E]))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc write a file to the file system. Provide UEX exeption on failure.
|
%% @doc write a file to the file system. Provide UEX exeption on failure.
|
||||||
-spec write(FileName::string(), Contents::string()) -> ok.
|
-spec write(FileName::string(), Contents::string()) -> ok.
|
||||||
write(FileName, Contents) ->
|
write(FileName, Contents) ->
|
||||||
case file:write_file(FileName, Contents) of
|
case file:write_file(FileName, Contents) of
|
||||||
ok ->
|
ok ->
|
||||||
ok;
|
ok;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
Msg = "Writing the file ~s to disk failed with reason ~p.~n" ++
|
Msg = "Writing the file ~s to disk failed with reason ~p.~n" ++
|
||||||
?CHECK_PERMS_MSG,
|
?CHECK_PERMS_MSG,
|
||||||
throw(?UEX({write_file_failure, {FileName, Reason}},
|
throw(?UEX({write_file_failure, {FileName, Reason}},
|
||||||
Msg,
|
Msg,
|
||||||
[FileName, Reason]))
|
[FileName, Reason]))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc write a term out to a file so that it can be consulted later.
|
%% @doc write a term out to a file so that it can be consulted later.
|
||||||
|
@ -191,18 +191,18 @@ find([], _) ->
|
||||||
[];
|
[];
|
||||||
find(FromDir, TargetPattern) ->
|
find(FromDir, TargetPattern) ->
|
||||||
case filelib:is_dir(FromDir) of
|
case filelib:is_dir(FromDir) of
|
||||||
false ->
|
false ->
|
||||||
case re:run(FromDir, TargetPattern) of
|
case re:run(FromDir, TargetPattern) of
|
||||||
{match, _} -> [FromDir];
|
{match, _} -> [FromDir];
|
||||||
_ -> []
|
_ -> []
|
||||||
end;
|
end;
|
||||||
true ->
|
true ->
|
||||||
FoundDir = case re:run(FromDir, TargetPattern) of
|
FoundDir = case re:run(FromDir, TargetPattern) of
|
||||||
{match, _} -> [FromDir];
|
{match, _} -> [FromDir];
|
||||||
_ -> []
|
_ -> []
|
||||||
end,
|
end,
|
||||||
List = find_in_subdirs(FromDir, TargetPattern),
|
List = find_in_subdirs(FromDir, TargetPattern),
|
||||||
FoundDir ++ List
|
FoundDir ++ List
|
||||||
end.
|
end.
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Internal Functions
|
%%% Internal Functions
|
||||||
|
@ -210,53 +210,53 @@ find(FromDir, TargetPattern) ->
|
||||||
-spec find_in_subdirs(path(), string()) -> [path()].
|
-spec find_in_subdirs(path(), string()) -> [path()].
|
||||||
find_in_subdirs(FromDir, TargetPattern) ->
|
find_in_subdirs(FromDir, TargetPattern) ->
|
||||||
lists:foldl(fun(CheckFromDir, Acc)
|
lists:foldl(fun(CheckFromDir, Acc)
|
||||||
when CheckFromDir == FromDir ->
|
when CheckFromDir == FromDir ->
|
||||||
Acc;
|
Acc;
|
||||||
(ChildFromDir, Acc) ->
|
(ChildFromDir, Acc) ->
|
||||||
case find(ChildFromDir, TargetPattern) of
|
case find(ChildFromDir, TargetPattern) of
|
||||||
[] -> Acc;
|
[] -> Acc;
|
||||||
Res -> Res ++ Acc
|
Res -> Res ++ Acc
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
[],
|
[],
|
||||||
filelib:wildcard(filename:join(FromDir, "*"))).
|
filelib:wildcard(filename:join(FromDir, "*"))).
|
||||||
|
|
||||||
-spec ec_file_remove(path(), [{atom(), any()}]) -> ok.
|
-spec ec_file_remove(path(), [{atom(), any()}]) -> ok.
|
||||||
ec_file_remove(Path, Options) ->
|
ec_file_remove(Path, Options) ->
|
||||||
case lists:member(recursive, Options) of
|
case lists:member(recursive, Options) of
|
||||||
false -> file:delete(Path);
|
false -> file:delete(Path);
|
||||||
true -> remove_recursive(Path, Options)
|
true -> remove_recursive(Path, Options)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec remove_recursive(path(), Options::list()) -> ok.
|
-spec remove_recursive(path(), Options::list()) -> ok.
|
||||||
remove_recursive(Path, Options) ->
|
remove_recursive(Path, Options) ->
|
||||||
case filelib:is_dir(Path) of
|
case filelib:is_dir(Path) of
|
||||||
false ->
|
false ->
|
||||||
file:delete(Path);
|
file:delete(Path);
|
||||||
true ->
|
true ->
|
||||||
lists:foreach(fun(ChildPath) ->
|
lists:foreach(fun(ChildPath) ->
|
||||||
remove_recursive(ChildPath, Options)
|
remove_recursive(ChildPath, Options)
|
||||||
end, filelib:wildcard(filename:join(Path, "*"))),
|
end, filelib:wildcard(filename:join(Path, "*"))),
|
||||||
ok = file:del_dir(Path)
|
ok = file:del_dir(Path)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec tmp() -> path().
|
-spec tmp() -> path().
|
||||||
tmp() ->
|
tmp() ->
|
||||||
case erlang:system_info(system_architecture) of
|
case erlang:system_info(system_architecture) of
|
||||||
"win32" ->
|
"win32" ->
|
||||||
"./tmp";
|
"./tmp";
|
||||||
_SysArch ->
|
_SysArch ->
|
||||||
"/tmp"
|
"/tmp"
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% Copy the subfiles of the From directory to the to directory.
|
%% Copy the subfiles of the From directory to the to directory.
|
||||||
-spec copy_subfiles(path(), path(), [option()]) -> ok.
|
-spec copy_subfiles(path(), path(), [option()]) -> ok.
|
||||||
copy_subfiles(From, To, Options) ->
|
copy_subfiles(From, To, Options) ->
|
||||||
Fun =
|
Fun =
|
||||||
fun(ChildFrom) ->
|
fun(ChildFrom) ->
|
||||||
ChildTo = filename:join([To, filename:basename(ChildFrom)]),
|
ChildTo = filename:join([To, filename:basename(ChildFrom)]),
|
||||||
copy(ChildFrom, ChildTo, Options)
|
copy(ChildFrom, ChildTo, Options)
|
||||||
end,
|
end,
|
||||||
lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))).
|
lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))).
|
||||||
|
|
||||||
-spec ec_file_copy(path(), path()) -> ok.
|
-spec ec_file_copy(path(), path()) -> ok.
|
||||||
|
@ -268,8 +268,8 @@ ec_file_copy(From, To) ->
|
||||||
-spec make_dir_if_dir(path()) -> ok.
|
-spec make_dir_if_dir(path()) -> ok.
|
||||||
make_dir_if_dir(File) ->
|
make_dir_if_dir(File) ->
|
||||||
case filelib:is_dir(File) of
|
case filelib:is_dir(File) of
|
||||||
true -> ok;
|
true -> ok;
|
||||||
false -> ok = mkdir_path(File)
|
false -> ok = mkdir_path(File)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc convert a list of integers into hex.
|
%% @doc convert a list of integers into hex.
|
||||||
|
@ -298,10 +298,10 @@ hex0(I) -> $0 + I.
|
||||||
|
|
||||||
setup_test() ->
|
setup_test() ->
|
||||||
case filelib:is_dir("/tmp/ec_file") of
|
case filelib:is_dir("/tmp/ec_file") of
|
||||||
true ->
|
true ->
|
||||||
remove("/tmp/ec_file", [recursive]);
|
remove("/tmp/ec_file", [recursive]);
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
mkdir_path("/tmp/ec_file/dir"),
|
mkdir_path("/tmp/ec_file/dir"),
|
||||||
?assertMatch(false, is_symlink("/tmp/ec_file/dir")),
|
?assertMatch(false, is_symlink("/tmp/ec_file/dir")),
|
||||||
|
@ -318,8 +318,8 @@ file_test() ->
|
||||||
?assertMatch("term", consult(TermFile)),
|
?assertMatch("term", consult(TermFile)),
|
||||||
?assertMatch(<<"\"term\". ">>, read(TermFile)),
|
?assertMatch(<<"\"term\". ">>, read(TermFile)),
|
||||||
copy(filename:dirname(TermFile),
|
copy(filename:dirname(TermFile),
|
||||||
filename:dirname(TermFileCopy),
|
filename:dirname(TermFileCopy),
|
||||||
[recursive]),
|
[recursive]),
|
||||||
?assertMatch("term", consult(TermFileCopy)).
|
?assertMatch("term", consult(TermFileCopy)).
|
||||||
|
|
||||||
teardown_test() ->
|
teardown_test() ->
|
||||||
|
@ -343,18 +343,18 @@ setup_base_and_target() ->
|
||||||
{BaseDir, SourceDir, {Name1, Name2, Name3, NoName}}.
|
{BaseDir, SourceDir, {Name1, Name2, Name3, NoName}}.
|
||||||
|
|
||||||
find_test() ->
|
find_test() ->
|
||||||
% Create a directory in /tmp for the test. Clean everything afterwards
|
% Create a directory in /tmp for the test. Clean everything afterwards
|
||||||
|
|
||||||
{setup,
|
{setup,
|
||||||
fun setup_base_and_target/0,
|
fun setup_base_and_target/0,
|
||||||
fun ({BaseDir, _, _}) ->
|
fun ({BaseDir, _, _}) ->
|
||||||
ewl_file:delete_dir(BaseDir)
|
ewl_file:delete_dir(BaseDir)
|
||||||
end,
|
end,
|
||||||
fun ({BaseDir, _, {Name1, Name2, Name3, _}}) ->
|
fun ({BaseDir, _, {Name1, Name2, Name3, _}}) ->
|
||||||
?assertMatch([Name2,
|
?assertMatch([Name2,
|
||||||
Name3,
|
Name3,
|
||||||
Name1],
|
Name1],
|
||||||
ewl_file:find(BaseDir, "file[a-z]+\$"))
|
ewl_file:find(BaseDir, "file[a-z]+\$"))
|
||||||
end}.
|
end}.
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
|
138
src/ec_lists.erl
138
src/ec_lists.erl
|
@ -42,10 +42,10 @@ search(_, []) ->
|
||||||
-spec find(fun(), list()) -> {ok, term()} | error.
|
-spec find(fun(), list()) -> {ok, term()} | error.
|
||||||
find(Fun, [Head|Tail]) when is_function(Fun) ->
|
find(Fun, [Head|Tail]) when is_function(Fun) ->
|
||||||
case Fun(Head) of
|
case Fun(Head) of
|
||||||
true ->
|
true ->
|
||||||
{ok, Head};
|
{ok, Head};
|
||||||
false ->
|
false ->
|
||||||
find(Fun, Tail)
|
find(Fun, Tail)
|
||||||
end;
|
end;
|
||||||
find(_Fun, []) ->
|
find(_Fun, []) ->
|
||||||
error.
|
error.
|
||||||
|
@ -57,10 +57,10 @@ find(_Fun, []) ->
|
||||||
-spec fetch(fun(), list()) -> term().
|
-spec fetch(fun(), list()) -> term().
|
||||||
fetch(Fun, List) when is_list(List), is_function(Fun) ->
|
fetch(Fun, List) when is_list(List), is_function(Fun) ->
|
||||||
case find(Fun, List) of
|
case find(Fun, List) of
|
||||||
{ok, Head} ->
|
{ok, Head} ->
|
||||||
Head;
|
Head;
|
||||||
error ->
|
error ->
|
||||||
throw(not_found)
|
throw(not_found)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
@ -73,60 +73,60 @@ fetch(Fun, List) when is_list(List), is_function(Fun) ->
|
||||||
find1_test() ->
|
find1_test() ->
|
||||||
TestData = [1, 2, 3, 4, 5, 6],
|
TestData = [1, 2, 3, 4, 5, 6],
|
||||||
Result = find(fun(5) ->
|
Result = find(fun(5) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch({ok, 5}, Result),
|
?assertMatch({ok, 5}, Result),
|
||||||
|
|
||||||
Result2 = find(fun(37) ->
|
Result2 = find(fun(37) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch(error, Result2).
|
?assertMatch(error, Result2).
|
||||||
|
|
||||||
find2_test() ->
|
find2_test() ->
|
||||||
TestData = ["one", "two", "three", "four", "five", "six"],
|
TestData = ["one", "two", "three", "four", "five", "six"],
|
||||||
Result = find(fun("five") ->
|
Result = find(fun("five") ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch({ok, "five"}, Result),
|
?assertMatch({ok, "five"}, Result),
|
||||||
|
|
||||||
Result2 = find(fun(super_duper) ->
|
Result2 = find(fun(super_duper) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch(error, Result2).
|
?assertMatch(error, Result2).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
find3_test() ->
|
find3_test() ->
|
||||||
TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5},
|
TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5},
|
||||||
{"six", 6}],
|
{"six", 6}],
|
||||||
Result = find(fun({"one", 1}) ->
|
Result = find(fun({"one", 1}) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch({ok, {"one", 1}}, Result),
|
?assertMatch({ok, {"one", 1}}, Result),
|
||||||
|
|
||||||
Result2 = find(fun([fo, bar, baz]) ->
|
Result2 = find(fun([fo, bar, baz]) ->
|
||||||
true;
|
true;
|
||||||
({"onehundred", 100}) ->
|
({"onehundred", 100}) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch(error, Result2).
|
?assertMatch(error, Result2).
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,48 +134,48 @@ find3_test() ->
|
||||||
fetch1_test() ->
|
fetch1_test() ->
|
||||||
TestData = [1, 2, 3, 4, 5, 6],
|
TestData = [1, 2, 3, 4, 5, 6],
|
||||||
Result = fetch(fun(5) ->
|
Result = fetch(fun(5) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch(5, Result),
|
?assertMatch(5, Result),
|
||||||
|
|
||||||
?assertThrow(not_found,
|
?assertThrow(not_found,
|
||||||
fetch(fun(37) ->
|
fetch(fun(37) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData)).
|
TestData)).
|
||||||
|
|
||||||
fetch2_test() ->
|
fetch2_test() ->
|
||||||
TestData = ["one", "two", "three", "four", "five", "six"],
|
TestData = ["one", "two", "three", "four", "five", "six"],
|
||||||
Result = fetch(fun("five") ->
|
Result = fetch(fun("five") ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch("five", Result),
|
?assertMatch("five", Result),
|
||||||
|
|
||||||
?assertThrow(not_found,
|
?assertThrow(not_found,
|
||||||
fetch(fun(super_duper) ->
|
fetch(fun(super_duper) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData)).
|
TestData)).
|
||||||
|
|
||||||
fetch3_test() ->
|
fetch3_test() ->
|
||||||
TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5},
|
TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5},
|
||||||
{"six", 6}],
|
{"six", 6}],
|
||||||
Result = fetch(fun({"one", 1}) ->
|
Result = fetch(fun({"one", 1}) ->
|
||||||
true;
|
true;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
TestData),
|
TestData),
|
||||||
?assertMatch({"one", 1}, Result),
|
?assertMatch({"one", 1}, Result),
|
||||||
|
|
||||||
?assertThrow(not_found,
|
?assertThrow(not_found,
|
||||||
|
|
|
@ -69,14 +69,14 @@ filter(Fun, List, Timeout) ->
|
||||||
run_list_fun_in_parallel(ListFun, Fun, List, Timeout) ->
|
run_list_fun_in_parallel(ListFun, Fun, List, Timeout) ->
|
||||||
LocalPid = self(),
|
LocalPid = self(),
|
||||||
Pids =
|
Pids =
|
||||||
lists:map(fun(E) ->
|
lists:map(fun(E) ->
|
||||||
Pid =
|
Pid =
|
||||||
proc_lib:spawn(fun() ->
|
proc_lib:spawn(fun() ->
|
||||||
wait(LocalPid, Fun,
|
wait(LocalPid, Fun,
|
||||||
E, Timeout)
|
E, Timeout)
|
||||||
end),
|
end),
|
||||||
{Pid, E}
|
{Pid, E}
|
||||||
end, List),
|
end, List),
|
||||||
gather(ListFun, Pids).
|
gather(ListFun, Pids).
|
||||||
|
|
||||||
-spec wait(pid(), fun(), any(), integer()) -> any().
|
-spec wait(pid(), fun(), any(), integer()) -> any().
|
||||||
|
@ -110,13 +110,13 @@ gather(filter, PidElementList) ->
|
||||||
map_gather([{Pid, _E} | Rest]) ->
|
map_gather([{Pid, _E} | Rest]) ->
|
||||||
receive
|
receive
|
||||||
{Pid, {value, Ret}} ->
|
{Pid, {value, Ret}} ->
|
||||||
[Ret|map_gather(Rest)];
|
[Ret|map_gather(Rest)];
|
||||||
% timeouts fall here too. Should timeouts be a return value
|
% timeouts fall here too. Should timeouts be a return value
|
||||||
% or an exception? I lean toward return value, but the code
|
% or an exception? I lean toward return value, but the code
|
||||||
% is easier with the exception. Thoughts?
|
% is easier with the exception. Thoughts?
|
||||||
{Pid, Exception} ->
|
{Pid, Exception} ->
|
||||||
killall(Rest),
|
killall(Rest),
|
||||||
throw(Exception)
|
throw(Exception)
|
||||||
end;
|
end;
|
||||||
map_gather([]) ->
|
map_gather([]) ->
|
||||||
[].
|
[].
|
||||||
|
@ -133,15 +133,15 @@ ftmap_gather([]) ->
|
||||||
filter_gather([{Pid, E} | Rest]) ->
|
filter_gather([{Pid, E} | Rest]) ->
|
||||||
receive
|
receive
|
||||||
{Pid, {value, false}} ->
|
{Pid, {value, false}} ->
|
||||||
filter_gather(Rest);
|
filter_gather(Rest);
|
||||||
{Pid, {value, true}} ->
|
{Pid, {value, true}} ->
|
||||||
[E|filter_gather(Rest)];
|
[E|filter_gather(Rest)];
|
||||||
{Pid, {value, NotBool}} ->
|
{Pid, {value, NotBool}} ->
|
||||||
killall(Rest),
|
killall(Rest),
|
||||||
throw({bad_return_value, NotBool});
|
throw({bad_return_value, NotBool});
|
||||||
{Pid, Exception} ->
|
{Pid, Exception} ->
|
||||||
killall(Rest),
|
killall(Rest),
|
||||||
throw(Exception)
|
throw(Exception)
|
||||||
end;
|
end;
|
||||||
filter_gather([]) ->
|
filter_gather([]) ->
|
||||||
[].
|
[].
|
||||||
|
@ -153,9 +153,9 @@ do_f(Parent, F, E) ->
|
||||||
Parent ! {self(), {value, Result}}
|
Parent ! {self(), {value, Result}}
|
||||||
catch
|
catch
|
||||||
_Class:Exception ->
|
_Class:Exception ->
|
||||||
% Losing class info here, but since throw does not accept
|
% Losing class info here, but since throw does not accept
|
||||||
% that arg anyhow and forces a class of throw it does not
|
% that arg anyhow and forces a class of throw it does not
|
||||||
% matter.
|
% matter.
|
||||||
Parent ! {self(), Exception}
|
Parent ! {self(), Exception}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -183,9 +183,9 @@ map_good_test() ->
|
||||||
|
|
||||||
ftmap_good_test() ->
|
ftmap_good_test() ->
|
||||||
Results = ftmap(fun(_) ->
|
Results = ftmap(fun(_) ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
lists:seq(1, 3), infinity),
|
lists:seq(1, 3), infinity),
|
||||||
?assertMatch([{value, ok}, {value, ok}, {value, ok}],
|
?assertMatch([{value, ok}, {value, ok}, {value, ok}],
|
||||||
Results).
|
Results).
|
||||||
|
|
||||||
|
@ -199,59 +199,59 @@ filter_good_test() ->
|
||||||
|
|
||||||
map_timeout_test() ->
|
map_timeout_test() ->
|
||||||
Results =
|
Results =
|
||||||
try
|
try
|
||||||
map(fun(T) ->
|
map(fun(T) ->
|
||||||
timer:sleep(T),
|
timer:sleep(T),
|
||||||
T
|
T
|
||||||
end,
|
end,
|
||||||
[1, 100], 10)
|
[1, 100], 10)
|
||||||
catch
|
catch
|
||||||
C:E -> {C, E}
|
C:E -> {C, E}
|
||||||
end,
|
end,
|
||||||
?assertMatch({throw, timeout}, Results).
|
?assertMatch({throw, timeout}, Results).
|
||||||
|
|
||||||
ftmap_timeout_test() ->
|
ftmap_timeout_test() ->
|
||||||
Results = ftmap(fun(X) ->
|
Results = ftmap(fun(X) ->
|
||||||
timer:sleep(X),
|
timer:sleep(X),
|
||||||
true
|
true
|
||||||
end,
|
end,
|
||||||
[100, 1], 10),
|
[100, 1], 10),
|
||||||
?assertMatch([timeout, {value, true}], Results).
|
?assertMatch([timeout, {value, true}], Results).
|
||||||
|
|
||||||
filter_timeout_test() ->
|
filter_timeout_test() ->
|
||||||
Results =
|
Results =
|
||||||
try
|
try
|
||||||
filter(fun(T) ->
|
filter(fun(T) ->
|
||||||
timer:sleep(T),
|
timer:sleep(T),
|
||||||
T == 1
|
T == 1
|
||||||
end,
|
end,
|
||||||
[1, 100], 10)
|
[1, 100], 10)
|
||||||
catch
|
catch
|
||||||
C:E -> {C, E}
|
C:E -> {C, E}
|
||||||
end,
|
end,
|
||||||
?assertMatch({throw, timeout}, Results).
|
?assertMatch({throw, timeout}, Results).
|
||||||
|
|
||||||
map_bad_test() ->
|
map_bad_test() ->
|
||||||
Results =
|
Results =
|
||||||
try
|
try
|
||||||
map(fun(_) ->
|
map(fun(_) ->
|
||||||
throw(test_exception)
|
throw(test_exception)
|
||||||
end,
|
end,
|
||||||
lists:seq(1, 5), infinity)
|
lists:seq(1, 5), infinity)
|
||||||
catch
|
catch
|
||||||
C:E -> {C, E}
|
C:E -> {C, E}
|
||||||
end,
|
end,
|
||||||
?assertMatch({throw, test_exception}, Results).
|
?assertMatch({throw, test_exception}, Results).
|
||||||
|
|
||||||
ftmap_bad_test() ->
|
ftmap_bad_test() ->
|
||||||
Results =
|
Results =
|
||||||
ftmap(fun(2) ->
|
ftmap(fun(2) ->
|
||||||
throw(test_exception);
|
throw(test_exception);
|
||||||
(N) ->
|
(N) ->
|
||||||
N
|
N
|
||||||
end,
|
end,
|
||||||
lists:seq(1, 5), infinity),
|
lists:seq(1, 5), infinity),
|
||||||
?assertMatch([{value, 1}, test_exception, {value, 3},
|
?assertMatch([{value, 1}, test_exception, {value, 3},
|
||||||
{value, 4}, {value, 5}] , Results).
|
{value, 4}, {value, 5}] , Results).
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
-module(ec_semver).
|
-module(ec_semver).
|
||||||
|
|
||||||
-exports([
|
-exports([
|
||||||
compare/2
|
compare/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export_type([
|
-export_type([
|
||||||
semvar/0
|
semvar/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Public Types
|
%%% Public Types
|
||||||
|
@ -21,9 +21,9 @@
|
||||||
|
|
||||||
-type semvar() :: string().
|
-type semvar() :: string().
|
||||||
-type parsed_semvar() :: {MajorVsn::string(),
|
-type parsed_semvar() :: {MajorVsn::string(),
|
||||||
MinorVsn::string(),
|
MinorVsn::string(),
|
||||||
PatchVsn::string(),
|
PatchVsn::string(),
|
||||||
PathString::string()}.
|
PathString::string()}.
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% API
|
%%% API
|
||||||
|
@ -48,13 +48,13 @@ tokens(Vsn) ->
|
||||||
{MajorVsn, MinorVsn, PatchVsn, PatchString}.
|
{MajorVsn, MinorVsn, PatchVsn, PatchString}.
|
||||||
|
|
||||||
-spec split_patch(string()) ->
|
-spec split_patch(string()) ->
|
||||||
{PatchVsn::string(), PatchStr::string()}.
|
{PatchVsn::string(), PatchStr::string()}.
|
||||||
split_patch(RawPatch) ->
|
split_patch(RawPatch) ->
|
||||||
{PatchVsn, PatchStr} = split_patch(RawPatch, {"", ""}),
|
{PatchVsn, PatchStr} = split_patch(RawPatch, {"", ""}),
|
||||||
{lists:reverse(PatchVsn), PatchStr}.
|
{lists:reverse(PatchVsn), PatchStr}.
|
||||||
|
|
||||||
-spec split_patch(string(), {AccPatchVsn::string(), AccPatchStr::string()}) ->
|
-spec split_patch(string(), {AccPatchVsn::string(), AccPatchStr::string()}) ->
|
||||||
{PatchVsn::string(), PatchStr::string()}.
|
{PatchVsn::string(), PatchStr::string()}.
|
||||||
split_patch([], Acc) ->
|
split_patch([], Acc) ->
|
||||||
Acc;
|
Acc;
|
||||||
split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 ->
|
split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 ->
|
||||||
|
@ -65,7 +65,7 @@ split_patch(PatchStr, {PatchVsn, ""}) ->
|
||||||
-spec compare_toks(parsed_semvar(), parsed_semvar()) -> boolean().
|
-spec compare_toks(parsed_semvar(), parsed_semvar()) -> boolean().
|
||||||
compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) ->
|
compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) ->
|
||||||
compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA},
|
compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA},
|
||||||
{to_int(MajB), to_int(MinB), to_int(PVB), PSB}).
|
{to_int(MajB), to_int(MinB), to_int(PVB), PSB}).
|
||||||
|
|
||||||
-spec compare_toks2(parsed_semvar(), parsed_semvar()) -> boolean().
|
-spec compare_toks2(parsed_semvar(), parsed_semvar()) -> boolean().
|
||||||
compare_toks2({MajA, _MinA, _PVA, _PSA}, {MajB, _MinB, _PVB, _PSB})
|
compare_toks2({MajA, _MinA, _PVA, _PSA}, {MajB, _MinB, _PVB, _PSB})
|
||||||
|
@ -89,10 +89,10 @@ compare_toks2(_ToksA, _ToksB) ->
|
||||||
-spec to_int(string()) -> integer().
|
-spec to_int(string()) -> integer().
|
||||||
to_int(String) ->
|
to_int(String) ->
|
||||||
try
|
try
|
||||||
list_to_integer(String)
|
list_to_integer(String)
|
||||||
catch
|
catch
|
||||||
error:badarg ->
|
error:badarg ->
|
||||||
throw(invalid_semver_string)
|
throw(invalid_semver_string)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
-module(ec_string).
|
-module(ec_string).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
compare_versions/2
|
compare_versions/2
|
||||||
]).
|
]).
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% API
|
%%% API
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
@ -39,7 +39,7 @@ compare([Str|TA], [Str|TB]) ->
|
||||||
compare(TA, TB);
|
compare(TA, TB);
|
||||||
compare([StrA|TA], [StrB|TB]) ->
|
compare([StrA|TA], [StrB|TB]) ->
|
||||||
fine_compare(split_numeric_alpha(StrA), TA,
|
fine_compare(split_numeric_alpha(StrA), TA,
|
||||||
split_numeric_alpha(StrB), TB);
|
split_numeric_alpha(StrB), TB);
|
||||||
compare([], [Str]) ->
|
compare([], [Str]) ->
|
||||||
not compare_against_nothing(Str);
|
not compare_against_nothing(Str);
|
||||||
compare([Str], []) ->
|
compare([Str], []) ->
|
||||||
|
@ -54,14 +54,14 @@ compare([], []) ->
|
||||||
-spec compare_against_nothing(string()) -> boolean().
|
-spec compare_against_nothing(string()) -> boolean().
|
||||||
compare_against_nothing(Str) ->
|
compare_against_nothing(Str) ->
|
||||||
case split_numeric_alpha(Str) of
|
case split_numeric_alpha(Str) of
|
||||||
{_StrDig, ""} -> true;
|
{_StrDig, ""} -> true;
|
||||||
{"", _StrAlpha} -> false;
|
{"", _StrAlpha} -> false;
|
||||||
{_StrDig, _StrAlpha} -> true
|
{_StrDig, _StrAlpha} -> true
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec fine_compare({string(), string()}, string(),
|
-spec fine_compare({string(), string()}, string(),
|
||||||
{string(), string()}, string()) ->
|
{string(), string()}, string()) ->
|
||||||
boolean().
|
boolean().
|
||||||
fine_compare({_StrDigA, StrA}, TA, {_StrDigB, _StrB}, _TB)
|
fine_compare({_StrDigA, StrA}, TA, {_StrDigB, _StrB}, _TB)
|
||||||
when StrA /= "", TA /= [] ->
|
when StrA /= "", TA /= [] ->
|
||||||
throw(invalid_version_string);
|
throw(invalid_version_string);
|
||||||
|
@ -84,14 +84,14 @@ fine_compare({StrDigA, _StrA}, _TA, {StrDigB, _StrB}, _TB) ->
|
||||||
%% In the case of a version sub part with a numeric then an alpha,
|
%% In the case of a version sub part with a numeric then an alpha,
|
||||||
%% split out the numeric and alpha "24alpha" becomes {"24", "alpha"}
|
%% split out the numeric and alpha "24alpha" becomes {"24", "alpha"}
|
||||||
-spec split_numeric_alpha(string()) ->
|
-spec split_numeric_alpha(string()) ->
|
||||||
{PatchVsn::string(), PatchStr::string()}.
|
{PatchVsn::string(), PatchStr::string()}.
|
||||||
split_numeric_alpha(RawVsn) ->
|
split_numeric_alpha(RawVsn) ->
|
||||||
{Num, Str} = split_numeric_alpha(RawVsn, {"", ""}),
|
{Num, Str} = split_numeric_alpha(RawVsn, {"", ""}),
|
||||||
{lists:reverse(Num), Str}.
|
{lists:reverse(Num), Str}.
|
||||||
|
|
||||||
-spec split_numeric_alpha(string(), {PatchVsnAcc::string(),
|
-spec split_numeric_alpha(string(), {PatchVsnAcc::string(),
|
||||||
PatchStrAcc::string()}) ->
|
PatchStrAcc::string()}) ->
|
||||||
{PatchVsn::string(), PatchStr::string()}.
|
{PatchVsn::string(), PatchStr::string()}.
|
||||||
split_numeric_alpha([], Acc) ->
|
split_numeric_alpha([], Acc) ->
|
||||||
Acc;
|
Acc;
|
||||||
split_numeric_alpha([Dig|T], {PatchVsn, PatchStr})
|
split_numeric_alpha([Dig|T], {PatchVsn, PatchStr})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue