diff --git a/src/ec_file.erl b/src/ec_file.erl index 399dd1a..5261ef1 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -22,7 +22,10 @@ consult/1 ]). --export_type([path/0]). +-export_type([ + path/0, + option/0 + ]). -include_lib("kernel/include/file.hrl"). @@ -34,19 +37,20 @@ Exception, 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"). %%============================================================================ %% Types %%============================================================================ -type path() :: string(). +-type option() :: [atom()]. %%%=================================================================== %%% API %%%=================================================================== %% @doc copy an entire directory to another location. --spec copy(path(), path(), Options::list()) -> ok. +-spec copy(path(), path(), Options::[option()]) -> ok. copy(From, To, []) -> copy(From, To); copy(From, To, [recursive] = Options) -> @@ -77,7 +81,7 @@ md5sum(Value) -> %%
 %% Example: remove("./tmp_dir", [recursive]).
 %% 
--spec remove(path(), Options::list()) -> ok | {error, Reason::term()}. +-spec remove(path(), Options::[option()]) -> ok | {error, Reason::term()}. remove(Path, Options) -> try ok = ec_file_remove(Path, Options) @@ -85,7 +89,7 @@ remove(Path, Options) -> _C:E -> throw(?UEX({remove_failed, E}, ?CHECK_PERMS_MSG, [])) end. -%% @doc delete a file. +%% @doc delete a file. -spec remove(path()) -> ok | {error, Reason::term()}. remove(Path) -> remove(Path, []). @@ -100,7 +104,7 @@ is_symlink(Path) -> false end. -%% @doc make a unique temorory directory. Similar function to BSD stdlib +%% @doc make a unique temorory directory. Similar function to BSD stdlib %% function of the same name. -spec mkdtemp() -> TmpDirPath::path(). mkdtemp() -> @@ -128,11 +132,11 @@ mkdir_path(Path) -> catch _C:E -> throw(?UEX({mkdir_path_failed, E}, ?CHECK_PERMS_MSG, [])) end. - - + + %% @doc consult an erlang term file from the file system. %% Provide user readible exeption on failure. --spec consult(FilePath::string()) -> term(). +-spec consult(FilePath::path()) -> term(). consult(FilePath) -> case file:consult(FilePath) of {ok, [Term]} -> @@ -181,7 +185,7 @@ write_term(FileName, Term) -> %% @doc Finds files and directories that match the regexp supplied in %% the TargetPattern regexp. --spec find(FromDir::path(), TargetPattern::string()) -> list(). +-spec find(FromDir::path(), TargetPattern::string()) -> [path()]. find([], _) -> []; find(FromDir, TargetPattern) -> @@ -202,6 +206,7 @@ find(FromDir, TargetPattern) -> %%%=================================================================== %%% Internal Functions %%%=================================================================== +-spec find_in_subdirs(path(), string()) -> [path()]. find_in_subdirs(FromDir, TargetPattern) -> lists:foldl(fun(CheckFromDir, Acc) when CheckFromDir == FromDir -> @@ -214,7 +219,8 @@ find_in_subdirs(FromDir, TargetPattern) -> end, [], filelib:wildcard(filename:join(FromDir, "*"))). - + +-spec ec_file_remove(path(), [{atom(), any()}]) -> ok. ec_file_remove(Path, Options) -> case lists:member(recursive, Options) of false -> file:delete(Path); @@ -233,6 +239,7 @@ remove_recursive(Path, Options) -> ok = file:del_dir(Path) end. +-spec tmp() -> path(). tmp() -> case erlang:system_info(system_architecture) of "win32" -> @@ -243,19 +250,22 @@ tmp() -> end. %% Copy the subfiles of the From directory to the to directory. +-spec copy_subfiles(path(), path(), [option()]) -> ok. copy_subfiles(From, To, Options) -> - Fun = + Fun = fun(ChildFrom) -> ChildTo = filename:join([To, filename:basename(ChildFrom)]), copy(ChildFrom, ChildTo, Options) end, lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))). +-spec ec_file_copy(path(), path()) -> ok. ec_file_copy(From, To) -> {ok, _} = file:copy(From, To), {ok, FileInfo} = file:read_file_info(From), ok = file:write_file_info(To, FileInfo). +-spec make_dir_if_dir(path()) -> ok. make_dir_if_dir(File) -> case filelib:is_dir(File) of true -> ok; @@ -263,6 +273,7 @@ make_dir_if_dir(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 -> @@ -295,10 +306,10 @@ setup_test() -> mkdir_path("/tmp/ec_file/dir"), ?assertMatch(false, is_symlink("/tmp/ec_file/dir")), ?assertMatch(true, filelib:is_dir("/tmp/ec_file/dir")). - - + + md5sum_test() -> - ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")). + ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")). file_test() -> TermFile = "/tmp/ec_file/dir/file.term", diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 8f4ec72..b41a701 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -11,6 +11,20 @@ compare/2 ]). +-export_type([ + semvar/0 + ]). + +%%%=================================================================== +%%% Public Types +%%%=================================================================== + +-type semvar() :: string(). +-type parsed_semvar() :: {MajorVsn::string(), + MinorVsn::string(), + PatchVsn::string(), + PathString::string()}. + %%%=================================================================== %%% API %%%=================================================================== @@ -26,15 +40,20 @@ compare(VsnA, VsnB) -> %%%=================================================================== %%% Internal Functions %%%=================================================================== +-spec tokens(semvar()) -> parsed_semvar(). tokens(Vsn) -> [MajorVsn, MinorVsn, RawPatch] = string:tokens(Vsn, "."), {PatchVsn, PatchString} = split_patch(RawPatch), {MajorVsn, MinorVsn, PatchVsn, PatchString}. +-spec split_patch(string()) -> + {PatchVsn::string(), PatchStr::string()}. split_patch(RawPatch) -> {PatchVsn, PatchStr} = split_patch(RawPatch, {"", ""}), {lists:reverse(PatchVsn), PatchStr}. +-spec split_patch(string(), {AccPatchVsn::string(), AccPatchStr::string()}) -> + {PatchVsn::string(), PatchStr::string()}. split_patch([], Acc) -> Acc; split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 -> @@ -42,10 +61,12 @@ split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 -> split_patch(PatchStr, {PatchVsn, ""}) -> {PatchVsn, PatchStr}. +-spec compare_toks(parsed_semvar(), parsed_semvar()) -> boolean(). compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) -> compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA}, {to_int(MajB), to_int(MinB), to_int(PVB), PSB}). +-spec compare_toks2(parsed_semvar(), parsed_semvar()) -> boolean(). compare_toks2({MajA, _MinA, _PVA, _PSA}, {MajB, _MinB, _PVB, _PSB}) when MajA > MajB -> true; compare_toks2({_Maj, MinA, _PVA, _PSA}, {_Maj, MinB, _PVB, _PSB}) when MinA > MinB -> @@ -60,7 +81,8 @@ compare_toks2({_Maj, _Min, _PV, PSA}, {_Maj, _Min, _PV, PSB}) when PSA > PSB -> true; compare_toks2(_ToksA, _ToksB) -> false. - + +-spec to_int(string()) -> integer(). to_int(String) -> case catch list_to_integer(String) of Integer when is_integer(Integer) -> diff --git a/src/ec_string.erl b/src/ec_string.erl index 1dcba81..f730b81 100644 --- a/src/ec_string.erl +++ b/src/ec_string.erl @@ -17,7 +17,7 @@ %% Valid version string elements are either separated by . or - or both. %% Final version string elements may have a numeric followed directly by an %% alpha numeric and will be compared separately as in 12alpha. -%% +%% %%
 %% Example: compare_versions("3-2-5-alpha", "3.10.6") will return false
 %%          compare_versions("3-2-alpha", "3.2.1-alpha") will return false
@@ -34,14 +34,15 @@ compare_versions(VsnA, VsnB) ->
 %%% Internal Functions
 %%%===================================================================
 
+-spec compare(string(), string()) -> boolean().
 compare([Str|TA], [Str|TB]) ->
     compare(TA, TB);
 compare([StrA|TA], [StrB|TB]) ->
     fine_compare(split_numeric_alpha(StrA), TA,
 		 split_numeric_alpha(StrB), TB);
-compare([], [Str]) -> 
+compare([], [Str]) ->
     not compare_against_nothing(Str);
-compare([Str], []) -> 
+compare([Str], []) ->
     compare_against_nothing(Str);
 compare([], [_,_|_]) ->
     false;
@@ -50,6 +51,7 @@ compare([_,_|_], []) ->
 compare([], []) ->
     false.
 
+-spec compare_against_nothing(string()) -> boolean().
 compare_against_nothing(Str) ->
     case split_numeric_alpha(Str) of
 	{_StrDig, ""} -> true;
@@ -57,6 +59,9 @@ compare_against_nothing(Str) ->
 	{_StrDig, _StrAlpha} -> true
     end.
 
+-spec fine_compare({string(), string()}, string(),
+		   {string(), string()}, string()) ->
+    boolean().
 fine_compare({_StrDigA, StrA}, TA, {_StrDigB, _StrB}, _TB) when StrA /= "", TA /= [] ->
     throw(invalid_version_string);
 fine_compare({_StrDigA, _StrA}, _TA, {_StrDigB, StrB}, TB) when StrB /= "", TB /= [] ->
@@ -74,12 +79,17 @@ fine_compare({StrDig, StrA}, _TA, {StrDig, StrB}, _TB) ->
 fine_compare({StrDigA, _StrA}, _TA, {StrDigB, _StrB}, _TB) ->
     list_to_integer(StrDigA) > list_to_integer(StrDigB).
 
-%% 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"}
+-spec split_numeric_alpha(string()) ->
+    {PatchVsn::string(), PatchStr::string()}.
 split_numeric_alpha(RawVsn) ->
     {Num, Str} = split_numeric_alpha(RawVsn, {"", ""}),
     {lists:reverse(Num), Str}.
 
+-spec split_numeric_alpha(string(), {PatchVsnAcc::string(),
+				     PatchStrAcc::string()}) ->
+    {PatchVsn::string(), PatchStr::string()}.
 split_numeric_alpha([], Acc) ->
     Acc;
 split_numeric_alpha([Dig|T], {PatchVsn, PatchStr})